Design Pattern Solidity: Initialize Contract after Deployment
How to use the Initializable pattern
There are a few reasons why you might want to initialize a contract after deployment and not directly by passing constructor arguments. But first let's look at an example:
contract MyCrowdsale {
uint256 rate;
function initialize(uint256 _rate) public {
rate = _rate;
}
}
What's the advantage over constructor(uint256 _rate)
?
- Deployment and configuration does not need to happen at the same time. This can be useful when your workflow requires it.
- Easier Etherscan verification as you do not have to deal with messy constructor arguments.
- Can be used to avoid the 'Stack too deep, try removing local variables' error when passing more than 13 variables.
- It allows your contracts to be upgradable.
Avoid multiple initializations
Make sure though that you do not allow multiple initializations. For just a few parameters, simply add a check for each parameter, e.g., require(rate == 0)
. For many parameters, add an isInitialized
boolean state variable:
contract MyContract {
bool isInitialized = false;
function initialize(
uint256 _param1,
uint256 _param2,
uint256 _param3,
address _param4,
address _param5,
bytes32 _param6,
bytes32 _param7
) public {
require(!isInitialized, 'Contract is already initialized!');
isInitialized = true;
param1 = _param1;
...
param7 = _param7;
}
}
Markus Waas
Solidity Developer