You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Funds in the FuelERC20Gateway can be drained due to returning an incorrect asset when claiming a refund.
Refunds are registered when there is a mismatch between the L1 and L2 assets.
Refunds are accounted for in the register_refund function and stored in the storage variable refund_amounts.
Figure 4.2: The register_refund function in bridge-fungible-token/bridge-fungible-token/src/bridge_fungible_token.sw
For a user to withdraw registered refunds the claim_refund function should be called. This function however incorrectly sets as the token to be withdrawn the BRIDGED_TOKEN instead of the asset variable.
Figure 4.3: The claim_refund function in bridge-fungible-token/bridge-fungible-token/src/bridge_fungible_token.sw
130fnclaim_refund(originator:b256, asset:b256) {
131letstored_amount=storage.refund_amounts.get(originator).get(asset).read();
132require(stored_amount!=ZERO_B256,
BridgeFungibleTokenError::NoRefundAvailable);
133134 // reset the refund amount to 0135storage.refund_amounts.get(originator).insert(asset, ZERO_B256);
136137 // send a message to unlock this amount on the base layer gateway contract138send_message(BRIDGED_TOKEN_GATEWAY, encode_data(originator, stored_amount,
BRIDGED_TOKEN), 0);
139 }
This allows an attacker to deposit any fake asset and to withdraw the true asset when claiming a refund.
Figure 4.4: The finalizeWithdrawal function in fuel-v2-contracts/contracts/messaging/gateway/FuelERC20Gateway.sol
function finalizeWithdrawal(
addressto,
addresstokenId,
uint256amount
) externalpayable whenNotPaused onlyFromPortal {
require(amount >0, "Cannot withdraw zero");
bytes32 fuelTokenId =messageSender();
//reduce deposit balance and transfer tokens (math will underflow if amount is larger than allowed)
_deposits[tokenId][fuelTokenId] = _deposits[tokenId][fuelTokenId] - amount;
IERC20Upgradeable(tokenId).safeTransfer(to, amount);
//emit event for successful token withdrawemitWithdrawal(bytes32(uint256(uint160(to))), tokenId, fuelTokenId, amount);
}
This is possible because there is no deposit accounting per user in the FuelERC20Gateway which allows for withdrawals to different addresses other than the depositors.
Exploit Scenario
Alice creates a fake token and bridges 10K FAKE while specifying the Fuel ETH token id on the Fuel chain. Because the bridged asset is not appropriate, Alice is able to claim a refund. Due to the error, she is able to refund 10K ETH on Ethereum.
Recommendations
Short term, update the encoded data to include the deposited asset instead of the bridge asset. Alternatively, the gateway could be re-designed to not require specifying the Fuel token id on Ethereum which could eliminate the need for refunds.
Long term, pay extra attention to the intersection between blockchains. Make sure these are well-documented and tested, since they are typically harder to test and more prone to errors.
The text was updated successfully, but these errors were encountered:
Description
Funds in the FuelERC20Gateway can be drained due to returning an incorrect asset when claiming a refund.
Refunds are registered when there is a mismatch between the L1 and L2 assets.
Refunds are accounted for in the register_refund function and stored in the storage variable refund_amounts.
Figure 4.2: The register_refund function in bridge-fungible-token/bridge-fungible-token/src/bridge_fungible_token.sw
For a user to withdraw registered refunds the claim_refund function should be called. This function however incorrectly sets as the token to be withdrawn the BRIDGED_TOKEN instead of the asset variable.
Figure 4.3: The claim_refund function in bridge-fungible-token/bridge-fungible-token/src/bridge_fungible_token.sw
This allows an attacker to deposit any fake asset and to withdraw the true asset when claiming a refund.
Figure 4.4: The finalizeWithdrawal function in fuel-v2-contracts/contracts/messaging/gateway/FuelERC20Gateway.sol
This is possible because there is no deposit accounting per user in the FuelERC20Gateway which allows for withdrawals to different addresses other than the depositors.
Exploit Scenario
Alice creates a fake token and bridges 10K FAKE while specifying the Fuel ETH token id on the Fuel chain. Because the bridged asset is not appropriate, Alice is able to claim a refund. Due to the error, she is able to refund 10K ETH on Ethereum.
Recommendations
Short term, update the encoded data to include the deposited asset instead of the bridge asset. Alternatively, the gateway could be re-designed to not require specifying the Fuel token id on Ethereum which could eliminate the need for refunds.
Long term, pay extra attention to the intersection between blockchains. Make sure these are well-documented and tested, since they are typically harder to test and more prone to errors.
The text was updated successfully, but these errors were encountered: