Tadle

Tadle
DeFi
30,000 USDC
View results
Submission Details
Severity: low
Invalid

Smart Contract Wallets Cannot Withdraw ETH.

Summary

Now days smart wallet are widely used, and the issue is happen when interaction with smart wallets that utilizing logic in their receive or fallback functions. The issue arises because the use of the transfer method for sending Ether to these smart wallets can lead to transaction reversion due to compatibility problems with the smart wallets.

Vulnerability Details

The withdraw function uses transfer to send ETH when user wants to get his funds out. If users attempt to withdraw funds using a Smart Wallet that has any extra logic on the receive method, the transaction will run out of gas and fail.

function withdraw(address _tokenAddress, TokenBalanceType _tokenBalanceType) external whenNotPaused {
// ...
if (_tokenAddress == wrappedNativeToken) {
// ...
IWrappedNativeToken(wrappedNativeToken).withdraw(claimAbleAmount);
@>>> payable(msg.sender).transfer(claimAbleAmount);
} else {
// ...
}

POC:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract Test {
constructor() payable {}
function withdraw() public payable {
@>>> payable(msg.sender).transfer(1 ether);
}
}
contract SmartWallet {
function callWithdraw(address _to) public {
(bool done, ) = _to.call(abi.encodeWithSignature("withdraw()"));
require(done, "Failed to receive funds...");
}
fallback() external payable {
// Simple logic
console.log(msg.value);
}
}

Output:

Error: VM Exception while processing transaction: reverted with reason string 'Failed to receive funds...'

Impact

this issue it prevents successful transactions to smart wallets that rely on custom logic within their receive or fallback functions.

Tools Used

Recommendations

Use call Method for Ether Transfers Instead of using the transfer method,

or give user chance to specify the receiver of funds.

- function withdraw(address _tokenAddress, TokenBalanceType _tokenBalanceType) external whenNotPaused {
+ function withdraw(address _tokenAddress, TokenBalanceType _tokenBalanceType, address receiver) external whenNotPaused {
// ...
if (_tokenAddress == wrappedNativeToken) {
// ...
IWrappedNativeToken(wrappedNativeToken).withdraw(claimAbleAmount);
- payable(msg.sender).transfer(claimAbleAmount);
+ payable(receiver).transfer(claimAbleAmount);
} else {
// ...
}
Updates

Lead Judging Commences

0xnevi Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

[invalid] finding-TokenManager-withdraw-transfer-2300-gas

Invalid, known issues [Medium-2](https://github.com/Cyfrin/2024-08-tadle/issues/1)

Support

FAQs

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