Shambolic Banana Barbel
Medium
When the MorphToken.sol
contract is deployed on L2 genesis, some of its storage values (including the dailyInflationRate_
) are not set properly. Because of assumptions in the updateRate()
and mintInflations()
functions, this means that the contract will be permanently blocked from updating its inflation rate or minting new inflation tokens.
MorphToken.sol
uses its initialize()
function to set a number of important parameters:
function initialize(
string memory name_,
string memory symbol_,
address _owner,
uint256 initialSupply_,
uint256 dailyInflationRate_
) public initializer {
_name = name_;
_symbol = symbol_;
_mint(_owner, initialSupply_);
_epochInflationRates.push(EpochInflationRate(dailyInflationRate_, 0));
_transferOwnership(_owner);
emit UpdateEpochInflationRate(dailyInflationRate_, 0);
}
Notably, the dailyInflationRate_
is set in this function. If this is not set, it can never be updated later, because the updateRate()
function loads the previous rate, which requires there to be at least one rate set:
function updateRate(uint256 newRate, uint256 effectiveEpochIndex) public onlyOwner {
require(
_epochInflationRates[_epochInflationRates.length - 1].rate != newRate,
"new rate is the same as the latest rate"
);
...
}
A similar assumption (taking _epochInflationRates.length - 1
) is made in the mintInflations()
function, which is called to mint new inflation tokens.
It turns out that in the deployment of this contract, the initialize()
function is locked, but the values are never set. We can see this in ops/l2-genesis/morph-chain-ops/genesis/config.go
, where it sets the storage values for all contracts. Specifically, we can see where the MorphToken is set:
storage["MorphToken"] = state.StorageValues{
"_initialized": 1,
"_initializing": false,
}
This will set the value of _initialized
to 1
, blocking future calls to initialize()
. But it will not set the dailyInflationRate_
value, which means that the updateRate()
function, as well as all calls to mintInflations()
, will always fail.
None
None
N/A
The MorphToken.sol
contract will be functionally useless, as it won't be able to update its inflation rate or mint new inflation tokens for sequencer rewards.
N/A
All the storage values should be set properly in the genesis file.
Additionally, for safety, updateRate()
can be adjusted to only perform its checks in the event that _epochInflationRates.length > 0
.