VTVL contest - wuwe1's results

Building no-code token management tools to empower web3 founders and investors, starting with token vesting.

General Information

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

VTVL

Findings Distribution

Researcher Performance

Rank: 23/198

Findings: 1

Award: $296.39

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: CertoraInc

Also found by: 0xhunter, Lambda, datapunk, dipp, wuwe1

Labels

bug
duplicate
2 (Med Risk)

Awards

296.3865 USDC - $296.39

External Links

Lines of code

https://github.com/code-423n4/2022-09-vtvl/blob/f68b7f3e61dad0d873b5b5a1e8126b839afeab5f/contracts/VTVLVesting.sol#L446-L451

Vulnerability details

Proof of Concept

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

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter