Let's do a concrete experiment, tested with solidity v0.8.11
-
Option 1
contract Greeter {
uint public x = 0;
constructor() {
}
function foo() public {
require(msg.sender == address(0x7D70653a55BcAc5B96c02FADcaC7f4272C1642B9));
x = 1;
}
}
Deployment: 115,183 gas
Call foo(): 41,256 gas
Option 2
contract Greeter {
uint public x = 0;
constructor() {
}
function call() internal pure returns (address) {
return address(0x7D70653a55BcAc5B96c02FADcaC7f4272C1642B9);
}
function foo() public {
require(msg.sender == call());
x = 1;
}
}
Deployment: 117,973 gas
Call foo(): 41,291 gas
Option 3
contract Greeter {
uint public x = 0;
address owner = address(0x7D70653a55BcAc5B96c02FADcaC7f4272C1642B9);
function foo() public {
require(msg.sender == owner);
x = 1;
}
}
Deployment: 140,392 gas
Call foo(): 42,092 gas
Option 4
contract Greeter {
uint public x = 0;
address constant owner = address(0x7D70653a55BcAc5B96c02FADcaC7f4272C1642B9);
function foo() public {
require(msg.sender == owner);
x = 1;
}
}
Deployment: 115,171 gas
Call foo(): 41,256 gas
Summary
Option 4 and option 1 are about the same and the cheapest both to deploy and to call. Option 1 is slightly more expensive to deploy.
That is because a constant
is about the same as a hardcoded value, both do not occupy storage space. But you need the keyword constant
for it to be treated as such (was missing from option 3).
So always use constant
where possible, better than s