Skip to content

Latest commit

 

History

History
77 lines (55 loc) · 2.86 KB

096.md

File metadata and controls

77 lines (55 loc) · 2.86 KB

Shambolic Banana Barbel

Medium

MorphToken cannot mint new tokens due to improper initialization

Summary

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.

Root Cause

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.

Internal Preconditions

None

External Preconditions

None

Attack Path

N/A

Impact

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.

PoC

N/A

Mitigation

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.