Platform: Code4rena
Start Date: 20/09/2022
Pot Size: $30,000 USDC
Total HM: 12
Participants: 198
Period: 3 days
Judge: 0xean
Total Solo HM: 2
Id: 164
League: ETH
Rank: 23/198
Findings: 1
Award: $296.39
🌟 Selected for report: 0
🚀 Solo Findings: 0
function withdrawOtherToken(IERC20 _otherTokenAddress) external onlyAdmin { require(_otherTokenAddress != tokenAddress, "INVALID_TOKEN"); // tokenAddress address is already sure to be nonzero due to constructor uint256 bal = _otherTokenAddress.balanceOf(address(this)); require(bal > 0, "INSUFFICIENT_BALANCE"); _otherTokenAddress.safeTransfer(_msgSender(), bal); }
tokenAddress
can be a different address but point to the same storage. In this case, admin can by pass the check and drain underlying token.
https://blog.openzeppelin.com/compound-tusd-integration-issue-retrospective/
add check on token balance
diff --git a/contracts/VTVLVesting.sol b/contracts/VTVLVesting.sol index c564c6f..2b9c606 100644 --- a/contracts/VTVLVesting.sol +++ b/contracts/VTVLVesting.sol @@ -445,8 +445,10 @@ contract VTVLVesting is Context, AccessProtected { */ function withdrawOtherToken(IERC20 _otherTokenAddress) external onlyAdmin { require(_otherTokenAddress != tokenAddress, "INVALID_TOKEN"); // tokenAddress address is already sure to be nonzero due to constructor + uint256 balBefore = IERC20(tokenAddress).balanceOf(address(this)); uint256 bal = _otherTokenAddress.balanceOf(address(this)); require(bal > 0, "INSUFFICIENT_BALANCE"); _otherTokenAddress.safeTransfer(_msgSender(), bal); + require(IERC20(tokenAddress).balanceOf(address(this)) == balBefore); } }
#0 - 0xean
2022-09-24T21:38:19Z
dupe of #429