Beatland Festival

AI First Flight #4
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: high
Likelihood: medium
Invalid

`withdraw` Uses `transfer()` with 2300 Gas Stipend Causing Permanent Withdrawal Failure for Smart Contract Wallets

Description

The withdraw() function transfers contract ETH to a recipient using Solidity's built-in payable(target).transfer(...):

// File: src/FestivalPass.sol
147: function withdraw(address target) external onlyOwner {
148: @> payable(target).transfer(address(this).balance);
149: }

Solidity's .transfer() forwards a fixed stipend of 2300 gas. If the target is a multisig contract (e.g. Gnosis Safe), DAO treasury, smart contract wallet (ERC-4337), or proxy, the 2300 gas limit will be exceeded, causing the withdrawal transaction to permanently revert and locking festival proceeds in the contract.

Proof of Concept

function test_PoC_M03_WithdrawTransferGasLimitDOS() public {
vm.prank(attacker1);
festivalPass.buyPass{value: GENERAL_PRICE}(1);
RejectingReceiver receiver = new RejectingReceiver();
vm.prank(owner);
vm.expectRevert();
festivalPass.withdraw(address(receiver));
}

Recommended Mitigation

Replace .transfer() with low-level .call{value: ...}(""):

- payable(target).transfer(address(this).balance);
+ (bool success, ) = payable(target).call{value: address(this).balance}("");
+ require(success, "ETH transfer failed");
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 1 hour ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!