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.
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 payingCash Token
during theTransfer Epoch
period to obtain more voting rights. However, if the purchasedpowerToken
is executed together withReset 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.In
L105
,IStandardGovernor(standardGovernor()).voteToken()
represents the address ofpowerToken
. Indicates the address ofpowerToken
. Entering the address ofpowerToken
into thezeroGovernor.sol#_resetContracts()
function means that whenReset Proposal
is executed, the oldpowerToken
becomes thebootstrapToken
of the newpowerToken
. Thus, the goal is to ensure that the balance of users in the oldpowerToken
is maintained in the newpowerToken
. However, as thePowerToken.sol#buy
function call and thePowerToken.sol#resetToPowerHolders
function call are executed in one block of the blockchain, thePowerToken.sol#reserToPowerHolders
function call is executed before thePowerToken.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 thepowerToken.sol#buy
function is for an oldpowerToken
, the user will pay to purchase the oldpowerToken
. However, the amount ofpowerToken
purchased by the user is not reflected in the newpowerToken
because thepowerToken.sol#resetToPowerHolders
function call has already been made.Impact
The user loses the
CashToken
paid to buypowerToken
.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
.Add the follow lines to
ZeroGovernor.sol#_resetContracts()
.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