An attacker can exploit the refund function in the contract to execute a Denial of Service (DoS) attack. By inflating the state (e.g., etherBalance mapping), the attacker increases the gas cost of the refund function for legitimate users. This attack can make the function prohibitively expensive or even impossible to execute if the gas required exceeds the block gas limit.
Vulnerable Code:
The refund function clears user balances from mappings such as etherBalance and balances:
'''solidity
function refund() external nonReentrant beforeDeadline {
address payable _to = payable(msg.sender);
_refundERC20(_to);
_refundETH(_to);
emit Refunded(msg.sender);
}
function _refundETH(address payable _to) internal {
uint256 refundValue = etherBalance[_to];
_to.transfer(refundValue);
etherBalance[_to] = 0;
}
'''
Attack Mechanism:
The attacker uses multiple Sybil accounts or bots to deposit small amounts of Ether or tokens into the contract.
Each deposit creates or inflates entries in the etherBalance and balances mappings.
When legitimate users call refund, the contract must process and clear these storage slots, leading to increased gas costs.
DoS Condition:
If the number of storage slots is large, the gas cost of clearing them during a refund may approach or exceed the block gas limit, preventing legitimate users from executing the function.
Even if the block gas limit is not exceeded, the higher gas cost could deter users from calling the function.
Increased Gas Costs for Legitimate Users:
Legitimate users must pay higher gas fees to execute the refund function due to the inflated state.
Denial of Service:
If the gas required for refund exceeds the block gas limit, legitimate users will be unable to withdraw their funds.
Steps to Reproduce
Deploy the ChristmasDinner contract.
Use multiple addresses (or bots) to call the deposit function with small amounts of Ether or tokens.
Observe that the mappings etherBalance and balances grow significantly.
Attempt to call the refund function as a legitimate user.
Notice the increased gas cost or failure of the transaction if the block gas limit is reached.
101 User: Gas used: 180,000 gas
First 100 users: Gas used: 70,000 gas
Break Refund into Smaller Transactions:
Allow users to process refunds in smaller chunks (e.g., one token or partial Ether balance at a time) rather than clearing all storage entries in a single transaction.
Limit State Inflation:
Impose a minimum deposit threshold to reduce the likelihood of attackers creating a large number of small entries.
Iterate Efficiently:
Use a mechanism that does not rely on iterating over large mappings. For example, users could be responsible for withdrawing specific balances themselves.
Transaction Throttling:
Implement a rate limiter to prevent spam deposits from Sybil accounts.
Gas Limit Monitoring:
Add logic to monitor and mitigate operations that may approach the block gas limit.
Manual review and analysis of the refund and _refundETH functions.
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.