The way MultiRewardStaking handles deposits does not work with fee-on-transfer tokens:
deposit() uses _convertToShares() to compute the number of shares to mint, which returns assets - ie a 1:1 equivalence between shares and the number of asset tokens.
98: function _convertToShares(uint256 assets, Math.Rounding) internal pure override returns (uint256) {
99: return assets;
100: }
But in the case of a fee-on-transfer token, the amount received by the contract will be less than assets. This means the contract has minted more shares than what it should have.
Because withdrawing/redeeming also computes shares and assets on a 1 to 1 basis, users can then call withdraw() and siphon assets from MultiRewardStaking.
Check asset balances of the contract before and after the transfer, and use that amount to _mint() and _burn shares (as the goal is to have a 1:1 ratio between shares and assets anyway).
This does introduce a reentrancy vector for ERC777 tokens, so ensure you add appropriate modifiers to prevent attacks.
Lines of code
https://github.com/code-423n4/2023-01-popcorn/blob/d95fc31449c260901811196d617366d6352258cd/src/utils/MultiRewardStaking.sol#L115
Vulnerability details
The way
MultiRewardStaking
handles deposits does not work with fee-on-transfer tokens:deposit()
uses_convertToShares()
to compute the number of shares to mint, which returnsassets
- ie a 1:1 equivalence between shares and the number of asset tokens.But in the case of a fee-on-transfer token, the amount received by the contract will be less than
assets
. This means the contract has minted moreshares
than what it should have.Because withdrawing/redeeming also computes shares and assets on a 1 to 1 basis, users can then call
withdraw()
and siphonassets
fromMultiRewardStaking
.Impact
Medium
Tools Used
Manual Analysis
Mitigation
Check asset balances of the contract before and after the transfer, and use that amount to
_mint()
and_burn
shares (as the goal is to have a 1:1 ratio between shares and assets anyway). This does introduce a reentrancy vector for ERC777 tokens, so ensure you add appropriate modifiers to prevent attacks.