Beatland Festival

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

ETH Withdrawal Failure Due to Fixed Gas Stipend in `.transfer()` Causing Incompatibility with Multisig and Smart-Contract Wallets

Description

The withdraw() function uses Solidity’s .transfer() method to send ETH, which forwards a fixed gas stipend of 2300 gas. While sufficient for Externally Owned Accounts (EOAs), this gas limit is insufficient for multisig wallets and smart-contract-based wallets, causing ETH withdrawals to revert and potentially leading to locked funds and loss of protocol functionality.
The protocol implements an ETH withdrawal mechanism allowing the contract owner to transfer accumulated ETH to a specified address:

function withdraw(address target) external onlyOwner {
payable(target).transfer(address(this).balance);
}

The .transfer() method forwards exactly 2300 gas to the recipient’s receive() or fallback() function. This design assumes that the recipient can accept ETH within this limited gas budget.

However, many modern Ethereum wallets—such as multisig wallets (e.g., Gnosis Safe) and other smart-contract wallets—execute additional logic when receiving ETH, including:

  • Event emission

  • State updates

  • Internal validation checks

These operations often require more than 2300 gas, causing the ETH transfer to fail and revert.


Impact

Primary Impact

  • ETH withdrawals to multisig wallets or smart-contract treasuries may consistently fail

  • Contract ETH balance may become temporarily or permanently inaccessible

Secondary Impact

  • Incompatibility with DAO treasuries and modern wallet infrastructure

  • Operational failure of protocol revenue collection

  • Reduced trust and reliability of the system

Proof of Concept (PoC)

Scenario

  1. ETH is accumulated in the contract through buyPass().

  2. The contract owner attempts to withdraw ETH to a multisig wallet.

  3. The multisig wallet’s receive() function executes logic exceeding 2300 gas.

  4. .transfer() forwards insufficient gas.

  5. Transaction reverts, preventing ETH withdrawal.

Result

  • ETH remains locked in the contract

  • Withdrawal function becomes unusable for certain valid recipient addresses


###Recommended Mitigation

✅ Replace .transfer() with .call()

Use Solidity’s low-level .call{value: amount}(""), which forwards all available gas and allows explicit error handling.

Mitigated Code Example

function withdraw(address target) external onlyOwner {
uint256 amount = address(this).balance;
(bool success, ) = target.call{value: amount}("");
require(success, "ETH transfer failed");
}
Updates

Lead Judging Commences

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