@@ -4,6 +4,7 @@ pragma solidity ^0.8.21;
44import { ILayerZero, SendParam, OFTReceipt, MessagingFee } from "../interfaces/ILayerZero.sol " ;
55import { IRateLimits } from "../interfaces/IRateLimits.sol " ;
66import { IALMProxy } from "../interfaces/IALMProxy.sol " ;
7+ import { IERC20Like } from "../interfaces/Common.sol " ;
78
89import { ApproveLib } from "./ApproveLib.sol " ;
910
@@ -12,7 +13,7 @@ import { OptionsBuilder } from "layerzerolabs/oapp-evm/contracts/oapp/libs/Optio
1213library LayerZeroLib {
1314
1415 using OptionsBuilder for bytes ;
15-
16+
1617 bytes32 public constant LIMIT_LAYERZERO_TRANSFER = keccak256 ("LIMIT_LAYERZERO_TRANSFER " );
1718
1819 /**********************************************************************************************/
@@ -27,61 +28,64 @@ library LayerZeroLib {
2728 uint32 destinationEndpointId ,
2829 bytes32 layerZeroRecipient
2930 ) external {
30- _rateLimited (
31- rateLimits,
32- keccak256 (
33- abi.encode (
34- LIMIT_LAYERZERO_TRANSFER,
35- oftAddress,
36- destinationEndpointId
37- )
38- ),
39- amount
40- );
41-
4231 require (layerZeroRecipient != bytes32 (0 ), "MC/recipient-not-set " );
4332
33+ address token = ILayerZero (oftAddress).token ();
34+
4435 // NOTE: Full integration testing of this logic is not possible without OFTs with
4536 // approvalRequired == false. Add integration testing for this case before
4637 // using in production.
4738 if (ILayerZero (oftAddress).approvalRequired ()) {
48- ApproveLib.approve (
49- ILayerZero (oftAddress).token (),
50- address (proxy),
51- oftAddress,
52- amount
53- );
39+ ApproveLib.approve (token, address (proxy), oftAddress, amount);
5440 }
5541
56- bytes memory options = OptionsBuilder.newOptions ().addExecutorLzReceiveOption (200_000 , 0 );
57-
5842 SendParam memory sendParams = SendParam ({
5943 dstEid : destinationEndpointId,
6044 to : layerZeroRecipient,
6145 amountLD : amount,
6246 minAmountLD : 0 ,
63- extraOptions : options ,
47+ extraOptions : OptionsBuilder. newOptions (). addExecutorLzReceiveOption ( 200_000 , 0 ) ,
6448 composeMsg : "" ,
6549 oftCmd : ""
6650 });
6751
6852 // Query the min amount received on the destination chain and set it.
69- ( , , OFTReceipt memory receipt ) = ILayerZero (oftAddress).quoteOFT (sendParams);
70- sendParams.minAmountLD = receipt.amountReceivedLD;
53+ sendParams.minAmountLD = _getQuotedAmountReceivedLD (oftAddress, sendParams);
7154
7255 MessagingFee memory fee = ILayerZero (oftAddress).quoteSend (sendParams, false );
7356
57+ uint256 balanceBefore = IERC20Like (token).balanceOf (address (proxy));
58+
7459 proxy.doCallWithValue {value: fee.nativeFee}(
7560 oftAddress,
7661 abi.encodeCall (ILayerZero.send, (sendParams, fee, address (proxy))),
7762 fee.nativeFee
7863 );
64+
65+ _rateLimited (
66+ rateLimits,
67+ keccak256 (
68+ abi.encode (
69+ LIMIT_LAYERZERO_TRANSFER,
70+ oftAddress,
71+ destinationEndpointId
72+ )
73+ ),
74+ balanceBefore - IERC20Like (token).balanceOf (address (proxy))
75+ );
7976 }
8077
8178 /**********************************************************************************************/
82- /*** Rate Limit helper functions ***/
79+ /*** Helper functions ***/
8380 /**********************************************************************************************/
8481
82+ function _getQuotedAmountReceivedLD (address oftAddress , SendParam memory sendParams )
83+ internal view returns (uint256 )
84+ {
85+ ( , , OFTReceipt memory receipt ) = ILayerZero (oftAddress).quoteOFT (sendParams);
86+ return receipt.amountReceivedLD;
87+ }
88+
8589 function _rateLimited (IRateLimits rateLimits , bytes32 key , uint256 amount ) internal {
8690 rateLimits.triggerRateLimitDecrease (key, amount);
8791 }
0 commit comments