code-423n4 / 2022-05-backd-findings

0 stars 0 forks source link

unstakeFor method in AmmGauge.sol does not respect CEI standard. #161

Closed code423n4 closed 2 years ago

code423n4 commented 2 years ago

Lines of code

https://github.com/code-423n4/2022-05-backd/blob/2a5664d35cde5b036074edef3c1369b984d10010/protocol/contracts/tokenomics/AmmGauge.sol#L131

Vulnerability details

Issue: unstakeFor method does not respect CEI which can lead to reentrancy attack.

Consequences: If a token that has a hook on transfer is used, an attacker can use unstakeFor to drain the AmmGauge of funds by calling unstakeFor via a custom contract that will reenter in the unstakeFor method once it receives the tokens on line 131.

File: AmmGauge.sol
118:     /**
119:      * @notice Unstake amount of AMM token and send to another account.
120:      * @param dst Account to which unstaked AMM tokens will be sent.
121:      * @param amount Amount of token to unstake.
122:      * @return `true` if success.
123:      */
124:     function unstakeFor(address dst, uint256 amount) public virtual override returns (bool) {
125:         require(amount > 0, Error.INVALID_AMOUNT);
126:         require(balances[msg.sender] >= amount, Error.INSUFFICIENT_BALANCE);
127: 
128:         _userCheckpoint(msg.sender);
129: 
130:         uint256 oldBal = IERC20(ammToken).balanceOf(address(this));
131:         IERC20(ammToken).safeTransfer(dst, amount);
132:         uint256 newBal = IERC20(ammToken).balanceOf(address(this));
133:         uint256 unstaked = oldBal - newBal;
134:         balances[msg.sender] -= unstaked;
135:         totalStaked -= unstaked;
136:         emit AmmUnstaked(msg.sender, ammToken, amount);
137:         return true;
138:     }

Proof of Concept

Mitigations

Consider adding a reentrancy guard.

chase-manning commented 2 years ago

We do not support tokens that offer reentrancy opportunities

GalloDaSballo commented 2 years ago

See #158