Change default owner/admin accounts to `tx.origin` rather than `msg.sender`
See original GitHub issue🧐 Motivation
Some background: I’m the author of the Hardhat plugin xdeployer
that helps to deploy smart contracts across multiple EVM chains with the same deterministic address (keyword CREATE2
opcode). Since opcodes can only be called via smart contracts, the default owner of a deployed contract with CREATE2
(and my plugin) will be a contract address (using your default npm
package as dependency) which is obviously not good. How about setting the default owner to tx.origin
and make everything more agnostic? Like that it can be ensured that the original EOA user will always be the owner. The same applies to the default roles in your OpenZeppelin Wizard for DEFAULT_ADMIN_ROLE
, PAUSER_ROLE
, MINTER_ROLE
:
constructor() ERC20("MyToken", "MTK") {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(PAUSER_ROLE, msg.sender);
_grantRole(MINTER_ROLE, msg.sender);
}
I’m fully aware of the security considerations re tx.origin
(https://docs.soliditylang.org/en/v0.8.11/security-considerations.html?highlight=tx.origin#tx-origin), however, in this case, we would not touch the authorization but rather “only” the constructor argument.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:2
- Comments:6 (4 by maintainers)
We already had some request to change the
Ownable
constructor toIMO this would be much better then using tx.origin, yet we rejected this proposition because it would be a breaking change. We are VERY careful about any breaking change, which you proposal would be. Also we are, like most of the community, against using tx.origin. This has been the source of a lot of bugs.
If you really want to set tx.origin has the original owner (I would advice against it) you always have the possibility to do.
We disagree that it’s okay to use
tx.origin
in the constructor, at least in general. What you really want for the scenario you describe is to use the address of the caller to the factory contract, but this is not the same astx.origin
, because the caller to the factory contract may be another smart contract that should become the owner of the newly created contract.This is always going to be a problem with factories and the factory created contract needs to be aware of that and/or offer a way to initialize it to the right values. For example, with an
Ownable
contract you can initialize the contract with a call totransferOwnership
.This is a proposal for a more general solution for the Wizard: