Beatland Festival

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

L-1: `withdraw` uses `transfer`, breaking withdrawals to contract wallets

Root + Impact

ETH withdrawals use Solidity’s transfer, which forwards only 2300 gas to the recipient. Smart contract wallets without a payable receive/fallback cannot accept the payment, locking festival proceeds until the owner picks an EOA.

Description

  • Normal behavior: the owner withdraws all ETH from pass sales to a chosen target address.

  • transfer is deprecated for this reason; many multisigs and account-abstraction wallets need more gas or use call.

// src/FestivalPass.sol
function withdraw(address target) external onlyOwner {
// @> 2300 gas stipend; fails for many contract recipients
payable(target).transfer(address(this).balance);
}

Risk

Likelihood:

  • The owner sets target to a Gnosis Safe, ERC4337 wallet, or any contract without a payable receive path.

  • Withdrawal is attempted after pass sales accumulate ETH in the contract.

Impact:

  • withdraw reverts; ETH remains stuck until an EOA is used.

  • Operational failure during payout, not attacker profit.

Proof of Concept

/// @dev No receive/fallback — cannot accept ETH via transfer()
contract ContractWalletNoReceive {}
function test_L01_withdrawTransferFailsToContractWallet() public {
ContractWalletNoReceive wallet = new ContractWalletNoReceive();
vm.prank(user1);
festivalPass.buyPass{value: GENERAL_PRICE}(1);
assertGt(address(festivalPass).balance, 0);
vm.expectRevert();
festivalPass.withdraw(address(wallet));
}

Recommended Mitigation

+ import {Address} from "@openzeppelin/contracts/utils/Address.sol";
function withdraw(address target) external onlyOwner {
+ require(target != address(0), "Zero address");
- payable(target).transfer(address(this).balance);
+ Address.sendValue(payable(target), address(this).balance);
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 4 hours 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!