@layerzerolabs/lz-evm-messagelib-v2 2.0.13 → 2.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/artifacts/contracts/Executor.sol/Executor.json +20 -20
  2. package/artifacts/contracts/ExecutorFeeLib.sol/ExecutorFeeLib.json +19 -19
  3. package/artifacts/contracts/MessageLibBase.sol/MessageLibBase.json +1 -1
  4. package/artifacts/contracts/PriceFeed.sol/PriceFeed.json +15 -15
  5. package/artifacts/contracts/ReceiveLibBaseE2.sol/ReceiveLibBaseE2.json +1 -1
  6. package/artifacts/contracts/SendLibBase.sol/SendLibBase.json +6 -6
  7. package/artifacts/contracts/SendLibBaseE2.sol/SendLibBaseE2.json +10 -10
  8. package/artifacts/contracts/Treasury.sol/Treasury.json +9 -9
  9. package/artifacts/contracts/Worker.sol/Worker.json +18 -18
  10. package/artifacts/contracts/interfaces/IExecutor.sol/IExecutor.json +3 -3
  11. package/artifacts/contracts/interfaces/IExecutorFeeLib.sol/IExecutorFeeLib.json +4 -4
  12. package/artifacts/contracts/interfaces/ILayerZeroPriceFeed.sol/ILayerZeroPriceFeed.json +3 -3
  13. package/artifacts/contracts/interfaces/IWorker.sol/IWorker.json +3 -3
  14. package/artifacts/contracts/uln/LzExecutor.sol/IReceiveUlnView.json +35 -0
  15. package/artifacts/contracts/uln/LzExecutor.sol/LzExecutor.json +279 -20
  16. package/artifacts/contracts/uln/ReceiveUlnBase.sol/ReceiveUlnBase.json +90 -11
  17. package/artifacts/contracts/uln/SendUlnBase.sol/SendUlnBase.json +7 -7
  18. package/artifacts/contracts/uln/UlnBase.sol/UlnBase.json +7 -7
  19. package/artifacts/contracts/uln/dvn/DVN.sol/DVN.json +31 -31
  20. package/artifacts/contracts/uln/dvn/DVNFeeLib.sol/DVNFeeLib.json +14 -14
  21. package/artifacts/contracts/uln/dvn/MultiSig.sol/MultiSig.json +5 -5
  22. package/artifacts/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapter.sol/CCIPDVNAdapter.json +488 -169
  23. package/artifacts/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapterFeeLib.sol/CCIPDVNAdapterFeeLib.json +372 -16
  24. package/artifacts/contracts/uln/dvn/adapters/DVNAdapterBase.sol/DVNAdapterBase.json +419 -93
  25. package/artifacts/contracts/uln/dvn/adapters/DVNAdapterBase.sol/IReceiveUln.json +34 -0
  26. package/artifacts/contracts/uln/dvn/adapters/DVNAdapterBase.sol/ISendLibBase.json +30 -0
  27. package/artifacts/contracts/uln/dvn/adapters/arbitrum/ArbitrumDVNAdapterL1.sol/ArbitrumDVNAdapterL1.json +936 -0
  28. package/artifacts/contracts/uln/dvn/adapters/arbitrum/ArbitrumDVNAdapterL2.sol/ArbitrumDVNAdapterL2.json +868 -0
  29. package/artifacts/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapter.sol/AxelarDVNAdapter.json +611 -249
  30. package/artifacts/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapter.sol/ISendLibBase.json +30 -0
  31. package/artifacts/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapterFeeLib.sol/AxelarDVNAdapterFeeLib.json +526 -13
  32. package/artifacts/contracts/uln/dvn/adapters/libs/DVNAdapterMessageCodec.sol/DVNAdapterMessageCodec.json +16 -0
  33. package/artifacts/contracts/uln/dvn/adapters/optimism/OptimismDVNAdapterL1.sol/OptimismDVNAdapterL1.json +924 -0
  34. package/artifacts/contracts/uln/dvn/adapters/optimism/OptimismDVNAdapterL2.sol/OptimismDVNAdapterL2.json +891 -0
  35. package/artifacts/contracts/uln/interfaces/IDVN.sol/IDVN.json +3 -3
  36. package/artifacts/contracts/uln/interfaces/IDVNFeeLib.sol/IDVNFeeLib.json +1 -1
  37. package/artifacts/contracts/uln/interfaces/IReceiveUlnE2.sol/IReceiveUlnE2.json +0 -24
  38. package/artifacts/contracts/uln/interfaces/adapters/IAxelarDVNAdapter.sol/IAxelarDVNAdapter.json +160 -0
  39. package/artifacts/contracts/uln/interfaces/adapters/IAxelarDVNAdapterFeeLib.sol/IAxelarDVNAdapterFeeLib.json +282 -0
  40. package/artifacts/contracts/uln/interfaces/adapters/ICCIPDVNAdapter.sol/ICCIPDVNAdapter.json +91 -0
  41. package/artifacts/contracts/uln/interfaces/adapters/ICCIPDVNAdapterFeeLib.sol/ICCIPDVNAdapterFeeLib.json +290 -0
  42. package/artifacts/contracts/uln/libs/DVNOptions.sol/DVNOptions.json +4 -4
  43. package/artifacts/contracts/uln/libs/UlnOptions.sol/UlnOptions.json +7 -7
  44. package/artifacts/contracts/uln/uln301/AddressSizeConfig.sol/AddressSizeConfig.json +2 -2
  45. package/artifacts/contracts/uln/uln301/ReceiveLibBaseE1.sol/ReceiveLibBaseE1.json +5 -5
  46. package/artifacts/contracts/uln/uln301/ReceiveUln301.sol/ReceiveUln301.json +88 -57
  47. package/artifacts/contracts/uln/uln301/ReceiveUln301View.sol/IReceiveUln301.json +178 -0
  48. package/artifacts/contracts/uln/uln301/ReceiveUln301View.sol/ReceiveUln301View.json +126 -0
  49. package/artifacts/contracts/uln/uln301/SendLibBaseE1.sol/SendLibBaseE1.json +15 -15
  50. package/artifacts/contracts/uln/uln301/SendUln301.sol/SendUln301.json +76 -76
  51. package/artifacts/contracts/uln/uln301/TreasuryFeeHandler.sol/TreasuryFeeHandler.json +5 -5
  52. package/artifacts/contracts/uln/uln301/interfaces/IMessageLibE1.sol/IMessageLibE1.json +4 -4
  53. package/artifacts/contracts/uln/uln302/ReceiveUln302.sol/ReceiveUln302.json +79 -24
  54. package/artifacts/contracts/uln/uln302/ReceiveUln302View.sol/IReceiveUln302.json +146 -0
  55. package/artifacts/contracts/uln/uln302/ReceiveUln302View.sol/ReceiveUln302View.json +251 -0
  56. package/artifacts/contracts/uln/uln302/SendUln302.sol/SendUln302.json +75 -75
  57. package/artifacts/contracts/upgradeable/WorkerUpgradeable.sol/WorkerUpgradeable.json +18 -18
  58. package/contracts/ExecutorFeeLib.sol +6 -6
  59. package/contracts/MessageLibBase.sol +2 -2
  60. package/contracts/PriceFeed.sol +3 -3
  61. package/contracts/ReceiveLibBaseE2.sol +0 -26
  62. package/contracts/SendLibBase.sol +10 -10
  63. package/contracts/SendLibBaseE2.sol +4 -4
  64. package/contracts/Treasury.sol +2 -2
  65. package/contracts/Worker.sol +3 -3
  66. package/contracts/interfaces/IExecutorFeeLib.sol +4 -4
  67. package/contracts/interfaces/ILayerZeroPriceFeed.sol +3 -3
  68. package/contracts/interfaces/IWorker.sol +3 -3
  69. package/contracts/uln/LzExecutor.sol +51 -19
  70. package/contracts/uln/ReceiveUlnBase.sol +21 -14
  71. package/contracts/uln/UlnBase.sol +19 -19
  72. package/contracts/uln/dvn/DVN.sol +16 -16
  73. package/contracts/uln/dvn/DVNFeeLib.sol +2 -2
  74. package/contracts/uln/dvn/MultiSig.sol +13 -13
  75. package/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapter.sol +95 -97
  76. package/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapterFeeLib.sol +64 -2
  77. package/contracts/uln/dvn/adapters/DVNAdapterBase.sol +74 -124
  78. package/contracts/uln/dvn/adapters/arbitrum/ArbitrumDVNAdapterL1.sol +126 -0
  79. package/contracts/uln/dvn/adapters/arbitrum/ArbitrumDVNAdapterL2.sol +50 -0
  80. package/contracts/uln/dvn/adapters/avalanche/NOTES.md +4 -0
  81. package/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapter.sol +85 -100
  82. package/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapterFeeLib.sol +121 -2
  83. package/contracts/uln/dvn/adapters/libs/DVNAdapterMessageCodec.sol +36 -0
  84. package/contracts/uln/dvn/adapters/optimism/OptimismDVNAdapterL1.sol +86 -0
  85. package/contracts/uln/dvn/adapters/optimism/OptimismDVNAdapterL2.sol +58 -0
  86. package/contracts/uln/interfaces/IDVNFeeLib.sol +1 -1
  87. package/contracts/uln/interfaces/IReceiveUlnE2.sol +0 -5
  88. package/contracts/uln/interfaces/adapters/IAxelarDVNAdapter.sol +45 -0
  89. package/contracts/uln/interfaces/adapters/IAxelarDVNAdapterFeeLib.sol +48 -0
  90. package/contracts/uln/interfaces/adapters/ICCIPDVNAdapter.sol +30 -0
  91. package/contracts/uln/interfaces/adapters/ICCIPDVNAdapterFeeLib.sol +45 -0
  92. package/contracts/uln/libs/DVNOptions.sol +6 -6
  93. package/contracts/uln/libs/UlnOptions.sol +13 -13
  94. package/contracts/uln/uln301/AddressSizeConfig.sol +4 -4
  95. package/contracts/uln/uln301/ReceiveLibBaseE1.sol +4 -4
  96. package/contracts/uln/uln301/ReceiveUln301.sol +4 -41
  97. package/contracts/uln/uln301/ReceiveUln301View.sol +89 -0
  98. package/contracts/uln/uln301/SendLibBaseE1.sol +5 -5
  99. package/contracts/uln/uln301/SendUln301.sol +3 -3
  100. package/contracts/uln/uln301/TreasuryFeeHandler.sol +6 -6
  101. package/contracts/uln/uln301/interfaces/IMessageLibE1.sol +4 -4
  102. package/contracts/uln/uln302/ReceiveUln302.sol +4 -27
  103. package/contracts/uln/uln302/ReceiveUln302View.sol +89 -0
  104. package/contracts/uln/uln302/SendUln302.sol +3 -3
  105. package/contracts/upgradeable/WorkerUpgradeable.sol +3 -3
  106. package/package.json +7 -5
  107. package/artifacts/contracts/uln/dvn/adapters/DVNAdapterFeeLibBase.sol/DVNAdapterFeeLibBase.json +0 -50
  108. package/artifacts/contracts/uln/interfaces/IDVNAdapterFeeLib.sol/IDVNAdapterFeeLib.json +0 -50
  109. package/contracts/uln/dvn/adapters/DVNAdapterFeeLibBase.sol +0 -20
  110. package/contracts/uln/interfaces/IDVNAdapterFeeLib.sol +0 -13
@@ -2,161 +2,111 @@
2
2
 
3
3
  pragma solidity ^0.8.20;
4
4
 
5
- import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
6
- import { BytesLib } from "solidity-bytes-utils/contracts/BytesLib.sol";
7
-
8
5
  import { Transfer } from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/Transfer.sol";
9
- import { IMessageLib } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.sol";
10
6
  import { ISendLib } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol";
11
7
 
12
8
  import { ILayerZeroDVN } from "../../interfaces/ILayerZeroDVN.sol";
13
- import { IReceiveUlnE2 } from "../../interfaces/IReceiveUlnE2.sol";
14
- import { IDVNAdapterFeeLib } from "../../interfaces/IDVNAdapterFeeLib.sol";
9
+ import { Worker } from "../../../Worker.sol";
10
+ import { DVNAdapterMessageCodec } from "./libs/DVNAdapterMessageCodec.sol";
11
+
12
+ interface ISendLibBase {
13
+ function fees(address _worker) external view returns (uint256);
14
+ }
15
+
16
+ interface IReceiveUln {
17
+ function verify(bytes calldata _packetHeader, bytes32 _payloadHash, uint64 _confirmations) external;
18
+ }
15
19
 
16
- /// @title DVNAdapterBase
20
+ struct ReceiveLibParam {
21
+ address sendLib;
22
+ uint32 dstEid;
23
+ bytes32 receiveLib;
24
+ }
25
+
26
+ /// @title SendDVNAdapterBase
17
27
  /// @notice base contract for DVN adapters
18
28
  /// @dev limitations:
19
29
  /// - doesn't accept alt token
20
30
  /// - doesn't respect block confirmations
21
- /// - doesn't support multiple libraries. One deployment per library
22
- abstract contract DVNAdapterBase is Ownable, ILayerZeroDVN {
23
- using BytesLib for bytes;
31
+ abstract contract DVNAdapterBase is Worker, ILayerZeroDVN {
32
+ // --- Errors ---
33
+ error DVNAdapter_InsufficientBalance(uint256 actual, uint256 requested);
34
+ error DVNAdapter_NotImplemented();
35
+ error DVNAdapter_MissingRecieveLib(address sendLib, uint32 dstEid);
24
36
 
25
- struct DstMultiplierParam {
26
- uint32 dstEid;
27
- uint16 multiplierBps;
28
- }
37
+ event ReceiveLibsSet(ReceiveLibParam[] params);
29
38
 
30
- /// @dev for protocols that doesn't allow to configure outbound block confirmations per message,
31
- /// ignore confirmations set in the config and use the maximum possible confirmations to prevent failure
32
- /// in the receive library due to insufficient confirmations if the config was changed before the message is received
39
+ /// @dev on change of application config, dvn adapters will not perform any additional verification
40
+ /// @dev to avoid messages from being stuck, all verifications from adapters will be done with the maximum possible confirmations
33
41
  uint64 internal constant MAX_CONFIRMATIONS = type(uint64).max;
34
42
 
35
- uint256 internal constant PACKET_HEADER_SIZE = 81;
36
- uint256 internal constant PAYLOAD_HASH_SIZE = 32;
37
- uint256 internal constant PAYLOAD_SIZE = PACKET_HEADER_SIZE + PAYLOAD_HASH_SIZE;
38
-
39
- ISendLib public immutable sendLib;
40
- IReceiveUlnE2 public immutable receiveLib;
41
- IDVNAdapterFeeLib public feeLib;
42
-
43
- uint16 public defaultMultiplierBps = 10_000; // no multiplier
44
- mapping(address admin => bool) public admins;
45
-
46
- error OnlySendLib();
47
- error Unauthorized();
48
- error InvalidPayloadSize();
49
- error VersionMismatch();
50
-
51
- event AdminSet(address indexed admin, bool isAdmin);
52
- event DefaultMultiplierSet(uint16 multiplierBps);
53
- event DstMultiplierSet(DstMultiplierParam[] params);
54
- event FeeLibSet(address indexed feeLib);
55
- event FeeWithdrawn(address indexed to, uint256 amount);
56
- event TokenWithdrawn(address indexed to, address token, uint256 amount);
57
-
58
- modifier onlySendLib() {
59
- if (msg.sender != address(sendLib)) revert OnlySendLib();
60
- _;
61
- }
62
-
63
- modifier onlyAdmin() {
64
- if (!admins[msg.sender]) revert Unauthorized();
65
- _;
66
- }
67
-
68
- constructor(address _sendLib, address _receiveLib, address[] memory _admins) {
69
- (uint64 sendMajor, uint8 sendMinor, uint8 sendEndpoint) = IMessageLib(_sendLib).version();
70
- (uint64 receiveMajor, uint8 receiveMinor, uint8 receiveEndpoint) = IMessageLib(_receiveLib).version();
71
-
72
- if (sendMajor != receiveMajor || sendMinor != receiveMinor || sendEndpoint != receiveEndpoint) {
73
- revert VersionMismatch();
43
+ /// @dev receive lib to call verify() on at destination
44
+ mapping(address sendLib => mapping(uint32 dstEid => bytes32 receiveLib)) public receiveLibs;
45
+
46
+ constructor(
47
+ address _roleAdmin,
48
+ address[] memory _admins,
49
+ uint16 _defaultMultiplierBps
50
+ ) Worker(new address[](0), address(0x0), _defaultMultiplierBps, _roleAdmin, _admins) {}
51
+
52
+ // ========================= OnlyAdmin =========================
53
+ /// @notice sets receive lib for destination chains
54
+ /// @dev DEFAULT_ADMIN_ROLE can set MESSAGE_LIB_ROLE for sendLibs and use below function to set receiveLibs
55
+ function setReceiveLibs(ReceiveLibParam[] calldata _params) external onlyRole(DEFAULT_ADMIN_ROLE) {
56
+ for (uint256 i = 0; i < _params.length; i++) {
57
+ ReceiveLibParam calldata param = _params[i];
58
+ receiveLibs[param.sendLib][param.dstEid] = param.receiveLib;
74
59
  }
75
60
 
76
- sendLib = ISendLib(_sendLib);
77
- receiveLib = IReceiveUlnE2(_receiveLib);
78
-
79
- for (uint256 i = 0; i < _admins.length; i++) {
80
- admins[_admins[i]] = true;
81
- emit AdminSet(_admins[i], true);
82
- }
61
+ emit ReceiveLibsSet(_params);
83
62
  }
84
63
 
85
- function setAdmin(address _admin, bool _isAdmin) external onlyOwner {
86
- admins[_admin] = _isAdmin;
87
- emit AdminSet(_admin, _isAdmin);
64
+ // ========================= Internal =========================
65
+ function _getAndAssertReceiveLib(address _sendLib, uint32 _dstEid) internal view returns (bytes32 lib) {
66
+ lib = receiveLibs[_sendLib][_dstEid];
67
+ if (lib == bytes32(0)) revert DVNAdapter_MissingRecieveLib(_sendLib, _dstEid);
88
68
  }
89
69
 
90
- // -------------------- Only Admin --------------------
91
-
92
- /// @notice sets the default fee multiplier in basis points
93
- /// @param _defaultMultiplierBps default fee multiplier
94
- function setDefaultMultiplier(uint16 _defaultMultiplierBps) external onlyAdmin {
95
- defaultMultiplierBps = _defaultMultiplierBps;
96
- emit DefaultMultiplierSet(_defaultMultiplierBps);
70
+ function _encode(
71
+ bytes32 _receiveLib,
72
+ bytes memory _packetHeader,
73
+ bytes32 _payloadHash
74
+ ) internal pure returns (bytes memory) {
75
+ return DVNAdapterMessageCodec.encode(_receiveLib, _packetHeader, _payloadHash);
97
76
  }
98
77
 
99
- function setFeeLib(address _feeLib) external onlyAdmin {
100
- feeLib = IDVNAdapterFeeLib(_feeLib);
101
- emit FeeLibSet(_feeLib);
78
+ function _encodeEmpty() internal pure returns (bytes memory) {
79
+ return
80
+ DVNAdapterMessageCodec.encode(bytes32(0), new bytes(DVNAdapterMessageCodec.PACKET_HEADER_SIZE), bytes32(0));
102
81
  }
103
82
 
104
- /// @dev supports withdrawing fee from ULN301, ULN302 and more
105
- /// @param _to address to withdraw fee to
106
- /// @param _amount amount to withdraw
107
- function withdrawFee(address _to, uint256 _amount) external onlyAdmin {
108
- _withdrawFee(_to, _amount);
109
- }
83
+ function _decodeAndVerify(bytes calldata _payload) internal {
84
+ (address receiveLib, bytes memory packetHeader, bytes32 payloadHash) = DVNAdapterMessageCodec.decode(_payload);
110
85
 
111
- /// @dev supports withdrawing token from the contract
112
- /// @param _token token address
113
- /// @param _to address to withdraw token to
114
- /// @param _amount amount to withdraw
115
- function withdrawToken(address _token, address _to, uint256 _amount) external onlyAdmin {
116
- // transfers native if _token is address(0x0)
117
- Transfer.nativeOrToken(_token, _to, _amount);
118
- emit TokenWithdrawn(_to, _token, _amount);
86
+ IReceiveUln(receiveLib).verify(packetHeader, payloadHash, MAX_CONFIRMATIONS);
119
87
  }
120
88
 
121
- // -------------------- Internal Functions --------------------
122
-
123
- function _assertBalanceAndWithdrawFee(uint256 _messageFee) internal {
124
- uint256 balance = address(this).balance;
125
-
126
- if (balance < _messageFee) {
127
- // withdraw fees from the sendLib if balance is insufficient
128
- // sendLib will revert if not enough fees were accumulated
129
- _withdrawFee(address(this), _messageFee - balance); // todo: why not withdraw all fees from sendLib? so that dont need to withdraw every time
89
+ function _withdrawFeeFromSendLib(address _sendLib, address _to) internal {
90
+ uint256 fee = ISendLibBase(_sendLib).fees(address(this));
91
+ if (fee > 0) {
92
+ ISendLib(_sendLib).withdrawFee(_to, fee);
93
+ emit Withdraw(_sendLib, _to, fee);
130
94
  }
131
95
  }
132
96
 
133
- function _withdrawFee(address _to, uint256 _amount) internal {
134
- sendLib.withdrawFee(_to, _amount);
135
- emit FeeWithdrawn(_to, _amount);
136
- }
137
-
138
- function _encodePayload(
139
- bytes memory _packetHeader,
140
- bytes32 _payloadHash
141
- ) internal pure returns (bytes memory payload) {
142
- return abi.encodePacked(_packetHeader, _payloadHash);
143
- }
144
-
145
- function _decodePayload(
146
- bytes memory _payload
147
- ) internal pure returns (bytes memory packetHeader, bytes32 payloadHash) {
148
- if (_payload.length != PAYLOAD_SIZE) revert InvalidPayloadSize();
149
- uint256 start = 0;
150
- packetHeader = _payload.slice(start, PACKET_HEADER_SIZE);
151
-
152
- start += PACKET_HEADER_SIZE;
153
- payloadHash = _payload.toBytes32(start);
154
- }
97
+ function _assertBalanceAndWithdrawFee(address _sendLib, uint256 _messageFee) internal {
98
+ uint256 balance = address(this).balance;
99
+ if (balance < _messageFee) {
100
+ // withdraw all fees from the sendLib if balance is insufficient
101
+ _withdrawFeeFromSendLib(_sendLib, address(this));
155
102
 
156
- function _verify(bytes memory _payload) internal {
157
- (bytes memory packetHeader, bytes32 payloadHash) = _decodePayload(_payload);
158
- receiveLib.verify(packetHeader, payloadHash, MAX_CONFIRMATIONS);
103
+ // check balance again
104
+ balance = address(this).balance;
105
+ // revert if balance is still insufficient, need to transfer more funds manually to the adapter
106
+ if (balance < _messageFee) revert DVNAdapter_InsufficientBalance(balance, _messageFee);
107
+ }
159
108
  }
160
109
 
110
+ /// @dev to receive refund
161
111
  receive() external payable {}
162
112
  }
@@ -0,0 +1,126 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import { IInbox } from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol";
6
+
7
+ import { ArbitrumDVNAdapterL2 } from "./ArbitrumDVNAdapterL2.sol";
8
+ import { DVNAdapterBase } from "../DVNAdapterBase.sol";
9
+ import { DVNAdapterMessageCodec } from "../libs/DVNAdapterMessageCodec.sol";
10
+
11
+ contract ArbitrumDVNAdapterL1 is DVNAdapterBase {
12
+ // --- Config Struct ---
13
+ struct DstConfig {
14
+ uint16 multiplierBps;
15
+ uint256 maxSubmissionCost;
16
+ uint256 gasLimit;
17
+ uint256 maxFeePerGas;
18
+ }
19
+
20
+ // --- Events ---
21
+ event RetryableTicketCreated(uint256 indexed ticketId);
22
+ error OnlyArbitrum();
23
+
24
+ uint32 public immutable arbitrumEid; // eid % 30000 (v1 eid)
25
+ IInbox public immutable inbox;
26
+
27
+ address public peer; // L2 adapter
28
+ DstConfig public dstConfig;
29
+
30
+ constructor(
31
+ address[] memory _admins,
32
+ uint32 _arbitrumEid,
33
+ address _inbox
34
+ ) DVNAdapterBase(msg.sender, _admins, 12000) {
35
+ arbitrumEid = _arbitrumEid; // eid % 30000 (v1 eid)
36
+ inbox = IInbox(_inbox);
37
+ }
38
+
39
+ // --- Admin ---
40
+ function setPeer(address _peer) external onlyRole(ADMIN_ROLE) {
41
+ peer = _peer;
42
+ }
43
+
44
+ function setDstConfig(
45
+ uint16 _multiplierBps,
46
+ uint256 _maxSubmissionCost,
47
+ uint256 _gasLimit,
48
+ uint256 _maxFeePerGas
49
+ ) external onlyRole(ADMIN_ROLE) {
50
+ dstConfig = DstConfig({
51
+ multiplierBps: _multiplierBps,
52
+ maxSubmissionCost: _maxSubmissionCost,
53
+ gasLimit: _gasLimit,
54
+ maxFeePerGas: _maxFeePerGas
55
+ });
56
+ }
57
+
58
+ // --- Send ---
59
+ function assignJob(
60
+ AssignJobParam calldata _param,
61
+ bytes calldata /*_options*/
62
+ ) external payable override onlyRole(MESSAGE_LIB_ROLE) onlyAcl(_param.sender) returns (uint256 fee) {
63
+ DstConfig storage config = dstConfig;
64
+ fee = _getArbitrumFee(_param.dstEid, config);
65
+
66
+ bytes memory payload = abi.encodeWithSelector(
67
+ ArbitrumDVNAdapterL2.verify.selector,
68
+ DVNAdapterMessageCodec.encode(
69
+ receiveLibs[msg.sender][_param.dstEid],
70
+ _param.packetHeader,
71
+ _param.payloadHash
72
+ )
73
+ );
74
+
75
+ // fee estimation: https://github.com/OffchainLabs/arbitrum-sdk/blob/main/src/lib/message/L1ToL2MessageCreator.ts#L52
76
+ uint256 ticketID = inbox.createRetryableTicket{ value: fee }(
77
+ peer,
78
+ 0,
79
+ config.maxSubmissionCost,
80
+ peer,
81
+ peer,
82
+ config.gasLimit,
83
+ config.maxFeePerGas,
84
+ payload
85
+ );
86
+ emit RetryableTicketCreated(ticketID);
87
+
88
+ // adjust fee based on multiplier
89
+ // if (workerFeeLib != address(0)) {
90
+ // fee = IDVNAdapterFeeLib(workerFeeLib).getFee(
91
+ // _param.dstEid,
92
+ // _param.sender,
93
+ // defaultMultiplierBps,
94
+ // config.multiplierBps,
95
+ // fee
96
+ // );
97
+ // }
98
+ }
99
+
100
+ // --- View ---
101
+ function getFee(
102
+ uint32 _dstEid,
103
+ uint64 /*_confirmations*/,
104
+ address _sender,
105
+ bytes calldata /*_options*/
106
+ ) public view override onlyAcl(_sender) returns (uint256 fee) {
107
+ DstConfig storage config = dstConfig;
108
+ fee = _getArbitrumFee(_dstEid, config);
109
+
110
+ // adjust fee based on multiplier
111
+ // if (workerFeeLib != address(0)) {
112
+ // fee = IDVNAdapterFeeLib(workerFeeLib).getFee(
113
+ // _dstEid,
114
+ // _sender,
115
+ // defaultMultiplierBps,
116
+ // config.multiplierBps,
117
+ // fee
118
+ // );
119
+ // }
120
+ }
121
+
122
+ function _getArbitrumFee(uint32 _dstEid, DstConfig storage _dstConfig) internal view returns (uint256 fee) {
123
+ if (_dstEid % 30000 != arbitrumEid) revert OnlyArbitrum();
124
+ fee = _dstConfig.maxSubmissionCost + _dstConfig.gasLimit * _dstConfig.maxFeePerGas;
125
+ }
126
+ }
@@ -0,0 +1,50 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import { AddressAliasHelper } from "@arbitrum/nitro-contracts/src/libraries/AddressAliasHelper.sol";
6
+
7
+ import { DVNAdapterBase } from "../DVNAdapterBase.sol";
8
+
9
+ contract ArbitrumDVNAdapterL2 is DVNAdapterBase {
10
+ // --- Errors ---
11
+ error UntrustedPeer(address peer);
12
+
13
+ // --- Events ---
14
+ event PeerSet(address peer);
15
+
16
+ // --- Variables ---
17
+ address public peer; // L1 adapter
18
+
19
+ constructor(address[] memory _admins) DVNAdapterBase(msg.sender, _admins, 12000) {}
20
+
21
+ // --- Admin ---
22
+ function setPeer(address _peer) external onlyRole(ADMIN_ROLE) {
23
+ peer = _peer;
24
+ emit PeerSet(_peer);
25
+ }
26
+
27
+ // --- Send ---
28
+ function assignJob(
29
+ AssignJobParam calldata /*_param*/,
30
+ bytes calldata /*_options*/
31
+ ) external payable override returns (uint256) {
32
+ revert DVNAdapter_NotImplemented();
33
+ }
34
+
35
+ function getFee(
36
+ uint32 /*_dstEid*/,
37
+ uint64 /*_confirmations*/,
38
+ address /*_sender*/,
39
+ bytes calldata /*_options*/
40
+ ) external pure override returns (uint256) {
41
+ revert DVNAdapter_NotImplemented();
42
+ }
43
+
44
+ // --- Receive ---
45
+ function verify(bytes calldata _payload) external {
46
+ // To check that message came from L1, we check that the sender is the L1 contract's L2 alias.
47
+ if (msg.sender != AddressAliasHelper.applyL1ToL2Alias(peer)) revert UntrustedPeer(msg.sender);
48
+ _decodeAndVerify(_payload);
49
+ }
50
+ }
@@ -0,0 +1,4 @@
1
+ https://github.com/ava-labs/teleporter/blob/main/contracts/src/Teleporter/README.md
2
+ https://github.com/ava-labs/teleporter/blob/main/contracts/src/CrossChainApplications/ExampleMessenger/ExampleCrossChainMessenger.sol
3
+ https://github.com/ava-labs/public-avalanche-sdks/tree/main/apps/teleporter-demo
4
+ https://github.com/ava-labs/xsvm
@@ -3,154 +3,139 @@
3
3
  pragma solidity ^0.8.20;
4
4
 
5
5
  import { AxelarExecutable } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol";
6
- import { IAxelarGasService } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol";
6
+ import { ISendLib } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol";
7
7
 
8
8
  import { DVNAdapterBase } from "../DVNAdapterBase.sol";
9
+ import { IAxelarDVNAdapter } from "../../../interfaces/adapters/IAxelarDVNAdapter.sol";
10
+ import { IAxelarDVNAdapterFeeLib } from "../../../interfaces/adapters/IAxelarDVNAdapterFeeLib.sol";
9
11
 
10
- contract AxelarDVNAdapter is AxelarExecutable, DVNAdapterBase {
11
- struct DstConfigParam {
12
- uint32 dstEid;
13
- uint16 multiplierBps;
14
- uint256 nativeGasFee;
15
- string peer;
16
- string chainName;
17
- }
18
-
19
- struct DstFeeParam {
20
- uint32 dstEid;
21
- uint256 nativeGasFee;
22
- }
23
-
24
- struct DstConfig {
25
- uint256 nativeGasFee;
26
- uint16 multiplierBps;
27
- string peer;
28
- string chainName;
29
- }
30
-
31
- event DstConfigSet(DstConfigParam[] params);
32
- event DstFeeSet(DstFeeParam[] params);
33
-
34
- IAxelarGasService public immutable gasService;
35
-
36
- mapping(uint32 dstEid => DstConfig config) public dstConfig;
37
- mapping(string axelarChain => uint32 eid) public axelarChainToEid;
12
+ interface ISendLibBase {
13
+ function fees(address _worker) external view returns (uint256);
14
+ }
38
15
 
16
+ /// @title AxelarDVNAdapter
17
+ /// @dev How Axelar DVN Adapter works:
18
+ /// 1. Estimate gas fee off-chain using the Axelar SDK.
19
+ /// refer to https://docs.axelar.dev/dev/axelarjs-sdk/axelar-query-api#estimategasfee
20
+ /// 2. Pay gas fee by calling `payNativeGasForContractCall` on the AxelarGasService contract.
21
+ /// refer to https://docs.axelar.dev/dev/general-message-passing/gas-services/pay-gas#paynativegasforcontractcall
22
+ /// 3. Send message by calling `callContract` on the AxelarGateway contract.
23
+ /// refer to https://docs.axelar.dev/dev/general-message-passing/gmp-messages#call-a-contract-on-chain-b-from-chain-a
24
+ /// 4. Refund surplus gas fee asynchronously.
25
+ /// refer to https://docs.axelar.dev/dev/general-message-passing/gas-services/refund
26
+ /// @dev Recovery:
27
+ /// 1. If not enough gas fee is paid, the message will be hangup on source chain and can `add gas` to retry.
28
+ /// refer to https://docs.axelar.dev/dev/general-message-passing/recovery#increase-gas-payment-to-the-gas-receiver-on-the-source-chain
29
+ /// 2. If the message is not executed on the destination chain, you can manually retry by calling `execute` on the `ReceiveAxelarDVNAdapter` contract.
30
+ /// refer to https://docs.axelar.dev/dev/general-message-passing/recovery#manually-execute-a-transfer
31
+ /// @dev As the Gas is estimated off-chain, we need to update the gas fee periodically on-chain by calling `setNativeGasFee` with the new fee.
32
+ contract AxelarDVNAdapter is DVNAdapterBase, AxelarExecutable, IAxelarDVNAdapter {
33
+ mapping(string axelarChain => string peer) public peers; // by chain name
34
+ mapping(uint32 dstEid => DstConfig) public dstConfig; // by dstEid
35
+
36
+ // set default multiplier to 2.5x
39
37
  constructor(
40
- address _sendLib,
41
- address _receiveLib,
42
38
  address[] memory _admins,
43
- address _gateway,
44
- address _gasReceiver
45
- ) AxelarExecutable(_gateway) DVNAdapterBase(_sendLib, _receiveLib, _admins) {
46
- gasService = IAxelarGasService(_gasReceiver);
47
- }
39
+ address _gateway
40
+ ) AxelarExecutable(_gateway) DVNAdapterBase(msg.sender, _admins, 12000) {}
48
41
 
49
- /// @notice sets configuration (`nativeGasFee`, `multiplierBps`, `peer`, and `chainName`) for destination chains
50
- /// @dev The `nativeGasFee` and `multiplierBps` can be updated separately using `setDstNativeGasFee` and `setDstMultiplier` functions
51
- /// @param _params array of chain configurations
52
- function setDstConfig(DstConfigParam[] calldata _params) external onlyAdmin {
42
+ // ========================= OnlyAdmin =========================
43
+ function setDstConfig(DstConfigParam[] calldata _params) external onlyRole(ADMIN_ROLE) {
53
44
  for (uint256 i = 0; i < _params.length; i++) {
54
45
  DstConfigParam calldata param = _params[i];
55
46
 
56
- delete axelarChainToEid[dstConfig[param.dstEid].chainName];
47
+ delete peers[dstConfig[param.dstEid].chainName]; // delete old peer in case chain name by dstEid is updated
48
+ peers[param.chainName] = param.peer; // update peer
57
49
 
58
- axelarChainToEid[param.chainName] = param.dstEid;
59
- dstConfig[param.dstEid] = DstConfig({
60
- nativeGasFee: param.nativeGasFee,
61
- multiplierBps: param.multiplierBps,
62
- peer: param.peer,
63
- chainName: param.chainName
64
- });
50
+ dstConfig[param.dstEid] = DstConfig(param.chainName, param.peer, param.multiplierBps, param.nativeGasFee); // update config by dstEid
65
51
  }
66
52
 
67
53
  emit DstConfigSet(_params);
68
54
  }
69
55
 
70
56
  /// @notice sets message fee in native gas for destination chains.
71
- /// @dev Axelar does not support quoting fee onchain. Instead, the fee needs to be obtained off-chain by querying through the Axelar SDK.
57
+ /// @dev Axelar does not support quoting fee on-chain. Instead, the fee needs to be obtained off-chain by querying through the Axelar SDK.
72
58
  /// @dev The fee may change over time when token prices change, requiring admins to monitor and make necessary updates to reflect the actual fee.
73
59
  /// @dev Adding a buffer to the required fee is advisable. Any surplus fee will be refunded asynchronously if it exceeds the necessary amount.
74
60
  /// https://docs.axelar.dev/dev/general-message-passing/gas-services/pay-gas
75
61
  /// https://github.com/axelarnetwork/axelarjs/blob/070c8fe061f1082e79772fdc5c4675c0237bbba2/packages/api/src/axelar-query/isomorphic.ts#L54
76
62
  /// https://github.com/axelarnetwork/axelar-cgp-solidity/blob/d4536599321774927bf9716178a9e360f8e0efac/contracts/gas-service/AxelarGasService.sol#L403
77
- /// @param _params array of message fees for destination chains
78
- function setDstNativeGasFee(DstFeeParam[] calldata _params) external onlyAdmin {
79
- // TODO - can delete and call setDstConfig instead?
63
+ function setNativeGasFee(NativeGasFeeParam[] calldata _params) external onlyRole(ADMIN_ROLE) {
80
64
  for (uint256 i = 0; i < _params.length; i++) {
81
- DstFeeParam calldata param = _params[i];
65
+ NativeGasFeeParam calldata param = _params[i];
82
66
  dstConfig[param.dstEid].nativeGasFee = param.nativeGasFee;
83
67
  }
84
-
85
- emit DstFeeSet(_params);
68
+ emit NativeGasFeeSet(_params);
86
69
  }
87
70
 
88
- /// @notice sets fee multiplier in basis points for destination chains
89
- /// @param _params array of multipliers for destination chains
90
- function setDstMultiplier(DstMultiplierParam[] calldata _params) external onlyAdmin {
91
- // TODO - can delete and call setDstConfig instead?
92
- for (uint256 i = 0; i < _params.length; i++) {
93
- DstMultiplierParam calldata param = _params[i];
94
- dstConfig[param.dstEid].multiplierBps = param.multiplierBps;
95
- }
71
+ // ========================= OnlyWorkerFeeLib =========================
72
+ function withdrawToFeeLib(address _sendLib) external {
73
+ if (msg.sender != workerFeeLib) revert AxelarDVNAdapter_OnlyWorkerFeeLib();
96
74
 
97
- emit DstMultiplierSet(_params);
75
+ _withdrawFeeFromSendLib(_sendLib, workerFeeLib);
98
76
  }
99
77
 
78
+ // ========================= OnlyMessageLib =========================
100
79
  function assignJob(
101
80
  AssignJobParam calldata _param,
102
- bytes calldata /*_options*/
103
- ) external payable override onlySendLib returns (uint256 fee) {
104
- DstConfig storage config = dstConfig[_param.dstEid];
105
- fee = config.nativeGasFee;
106
- string memory dstChainName = config.chainName;
107
- string memory dstPeer = config.peer;
108
- bytes memory payload = _encodePayload(_param.packetHeader, _param.payloadHash);
109
-
110
- _assertBalanceAndWithdrawFee(fee);
111
-
112
- // https://docs.axelar.dev/dev/general-message-passing/gas-services/pay-gas#paynativegasforcontractcall
113
- gasService.payNativeGasForContractCall{ value: fee }(
114
- address(this), // sender
115
- dstChainName, // destinationChain
116
- dstPeer, // destinationAddress
117
- payload, // payload
118
- address(this) // refundAddress
81
+ bytes calldata _options
82
+ ) external payable override onlyAcl(_param.sender) returns (uint totalFee) {
83
+ bytes32 receiveLib = _getAndAssertReceiveLib(msg.sender, _param.dstEid);
84
+
85
+ IAxelarDVNAdapterFeeLib.Param memory feeLibParam = IAxelarDVNAdapterFeeLib.Param({
86
+ dstEid: _param.dstEid,
87
+ confirmations: _param.confirmations,
88
+ sender: _param.sender,
89
+ defaultMultiplierBps: defaultMultiplierBps
90
+ });
91
+ DstConfig memory config = dstConfig[_param.dstEid];
92
+
93
+ bytes memory payload = _encode(receiveLib, _param.packetHeader, _param.payloadHash);
94
+
95
+ totalFee = IAxelarDVNAdapterFeeLib(workerFeeLib).getFeeOnSend(
96
+ feeLibParam,
97
+ config,
98
+ payload,
99
+ _options,
100
+ msg.sender
119
101
  );
120
- // https://docs.axelar.dev/dev/general-message-passing/gmp-messages#call-a-contract-on-chain-b-from-chain-a
121
- gateway.callContract(dstChainName, dstPeer, payload);
122
102
 
123
- if (address(feeLib) != address(0)) {
124
- fee = feeLib.getFee(_param.dstEid, _param.sender, defaultMultiplierBps, config.multiplierBps, fee);
125
- }
103
+ gateway.callContract(config.chainName, config.peer, payload);
126
104
  }
127
105
 
106
+ // ========================= View =========================
128
107
  function getFee(
129
108
  uint32 _dstEid,
130
- uint64 /*_confirmations*/,
109
+ uint64 _confirmations,
131
110
  address _sender,
132
- bytes calldata /*_options*/
133
- ) external view override returns (uint256 fee) {
134
- DstConfig storage config = dstConfig[_dstEid];
135
- fee = config.nativeGasFee;
136
- if (address(feeLib) != address(0)) {
137
- fee = feeLib.getFee(_dstEid, _sender, defaultMultiplierBps, config.multiplierBps, fee);
138
- }
111
+ bytes calldata _options
112
+ ) external view override returns (uint256 totalFee) {
113
+ IAxelarDVNAdapterFeeLib.Param memory feeLibParam = IAxelarDVNAdapterFeeLib.Param(
114
+ _dstEid,
115
+ _confirmations,
116
+ _sender,
117
+ defaultMultiplierBps
118
+ );
119
+
120
+ totalFee = IAxelarDVNAdapterFeeLib(workerFeeLib).getFee(feeLibParam, dstConfig[_dstEid], _options);
139
121
  }
140
122
 
123
+ // ========================= Internal =========================
141
124
  function _execute(
142
125
  string calldata _sourceChain,
143
126
  string calldata _sourceAddress,
144
127
  bytes calldata _payload
145
128
  ) internal override {
129
+ // assert peer is the same as the source chain
146
130
  _assertPeer(_sourceChain, _sourceAddress);
147
- _verify(_payload);
148
- }
149
131
 
150
- function _assertPeer(string calldata _sourceChain, string calldata _sourceAddress) private view {
151
- uint32 sourceEid = axelarChainToEid[_sourceChain];
152
- string memory sourcePeer = dstConfig[sourceEid].peer;
132
+ _decodeAndVerify(_payload);
133
+ }
153
134
 
154
- if (keccak256(bytes(_sourceAddress)) != keccak256(bytes(sourcePeer))) revert Unauthorized();
135
+ function _assertPeer(string memory _sourceChain, string memory _sourceAddress) private view {
136
+ string memory sourcePeer = peers[_sourceChain];
137
+ if (keccak256(bytes(_sourceAddress)) != keccak256(bytes(sourcePeer))) {
138
+ revert AxelarDVNAdapter_UntrustedPeer(_sourceChain, _sourceAddress);
139
+ }
155
140
  }
156
141
  }