Glamorous Plum Baboon
Medium
The executeBackUnbacked
function in the BridgeLogic
contract uses IERC20.safeTransferFrom
to transfer tokens without explicitly checking the return value. While GPv2SafeERC20
is employed to enforce safety checks, certain improperly implemented or malicious ERC20 tokens may bypass these checks, leading to unexpected behavior or potential token losses.
The GPv2SafeERC20.safeTransferFrom
function wraps IERC20.safeTransferFrom
to handle potential issues with token transfers (e.g., by reverting on failure). However, the implementation of GPv2SafeERC20
does not guarantee proper functionality with non-standard or poorly implemented ERC20 tokens. If an improperly implemented token fails to execute the transfer as expected, the absence of an explicit return value check may result in undetected token losses.
The relevant code is found in the following lines:
IERC20(asset).safeTransferFrom(msg.sender, reserveCache.aTokenAddress, added);
Without explicit validation of the successful token transfer, this operation may fail silently, potentially leading to discrepancies between the intended and actual token balances.
The root cause of this vulnerability is the implicit reliance on the GPv2SafeERC20.safeTransferFrom
function to handle transfer failures, which does not account for non-compliant ERC20 implementations. The following line in the executeBackUnbacked
function is affected:
This issue may result in the following consequences:
- Token transfers may silently fail when interacting with non-standard ERC20 tokens, potentially causing token losses.
- Critical financial operations within the protocol may behave unexpectedly, leading to inconsistencies in reserve and liquidity management.
- Potentially exploitable scenarios for malicious tokens.
To demonstrate the vulnerability, consider an ERC20 token implementation that does not return a boolean value for the transferFrom
function or reverts silently:
contract MaliciousToken is IERC20 {
function transferFrom(address, address, uint256) external override returns (bool) {
// Fails without revert or returns false, bypassing checks
return false;
}
}
- Deploy the
MaliciousToken
and mint tokens to an attacker-controlled address. - Call the
executeBackUnbacked
function usingMaliciousToken
as the asset. - The
safeTransferFrom
operation will fail silently, and the protocol will assume tokens were transferred successfully, leading to accounting discrepancies or lost tokens.
To address this issue, explicitly validate the successful completion of the token transfer. Use a require statement to enforce the correct return value:
require(
IERC20(asset).safeTransferFrom(msg.sender, reserveCache.aTokenAddress, added),
"Token transfer failed"
);
This approach ensures that any failure in the token transfer process is detected and handled appropriately, preventing silent failures and token losses.