Skip to content

Commit 11c1cd0

Browse files
committed
feat: fix rate limit for transferTokenLayerZero
1 parent c12f481 commit 11c1cd0

File tree

2 files changed

+110
-94
lines changed

2 files changed

+110
-94
lines changed

src/libraries/LayerZeroLib.sol

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pragma solidity ^0.8.21;
44
import { ILayerZero, SendParam, OFTReceipt, MessagingFee } from "../interfaces/ILayerZero.sol";
55
import { IRateLimits } from "../interfaces/IRateLimits.sol";
66
import { IALMProxy } from "../interfaces/IALMProxy.sol";
7+
import { IERC20Like } from "../interfaces/Common.sol";
78

89
import { ApproveLib } from "./ApproveLib.sol";
910

@@ -12,7 +13,7 @@ import { OptionsBuilder } from "layerzerolabs/oapp-evm/contracts/oapp/libs/Optio
1213
library 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

Comments
 (0)