The Treasury
contract is vulnerable to silent transfer failures due to missing return value checks when interacting with ERC-20 tokens. If a malicious or non-standard token fails a transferFrom
or transfer
operation without reverting, the contract incorrectly assumes the transaction was successful, leading to fund misaccounting.
The vulnerability arises from ignoring the return values of IERC20.transferFrom
and IERC20.transfer
calls in the Treasury
contract:
deposit()
function (contracts/core/collectors/Treasury.sol:50)
Issue: The function does not check if transferFrom
returned true
.
Risk: A malicious token could always return false
, tricking the contract into recording a deposit that never actually happened.
withdraw()
function (contracts/core/collectors/Treasury.sol:75)
Issue: The function does not check if transfer
returned true
.
Risk: If a token silently fails (returns false
without reverting), the Treasury will deduct the balance internally but never actually transfer the funds, leading to misaccounted funds.
Misaccounted Funds: The Treasury thinks it holds more assets than it actually does, leading to incorrect reporting.
Loss of Funds: If withdraw()
is called on a non-standard or malicious token that always returns false
, funds are deducted internally but never received by the recipient.
Potential Exploits: Attackers can use malicious tokens to fake deposits and later withdraw actual funds, draining the Treasury.
Even though only managers can initiate withdrawals, the Treasury contract incorrectly assumes all transfers succeed without verifying their outcomes. This leads to misaccounted funds, and since deposits also lack proper validation, a regular user—without any special roles—can still exploit the vulnerability.
Create the MockMalicious.sol
Create the test file
The output:
Hardhat
transfer
and transferFrom
Modify both functions to explicitly check return values:
Why? Ensures that deposits and withdrawals only proceed if tokens are actually transferred.
Instead of calling IERC20
directly, use SafeERC20, which automatically reverts if a token fails to transfer:
Why? Prevents silent failures by ensuring transfers either succeed or revert.
Before recording deposits, check the Treasury’s actual token balance:
Why? Ensures deposits only succeed if the Treasury actually receives the tokens.
LightChaser Low-60
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.