diff --git a/src/ForeignController.sol b/src/ForeignController.sol index 31ebf1cb..09176ff5 100644 --- a/src/ForeignController.sol +++ b/src/ForeignController.sol @@ -16,6 +16,8 @@ import { IERC4626 } from "../lib/openzeppelin-contracts/contracts/interfaces/IER import { IPSM3 } from "spark-psm/src/interfaces/IPSM3.sol"; +import { LayerZeroLib } from "./libraries/LayerZeroLib.sol"; + import { IALMProxy } from "./interfaces/IALMProxy.sol"; import { ICCTPLike } from "./interfaces/CCTPInterfaces.sol"; import { IRateLimits } from "./interfaces/IRateLimits.sol"; @@ -68,7 +70,7 @@ contract ForeignController is ReentrancyGuard, AccessControlEnumerable { bytes32 public constant LIMIT_AAVE_DEPOSIT = keccak256("LIMIT_AAVE_DEPOSIT"); bytes32 public constant LIMIT_AAVE_WITHDRAW = keccak256("LIMIT_AAVE_WITHDRAW"); bytes32 public constant LIMIT_ASSET_TRANSFER = keccak256("LIMIT_ASSET_TRANSFER"); - bytes32 public constant LIMIT_LAYERZERO_TRANSFER = keccak256("LIMIT_LAYERZERO_TRANSFER"); + bytes32 public constant LIMIT_LAYERZERO_TRANSFER = LayerZeroLib.LIMIT_LAYERZERO_TRANSFER; bytes32 public constant LIMIT_PSM_DEPOSIT = keccak256("LIMIT_PSM_DEPOSIT"); bytes32 public constant LIMIT_PSM_WITHDRAW = keccak256("LIMIT_PSM_WITHDRAW"); bytes32 public constant LIMIT_SPARK_VAULT_TAKE = keccak256("LIMIT_SPARK_VAULT_TAKE"); @@ -301,45 +303,15 @@ contract ForeignController is ReentrancyGuard, AccessControlEnumerable { payable nonReentrant onlyRole(RELAYER) - rateLimited( - keccak256(abi.encode(LIMIT_LAYERZERO_TRANSFER, oftAddress, destinationEndpointId)), - amount - ) { - bytes32 recipient = layerZeroRecipients[destinationEndpointId]; - - require(recipient != bytes32(0), "FC/recipient-not-set"); - - // NOTE: Full integration testing of this logic is not possible without OFTs with - // approvalRequired == true. Add integration testing for this case before - // using in production. - if (ILayerZero(oftAddress).approvalRequired()) { - _approve(ILayerZero(oftAddress).token(), oftAddress, amount); - } - - bytes memory options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(200_000, 0); - - SendParam memory sendParams = SendParam({ - dstEid : destinationEndpointId, - to : recipient, - amountLD : amount, - minAmountLD : 0, - extraOptions : options, - composeMsg : "", - oftCmd : "" + LayerZeroLib.transferTokenLayerZero({ + proxy : proxy, + rateLimits : rateLimits, + oftAddress : oftAddress, + amount : amount, + destinationEndpointId : destinationEndpointId, + layerZeroRecipient : layerZeroRecipients[destinationEndpointId] }); - - // Query the min amount received on the destination chain and set it. - ( ,, OFTReceipt memory receipt ) = ILayerZero(oftAddress).quoteOFT(sendParams); - sendParams.minAmountLD = receipt.amountReceivedLD; - - MessagingFee memory fee = ILayerZero(oftAddress).quoteSend(sendParams, false); - - proxy.doCallWithValue{value: fee.nativeFee}( - oftAddress, - abi.encodeCall(ILayerZero.send, (sendParams, fee, address(proxy))), - fee.nativeFee - ); } /**********************************************************************************************/ diff --git a/src/libraries/LayerZeroLib.sol b/src/libraries/LayerZeroLib.sol index 27fafd00..1cf67ca3 100644 --- a/src/libraries/LayerZeroLib.sol +++ b/src/libraries/LayerZeroLib.sol @@ -47,7 +47,7 @@ library LayerZeroLib { amount ); - require(layerZeroRecipient != bytes32(0), "MC/recipient-not-set"); + require(layerZeroRecipient != bytes32(0), "LayerZeroLib/recipient-not-set"); // NOTE: Full integration testing of this logic is not possible without OFTs with // approvalRequired == false. Add integration testing for this case before diff --git a/test/mainnet-fork/LayerZero.t.sol b/test/mainnet-fork/LayerZero.t.sol index 6b5e8748..d9fa48e6 100644 --- a/test/mainnet-fork/LayerZero.t.sol +++ b/test/mainnet-fork/LayerZero.t.sol @@ -173,7 +173,7 @@ contract MainnetControllerTransferLayerZeroFailureTests is MainnetControllerLaye deal(relayer, fee.nativeFee); vm.prank(relayer); - vm.expectRevert("MC/recipient-not-set"); + vm.expectRevert("LayerZeroLib/recipient-not-set"); mainnetController.transferTokenLayerZero{value: fee.nativeFee}( USDT_OFT, 10_000_000e6, @@ -540,7 +540,7 @@ contract ForeignControllerTransferLayerZeroFailureTests is ArbitrumChainLayerZer deal(relayer, fee.nativeFee); vm.prank(relayer); - vm.expectRevert("FC/recipient-not-set"); + vm.expectRevert("LayerZeroLib/recipient-not-set"); foreignController.transferTokenLayerZero{value: fee.nativeFee}( USDT_OFT, 10_000_000e6,