40,000 USDC
View results
Submission Details
Severity: medium
Valid

[ M ] Some ERC20 tokens return a false bool even if transfer was successful

Summary

In confirmReceipt, it is expected that the buyer will confirm the receipt of the report by calling the confirmReceipt function.

Vulnerability Details

However, despite recommendations by Code Hawk, there may be some cases where the buyer and seller agree
to use a specific ERC20 Token. Some particularly pathological tokens (e.g. Tether Gold) declare a bool return,
but then return false, even when the transfer was successful.

Impact

If Tether Gold or any other token with similar behavior is used, the safeTransfer method might not be able to correctly determine if the transfer was successful.

As a result, the state of the escrow contract might not be updated appropriately,
and funds could be left in the contract, leading to potential disputes or incorrect handling of funds.

Tools Used

Manual Review

Recommendations

Before calling safeTransfer, record the initial token balance of the recipient (in this case, the seller)
using the ERC20 balanceOf function.
You can do this in the confirmReceipt function before the safeTransfer call.

Proceed with the safeTransfer to send the tokens from the escrow contract to the seller's address.

After the safeTransfer call, retrieve the final token balance of the recipient (seller) again using the ERC20 balanceOf function.

Before calling safeTransfer, record the initial token balance of the recipient (in this case, the seller) using the ERC20 balanceOf function. You can do this in the confirmReceipt function before the safeTransfer call.

Proceed with the safeTransfer to send the tokens from the escrow contract to the seller's address.

After the safeTransfer call, retrieve the final token balance of the recipient (seller) again using the ERC20 balanceOf function.

Compare the initial token balance with the final token balance. If the final balance is greater than the initial balance by the expected amount (the escrow amount), then the transfer was successful. Otherwise, it indicates that the transfer might have failed.

Something like this:

function confirmReceipt() external onlyBuyer inState(State.Created) {
s_state = State.Confirmed;
emit Confirmed(i_seller);
uint256 initialBalance = i_tokenContract.balanceOf(i_seller);
// Perform the transfer
i_tokenContract.safeTransfer(i_seller, i_tokenContract.balanceOf(address(this)));
uint256 finalBalance = i_tokenContract.balanceOf(i_seller);
// Check if the transfer was successful
uint256 expectedFinalBalance = initialBalance + i_price;
if (finalBalance != expectedFinalBalance) {
// Handle transfer failure, e.g., revert the transaction or take other appropriate actions
revert("Transfer failed");
}
}

Support

FAQs

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