@@ -8,27 +8,55 @@ import { SwapperV2 } from "../Helpers/SwapperV2.sol";
88import { ReentrancyGuard } from "../Helpers/ReentrancyGuard.sol " ;
99import { Validatable } from "../Helpers/Validatable.sol " ;
1010import { LibSwap } from "../Libraries/LibSwap.sol " ;
11+ import { InvalidConfig, InvalidCallData, InvalidNonEVMReceiver, InvalidReceiver } from "../Errors/GenericErrors.sol " ;
12+ import { LiFiData } from "../Helpers/LiFiData.sol " ;
1113
1214/// @title Allbridge Facet
13- /// @author Li.Finance (https://li.finance )
15+ /// @author LI.FI (https://li.fi )
1416/// @notice Provides functionality for bridging through AllBridge
15- /// @custom:version 2.0.0
16- contract AllBridgeFacet is ILiFi , ReentrancyGuard , SwapperV2 , Validatable {
17+ /// @custom:version 2.1.0
18+ contract AllBridgeFacet is
19+ ILiFi ,
20+ ReentrancyGuard ,
21+ SwapperV2 ,
22+ Validatable ,
23+ LiFiData
24+ {
25+ uint32 private constant ALLBRIDGE_ID_ETHEREUM = 1 ;
26+ uint32 private constant ALLBRIDGE_ID_BSC = 2 ;
27+ uint32 private constant ALLBRIDGE_ID_TRON = 3 ;
28+ uint32 private constant ALLBRIDGE_ID_SOLANA = 4 ;
29+ uint32 private constant ALLBRIDGE_ID_POLYGON = 5 ;
30+ uint32 private constant ALLBRIDGE_ID_ARBITRUM = 6 ;
31+ uint32 private constant ALLBRIDGE_ID_AVALANCHE = 8 ;
32+ uint32 private constant ALLBRIDGE_ID_BASE = 9 ;
33+ uint32 private constant ALLBRIDGE_ID_OPTIMISM = 10 ;
34+ uint32 private constant ALLBRIDGE_ID_CELO = 11 ;
35+ uint32 private constant ALLBRIDGE_ID_SUI = 13 ;
36+ uint256 internal constant LIFI_CHAIN_ID_ARBITRUM = 42161 ;
37+ uint256 internal constant LIFI_CHAIN_ID_AVALANCHE = 43114 ;
38+ uint256 internal constant LIFI_CHAIN_ID_BASE = 8453 ;
39+ uint256 internal constant LIFI_CHAIN_ID_BSC = 56 ;
40+ uint256 internal constant LIFI_CHAIN_ID_CELO = 42220 ;
41+ uint256 internal constant LIFI_CHAIN_ID_POLYGON = 137 ;
42+
43+ error UnsupportedAllBridgeChainId ();
44+
1745 /// @notice The contract address of the AllBridge router on the source chain.
1846 // solhint-disable-next-line immutable-vars-naming
19- IAllBridge private immutable allBridge ;
47+ IAllBridge private immutable ALLBRIDGE ;
2048
2149 /// @notice The struct for the AllBridge data.
22- /// @param fees The amount of token to pay the messenger and the bridge
2350 /// @param recipient The address of the token receiver after bridging.
51+ /// @param fees The amount of token to pay the messenger and the bridge
2452 /// @param destinationChainId The destination chain id.
2553 /// @param receiveToken The token to receive on the destination chain.
2654 /// @param nonce A random nonce to associate with the tx.
2755 /// @param messenger The messenger protocol enum
2856 /// @param payFeeWithSendingAsset Whether to pay the relayer fee with the sending asset or not
2957 struct AllBridgeData {
30- uint256 fees;
3158 bytes32 recipient;
59+ uint256 fees;
3260 uint256 destinationChainId;
3361 bytes32 receiveToken;
3462 uint256 nonce;
@@ -39,7 +67,9 @@ contract AllBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
3967 /// @notice Initializes the AllBridge contract
4068 /// @param _allBridge The address of the AllBridge contract
4169 constructor (IAllBridge _allBridge ) {
42- allBridge = _allBridge;
70+ if (address (_allBridge) == address (0 )) revert InvalidConfig ();
71+
72+ ALLBRIDGE = _allBridge;
4373 }
4474
4575 /// @notice Bridge tokens to another chain via AllBridge
@@ -96,14 +126,38 @@ contract AllBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
96126 ILiFi.BridgeData memory _bridgeData ,
97127 AllBridgeData calldata _allBridgeData
98128 ) internal {
129+ // make sure destinationChainId matches in bridgeData and allBridgeData
130+ if (
131+ _allBridgeData.destinationChainId !=
132+ _getAllBridgeChainId (_bridgeData.destinationChainId)
133+ ) revert InvalidCallData ();
134+
135+ // validate receiver address
136+ if (_bridgeData.receiver == NON_EVM_ADDRESS) {
137+ // destination chain is non-EVM
138+ // make sure it's non-zero (we cannot validate further)
139+ if (_allBridgeData.recipient == bytes32 (0 ))
140+ revert InvalidNonEVMReceiver ();
141+ } else {
142+ // destination chain is EVM
143+ // make sure that bridgeData and allBridgeData receiver addresses match
144+ if (
145+ _bridgeData.receiver !=
146+ address (uint160 (uint256 (_allBridgeData.recipient)))
147+ ) revert InvalidReceiver ();
148+ }
149+
150+ // set max approval to allBridge, if current allowance is insufficient
99151 LibAsset.maxApproveERC20 (
100152 IERC20 (_bridgeData.sendingAssetId),
101- address (allBridge ),
153+ address (ALLBRIDGE ),
102154 _bridgeData.minAmount
103155 );
104156
157+ // check if bridge fee should be paid with sending or native asset
105158 if (_allBridgeData.payFeeWithSendingAsset) {
106- allBridge.swapAndBridge (
159+ // pay fee with sending asset
160+ ALLBRIDGE.swapAndBridge (
107161 bytes32 (uint256 (uint160 (_bridgeData.sendingAssetId))),
108162 _bridgeData.minAmount,
109163 _allBridgeData.recipient,
@@ -114,7 +168,8 @@ contract AllBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
114168 _allBridgeData.fees
115169 );
116170 } else {
117- allBridge.swapAndBridge { value: _allBridgeData.fees }(
171+ // pay fee with native asset
172+ ALLBRIDGE.swapAndBridge { value: _allBridgeData.fees }(
118173 bytes32 (uint256 (uint160 (_bridgeData.sendingAssetId))),
119174 _bridgeData.minAmount,
120175 _allBridgeData.recipient,
@@ -128,4 +183,41 @@ contract AllBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
128183
129184 emit LiFiTransferStarted (_bridgeData);
130185 }
186+
187+ /// @notice Converts LiFi internal chain IDs to AllBridge chain IDs
188+ /// @param _destinationChainId The LiFi chain ID to convert
189+ /// @return The corresponding Chainflip chain ID
190+ /// @dev Reverts if the destination chain is not supported
191+ function _getAllBridgeChainId (
192+ uint256 _destinationChainId
193+ ) internal pure returns (uint256 ) {
194+ // split possible values in half for more efficient search/matching
195+
196+ // first try to match cases where chainId is the same and does not need to be mapped
197+ if (
198+ _destinationChainId == ALLBRIDGE_ID_ETHEREUM ||
199+ _destinationChainId == ALLBRIDGE_ID_OPTIMISM
200+ ) return _destinationChainId;
201+ // all others have custom chainIds
202+ else if (_destinationChainId == LIFI_CHAIN_ID_BSC)
203+ return ALLBRIDGE_ID_BSC;
204+ else if (_destinationChainId == LIFI_CHAIN_ID_TRON)
205+ return ALLBRIDGE_ID_TRON;
206+ else if (_destinationChainId == LIFI_CHAIN_ID_SOLANA)
207+ return ALLBRIDGE_ID_SOLANA;
208+ else if (_destinationChainId == LIFI_CHAIN_ID_POLYGON)
209+ return ALLBRIDGE_ID_POLYGON;
210+ else if (_destinationChainId == LIFI_CHAIN_ID_ARBITRUM)
211+ return ALLBRIDGE_ID_ARBITRUM;
212+ else if (_destinationChainId == LIFI_CHAIN_ID_AVALANCHE)
213+ return ALLBRIDGE_ID_AVALANCHE;
214+ else if (_destinationChainId == LIFI_CHAIN_ID_BASE)
215+ return ALLBRIDGE_ID_BASE;
216+ else if (_destinationChainId == LIFI_CHAIN_ID_CELO)
217+ return ALLBRIDGE_ID_CELO;
218+ else if (_destinationChainId == LIFI_CHAIN_ID_SUI)
219+ return ALLBRIDGE_ID_SUI;
220+ // revert if no match found
221+ else revert UnsupportedAllBridgeChainId ();
222+ }
131223}
0 commit comments