sherlock-audit / 2023-10-mzero-judging

3 stars 2 forks source link

FastTiger - The user's 'buy' of the 'power token' may not have any effect on the user and may only cause damage to the user. #82

Closed sherlock-admin4 closed 7 months ago

sherlock-admin4 commented 7 months ago

FastTiger

medium

The user's 'buy' of the 'power token' may not have any effect on the user and may only cause damage to the user.

Summary

Users purchase PowerToken by paying Cash Token during the Transfer Epoch period to obtain more voting rights. However, if the purchased powerToken is executed together with Reset Proposal in one block of the chain or is in the mempool, it may not have any effect on the user.

Vulnerability Detail

The ZeroGovernor.sol#resetToPowerHolders function is as follows.

    function resetToPowerHolders() external onlySelf {
L105:    _resetContracts(IStandardGovernor(standardGovernor()).voteToken());
    }

In L105, IStandardGovernor(standardGovernor()).voteToken() represents the address of powerToken. Indicates the address of powerToken. Entering the address of powerToken into the zeroGovernor.sol#_resetContracts() function means that when Reset Proposal is executed, the old powerToken becomes the bootstrapToken of the new powerToken. Thus, the goal is to ensure that the balance of users in the old powerToken is maintained in the new powerToken. However, as the PowerToken.sol#buy function call and the PowerToken.sol#resetToPowerHolders function call are executed in one block of the blockchain, the PowerToken.sol#reserToPowerHolders function call is executed before the PowerToken.sol#buy function call. If that happens, a problem arises. The same problem occurs even when the mempool is present and the call is made like this. Since the user's call to the powerToken.sol#buy function is for an old powerToken, the user will pay to purchase the old powerToken. However, the amount of powerToken purchased by the user is not reflected in the new powerToken because the powerToken.sol#resetToPowerHolders function call has already been made.

Impact

The user loses the CashToken paid to buy powerToken.

Code Snippet

https://github.com/sherlock-audit/2023-10-mzero/blob/main/ttg/src/PowerToken.sol https://github.com/sherlock-audit/2023-10-mzero/blob/main/ttg/src/ZeroGovernor.sol

Tool used

Manual Review

Recommendation

Add the follow function to PowerToken.sol.

bool _flag;
function setFlag(bool flag_) external {
    require(msg.sender == zeroGovernor);
    _flag = flag_;
}

Add the follow lines to ZeroGovernor.sol#_resetContracts().

    function _resetContracts(address bootstrapToken_) internal {
        IStandardGovernor standardGovernor_ = IStandardGovernor(standardGovernor());
+++     IPowerToken powerToken_ = IPowerToken(powerToken());
+++     powerToken_.setFlag(false);
...SNIP
    }

Add the follow lines to PowerToken.sol#buy(). function buy( uint256 minAmount, uint256 maxAmount, address destination, uint16 expiryEpoch ) external returns (uint240 amount, uint256 cost) { +++ require(_flag==true); ...SNIP }

Duplicate of #59