ERC20-related bugs
ZeroAmountTransfer
amount=0 で transfer するとエラーが発生する
🔗 URL
https://github.com/code-423n4/2022-02-hubble-findings/issues/29
⛳️ Condition
- ERC20 トークンが transfer される際に、amount が 0 でないことを確認していない
- トークンの制限をしていないため、どんな ERC20 トークンでも transfer する可能性がある
function _transferYield(address _asset) internal {
require(_asset != address(0), Errors.VT_PROCESS_YIELD_INVALID);
uint256 yieldAmount = IERC20(_asset).balanceOf(address(this));
// transfer to treasury
if (_vaultFee > 0) {
uint256 treasuryAmount = _processTreasury(_asset, yieldAmount);
yieldAmount = yieldAmount.sub(treasuryAmount);
}
// transfer to yieldManager
address yieldManager = _addressesProvider.getAddress('YIELD_MANAGER');
TransferHelper.safeTransfer(_asset, yieldManager, yieldAmount);
emit ProcessYield(_asset, yieldAmount);
}
👨💻 PoC
ERC20 トークンの中には、ゼロ枚の transfer で revert されるものがあります(例:LEND)
参照: https://github.com/d-xo/weird-erc20#revert-on-zero-value-transfers
_asset
に LEND トークンが入力されるyieldAmount
が 0 になる- 下記のように関数が実行される
TransferHelper.safeTransfer(LEND_TOKEN_ADDRESS, yieldManager, 0);
- トランザクションが revert される
// transfer to treasury
if (_vaultFee > 0) {
uint256 treasuryAmount = _processTreasury(_asset, yieldAmount);
yieldAmount = yieldAmount.sub(treasuryAmount);
}
// transfer to yieldManager
address yieldManager = _addressesProvider.getAddress('YIELD_MANAGER');
TransferHelper.safeTransfer(_asset, yieldManager, yieldAmount);
✅ Recommendation
例: 下記のように変更してください
+ if (yieldAmount > 0) {
// transfer to treasury
if (_vaultFee > 0) {
uint256 treasuryAmount = _processTreasury(_asset, yieldAmount);
yieldAmount = yieldAmount.sub(treasuryAmount);
}
// transfer to yieldManager
address yieldManager = _addressesProvider.getAddress('YIELD_MANAGER');
TransferHelper.safeTransfer(_asset, yieldManager, yieldAmount);
+ }
👬 Similar Issue
https://github.com/code-423n4/2022-02-concur-findings/issues/231