Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use SafeTransferLib for ETH transfers [GasZipFacet v2.0.1,LibAsset v1.0.2,FeeCollector v1.0.1,GasZipPeriphery v1.0.1,LiFiDEXAggregator v1.5.1,LiFuelFeeCollector v1.0.2,Permit2Proxy v1.0.2,Receiver v2.0.3,ReceiverAcrossV3 v1.0.3,ReceiverStargateV2 v1.0.1,RelayerCelerIM v2.0.1,TokenWrapper v1.0.1] #912

Merged
merged 15 commits into from
Jan 10, 2025
Merged
55 changes: 55 additions & 0 deletions audit/auditLog.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@
"auditorGitHandle": "sujithsomraaj",
"auditReportPath": "./audit/reports/2025.01.09_ThorSwapFacet(v1.2.1).pdf",
"auditCommitHash": "5005bf62858a9cb2a7628976ef870e91bb732a75"
},
"audit20250109_3": {
"auditCompletedOn": "09.01.2025",
"auditedBy": "Sujith Somraaj (individual security researcher)",
"auditorGitHandle": "sujithsomraaj",
"auditReportPath": "./audit/reports/2025.01.09_SafeTransferETHUpdate.pdf",
"auditCommitHash": "e4f27b0c4f572e5c64ca132dc2e496a3fe6c7c1d"
}
},
"auditedContracts": {
Expand Down Expand Up @@ -122,14 +129,25 @@
"audit20241105"
]
},
"FeeCollector": {
"1.0.1": [
"audit20250109_3"
]
},
"GasZipFacet": {
"2.0.0": [
"audit20241107"
],
"2.0.1": [
"audit20250109_3"
]
},
"GasZipPeriphery": {
"1.0.0": [
"audit20241107"
],
"1.0.1": [
"audit20250109_3"
]
},
"IGasZip": {
Expand All @@ -140,16 +158,35 @@
"LibAsset": {
"1.0.1": [
"audit20241202"
],
"1.0.2": [
"audit20250109_3"
]
},
"LiFiDEXAggregator": {
"1.5.0": [
"audit20241203"
],
"1.5.1": [
"audit20250109_3"
]
},
"LiFuelFeeCollector": {
"1.0.2": [
"audit20250109_3"
]
},
"Permit2Proxy": {
"1.0.0": [
"audit20241122"
],
"1.0.2": [
"audit20250109_3"
]
},
"Receiver": {
"2.0.3": [
"audit20250109_3"
]
},
"ReceiverAcrossV3": {
Expand All @@ -158,6 +195,19 @@
],
"1.0.1": [
"audit20241206"
],
"1.0.3": [
"audit20250109_3"
]
},
"ReceiverStargateV2": {
"1.0.1": [
"audit20250109_3"
]
},
"RelayerCelerIM": {
"2.0.1": [
"audit20250109_3"
]
},
"RelayFacet": {
Expand All @@ -175,6 +225,11 @@
"audit20250109_1"
]
},
"TokenWrapper": {
"1.0.1": [
"audit20250109_3"
]
},
"WithdrawablePeriphery": {
"1.0.0": [
"audit20241014"
Expand Down
Binary file not shown.
10 changes: 6 additions & 4 deletions src/Facets/GasZipFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ import { InvalidCallData, CannotBridgeToSameNetwork, InvalidAmount } from "lifi/
/// @title GasZipFacet
/// @author LI.FI (https://li.fi)
/// @notice Provides functionality to swap ERC20 tokens to native and deposit them to the gas.zip protocol (https://www.gas.zip/)
/// @custom:version 2.0.0
/// @custom:version 2.0.1
contract GasZipFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
using SafeTransferLib for address;

uint256 internal constant MAX_CHAINID_LENGTH_ALLOWED = 32;

error OnlyNativeAllowed();
error TooManyChainIds();

/// State ///
address public constant NON_EVM_RECEIVER_IDENTIFIER =
address public constant NON_EVM_ADDRESS =
0x11f111f111f111F111f111f111F111f111f111F1;
IGasZip public immutable gasZipRouter;

Expand Down Expand Up @@ -104,7 +106,7 @@ contract GasZipFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {

// validate that receiverAddress matches with bridgeData in case of EVM target chain
if (
_bridgeData.receiver != NON_EVM_RECEIVER_IDENTIFIER &&
_bridgeData.receiver != NON_EVM_ADDRESS &&
_gasZipData.receiverAddress !=
bytes32(uint256(uint160(_bridgeData.receiver)))
) revert InvalidCallData();
Expand All @@ -130,7 +132,7 @@ contract GasZipFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
) external pure returns (uint256 destinationChains) {
uint256 length = _chainIds.length;

if (length > 32) revert TooManyChainIds();
if (length > MAX_CHAINID_LENGTH_ALLOWED) revert TooManyChainIds();

for (uint256 i; i < length; ++i) {
// Shift destinationChains left by 8 bits and add the next chainID
Expand Down
5 changes: 2 additions & 3 deletions src/Libraries/LibAsset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { LibSwap } from "./LibSwap.sol";

/// @title LibAsset
/// @custom:version 1.0.1
/// @custom:version 1.0.2
/// @notice This library contains helpers for dealing with onchain transfers
/// of assets, including accounting for the native asset `assetId`
/// conventions and any noncompliant ERC20 transfers
Expand Down Expand Up @@ -67,8 +67,7 @@ library LibAsset {
}

if (assetId.allowance(address(this), spender) < amount) {
SafeERC20.safeApprove(IERC20(assetId), spender, 0);
SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);
SafeERC20.forceApprove(IERC20(assetId), spender, MAX_UINT);
}
}

Expand Down
10 changes: 3 additions & 7 deletions src/Periphery/FeeCollector.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ pragma solidity ^0.8.17;

import { LibAsset } from "../Libraries/LibAsset.sol";
import { TransferrableOwnership } from "../Helpers/TransferrableOwnership.sol";
import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";

/// @title Fee Collector
/// @author LI.FI (https://li.fi)
/// @notice Provides functionality for collecting integrator fees
/// @custom:version 1.0.0
/// @custom:version 1.0.1
contract FeeCollector is TransferrableOwnership {
/// State ///

Expand Down Expand Up @@ -84,12 +85,7 @@ contract FeeCollector is TransferrableOwnership {
// Prevent extra native token from being locked in the contract
if (remaining > 0) {
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = payable(msg.sender).call{ value: remaining }(
""
);
if (!success) {
revert TransferFailure();
}
SafeTransferLib.safeTransferETH(msg.sender, remaining);
}
emit FeesCollected(
LibAsset.NULL_ADDRESS,
Expand Down
18 changes: 5 additions & 13 deletions src/Periphery/GasZipPeriphery.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,21 @@ import { IGasZip } from "../Interfaces/IGasZip.sol";
import { LibSwap } from "../Libraries/LibSwap.sol";
import { LibAsset, IERC20 } from "../Libraries/LibAsset.sol";
import { LibUtil } from "../Libraries/LibUtil.sol";
import { ReentrancyGuard } from "../Helpers/ReentrancyGuard.sol";
import { SwapperV2 } from "../Helpers/SwapperV2.sol";
import { WithdrawablePeriphery } from "../Helpers/WithdrawablePeriphery.sol";
import { Validatable } from "../Helpers/Validatable.sol";
import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";
import { InvalidCallData } from "../Errors/GenericErrors.sol";

/// @title GasZipPeriphery
/// @author LI.FI (https://li.fi)
/// @notice Provides functionality to swap ERC20 tokens to use the gas.zip protocol as a pre-bridge step (https://www.gas.zip/)
/// @custom:version 1.0.0
contract GasZipPeriphery is
ILiFi,
ReentrancyGuard,
SwapperV2,
Validatable,
WithdrawablePeriphery
{
/// @custom:version 1.0.1
contract GasZipPeriphery is ILiFi, WithdrawablePeriphery {
using SafeTransferLib for address;

/// State ///
IGasZip public immutable gasZipRouter;
address public immutable liFiDEXAggregator;
uint256 internal constant MAX_CHAINID_LENGTH_ALLOWED = 32;

/// Errors ///
error TooManyChainIds();
Expand Down Expand Up @@ -59,7 +51,7 @@ contract GasZipPeriphery is
LibAsset.maxApproveERC20(
IERC20(_swapData.sendingAssetId),
liFiDEXAggregator,
type(uint256).max
_swapData.fromAmount
);

// execute swap using LiFiDEXAggregator
Expand Down Expand Up @@ -110,7 +102,7 @@ contract GasZipPeriphery is
) external pure returns (uint256 destinationChains) {
uint256 length = _chainIds.length;

if (length > 32) revert TooManyChainIds();
if (length > MAX_CHAINID_LENGTH_ALLOWED) revert TooManyChainIds();

for (uint256 i; i < length; ++i) {
// Shift destinationChains left by 8 bits and add the next chainID
Expand Down
24 changes: 5 additions & 19 deletions src/Periphery/LiFiDEXAggregator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.17;

import { SafeERC20, IERC20, IERC20Permit } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";

address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;
Expand All @@ -22,7 +23,7 @@ uint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970
/// @title LiFi DEX Aggregator
/// @author Ilya Lyalin (contract copied from: https://github.com/sushiswap/sushiswap/blob/c8c80dec821003eb72eb77c7e0446ddde8ca9e1e/protocols/route-processor/contracts/RouteProcessor4.sol)
/// @notice Processes calldata to swap using various DEXs
/// @custom:version 1.5.0
/// @custom:version 1.5.1
contract LiFiDEXAggregator is Ownable {
using SafeERC20 for IERC20;
using Approve for IERC20;
Expand Down Expand Up @@ -130,14 +131,7 @@ contract LiFiDEXAggregator is Ownable {
address to,
bytes memory route
) external payable lock returns (uint256 amountOut) {
(bool success, bytes memory returnBytes) = transferValueTo.call{
value: amountValueTransfer
}("");
if (!success) {
assembly {
revert(add(32, returnBytes), mload(returnBytes))
}
}
SafeTransferLib.safeTransferETH(transferValueTo, amountValueTransfer);
return
processRouteInternal(
tokenIn,
Expand Down Expand Up @@ -370,11 +364,7 @@ contract LiFiDEXAggregator is Ownable {
);
IWETH(tokenIn).withdraw(amountIn);
}
(bool success, ) = payable(to).call{ value: amountIn }("");
require(
success,
"RouteProcessor.wrapNative: Native token transfer failed"
);
SafeTransferLib.safeTransferETH(to, amountIn);
}
}

Expand Down Expand Up @@ -750,11 +740,7 @@ contract LiFiDEXAggregator is Ownable {

if (to != address(this)) {
if (tokenOut == NATIVE_ADDRESS) {
(bool success, ) = payable(to).call{ value: amountOut }("");
require(
success,
"RouteProcessor.swapCurve: Native token transfer failed"
);
SafeTransferLib.safeTransferETH(to, amountOut);
} else {
IERC20(tokenOut).safeTransfer(to, amountOut);
}
Expand Down
8 changes: 3 additions & 5 deletions src/Periphery/LiFuelFeeCollector.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ pragma solidity ^0.8.17;

import { LibAsset } from "../Libraries/LibAsset.sol";
import { TransferrableOwnership } from "../Helpers/TransferrableOwnership.sol";
import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";

/// @title LiFuelFeeCollector
/// @author LI.FI (https://li.fi)
/// @notice Provides functionality for collecting fees for LiFuel
/// @custom:version 1.0.1
/// @custom:version 1.0.2
contract LiFuelFeeCollector is TransferrableOwnership {
/// Errors ///
error TransferFailure();
Expand Down Expand Up @@ -65,10 +66,7 @@ contract LiFuelFeeCollector is TransferrableOwnership {
);
uint256 amountMinusFees = msg.value - feeAmount;
if (amountMinusFees > 0) {
(bool success, ) = msg.sender.call{ value: amountMinusFees }("");
if (!success) {
revert TransferFailure();
}
SafeTransferLib.safeTransferETH(msg.sender, amountMinusFees);
}
}

Expand Down
Loading
Loading