@layerzerolabs/lz-evm-sdk-v2 3.0.113 → 3.0.114

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 (177) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/artifacts/verification/verification-data-25ddf6a7583f79046cf40a127519d382.json +226 -0
  3. package/artifacts/{verification-data.json → verification/verification-data-a8863204d99e527a43bf167bfb175e3d.json} +30 -208
  4. package/artifacts/verification/verification-data-bcbd337ac361c0226ab3df95de084331.json +175 -0
  5. package/artifacts-tron/verification/verification-data-0aa95d94acbfa5a997361f092b2c3cdb.json +226 -0
  6. package/artifacts-tron/verification/verification-data-59399a7002f16d8b85f75e0cbced0107.json +220 -0
  7. package/artifacts-tron/{verification-data.json → verification/verification-data-a5f4488d362c50b6eca4ee196216587a.json} +30 -208
  8. package/artifacts-tron/verification/verification-data-bbff712af1796cf3cc91235aad448a01.json +97 -0
  9. package/artifacts-tron/verification/verification-data-f032c27816b48be5fcf3cc7ed3c366c0.json +175 -0
  10. package/artifacts-zk/verification/verification-data-2436ac350a5ed6bda1e5c836721d5444.json +170 -0
  11. package/artifacts-zk/{verification-data.json → verification/verification-data-8e3240debec8007ae59598d4a47ea27a.json} +25 -208
  12. package/artifacts-zk/verification/verification-data-c8fdeec934f86e4f0d4613b885a38d08.json +221 -0
  13. package/deployments/arbitrum-sandbox-local/DVN.json +1 -1
  14. package/deployments/arbitrum-sandbox-local/DVNDecompressor.json +1 -1
  15. package/deployments/arbitrum-sandbox-local/DVNFeeLib.json +1 -1
  16. package/deployments/arbitrum-sandbox-local/DefaultProxyAdmin.json +1 -1
  17. package/deployments/arbitrum-sandbox-local/EndpointV2.json +1 -1
  18. package/deployments/arbitrum-sandbox-local/EndpointV2View.json +1 -1
  19. package/deployments/arbitrum-sandbox-local/EndpointV2View_Implementation.json +1 -1
  20. package/deployments/arbitrum-sandbox-local/EndpointV2View_Proxy.json +1 -1
  21. package/deployments/arbitrum-sandbox-local/Executor.json +1 -1
  22. package/deployments/arbitrum-sandbox-local/ExecutorDecompressor.json +1 -1
  23. package/deployments/arbitrum-sandbox-local/ExecutorFeeLib.json +1 -1
  24. package/deployments/arbitrum-sandbox-local/ExecutorProxyAdmin.json +1 -1
  25. package/deployments/arbitrum-sandbox-local/Executor_Implementation.json +1 -1
  26. package/deployments/arbitrum-sandbox-local/Executor_Proxy.json +1 -1
  27. package/deployments/arbitrum-sandbox-local/LzExecutor.json +1 -1
  28. package/deployments/arbitrum-sandbox-local/LzExecutor_Implementation.json +1 -1
  29. package/deployments/arbitrum-sandbox-local/LzExecutor_Proxy.json +1 -1
  30. package/deployments/arbitrum-sandbox-local/MultiCall.json +1 -1
  31. package/deployments/arbitrum-sandbox-local/NonceContractMock.json +1 -1
  32. package/deployments/arbitrum-sandbox-local/PriceFeed.json +1 -1
  33. package/deployments/arbitrum-sandbox-local/PriceFeedProxyAdmin.json +1 -1
  34. package/deployments/arbitrum-sandbox-local/PriceFeed_Implementation.json +1 -1
  35. package/deployments/arbitrum-sandbox-local/PriceFeed_Proxy.json +1 -1
  36. package/deployments/arbitrum-sandbox-local/ReadLib1002.json +1 -1
  37. package/deployments/arbitrum-sandbox-local/ReadLib1002View.json +1 -1
  38. package/deployments/arbitrum-sandbox-local/ReadLib1002ViewProxyAdmin.json +1 -1
  39. package/deployments/arbitrum-sandbox-local/ReadLib1002View_Implementation.json +1 -1
  40. package/deployments/arbitrum-sandbox-local/ReadLib1002View_Proxy.json +1 -1
  41. package/deployments/arbitrum-sandbox-local/ReceiveUln301.json +1 -1
  42. package/deployments/arbitrum-sandbox-local/ReceiveUln301View.json +1 -1
  43. package/deployments/arbitrum-sandbox-local/ReceiveUln301View_Implementation.json +1 -1
  44. package/deployments/arbitrum-sandbox-local/ReceiveUln301View_Proxy.json +1 -1
  45. package/deployments/arbitrum-sandbox-local/ReceiveUln302.json +1 -1
  46. package/deployments/arbitrum-sandbox-local/ReceiveUln302View.json +1 -1
  47. package/deployments/arbitrum-sandbox-local/ReceiveUln302View_Implementation.json +1 -1
  48. package/deployments/arbitrum-sandbox-local/ReceiveUln302View_Proxy.json +1 -1
  49. package/deployments/arbitrum-sandbox-local/SendUln301.json +1 -1
  50. package/deployments/arbitrum-sandbox-local/SendUln302.json +1 -1
  51. package/deployments/arbitrum-sandbox-local/SimpleMessageLib.json +1 -1
  52. package/deployments/arbitrum-sandbox-local/Treasury.json +1 -1
  53. package/deployments/arbitrum-sandbox-local/TreasuryFeeHandler.json +1 -1
  54. package/deployments/bsc-sandbox-local/DVN.json +1 -1
  55. package/deployments/bsc-sandbox-local/DVNDecompressor.json +1 -1
  56. package/deployments/bsc-sandbox-local/DVNFeeLib.json +1 -1
  57. package/deployments/bsc-sandbox-local/DefaultProxyAdmin.json +1 -1
  58. package/deployments/bsc-sandbox-local/EndpointV2.json +1 -1
  59. package/deployments/bsc-sandbox-local/EndpointV2View.json +1 -1
  60. package/deployments/bsc-sandbox-local/EndpointV2View_Implementation.json +1 -1
  61. package/deployments/bsc-sandbox-local/EndpointV2View_Proxy.json +1 -1
  62. package/deployments/bsc-sandbox-local/Executor.json +1 -1
  63. package/deployments/bsc-sandbox-local/ExecutorDecompressor.json +1 -1
  64. package/deployments/bsc-sandbox-local/ExecutorFeeLib.json +1 -1
  65. package/deployments/bsc-sandbox-local/ExecutorProxyAdmin.json +1 -1
  66. package/deployments/bsc-sandbox-local/Executor_Implementation.json +1 -1
  67. package/deployments/bsc-sandbox-local/Executor_Proxy.json +1 -1
  68. package/deployments/bsc-sandbox-local/LzExecutor.json +1 -1
  69. package/deployments/bsc-sandbox-local/LzExecutor_Implementation.json +1 -1
  70. package/deployments/bsc-sandbox-local/LzExecutor_Proxy.json +1 -1
  71. package/deployments/bsc-sandbox-local/MultiCall.json +1 -1
  72. package/deployments/bsc-sandbox-local/NonceContractMock.json +1 -1
  73. package/deployments/bsc-sandbox-local/PriceFeed.json +1 -1
  74. package/deployments/bsc-sandbox-local/PriceFeedProxyAdmin.json +1 -1
  75. package/deployments/bsc-sandbox-local/PriceFeed_Implementation.json +1 -1
  76. package/deployments/bsc-sandbox-local/PriceFeed_Proxy.json +1 -1
  77. package/deployments/bsc-sandbox-local/ReadLib1002.json +1 -1
  78. package/deployments/bsc-sandbox-local/ReadLib1002View.json +1 -1
  79. package/deployments/bsc-sandbox-local/ReadLib1002ViewProxyAdmin.json +1 -1
  80. package/deployments/bsc-sandbox-local/ReadLib1002View_Implementation.json +1 -1
  81. package/deployments/bsc-sandbox-local/ReadLib1002View_Proxy.json +1 -1
  82. package/deployments/bsc-sandbox-local/ReceiveUln301.json +1 -1
  83. package/deployments/bsc-sandbox-local/ReceiveUln301View.json +1 -1
  84. package/deployments/bsc-sandbox-local/ReceiveUln301View_Implementation.json +1 -1
  85. package/deployments/bsc-sandbox-local/ReceiveUln301View_Proxy.json +1 -1
  86. package/deployments/bsc-sandbox-local/ReceiveUln302.json +1 -1
  87. package/deployments/bsc-sandbox-local/ReceiveUln302View.json +1 -1
  88. package/deployments/bsc-sandbox-local/ReceiveUln302View_Implementation.json +1 -1
  89. package/deployments/bsc-sandbox-local/ReceiveUln302View_Proxy.json +1 -1
  90. package/deployments/bsc-sandbox-local/SendUln301.json +1 -1
  91. package/deployments/bsc-sandbox-local/SendUln302.json +1 -1
  92. package/deployments/bsc-sandbox-local/SimpleMessageLib.json +1 -1
  93. package/deployments/bsc-sandbox-local/Treasury.json +1 -1
  94. package/deployments/bsc-sandbox-local/TreasuryFeeHandler.json +1 -1
  95. package/deployments/ethereum-sandbox-local/DVN.json +1 -1
  96. package/deployments/ethereum-sandbox-local/DVNDecompressor.json +1 -1
  97. package/deployments/ethereum-sandbox-local/DVNFeeLib.json +1 -1
  98. package/deployments/ethereum-sandbox-local/DefaultProxyAdmin.json +1 -1
  99. package/deployments/ethereum-sandbox-local/EndpointV2.json +1 -1
  100. package/deployments/ethereum-sandbox-local/EndpointV2View.json +1 -1
  101. package/deployments/ethereum-sandbox-local/EndpointV2View_Implementation.json +1 -1
  102. package/deployments/ethereum-sandbox-local/EndpointV2View_Proxy.json +1 -1
  103. package/deployments/ethereum-sandbox-local/Executor.json +1 -1
  104. package/deployments/ethereum-sandbox-local/ExecutorDecompressor.json +1 -1
  105. package/deployments/ethereum-sandbox-local/ExecutorFeeLib.json +1 -1
  106. package/deployments/ethereum-sandbox-local/ExecutorProxyAdmin.json +1 -1
  107. package/deployments/ethereum-sandbox-local/Executor_Implementation.json +1 -1
  108. package/deployments/ethereum-sandbox-local/Executor_Proxy.json +1 -1
  109. package/deployments/ethereum-sandbox-local/LzExecutor.json +1 -1
  110. package/deployments/ethereum-sandbox-local/LzExecutor_Implementation.json +1 -1
  111. package/deployments/ethereum-sandbox-local/LzExecutor_Proxy.json +1 -1
  112. package/deployments/ethereum-sandbox-local/MultiCall.json +1 -1
  113. package/deployments/ethereum-sandbox-local/NonceContractMock.json +1 -1
  114. package/deployments/ethereum-sandbox-local/PriceFeed.json +1 -1
  115. package/deployments/ethereum-sandbox-local/PriceFeedProxyAdmin.json +1 -1
  116. package/deployments/ethereum-sandbox-local/PriceFeed_Implementation.json +1 -1
  117. package/deployments/ethereum-sandbox-local/PriceFeed_Proxy.json +1 -1
  118. package/deployments/ethereum-sandbox-local/ReadLib1002.json +1 -1
  119. package/deployments/ethereum-sandbox-local/ReadLib1002View.json +1 -1
  120. package/deployments/ethereum-sandbox-local/ReadLib1002ViewProxyAdmin.json +1 -1
  121. package/deployments/ethereum-sandbox-local/ReadLib1002View_Implementation.json +1 -1
  122. package/deployments/ethereum-sandbox-local/ReadLib1002View_Proxy.json +1 -1
  123. package/deployments/ethereum-sandbox-local/ReceiveUln301.json +1 -1
  124. package/deployments/ethereum-sandbox-local/ReceiveUln301View.json +1 -1
  125. package/deployments/ethereum-sandbox-local/ReceiveUln301View_Implementation.json +1 -1
  126. package/deployments/ethereum-sandbox-local/ReceiveUln301View_Proxy.json +1 -1
  127. package/deployments/ethereum-sandbox-local/ReceiveUln302.json +1 -1
  128. package/deployments/ethereum-sandbox-local/ReceiveUln302View.json +1 -1
  129. package/deployments/ethereum-sandbox-local/ReceiveUln302View_Implementation.json +1 -1
  130. package/deployments/ethereum-sandbox-local/ReceiveUln302View_Proxy.json +1 -1
  131. package/deployments/ethereum-sandbox-local/SendUln301.json +1 -1
  132. package/deployments/ethereum-sandbox-local/SendUln302.json +1 -1
  133. package/deployments/ethereum-sandbox-local/SimpleMessageLib.json +1 -1
  134. package/deployments/ethereum-sandbox-local/Treasury.json +1 -1
  135. package/deployments/ethereum-sandbox-local/TreasuryFeeHandler.json +1 -1
  136. package/deployments/tron-sandbox-local/DVN.json +2 -2
  137. package/deployments/tron-sandbox-local/DVNDecompressor.json +2 -2
  138. package/deployments/tron-sandbox-local/DVNFeeLib.json +2 -2
  139. package/deployments/tron-sandbox-local/DefaultProxyAdmin.json +2 -2
  140. package/deployments/tron-sandbox-local/EndpointV2.json +2 -2
  141. package/deployments/tron-sandbox-local/EndpointV2View.json +2 -2
  142. package/deployments/tron-sandbox-local/EndpointV2View_Implementation.json +2 -2
  143. package/deployments/tron-sandbox-local/EndpointV2View_Proxy.json +2 -2
  144. package/deployments/tron-sandbox-local/Executor.json +2 -2
  145. package/deployments/tron-sandbox-local/ExecutorDecompressor.json +2 -2
  146. package/deployments/tron-sandbox-local/ExecutorFeeLib.json +2 -2
  147. package/deployments/tron-sandbox-local/ExecutorProxyAdmin.json +2 -2
  148. package/deployments/tron-sandbox-local/Executor_Implementation.json +2 -2
  149. package/deployments/tron-sandbox-local/Executor_Proxy.json +2 -2
  150. package/deployments/tron-sandbox-local/LzExecutor.json +2 -2
  151. package/deployments/tron-sandbox-local/LzExecutor_Implementation.json +2 -2
  152. package/deployments/tron-sandbox-local/LzExecutor_Proxy.json +2 -2
  153. package/deployments/tron-sandbox-local/MultiCall.json +2 -2
  154. package/deployments/tron-sandbox-local/NonceContractMock.json +2 -2
  155. package/deployments/tron-sandbox-local/PriceFeed.json +2 -2
  156. package/deployments/tron-sandbox-local/PriceFeedProxyAdmin.json +2 -2
  157. package/deployments/tron-sandbox-local/PriceFeed_Implementation.json +2 -2
  158. package/deployments/tron-sandbox-local/PriceFeed_Proxy.json +2 -2
  159. package/deployments/tron-sandbox-local/ReadLib1002.json +2 -2
  160. package/deployments/tron-sandbox-local/ReadLib1002View.json +2 -2
  161. package/deployments/tron-sandbox-local/ReadLib1002ViewProxyAdmin.json +2 -2
  162. package/deployments/tron-sandbox-local/ReadLib1002View_Implementation.json +2 -2
  163. package/deployments/tron-sandbox-local/ReadLib1002View_Proxy.json +2 -2
  164. package/deployments/tron-sandbox-local/ReceiveUln301.json +2 -2
  165. package/deployments/tron-sandbox-local/ReceiveUln301View.json +2 -2
  166. package/deployments/tron-sandbox-local/ReceiveUln301View_Implementation.json +2 -2
  167. package/deployments/tron-sandbox-local/ReceiveUln301View_Proxy.json +2 -2
  168. package/deployments/tron-sandbox-local/ReceiveUln302.json +2 -2
  169. package/deployments/tron-sandbox-local/ReceiveUln302View.json +2 -2
  170. package/deployments/tron-sandbox-local/ReceiveUln302View_Implementation.json +2 -2
  171. package/deployments/tron-sandbox-local/ReceiveUln302View_Proxy.json +2 -2
  172. package/deployments/tron-sandbox-local/SendUln301.json +2 -2
  173. package/deployments/tron-sandbox-local/SendUln302.json +2 -2
  174. package/deployments/tron-sandbox-local/SimpleMessageLib.json +2 -2
  175. package/deployments/tron-sandbox-local/Treasury.json +2 -2
  176. package/deployments/tron-sandbox-local/TreasuryFeeHandler.json +2 -2
  177. package/package.json +12 -12
@@ -1,6 +1,8 @@
1
1
  {
2
+ "id": "a5f4488d362c50b6eca4ee196216587a",
2
3
  "solcLongVersion": "0.8.20+commit.5f1834bc.Emscripten.clang",
3
4
  "input": {
5
+ "language": "Solidity",
4
6
  "sources": {
5
7
  "@arbitrum/nitro-contracts/src/bridge/IBridge.sol": {
6
8
  "content": "// Copyright 2021-2022, Offchain Labs, Inc.\n// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE\n// SPDX-License-Identifier: BUSL-1.1\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.6.9 <0.9.0;\n\nimport \"./IOwnable.sol\";\n\ninterface IBridge {\n event MessageDelivered(\n uint256 indexed messageIndex,\n bytes32 indexed beforeInboxAcc,\n address inbox,\n uint8 kind,\n address sender,\n bytes32 messageDataHash,\n uint256 baseFeeL1,\n uint64 timestamp\n );\n\n event BridgeCallTriggered(\n address indexed outbox,\n address indexed to,\n uint256 value,\n bytes data\n );\n\n event InboxToggle(address indexed inbox, bool enabled);\n\n event OutboxToggle(address indexed outbox, bool enabled);\n\n event SequencerInboxUpdated(address newSequencerInbox);\n\n event RollupUpdated(address rollup);\n\n function allowedDelayedInboxList(uint256) external returns (address);\n\n function allowedOutboxList(uint256) external returns (address);\n\n /// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.\n function delayedInboxAccs(uint256) external view returns (bytes32);\n\n /// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.\n function sequencerInboxAccs(uint256) external view returns (bytes32);\n\n function rollup() external view returns (IOwnable);\n\n function sequencerInbox() external view returns (address);\n\n function activeOutbox() external view returns (address);\n\n function allowedDelayedInboxes(address inbox) external view returns (bool);\n\n function allowedOutboxes(address outbox) external view returns (bool);\n\n function sequencerReportedSubMessageCount() external view returns (uint256);\n\n function executeCall(\n address to,\n uint256 value,\n bytes calldata data\n ) external returns (bool success, bytes memory returnData);\n\n function delayedMessageCount() external view returns (uint256);\n\n function sequencerMessageCount() external view returns (uint256);\n\n // ---------- onlySequencerInbox functions ----------\n\n function enqueueSequencerMessage(\n bytes32 dataHash,\n uint256 afterDelayedMessagesRead,\n uint256 prevMessageCount,\n uint256 newMessageCount\n )\n external\n returns (\n uint256 seqMessageIndex,\n bytes32 beforeAcc,\n bytes32 delayedAcc,\n bytes32 acc\n );\n\n /**\n * @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type\n * This is done through a separate function entrypoint instead of allowing the sequencer inbox\n * to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either\n * every delayed inbox or every sequencer inbox call.\n */\n function submitBatchSpendingReport(address batchPoster, bytes32 dataHash)\n external\n returns (uint256 msgNum);\n\n // ---------- onlyRollupOrOwner functions ----------\n\n function setSequencerInbox(address _sequencerInbox) external;\n\n function setDelayedInbox(address inbox, bool enabled) external;\n\n function setOutbox(address inbox, bool enabled) external;\n\n function updateRollupAddress(IOwnable _rollup) external;\n}\n"
@@ -484,215 +486,35 @@
484
486
  },
485
487
  "solidity-bytes-utils/contracts/BytesLib.sol": {
486
488
  "content": "// SPDX-License-Identifier: Unlicense\n/*\n * @title Solidity Bytes Arrays Utils\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\n *\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\n * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\n */\npragma solidity >=0.8.0 <0.9.0;\n\n\nlibrary BytesLib {\n function concat(\n bytes memory _preBytes,\n bytes memory _postBytes\n )\n internal\n pure\n returns (bytes memory)\n {\n bytes memory tempBytes;\n\n assembly {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // Store the length of the first bytes array at the beginning of\n // the memory for tempBytes.\n let length := mload(_preBytes)\n mstore(tempBytes, length)\n\n // Maintain a memory counter for the current write location in the\n // temp bytes array by adding the 32 bytes for the array length to\n // the starting location.\n let mc := add(tempBytes, 0x20)\n // Stop copying when the memory counter reaches the length of the\n // first bytes array.\n let end := add(mc, length)\n\n for {\n // Initialize a copy counter to the start of the _preBytes data,\n // 32 bytes into its memory.\n let cc := add(_preBytes, 0x20)\n } lt(mc, end) {\n // Increase both counters by 32 bytes each iteration.\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n // Write the _preBytes data into the tempBytes memory 32 bytes\n // at a time.\n mstore(mc, mload(cc))\n }\n\n // Add the length of _postBytes to the current length of tempBytes\n // and store it as the new length in the first 32 bytes of the\n // tempBytes memory.\n length := mload(_postBytes)\n mstore(tempBytes, add(length, mload(tempBytes)))\n\n // Move the memory counter back from a multiple of 0x20 to the\n // actual end of the _preBytes data.\n mc := end\n // Stop copying when the memory counter reaches the new combined\n // length of the arrays.\n end := add(mc, length)\n\n for {\n let cc := add(_postBytes, 0x20)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n // Update the free-memory pointer by padding our last write location\n // to 32 bytes: add 31 bytes to the end of tempBytes to move to the\n // next 32 byte block, then round down to the nearest multiple of\n // 32. If the sum of the length of the two arrays is zero then add\n // one before rounding down to leave a blank 32 bytes (the length block with 0).\n mstore(0x40, and(\n add(add(end, iszero(add(length, mload(_preBytes)))), 31),\n not(31) // Round down to the nearest 32 bytes.\n ))\n }\n\n return tempBytes;\n }\n\n function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {\n assembly {\n // Read the first 32 bytes of _preBytes storage, which is the length\n // of the array. (We don't need to use the offset into the slot\n // because arrays use the entire slot.)\n let fslot := sload(_preBytes.slot)\n // Arrays of 31 bytes or less have an even value in their slot,\n // while longer arrays have an odd value. The actual length is\n // the slot divided by two for odd values, and the lowest order\n // byte divided by two for even values.\n // If the slot is even, bitwise and the slot with 255 and divide by\n // two to get the length. If the slot is odd, bitwise and the slot\n // with -1 and divide by two.\n let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n let mlength := mload(_postBytes)\n let newlength := add(slength, mlength)\n // slength can contain both the length and contents of the array\n // if length < 32 bytes so let's prepare for that\n // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n switch add(lt(slength, 32), lt(newlength, 32))\n case 2 {\n // Since the new array still fits in the slot, we just need to\n // update the contents of the slot.\n // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length\n sstore(\n _preBytes.slot,\n // all the modifications to the slot are inside this\n // next block\n add(\n // we can just add to the slot contents because the\n // bytes we want to change are the LSBs\n fslot,\n add(\n mul(\n div(\n // load the bytes from memory\n mload(add(_postBytes, 0x20)),\n // zero all bytes to the right\n exp(0x100, sub(32, mlength))\n ),\n // and now shift left the number of bytes to\n // leave space for the length in the slot\n exp(0x100, sub(32, newlength))\n ),\n // increase length by the double of the memory\n // bytes length\n mul(mlength, 2)\n )\n )\n )\n }\n case 1 {\n // The stored value fits in the slot, but the combined value\n // will exceed it.\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n // save new length\n sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n // The contents of the _postBytes array start 32 bytes into\n // the structure. Our first read should obtain the `submod`\n // bytes that can fit into the unused space in the last word\n // of the stored array. To get this, we read 32 bytes starting\n // from `submod`, so the data we read overlaps with the array\n // contents by `submod` bytes. Masking the lowest-order\n // `submod` bytes allows us to add that value directly to the\n // stored value.\n\n let submod := sub(32, slength)\n let mc := add(_postBytes, submod)\n let end := add(_postBytes, mlength)\n let mask := sub(exp(0x100, submod), 1)\n\n sstore(\n sc,\n add(\n and(\n fslot,\n 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00\n ),\n and(mload(mc), mask)\n )\n )\n\n for {\n mc := add(mc, 0x20)\n sc := add(sc, 1)\n } lt(mc, end) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n sstore(sc, mload(mc))\n }\n\n mask := exp(0x100, sub(mc, end))\n\n sstore(sc, mul(div(mload(mc), mask), mask))\n }\n default {\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n // Start copying to the last used word of the stored array.\n let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n // save new length\n sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n // Copy over the first `submod` bytes of the new data as in\n // case 1 above.\n let slengthmod := mod(slength, 32)\n let mlengthmod := mod(mlength, 32)\n let submod := sub(32, slengthmod)\n let mc := add(_postBytes, submod)\n let end := add(_postBytes, mlength)\n let mask := sub(exp(0x100, submod), 1)\n\n sstore(sc, add(sload(sc), and(mload(mc), mask)))\n\n for {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } lt(mc, end) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n sstore(sc, mload(mc))\n }\n\n mask := exp(0x100, sub(mc, end))\n\n sstore(sc, mul(div(mload(mc), mask), mask))\n }\n }\n }\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n )\n internal\n pure\n returns (bytes memory)\n {\n require(_length + 31 >= _length, \"slice_overflow\");\n require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\n require(_bytes.length >= _start + 20, \"toAddress_outOfBounds\");\n address tempAddress;\n\n assembly {\n tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\n }\n\n return tempAddress;\n }\n\n function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {\n require(_bytes.length >= _start + 1 , \"toUint8_outOfBounds\");\n uint8 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x1), _start))\n }\n\n return tempUint;\n }\n\n function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {\n require(_bytes.length >= _start + 2, \"toUint16_outOfBounds\");\n uint16 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x2), _start))\n }\n\n return tempUint;\n }\n\n function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {\n require(_bytes.length >= _start + 4, \"toUint32_outOfBounds\");\n uint32 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x4), _start))\n }\n\n return tempUint;\n }\n\n function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {\n require(_bytes.length >= _start + 8, \"toUint64_outOfBounds\");\n uint64 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x8), _start))\n }\n\n return tempUint;\n }\n\n function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {\n require(_bytes.length >= _start + 12, \"toUint96_outOfBounds\");\n uint96 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0xc), _start))\n }\n\n return tempUint;\n }\n\n function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {\n require(_bytes.length >= _start + 16, \"toUint128_outOfBounds\");\n uint128 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x10), _start))\n }\n\n return tempUint;\n }\n\n function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {\n require(_bytes.length >= _start + 32, \"toUint256_outOfBounds\");\n uint256 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x20), _start))\n }\n\n return tempUint;\n }\n\n function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {\n require(_bytes.length >= _start + 32, \"toBytes32_outOfBounds\");\n bytes32 tempBytes32;\n\n assembly {\n tempBytes32 := mload(add(add(_bytes, 0x20), _start))\n }\n\n return tempBytes32;\n }\n\n function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {\n bool success = true;\n\n assembly {\n let length := mload(_preBytes)\n\n // if lengths don't match the arrays are not equal\n switch eq(length, mload(_postBytes))\n case 1 {\n // cb is a circuit breaker in the for loop since there's\n // no said feature for inline assembly loops\n // cb = 1 - don't breaker\n // cb = 0 - break\n let cb := 1\n\n let mc := add(_preBytes, 0x20)\n let end := add(mc, length)\n\n for {\n let cc := add(_postBytes, 0x20)\n // the next line is the loop condition:\n // while(uint256(mc < end) + cb == 2)\n } eq(add(lt(mc, end), cb), 2) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n // if any of these checks fails then arrays are not equal\n if iszero(eq(mload(mc), mload(cc))) {\n // unsuccess:\n success := 0\n cb := 0\n }\n }\n }\n default {\n // unsuccess:\n success := 0\n }\n }\n\n return success;\n }\n\n function equalStorage(\n bytes storage _preBytes,\n bytes memory _postBytes\n )\n internal\n view\n returns (bool)\n {\n bool success = true;\n\n assembly {\n // we know _preBytes_offset is 0\n let fslot := sload(_preBytes.slot)\n // Decode the length of the stored array like in concatStorage().\n let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n let mlength := mload(_postBytes)\n\n // if lengths don't match the arrays are not equal\n switch eq(slength, mlength)\n case 1 {\n // slength can contain both the length and contents of the array\n // if length < 32 bytes so let's prepare for that\n // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n if iszero(iszero(slength)) {\n switch lt(slength, 32)\n case 1 {\n // blank the last byte which is the length\n fslot := mul(div(fslot, 0x100), 0x100)\n\n if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {\n // unsuccess:\n success := 0\n }\n }\n default {\n // cb is a circuit breaker in the for loop since there's\n // no said feature for inline assembly loops\n // cb = 1 - don't breaker\n // cb = 0 - break\n let cb := 1\n\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n let sc := keccak256(0x0, 0x20)\n\n let mc := add(_postBytes, 0x20)\n let end := add(mc, mlength)\n\n // the next line is the loop condition:\n // while(uint256(mc < end) + cb == 2)\n for {} eq(add(lt(mc, end), cb), 2) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n if iszero(eq(sload(sc), mload(mc))) {\n // unsuccess:\n success := 0\n cb := 0\n }\n }\n }\n }\n }\n default {\n // unsuccess:\n success := 0\n }\n }\n\n return success;\n }\n}\n"
487
- },
488
- "contracts/EndpointV2.sol": {
489
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { MessagingFee, MessagingParams, MessagingReceipt, Origin, ILayerZeroEndpointV2 } from \"./interfaces/ILayerZeroEndpointV2.sol\";\nimport { ISendLib, Packet } from \"./interfaces/ISendLib.sol\";\nimport { ILayerZeroReceiver } from \"./interfaces/ILayerZeroReceiver.sol\";\nimport { Errors } from \"./libs/Errors.sol\";\nimport { GUID } from \"./libs/GUID.sol\";\nimport { Transfer } from \"./libs/Transfer.sol\";\nimport { MessagingChannel } from \"./MessagingChannel.sol\";\nimport { MessagingComposer } from \"./MessagingComposer.sol\";\nimport { MessageLibManager } from \"./MessageLibManager.sol\";\nimport { MessagingContext } from \"./MessagingContext.sol\";\n\n// LayerZero EndpointV2 is fully backward compatible with LayerZero Endpoint(V1), but it also supports additional\n// features that Endpoint(V1) does not support now and may not in the future. We have also changed some terminology\n// to clarify pre-existing language that might have been confusing.\n//\n// The following is a list of terminology changes:\n// -chainId -> eid\n// - Rationale: chainId was a term we initially used to describe an endpoint on a specific chain. Since\n// LayerZero supports non-EVMs we could not map the classic EVM chainIds to the LayerZero chainIds, making it\n// confusing for developers. With the addition of EndpointV2 and its backward compatible nature, we would have\n// two chainIds per chain that has Endpoint(V1), further confusing developers. We have decided to change the\n// name to Endpoint Id, or eid, for simplicity and clarity.\n// -adapterParams -> options\n// -userApplication -> oapp. Omnichain Application\n// -srcAddress -> sender\n// -dstAddress -> receiver\n// - Rationale: The sender/receiver on EVM is the address. However, on non-EVM chains, the sender/receiver could\n// represented as a public key, or some other identifier. The term sender/receiver is more generic\n// -payload -> message.\n// - Rationale: The term payload is used in the context of a packet, which is a combination of the message and GUID\ncontract EndpointV2 is ILayerZeroEndpointV2, MessagingChannel, MessageLibManager, MessagingComposer, MessagingContext {\n address public lzToken;\n\n mapping(address oapp => address delegate) public delegates;\n\n /// @param _eid the unique Endpoint Id for this deploy that all other Endpoints can use to send to it\n constructor(uint32 _eid, address _owner) MessagingChannel(_eid) {\n _transferOwnership(_owner);\n }\n\n /// @dev MESSAGING STEP 0\n /// @notice This view function gives the application built on top of LayerZero the ability to requests a quote\n /// with the same parameters as they would to send their message. Since the quotes are given on chain there is a\n /// race condition in which the prices could change between the time the user gets their quote and the time they\n /// submit their message. If the price moves up and the user doesn't send enough funds the transaction will revert,\n /// if the price goes down the _refundAddress provided by the app will be refunded the difference.\n /// @param _params the messaging parameters\n /// @param _sender the sender of the message\n function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory) {\n // lzToken must be set to support payInLzToken\n if (_params.payInLzToken && lzToken == address(0x0)) revert Errors.LZ_LzTokenUnavailable();\n\n // get the correct outbound nonce\n uint64 nonce = outboundNonce[_sender][_params.dstEid][_params.receiver] + 1;\n\n // construct the packet with a GUID\n Packet memory packet = Packet({\n nonce: nonce,\n srcEid: eid,\n sender: _sender,\n dstEid: _params.dstEid,\n receiver: _params.receiver,\n guid: GUID.generate(nonce, eid, _sender, _params.dstEid, _params.receiver),\n message: _params.message\n });\n\n // get the send library by sender and dst eid\n // use _ to avoid variable shadowing\n address _sendLibrary = getSendLibrary(_sender, _params.dstEid);\n\n return ISendLib(_sendLibrary).quote(packet, _params.options, _params.payInLzToken);\n }\n\n /// @dev MESSAGING STEP 1 - OApp need to transfer the fees to the endpoint before sending the message\n /// @param _params the messaging parameters\n /// @param _refundAddress the address to refund both the native and lzToken\n function send(\n MessagingParams calldata _params,\n address _refundAddress\n ) external payable sendContext(_params.dstEid, msg.sender) returns (MessagingReceipt memory) {\n if (_params.payInLzToken && lzToken == address(0x0)) revert Errors.LZ_LzTokenUnavailable();\n\n // send message\n (MessagingReceipt memory receipt, address _sendLibrary) = _send(msg.sender, _params);\n\n // OApp can simulate with 0 native value it will fail with error including the required fee, which can be provided in the actual call\n // this trick can be used to avoid the need to write the quote() function\n // however, without the quote view function it will be hard to compose an oapp on chain\n uint256 suppliedNative = _suppliedNative();\n uint256 suppliedLzToken = _suppliedLzToken(_params.payInLzToken);\n _assertMessagingFee(receipt.fee, suppliedNative, suppliedLzToken);\n\n // handle lz token fees\n _payToken(lzToken, receipt.fee.lzTokenFee, suppliedLzToken, _sendLibrary, _refundAddress);\n\n // handle native fees\n _payNative(receipt.fee.nativeFee, suppliedNative, _sendLibrary, _refundAddress);\n\n return receipt;\n }\n\n /// @dev internal function for sending the messages used by all external send methods\n /// @param _sender the address of the application sending the message to the destination chain\n /// @param _params the messaging parameters\n function _send(\n address _sender,\n MessagingParams calldata _params\n ) internal returns (MessagingReceipt memory, address) {\n // get the correct outbound nonce\n uint64 latestNonce = _outbound(_sender, _params.dstEid, _params.receiver);\n\n // construct the packet with a GUID\n Packet memory packet = Packet({\n nonce: latestNonce,\n srcEid: eid,\n sender: _sender,\n dstEid: _params.dstEid,\n receiver: _params.receiver,\n guid: GUID.generate(latestNonce, eid, _sender, _params.dstEid, _params.receiver),\n message: _params.message\n });\n\n // get the send library by sender and dst eid\n address _sendLibrary = getSendLibrary(_sender, _params.dstEid);\n\n // messageLib always returns encodedPacket with guid\n (MessagingFee memory fee, bytes memory encodedPacket) = ISendLib(_sendLibrary).send(\n packet,\n _params.options,\n _params.payInLzToken\n );\n\n // Emit packet information for DVNs, Executors, and any other offchain infrastructure to only listen\n // for this one event to perform their actions.\n emit PacketSent(encodedPacket, _params.options, _sendLibrary);\n\n return (MessagingReceipt(packet.guid, latestNonce, fee), _sendLibrary);\n }\n\n /// @dev MESSAGING STEP 2 - on the destination chain\n /// @dev configured receive library verifies a message\n /// @param _origin a struct holding the srcEid, nonce, and sender of the message\n /// @param _receiver the receiver of the message\n /// @param _payloadHash the payload hash of the message\n function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external {\n if (!isValidReceiveLibrary(_receiver, _origin.srcEid, msg.sender)) revert Errors.LZ_InvalidReceiveLibrary();\n\n uint64 lazyNonce = lazyInboundNonce[_receiver][_origin.srcEid][_origin.sender];\n if (!_initializable(_origin, _receiver, lazyNonce)) revert Errors.LZ_PathNotInitializable();\n if (!_verifiable(_origin, _receiver, lazyNonce)) revert Errors.LZ_PathNotVerifiable();\n\n // insert the message into the message channel\n _inbound(_receiver, _origin.srcEid, _origin.sender, _origin.nonce, _payloadHash);\n emit PacketVerified(_origin, _receiver, _payloadHash);\n }\n\n /// @dev MESSAGING STEP 3 - the last step\n /// @dev execute a verified message to the designated receiver\n /// @dev the execution provides the execution context (caller, extraData) to the receiver. the receiver can optionally assert the caller and validate the untrusted extraData\n /// @dev cant reentrant because the payload is cleared before execution\n /// @param _origin the origin of the message\n /// @param _receiver the receiver of the message\n /// @param _guid the guid of the message\n /// @param _message the message\n /// @param _extraData the extra data provided by the executor. this data is untrusted and should be validated.\n function lzReceive(\n Origin calldata _origin,\n address _receiver,\n bytes32 _guid,\n bytes calldata _message,\n bytes calldata _extraData\n ) external payable {\n // clear the payload first to prevent reentrancy, and then execute the message\n _clearPayload(_receiver, _origin.srcEid, _origin.sender, _origin.nonce, abi.encodePacked(_guid, _message));\n ILayerZeroReceiver(_receiver).lzReceive{ value: msg.value }(_origin, _guid, _message, msg.sender, _extraData);\n emit PacketDelivered(_origin, _receiver);\n }\n\n /// @param _origin the origin of the message\n /// @param _receiver the receiver of the message\n /// @param _guid the guid of the message\n /// @param _message the message\n /// @param _extraData the extra data provided by the executor.\n /// @param _reason the reason for failure\n function lzReceiveAlert(\n Origin calldata _origin,\n address _receiver,\n bytes32 _guid,\n uint256 _gas,\n uint256 _value,\n bytes calldata _message,\n bytes calldata _extraData,\n bytes calldata _reason\n ) external {\n emit LzReceiveAlert(_receiver, msg.sender, _origin, _guid, _gas, _value, _message, _extraData, _reason);\n }\n\n /// @dev Oapp uses this interface to clear a message.\n /// @dev this is a PULL mode versus the PUSH mode of lzReceive\n /// @dev the cleared message can be ignored by the app (effectively burnt)\n /// @dev authenticated by oapp\n /// @param _origin the origin of the message\n /// @param _guid the guid of the message\n /// @param _message the message\n function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external {\n _assertAuthorized(_oapp);\n\n bytes memory payload = abi.encodePacked(_guid, _message);\n _clearPayload(_oapp, _origin.srcEid, _origin.sender, _origin.nonce, payload);\n emit PacketDelivered(_origin, _oapp);\n }\n\n /// @dev allows reconfiguration to recover from wrong configurations\n /// @dev users should never approve the EndpointV2 contract to spend their non-layerzero tokens\n /// @dev override this function if the endpoint is charging ERC20 tokens as native\n /// @dev only owner\n /// @param _lzToken the new layer zero token address\n function setLzToken(address _lzToken) public virtual onlyOwner {\n lzToken = _lzToken;\n emit LzTokenSet(_lzToken);\n }\n\n /// @dev recover the token sent to this contract by mistake\n /// @dev only owner\n /// @param _token the token to recover. if 0x0 then it is native token\n /// @param _to the address to send the token to\n /// @param _amount the amount to send\n function recoverToken(address _token, address _to, uint256 _amount) external onlyOwner {\n Transfer.nativeOrToken(_token, _to, _amount);\n }\n\n /// @dev handling token payments on endpoint. the sender must approve the endpoint to spend the token\n /// @dev internal function\n /// @param _token the token to pay\n /// @param _required the amount required\n /// @param _supplied the amount supplied\n /// @param _receiver the receiver of the token\n function _payToken(\n address _token,\n uint256 _required,\n uint256 _supplied,\n address _receiver,\n address _refundAddress\n ) internal {\n if (_required > 0) {\n Transfer.token(_token, _receiver, _required);\n }\n if (_required < _supplied) {\n unchecked {\n // refund the excess\n Transfer.token(_token, _refundAddress, _supplied - _required);\n }\n }\n }\n\n /// @dev handling native token payments on endpoint\n /// @dev override this if the endpoint is charging ERC20 tokens as native\n /// @dev internal function\n /// @param _required the amount required\n /// @param _supplied the amount supplied\n /// @param _receiver the receiver of the native token\n /// @param _refundAddress the address to refund the excess to\n function _payNative(\n uint256 _required,\n uint256 _supplied,\n address _receiver,\n address _refundAddress\n ) internal virtual {\n if (_required > 0) {\n Transfer.native(_receiver, _required);\n }\n if (_required < _supplied) {\n unchecked {\n // refund the excess\n Transfer.native(_refundAddress, _supplied - _required);\n }\n }\n }\n\n /// @dev get the balance of the lzToken as the supplied lzToken fee if payInLzToken is true\n function _suppliedLzToken(bool _payInLzToken) internal view returns (uint256 supplied) {\n if (_payInLzToken) {\n supplied = IERC20(lzToken).balanceOf(address(this));\n\n // if payInLzToken is true, the supplied fee must be greater than 0 to prevent a race condition\n // in which an oapp sending a message with lz token and the lz token is set to a new token between the tx\n // being sent and the tx being mined. if the required lz token fee is 0 and the old lz token would be\n // locked in the contract instead of being refunded\n if (supplied == 0) revert Errors.LZ_ZeroLzTokenFee();\n }\n }\n\n /// @dev override this if the endpoint is charging ERC20 tokens as native\n function _suppliedNative() internal view virtual returns (uint256) {\n return msg.value;\n }\n\n /// @dev Assert the required fees and the supplied fees are enough\n function _assertMessagingFee(\n MessagingFee memory _required,\n uint256 _suppliedNativeFee,\n uint256 _suppliedLzTokenFee\n ) internal pure {\n if (_required.nativeFee > _suppliedNativeFee || _required.lzTokenFee > _suppliedLzTokenFee) {\n revert Errors.LZ_InsufficientFee(\n _required.nativeFee,\n _suppliedNativeFee,\n _required.lzTokenFee,\n _suppliedLzTokenFee\n );\n }\n }\n\n /// @dev override this if the endpoint is charging ERC20 tokens as native\n /// @return 0x0 if using native. otherwise the address of the native ERC20 token\n function nativeToken() external view virtual returns (address) {\n return address(0x0);\n }\n\n /// @notice delegate is authorized by the oapp to configure anything in layerzero\n function setDelegate(address _delegate) external {\n delegates[msg.sender] = _delegate;\n emit DelegateSet(msg.sender, _delegate);\n }\n\n // ========================= Internal =========================\n function _initializable(\n Origin calldata _origin,\n address _receiver,\n uint64 _lazyInboundNonce\n ) internal view returns (bool) {\n return\n _lazyInboundNonce > 0 || // allowInitializePath already checked\n ILayerZeroReceiver(_receiver).allowInitializePath(_origin);\n }\n\n /// @dev bytes(0) payloadHash can never be submitted\n function _verifiable(\n Origin calldata _origin,\n address _receiver,\n uint64 _lazyInboundNonce\n ) internal view returns (bool) {\n return\n _origin.nonce > _lazyInboundNonce || // either initializing an empty slot or reverifying\n inboundPayloadHash[_receiver][_origin.srcEid][_origin.sender][_origin.nonce] != EMPTY_PAYLOAD_HASH; // only allow reverifying if it hasn't been executed\n }\n\n /// @dev assert the caller to either be the oapp or the delegate\n function _assertAuthorized(address _oapp) internal view override(MessagingChannel, MessageLibManager) {\n if (msg.sender != _oapp && msg.sender != delegates[_oapp]) revert Errors.LZ_Unauthorized();\n }\n\n // ========================= VIEW FUNCTIONS FOR OFFCHAIN ONLY =========================\n // Not involved in any state transition function.\n // ====================================================================================\n function initializable(Origin calldata _origin, address _receiver) external view returns (bool) {\n return _initializable(_origin, _receiver, lazyInboundNonce[_receiver][_origin.srcEid][_origin.sender]);\n }\n\n function verifiable(Origin calldata _origin, address _receiver) external view returns (bool) {\n return _verifiable(_origin, _receiver, lazyInboundNonce[_receiver][_origin.srcEid][_origin.sender]);\n }\n}\n"
490
- },
491
- "contracts/EndpointV2Alt.sol": {
492
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { EndpointV2 } from \"./EndpointV2.sol\";\nimport { Errors } from \"./libs/Errors.sol\";\n\n/// @notice this is the endpoint contract for layerzero v2 deployed on chains using ERC20 as native tokens\ncontract EndpointV2Alt is EndpointV2 {\n error LZ_OnlyAltToken();\n\n /// @dev the altFeeToken is used for fees when the native token has no value\n /// @dev it is immutable for gas saving. only 1 endpoint for such chains\n address internal immutable nativeErc20;\n\n constructor(uint32 _eid, address _owner, address _altToken) EndpointV2(_eid, _owner) {\n nativeErc20 = _altToken;\n }\n\n /// @dev handling native token payments on endpoint\n /// @dev internal function\n /// @param _required the amount required\n /// @param _supplied the amount supplied\n /// @param _receiver the receiver of the native token\n /// @param _refundAddress the address to refund the excess to\n function _payNative(\n uint256 _required,\n uint256 _supplied,\n address _receiver,\n address _refundAddress\n ) internal override {\n if (msg.value > 0) revert LZ_OnlyAltToken();\n _payToken(nativeErc20, _required, _supplied, _receiver, _refundAddress);\n }\n\n /// @dev return the balance of the native token\n function _suppliedNative() internal view override returns (uint256) {\n return IERC20(nativeErc20).balanceOf(address(this));\n }\n\n /// @dev check if lzToken is set to the same address\n function setLzToken(address _lzToken) public override onlyOwner {\n if (_lzToken == nativeErc20) revert Errors.LZ_InvalidArgument();\n super.setLzToken(_lzToken);\n }\n\n function nativeToken() external view override returns (address) {\n return nativeErc20;\n }\n}\n"
493
- },
494
- "contracts/EndpointV2View.sol": {
495
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { Proxied } from \"hardhat-deploy/solc_0.8/proxy/Proxied.sol\";\nimport \"./EndpointV2ViewUpgradeable.sol\";\n\ncontract EndpointV2View is EndpointV2ViewUpgradeable, Proxied {\n function initialize(address _endpoint) external proxied initializer {\n __EndpointV2View_init(_endpoint);\n }\n}\n"
496
- },
497
- "contracts/EndpointV2ViewUpgradeable.sol": {
498
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"./interfaces/ILayerZeroEndpointV2.sol\";\n\nenum ExecutionState {\n NotExecutable, // executor: waits for PayloadVerified event and starts polling for executable\n VerifiedButNotExecutable, // executor: starts active polling for executable\n Executable,\n Executed\n}\n\ncontract EndpointV2ViewUpgradeable is Initializable {\n bytes32 public constant EMPTY_PAYLOAD_HASH = bytes32(0);\n bytes32 public constant NIL_PAYLOAD_HASH = bytes32(type(uint256).max);\n\n ILayerZeroEndpointV2 public endpoint;\n\n function __EndpointV2View_init(address _endpoint) internal onlyInitializing {\n __EndpointV2View_init_unchained(_endpoint);\n }\n\n function __EndpointV2View_init_unchained(address _endpoint) internal onlyInitializing {\n endpoint = ILayerZeroEndpointV2(_endpoint);\n }\n\n function initializable(Origin memory _origin, address _receiver) public view returns (bool) {\n try endpoint.initializable(_origin, _receiver) returns (bool _initializable) {\n return _initializable;\n } catch {\n return false;\n }\n }\n\n /// @dev check if a message is verifiable.\n function verifiable(\n Origin memory _origin,\n address _receiver,\n address _receiveLib,\n bytes32 _payloadHash\n ) public view returns (bool) {\n if (!endpoint.isValidReceiveLibrary(_receiver, _origin.srcEid, _receiveLib)) return false;\n\n if (!endpoint.verifiable(_origin, _receiver)) return false;\n\n // checked in _inbound for verify\n if (_payloadHash == EMPTY_PAYLOAD_HASH) return false;\n\n return true;\n }\n\n /// @dev check if a message is executable.\n /// @return ExecutionState of Executed, Executable, or NotExecutable\n function executable(Origin memory _origin, address _receiver) public view returns (ExecutionState) {\n bytes32 payloadHash = endpoint.inboundPayloadHash(_receiver, _origin.srcEid, _origin.sender, _origin.nonce);\n\n // executed if the payload hash has been cleared and the nonce is less than or equal to lazyInboundNonce\n if (\n payloadHash == EMPTY_PAYLOAD_HASH &&\n _origin.nonce <= endpoint.lazyInboundNonce(_receiver, _origin.srcEid, _origin.sender)\n ) {\n return ExecutionState.Executed;\n }\n\n // executable if nonce has not been executed and has not been nilified and nonce is less than or equal to inboundNonce\n if (\n payloadHash != NIL_PAYLOAD_HASH &&\n _origin.nonce <= endpoint.inboundNonce(_receiver, _origin.srcEid, _origin.sender)\n ) {\n return ExecutionState.Executable;\n }\n\n // only start active executable polling if payload hash is not empty nor nil\n if (payloadHash != EMPTY_PAYLOAD_HASH && payloadHash != NIL_PAYLOAD_HASH) {\n return ExecutionState.VerifiedButNotExecutable;\n }\n\n // return NotExecutable as a catch-all\n return ExecutionState.NotExecutable;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n"
499
- },
500
- "contracts/interfaces/ILayerZeroComposer.sol": {
501
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\n/**\n * @title ILayerZeroComposer\n */\ninterface ILayerZeroComposer {\n /**\n * @notice Composes a LayerZero message from an OApp.\n * @dev To ensure non-reentrancy, implementers of this interface MUST assert msg.sender is the corresponding EndpointV2 contract (i.e., onlyEndpointV2).\n * @param _from The address initiating the composition, typically the OApp where the lzReceive was called.\n * @param _guid The unique identifier for the corresponding LayerZero src/dst tx.\n * @param _message The composed message payload in bytes. NOT necessarily the same payload passed via lzReceive.\n * @param _executor The address of the executor for the composed message.\n * @param _extraData Additional arbitrary data in bytes passed by the entity who executes the lzCompose.\n */\n function lzCompose(\n address _from,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) external payable;\n}\n"
502
- },
503
- "contracts/interfaces/ILayerZeroEndpointV2.sol": {
504
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nimport { IMessageLibManager } from \"./IMessageLibManager.sol\";\nimport { IMessagingComposer } from \"./IMessagingComposer.sol\";\nimport { IMessagingChannel } from \"./IMessagingChannel.sol\";\nimport { IMessagingContext } from \"./IMessagingContext.sol\";\n\nstruct MessagingParams {\n uint32 dstEid;\n bytes32 receiver;\n bytes message;\n bytes options;\n bool payInLzToken;\n}\n\nstruct MessagingReceipt {\n bytes32 guid;\n uint64 nonce;\n MessagingFee fee;\n}\n\nstruct MessagingFee {\n uint256 nativeFee;\n uint256 lzTokenFee;\n}\n\nstruct Origin {\n uint32 srcEid;\n bytes32 sender;\n uint64 nonce;\n}\n\ninterface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext {\n event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);\n\n event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);\n\n event PacketDelivered(Origin origin, address receiver);\n\n event LzReceiveAlert(\n address indexed receiver,\n address indexed executor,\n Origin origin,\n bytes32 guid,\n uint256 gas,\n uint256 value,\n bytes message,\n bytes extraData,\n bytes reason\n );\n\n event LzTokenSet(address token);\n\n event DelegateSet(address sender, address delegate);\n\n function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);\n\n function send(\n MessagingParams calldata _params,\n address _refundAddress\n ) external payable returns (MessagingReceipt memory);\n\n function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;\n\n function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);\n\n function initializable(Origin calldata _origin, address _receiver) external view returns (bool);\n\n function lzReceive(\n Origin calldata _origin,\n address _receiver,\n bytes32 _guid,\n bytes calldata _message,\n bytes calldata _extraData\n ) external payable;\n\n // oapp can burn messages partially by calling this function with its own business logic if messages are verified in order\n function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;\n\n function setLzToken(address _lzToken) external;\n\n function lzToken() external view returns (address);\n\n function nativeToken() external view returns (address);\n\n function setDelegate(address _delegate) external;\n}\n"
505
- },
506
- "contracts/interfaces/ILayerZeroReceiver.sol": {
507
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nimport { Origin } from \"./ILayerZeroEndpointV2.sol\";\n\ninterface ILayerZeroReceiver {\n function allowInitializePath(Origin calldata _origin) external view returns (bool);\n\n function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);\n\n function lzReceive(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) external payable;\n}\n"
508
- },
509
- "contracts/interfaces/IMessageLib.sol": {
510
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\nimport { SetConfigParam } from \"./IMessageLibManager.sol\";\n\nenum MessageLibType {\n Send,\n Receive,\n SendAndReceive\n}\n\ninterface IMessageLib is IERC165 {\n function setConfig(address _oapp, SetConfigParam[] calldata _config) external;\n\n function getConfig(uint32 _eid, address _oapp, uint32 _configType) external view returns (bytes memory config);\n\n function isSupportedEid(uint32 _eid) external view returns (bool);\n\n // message libs of same major version are compatible\n function version() external view returns (uint64 major, uint8 minor, uint8 endpointVersion);\n\n function messageLibType() external view returns (MessageLibType);\n}\n"
511
- },
512
- "contracts/interfaces/IMessageLibManager.sol": {
513
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nstruct SetConfigParam {\n uint32 eid;\n uint32 configType;\n bytes config;\n}\n\ninterface IMessageLibManager {\n struct Timeout {\n address lib;\n uint256 expiry;\n }\n\n event LibraryRegistered(address newLib);\n event DefaultSendLibrarySet(uint32 eid, address newLib);\n event DefaultReceiveLibrarySet(uint32 eid, address newLib);\n event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry);\n event SendLibrarySet(address sender, uint32 eid, address newLib);\n event ReceiveLibrarySet(address receiver, uint32 eid, address newLib);\n event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout);\n\n function registerLibrary(address _lib) external;\n\n function isRegisteredLibrary(address _lib) external view returns (bool);\n\n function getRegisteredLibraries() external view returns (address[] memory);\n\n function setDefaultSendLibrary(uint32 _eid, address _newLib) external;\n\n function defaultSendLibrary(uint32 _eid) external view returns (address);\n\n function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _gracePeriod) external;\n\n function defaultReceiveLibrary(uint32 _eid) external view returns (address);\n\n function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external;\n\n function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry);\n\n function isSupportedEid(uint32 _eid) external view returns (bool);\n\n function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool);\n\n /// ------------------- OApp interfaces -------------------\n function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external;\n\n function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib);\n\n function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool);\n\n function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external;\n\n function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault);\n\n function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _expiry) external;\n\n function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry);\n\n function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external;\n\n function getConfig(\n address _oapp,\n address _lib,\n uint32 _eid,\n uint32 _configType\n ) external view returns (bytes memory config);\n}\n"
514
- },
515
- "contracts/interfaces/IMessagingChannel.sol": {
516
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\ninterface IMessagingChannel {\n event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce);\n event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);\n event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash);\n\n function eid() external view returns (uint32);\n\n // this is an emergency function if a message cannot be verified for some reasons\n // required to provide _nextNonce to avoid race condition\n function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external;\n\n function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;\n\n function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external;\n\n function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32);\n\n function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);\n\n function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64);\n\n function inboundPayloadHash(\n address _receiver,\n uint32 _srcEid,\n bytes32 _sender,\n uint64 _nonce\n ) external view returns (bytes32);\n\n function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64);\n}\n"
517
- },
518
- "contracts/interfaces/IMessagingComposer.sol": {
519
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\ninterface IMessagingComposer {\n event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message);\n event ComposeDelivered(address from, address to, bytes32 guid, uint16 index);\n event LzComposeAlert(\n address indexed from,\n address indexed to,\n address indexed executor,\n bytes32 guid,\n uint16 index,\n uint256 gas,\n uint256 value,\n bytes message,\n bytes extraData,\n bytes reason\n );\n\n function composeQueue(\n address _from,\n address _to,\n bytes32 _guid,\n uint16 _index\n ) external view returns (bytes32 messageHash);\n\n function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external;\n\n function lzCompose(\n address _from,\n address _to,\n bytes32 _guid,\n uint16 _index,\n bytes calldata _message,\n bytes calldata _extraData\n ) external payable;\n}\n"
520
- },
521
- "contracts/interfaces/IMessagingContext.sol": {
522
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\ninterface IMessagingContext {\n function isSendingMessage() external view returns (bool);\n\n function getSendContext() external view returns (uint32 dstEid, address sender);\n}\n"
523
- },
524
- "contracts/interfaces/ISendLib.sol": {
525
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nimport { MessagingFee } from \"./ILayerZeroEndpointV2.sol\";\nimport { IMessageLib } from \"./IMessageLib.sol\";\n\nstruct Packet {\n uint64 nonce;\n uint32 srcEid;\n address sender;\n uint32 dstEid;\n bytes32 receiver;\n bytes32 guid;\n bytes message;\n}\n\ninterface ISendLib is IMessageLib {\n function send(\n Packet calldata _packet,\n bytes calldata _options,\n bool _payInLzToken\n ) external returns (MessagingFee memory, bytes memory encodedPacket);\n\n function quote(\n Packet calldata _packet,\n bytes calldata _options,\n bool _payInLzToken\n ) external view returns (MessagingFee memory);\n\n function setTreasury(address _treasury) external;\n\n function withdrawFee(address _to, uint256 _amount) external;\n\n function withdrawLzTokenFee(address _lzToken, address _to, uint256 _amount) external;\n}\n"
526
- },
527
- "contracts/libs/AddressCast.sol": {
528
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nlibrary AddressCast {\n error AddressCast_InvalidSizeForAddress();\n error AddressCast_InvalidAddress();\n\n function toBytes32(bytes calldata _addressBytes) internal pure returns (bytes32 result) {\n if (_addressBytes.length > 32) revert AddressCast_InvalidAddress();\n result = bytes32(_addressBytes);\n unchecked {\n uint256 offset = 32 - _addressBytes.length;\n result = result >> (offset * 8);\n }\n }\n\n function toBytes32(address _address) internal pure returns (bytes32 result) {\n result = bytes32(uint256(uint160(_address)));\n }\n\n function toBytes(bytes32 _addressBytes32, uint256 _size) internal pure returns (bytes memory result) {\n if (_size == 0 || _size > 32) revert AddressCast_InvalidSizeForAddress();\n result = new bytes(_size);\n unchecked {\n uint256 offset = 256 - _size * 8;\n assembly {\n mstore(add(result, 32), shl(offset, _addressBytes32))\n }\n }\n }\n\n function toAddress(bytes32 _addressBytes32) internal pure returns (address result) {\n result = address(uint160(uint256(_addressBytes32)));\n }\n\n function toAddress(bytes calldata _addressBytes) internal pure returns (address result) {\n if (_addressBytes.length != 20) revert AddressCast_InvalidAddress();\n result = address(bytes20(_addressBytes));\n }\n}\n"
529
- },
530
- "contracts/libs/CalldataBytesLib.sol": {
531
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nlibrary CalldataBytesLib {\n function toU8(bytes calldata _bytes, uint256 _start) internal pure returns (uint8) {\n return uint8(_bytes[_start]);\n }\n\n function toU16(bytes calldata _bytes, uint256 _start) internal pure returns (uint16) {\n unchecked {\n uint256 end = _start + 2;\n return uint16(bytes2(_bytes[_start:end]));\n }\n }\n\n function toU32(bytes calldata _bytes, uint256 _start) internal pure returns (uint32) {\n unchecked {\n uint256 end = _start + 4;\n return uint32(bytes4(_bytes[_start:end]));\n }\n }\n\n function toU64(bytes calldata _bytes, uint256 _start) internal pure returns (uint64) {\n unchecked {\n uint256 end = _start + 8;\n return uint64(bytes8(_bytes[_start:end]));\n }\n }\n\n function toU128(bytes calldata _bytes, uint256 _start) internal pure returns (uint128) {\n unchecked {\n uint256 end = _start + 16;\n return uint128(bytes16(_bytes[_start:end]));\n }\n }\n\n function toU256(bytes calldata _bytes, uint256 _start) internal pure returns (uint256) {\n unchecked {\n uint256 end = _start + 32;\n return uint256(bytes32(_bytes[_start:end]));\n }\n }\n\n function toAddr(bytes calldata _bytes, uint256 _start) internal pure returns (address) {\n unchecked {\n uint256 end = _start + 20;\n return address(bytes20(_bytes[_start:end]));\n }\n }\n\n function toB32(bytes calldata _bytes, uint256 _start) internal pure returns (bytes32) {\n unchecked {\n uint256 end = _start + 32;\n return bytes32(_bytes[_start:end]);\n }\n }\n}\n"
532
- },
533
- "contracts/libs/Errors.sol": {
534
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nlibrary Errors {\n error LZ_LzTokenUnavailable();\n error LZ_InvalidReceiveLibrary();\n error LZ_InvalidNonce(uint64 nonce);\n error LZ_InvalidArgument();\n error LZ_InvalidExpiry();\n error LZ_InvalidAmount(uint256 required, uint256 supplied);\n error LZ_OnlyRegisteredOrDefaultLib();\n error LZ_OnlyRegisteredLib();\n error LZ_OnlyNonDefaultLib();\n error LZ_Unauthorized();\n error LZ_DefaultSendLibUnavailable();\n error LZ_DefaultReceiveLibUnavailable();\n error LZ_PathNotInitializable();\n error LZ_PathNotVerifiable();\n error LZ_OnlySendLib();\n error LZ_OnlyReceiveLib();\n error LZ_UnsupportedEid();\n error LZ_UnsupportedInterface();\n error LZ_AlreadyRegistered();\n error LZ_SameValue();\n error LZ_InvalidPayloadHash();\n error LZ_PayloadHashNotFound(bytes32 expected, bytes32 actual);\n error LZ_ComposeNotFound(bytes32 expected, bytes32 actual);\n error LZ_ComposeExists();\n error LZ_SendReentrancy();\n error LZ_NotImplemented();\n error LZ_InsufficientFee(\n uint256 requiredNative,\n uint256 suppliedNative,\n uint256 requiredLzToken,\n uint256 suppliedLzToken\n );\n error LZ_ZeroLzTokenFee();\n}\n"
535
- },
536
- "contracts/libs/GUID.sol": {
537
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { AddressCast } from \"./AddressCast.sol\";\n\nlibrary GUID {\n using AddressCast for address;\n\n function generate(\n uint64 _nonce,\n uint32 _srcEid,\n address _sender,\n uint32 _dstEid,\n bytes32 _receiver\n ) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(_nonce, _srcEid, _sender.toBytes32(), _dstEid, _receiver));\n }\n}\n"
538
- },
539
- "contracts/libs/Transfer.sol": {
540
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary Transfer {\n using SafeERC20 for IERC20;\n\n address internal constant ADDRESS_ZERO = address(0);\n\n error Transfer_NativeFailed(address _to, uint256 _value);\n error Transfer_ToAddressIsZero();\n\n function native(address _to, uint256 _value) internal {\n if (_to == ADDRESS_ZERO) revert Transfer_ToAddressIsZero();\n (bool success, ) = _to.call{ value: _value }(\"\");\n if (!success) revert Transfer_NativeFailed(_to, _value);\n }\n\n function token(address _token, address _to, uint256 _value) internal {\n if (_to == ADDRESS_ZERO) revert Transfer_ToAddressIsZero();\n IERC20(_token).safeTransfer(_to, _value);\n }\n\n function nativeOrToken(address _token, address _to, uint256 _value) internal {\n if (_token == ADDRESS_ZERO) {\n native(_to, _value);\n } else {\n token(_token, _to, _value);\n }\n }\n}\n"
541
- },
542
- "contracts/messagelib/BlockedMessageLib.sol": {
543
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { ERC165 } from \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\nimport { IMessageLib, MessageLibType } from \"../interfaces/IMessageLib.sol\";\nimport { Errors } from \"../libs/Errors.sol\";\n\ncontract BlockedMessageLib is ERC165 {\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\n return interfaceId == type(IMessageLib).interfaceId || super.supportsInterface(interfaceId);\n }\n\n function version() external pure returns (uint64 major, uint8 minor, uint8 endpointVersion) {\n return (type(uint64).max, type(uint8).max, 2);\n }\n\n function messageLibType() external pure returns (MessageLibType) {\n return MessageLibType.SendAndReceive;\n }\n\n function isSupportedEid(uint32) external pure returns (bool) {\n return true;\n }\n\n fallback() external {\n revert Errors.LZ_NotImplemented();\n }\n}\n"
544
- },
545
- "contracts/messagelib/libs/BitMaps.sol": {
546
- "content": "// SPDX-License-Identifier: MIT\n\n// modified from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/structs/BitMaps.sol\npragma solidity ^0.8.20;\n\ntype BitMap256 is uint256;\n\nusing BitMaps for BitMap256 global;\n\nlibrary BitMaps {\n /**\n * @dev Returns whether the bit at `index` is set.\n */\n function get(BitMap256 bitmap, uint8 index) internal pure returns (bool) {\n uint256 mask = 1 << index;\n return BitMap256.unwrap(bitmap) & mask != 0;\n }\n\n /**\n * @dev Sets the bit at `index`.\n */\n function set(BitMap256 bitmap, uint8 index) internal pure returns (BitMap256) {\n uint256 mask = 1 << index;\n return BitMap256.wrap(BitMap256.unwrap(bitmap) | mask);\n }\n}\n"
547
- },
548
- "contracts/messagelib/libs/ExecutorOptions.sol": {
549
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { CalldataBytesLib } from \"../../libs/CalldataBytesLib.sol\";\n\nlibrary ExecutorOptions {\n using CalldataBytesLib for bytes;\n\n uint8 internal constant WORKER_ID = 1;\n\n uint8 internal constant OPTION_TYPE_LZRECEIVE = 1;\n uint8 internal constant OPTION_TYPE_NATIVE_DROP = 2;\n uint8 internal constant OPTION_TYPE_LZCOMPOSE = 3;\n uint8 internal constant OPTION_TYPE_ORDERED_EXECUTION = 4;\n\n error Executor_InvalidLzReceiveOption();\n error Executor_InvalidNativeDropOption();\n error Executor_InvalidLzComposeOption();\n\n /// @dev decode the next executor option from the options starting from the specified cursor\n /// @param _options [executor_id][executor_option][executor_id][executor_option]...\n /// executor_option = [option_size][option_type][option]\n /// option_size = len(option_type) + len(option)\n /// executor_id: uint8, option_size: uint16, option_type: uint8, option: bytes\n /// @param _cursor the cursor to start decoding from\n /// @return optionType the type of the option\n /// @return option the option of the executor\n /// @return cursor the cursor to start decoding the next executor option\n function nextExecutorOption(\n bytes calldata _options,\n uint256 _cursor\n ) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) {\n unchecked {\n // skip worker id\n cursor = _cursor + 1;\n\n // read option size\n uint16 size = _options.toU16(cursor);\n cursor += 2;\n\n // read option type\n optionType = _options.toU8(cursor);\n\n // startCursor and endCursor are used to slice the option from _options\n uint256 startCursor = cursor + 1; // skip option type\n uint256 endCursor = cursor + size;\n option = _options[startCursor:endCursor];\n cursor += size;\n }\n }\n\n function decodeLzReceiveOption(bytes calldata _option) internal pure returns (uint128 gas, uint128 value) {\n if (_option.length != 16 && _option.length != 32) revert Executor_InvalidLzReceiveOption();\n gas = _option.toU128(0);\n value = _option.length == 32 ? _option.toU128(16) : 0;\n }\n\n function decodeNativeDropOption(bytes calldata _option) internal pure returns (uint128 amount, bytes32 receiver) {\n if (_option.length != 48) revert Executor_InvalidNativeDropOption();\n amount = _option.toU128(0);\n receiver = _option.toB32(16);\n }\n\n function decodeLzComposeOption(\n bytes calldata _option\n ) internal pure returns (uint16 index, uint128 gas, uint128 value) {\n if (_option.length != 18 && _option.length != 34) revert Executor_InvalidLzComposeOption();\n index = _option.toU16(0);\n gas = _option.toU128(2);\n value = _option.length == 34 ? _option.toU128(18) : 0;\n }\n\n function encodeLzReceiveOption(uint128 _gas, uint128 _value) internal pure returns (bytes memory) {\n return _value == 0 ? abi.encodePacked(_gas) : abi.encodePacked(_gas, _value);\n }\n\n function encodeNativeDropOption(uint128 _amount, bytes32 _receiver) internal pure returns (bytes memory) {\n return abi.encodePacked(_amount, _receiver);\n }\n\n function encodeLzComposeOption(uint16 _index, uint128 _gas, uint128 _value) internal pure returns (bytes memory) {\n return _value == 0 ? abi.encodePacked(_index, _gas) : abi.encodePacked(_index, _gas, _value);\n }\n}\n"
550
- },
551
- "contracts/messagelib/libs/PacketV1Codec.sol": {
552
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { Packet } from \"../../interfaces/ISendLib.sol\";\nimport { AddressCast } from \"../../libs/AddressCast.sol\";\n\nlibrary PacketV1Codec {\n using AddressCast for address;\n using AddressCast for bytes32;\n\n uint8 internal constant PACKET_VERSION = 1;\n\n // header (version + nonce + path)\n // version\n uint256 private constant PACKET_VERSION_OFFSET = 0;\n // nonce\n uint256 private constant NONCE_OFFSET = 1;\n // path\n uint256 private constant SRC_EID_OFFSET = 9;\n uint256 private constant SENDER_OFFSET = 13;\n uint256 private constant DST_EID_OFFSET = 45;\n uint256 private constant RECEIVER_OFFSET = 49;\n // payload (guid + message)\n uint256 private constant GUID_OFFSET = 81; // keccak256(nonce + path)\n uint256 private constant MESSAGE_OFFSET = 113;\n\n function encode(Packet memory _packet) internal pure returns (bytes memory encodedPacket) {\n encodedPacket = abi.encodePacked(\n PACKET_VERSION,\n _packet.nonce,\n _packet.srcEid,\n _packet.sender.toBytes32(),\n _packet.dstEid,\n _packet.receiver,\n _packet.guid,\n _packet.message\n );\n }\n\n function encodePacketHeader(Packet memory _packet) internal pure returns (bytes memory) {\n return\n abi.encodePacked(\n PACKET_VERSION,\n _packet.nonce,\n _packet.srcEid,\n _packet.sender.toBytes32(),\n _packet.dstEid,\n _packet.receiver\n );\n }\n\n function encodePayload(Packet memory _packet) internal pure returns (bytes memory) {\n return abi.encodePacked(_packet.guid, _packet.message);\n }\n\n function header(bytes calldata _packet) internal pure returns (bytes calldata) {\n return _packet[0:GUID_OFFSET];\n }\n\n function version(bytes calldata _packet) internal pure returns (uint8) {\n return uint8(bytes1(_packet[PACKET_VERSION_OFFSET:NONCE_OFFSET]));\n }\n\n function nonce(bytes calldata _packet) internal pure returns (uint64) {\n return uint64(bytes8(_packet[NONCE_OFFSET:SRC_EID_OFFSET]));\n }\n\n function srcEid(bytes calldata _packet) internal pure returns (uint32) {\n return uint32(bytes4(_packet[SRC_EID_OFFSET:SENDER_OFFSET]));\n }\n\n function sender(bytes calldata _packet) internal pure returns (bytes32) {\n return bytes32(_packet[SENDER_OFFSET:DST_EID_OFFSET]);\n }\n\n function senderAddressB20(bytes calldata _packet) internal pure returns (address) {\n return sender(_packet).toAddress();\n }\n\n function dstEid(bytes calldata _packet) internal pure returns (uint32) {\n return uint32(bytes4(_packet[DST_EID_OFFSET:RECEIVER_OFFSET]));\n }\n\n function receiver(bytes calldata _packet) internal pure returns (bytes32) {\n return bytes32(_packet[RECEIVER_OFFSET:GUID_OFFSET]);\n }\n\n function receiverB20(bytes calldata _packet) internal pure returns (address) {\n return receiver(_packet).toAddress();\n }\n\n function guid(bytes calldata _packet) internal pure returns (bytes32) {\n return bytes32(_packet[GUID_OFFSET:MESSAGE_OFFSET]);\n }\n\n function message(bytes calldata _packet) internal pure returns (bytes calldata) {\n return bytes(_packet[MESSAGE_OFFSET:]);\n }\n\n function payload(bytes calldata _packet) internal pure returns (bytes calldata) {\n return bytes(_packet[GUID_OFFSET:]);\n }\n\n function payloadHash(bytes calldata _packet) internal pure returns (bytes32) {\n return keccak256(payload(_packet));\n }\n}\n"
553
- },
554
- "contracts/messagelib/SimpleMessageLib.sol": {
555
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { ERC165 } from \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport { IMessageLib, MessageLibType } from \"../interfaces/IMessageLib.sol\";\nimport { Packet } from \"../interfaces/ISendLib.sol\";\nimport { ILayerZeroEndpointV2, MessagingFee, Origin } from \"../interfaces/ILayerZeroEndpointV2.sol\";\nimport { Errors } from \"../libs/Errors.sol\";\nimport { PacketV1Codec } from \"./libs/PacketV1Codec.sol\";\nimport { Transfer } from \"../libs/Transfer.sol\";\n\ncontract SimpleMessageLib is Ownable, ERC165 {\n using SafeERC20 for IERC20;\n using PacketV1Codec for bytes;\n\n address public immutable endpoint;\n address public immutable treasury;\n uint32 public immutable localEid;\n uint8 public constant PACKET_VERSION = 1;\n\n address public whitelistCaller;\n\n uint256 public lzTokenFee;\n uint256 public nativeFee;\n\n bytes public defaultOption;\n\n error OnlyEndpoint();\n error OnlyWhitelistCaller();\n error InvalidEndpoint(address expected, address actual);\n error ToIsAddressZero();\n error LzTokenIsAddressZero();\n error TransferFailed();\n\n // only the endpoint can call SEND() and setConfig()\n modifier onlyEndpoint() {\n if (endpoint != msg.sender) {\n revert OnlyEndpoint();\n }\n _;\n }\n\n constructor(address _endpoint, address _treasury) {\n endpoint = _endpoint;\n treasury = _treasury;\n localEid = ILayerZeroEndpointV2(_endpoint).eid();\n lzTokenFee = 99;\n nativeFee = 100;\n // defaultOption = Options.encodeLegacyOptionsType1(200000);\n }\n\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\n return interfaceId == type(IMessageLib).interfaceId || super.supportsInterface(interfaceId);\n }\n\n // no validation logic at all\n function validatePacket(bytes calldata packetBytes) external {\n if (whitelistCaller != address(0x0) && msg.sender != whitelistCaller) {\n revert OnlyWhitelistCaller();\n }\n Origin memory origin = Origin(packetBytes.srcEid(), packetBytes.sender(), packetBytes.nonce());\n ILayerZeroEndpointV2(endpoint).verify(origin, packetBytes.receiverB20(), keccak256(packetBytes.payload()));\n }\n\n // ------------------ onlyEndpoint ------------------\n function send(\n Packet calldata _packet,\n bytes memory _options,\n bool _payInLzToken\n ) external onlyEndpoint returns (MessagingFee memory fee, bytes memory encodedPacket, bytes memory options) {\n encodedPacket = PacketV1Codec.encode(_packet);\n\n options = _options.length == 0 ? defaultOption : _options;\n _handleMessagingParamsHook(encodedPacket, options);\n\n fee = MessagingFee(nativeFee, _payInLzToken ? lzTokenFee : 0);\n }\n\n // ------------------ onlyOwner ------------------\n function setDefaultOption(bytes memory _defaultOption) external onlyOwner {\n defaultOption = _defaultOption;\n }\n\n function setMessagingFee(uint256 _nativeFee, uint256 _lzTokenFee) external onlyOwner {\n nativeFee = _nativeFee;\n lzTokenFee = _lzTokenFee;\n }\n\n function setWhitelistCaller(address _whitelistCaller) external onlyOwner {\n whitelistCaller = _whitelistCaller;\n }\n\n function withdrawFee(address _to, uint256 _amount) external onlyOwner {\n if (_to == address(0x0)) {\n revert ToIsAddressZero();\n }\n\n address altTokenAddr = ILayerZeroEndpointV2(endpoint).nativeToken();\n\n // transfers native if altTokenAddr == address(0x0)\n Transfer.nativeOrToken(altTokenAddr, _to, _amount);\n }\n\n function withdrawLzTokenFee(address _to, uint256 _amount) external onlyOwner {\n if (_to == address(0x0)) {\n revert ToIsAddressZero();\n }\n address lzToken = ILayerZeroEndpointV2(endpoint).lzToken();\n if (lzToken == address(0x0)) {\n revert LzTokenIsAddressZero();\n }\n IERC20(lzToken).safeTransfer(_to, _amount);\n }\n\n // ------------------ View ------------------\n function quote(\n Packet calldata /*_packet*/,\n bytes calldata /*_options*/,\n bool _payInLzToken\n ) external view returns (MessagingFee memory) {\n return MessagingFee(nativeFee, _payInLzToken ? lzTokenFee : 0);\n }\n\n function isSupportedEid(uint32) external pure returns (bool) {\n return true;\n }\n\n function version() external pure returns (uint64 major, uint8 minor, uint8 endpointVersion) {\n return (0, 0, 2);\n }\n\n function messageLibType() external pure returns (MessageLibType) {\n return MessageLibType.SendAndReceive;\n }\n\n // ------------------ Internal ------------------\n function _handleMessagingParamsHook(bytes memory _encodedPacket, bytes memory _options) internal virtual {}\n\n fallback() external payable {\n revert Errors.LZ_NotImplemented();\n }\n\n receive() external payable {}\n}\n"
556
- },
557
- "contracts/MessageLibManager.sol": {
558
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport { IMessageLib, MessageLibType } from \"./interfaces/IMessageLib.sol\";\nimport { IMessageLibManager, SetConfigParam } from \"./interfaces/IMessageLibManager.sol\";\nimport { Errors } from \"./libs/Errors.sol\";\nimport { BlockedMessageLib } from \"./messagelib/BlockedMessageLib.sol\";\n\nabstract contract MessageLibManager is Ownable, IMessageLibManager {\n address private constant DEFAULT_LIB = address(0);\n\n // the library that reverts both on send and quote\n // must be configured on construction and be immutable\n address public immutable blockedLibrary;\n\n // only registered libraries all valid libraries\n // the blockedLibrary will be registered on construction\n address[] internal registeredLibraries;\n mapping(address lib => bool) public isRegisteredLibrary;\n\n // both sendLibrary and receiveLibrary config can be lazily resolved\n mapping(address sender => mapping(uint32 dstEid => address lib)) internal sendLibrary;\n mapping(address receiver => mapping(uint32 srcEid => address lib)) internal receiveLibrary;\n mapping(address receiver => mapping(uint32 srcEid => Timeout)) public receiveLibraryTimeout;\n\n mapping(uint32 dstEid => address lib) public defaultSendLibrary;\n mapping(uint32 srcEid => address lib) public defaultReceiveLibrary;\n mapping(uint32 srcEid => Timeout) public defaultReceiveLibraryTimeout;\n\n constructor() {\n blockedLibrary = address(new BlockedMessageLib());\n registerLibrary(blockedLibrary);\n }\n\n modifier onlyRegistered(address _lib) {\n if (!isRegisteredLibrary[_lib]) revert Errors.LZ_OnlyRegisteredLib();\n _;\n }\n\n modifier isSendLib(address _lib) {\n if (_lib != DEFAULT_LIB) {\n if (IMessageLib(_lib).messageLibType() == MessageLibType.Receive) revert Errors.LZ_OnlySendLib();\n }\n _;\n }\n\n modifier isReceiveLib(address _lib) {\n if (_lib != DEFAULT_LIB) {\n if (IMessageLib(_lib).messageLibType() == MessageLibType.Send) revert Errors.LZ_OnlyReceiveLib();\n }\n _;\n }\n\n modifier onlyRegisteredOrDefault(address _lib) {\n if (!isRegisteredLibrary[_lib] && _lib != DEFAULT_LIB) revert Errors.LZ_OnlyRegisteredOrDefaultLib();\n _;\n }\n\n /// @dev check if the library supported the eid.\n modifier onlySupportedEid(address _lib, uint32 _eid) {\n /// @dev doesnt need to check for default lib, because when they are initially added they get passed through this modifier\n if (_lib != DEFAULT_LIB) {\n if (!IMessageLib(_lib).isSupportedEid(_eid)) revert Errors.LZ_UnsupportedEid();\n }\n _;\n }\n\n function getRegisteredLibraries() external view returns (address[] memory) {\n return registeredLibraries;\n }\n\n /// @notice The Send Library is the Oapp specified library that will be used to send the message to the destination\n /// endpoint. If the Oapp does not specify a Send Library, the default Send Library will be used.\n /// @dev If the Oapp does not have a selected Send Library, this function will resolve to the default library\n /// configured by LayerZero\n /// @return lib address of the Send Library\n /// @param _sender The address of the Oapp that is sending the message\n /// @param _dstEid The destination endpoint id\n function getSendLibrary(address _sender, uint32 _dstEid) public view returns (address lib) {\n lib = sendLibrary[_sender][_dstEid];\n if (lib == DEFAULT_LIB) {\n lib = defaultSendLibrary[_dstEid];\n if (lib == address(0x0)) revert Errors.LZ_DefaultSendLibUnavailable();\n }\n }\n\n function isDefaultSendLibrary(address _sender, uint32 _dstEid) public view returns (bool) {\n return sendLibrary[_sender][_dstEid] == DEFAULT_LIB;\n }\n\n /// @dev the receiveLibrary can be lazily resolved that if not set it will point to the default configured by LayerZero\n function getReceiveLibrary(address _receiver, uint32 _srcEid) public view returns (address lib, bool isDefault) {\n lib = receiveLibrary[_receiver][_srcEid];\n if (lib == DEFAULT_LIB) {\n lib = defaultReceiveLibrary[_srcEid];\n if (lib == address(0x0)) revert Errors.LZ_DefaultReceiveLibUnavailable();\n isDefault = true;\n }\n }\n\n /// @dev called when the endpoint checks if the msgLib attempting to verify the msg is the configured msgLib of the Oapp\n /// @dev this check provides the ability for Oapp to lock in a trusted msgLib\n /// @dev it will fist check if the msgLib is the currently configured one. then check if the msgLib is the one in grace period of msgLib versioning upgrade\n function isValidReceiveLibrary(\n address _receiver,\n uint32 _srcEid,\n address _actualReceiveLib\n ) public view returns (bool) {\n // early return true if the _actualReceiveLib is the currently configured one\n (address expectedReceiveLib, bool isDefault) = getReceiveLibrary(_receiver, _srcEid);\n if (_actualReceiveLib == expectedReceiveLib) {\n return true;\n }\n\n // check the timeout condition otherwise\n // if the Oapp is using defaultReceiveLibrary, use the default Timeout config\n // otherwise, use the Timeout configured by the Oapp\n Timeout memory timeout = isDefault\n ? defaultReceiveLibraryTimeout[_srcEid]\n : receiveLibraryTimeout[_receiver][_srcEid];\n\n // requires the _actualReceiveLib to be the same as the one in grace period and the grace period has not expired\n // block.number is uint256 so timeout.expiry must > 0, which implies a non-ZERO value\n if (timeout.lib == _actualReceiveLib && timeout.expiry > block.number) {\n // timeout lib set and has not expired\n return true;\n }\n\n // returns false by default\n return false;\n }\n\n //------- Owner interfaces\n /// @dev all libraries have to implement the erc165 interface to prevent wrong configurations\n /// @dev only owner\n function registerLibrary(address _lib) public onlyOwner {\n // must have the right interface\n if (!IERC165(_lib).supportsInterface(type(IMessageLib).interfaceId)) revert Errors.LZ_UnsupportedInterface();\n // must have not been registered\n if (isRegisteredLibrary[_lib]) revert Errors.LZ_AlreadyRegistered();\n\n // insert into both the map and the list\n isRegisteredLibrary[_lib] = true;\n registeredLibraries.push(_lib);\n\n emit LibraryRegistered(_lib);\n }\n\n /// @dev owner setting the defaultSendLibrary\n /// @dev can set to the blockedLibrary, which is a registered library\n /// @dev the msgLib must enable the support before they can be registered to the endpoint as the default\n /// @dev only owner\n function setDefaultSendLibrary(\n uint32 _eid,\n address _newLib\n ) external onlyOwner onlyRegistered(_newLib) isSendLib(_newLib) onlySupportedEid(_newLib, _eid) {\n // must provide a different value\n if (defaultSendLibrary[_eid] == _newLib) revert Errors.LZ_SameValue();\n defaultSendLibrary[_eid] = _newLib;\n emit DefaultSendLibrarySet(_eid, _newLib);\n }\n\n /// @dev owner setting the defaultSendLibrary\n /// @dev must be a registered library (including blockLibrary) with the eid support enabled\n /// @dev in version migration, it can add a grace period to the old library. if the grace period is 0, it will delete the timeout configuration.\n /// @dev only owner\n function setDefaultReceiveLibrary(\n uint32 _eid,\n address _newLib,\n uint256 _gracePeriod\n ) external onlyOwner onlyRegistered(_newLib) isReceiveLib(_newLib) onlySupportedEid(_newLib, _eid) {\n address oldLib = defaultReceiveLibrary[_eid];\n // must provide a different value\n if (oldLib == _newLib) revert Errors.LZ_SameValue();\n\n defaultReceiveLibrary[_eid] = _newLib;\n emit DefaultReceiveLibrarySet(_eid, _newLib);\n\n if (_gracePeriod > 0) {\n // override the current default timeout to the [old_lib + new expiry]\n Timeout storage timeout = defaultReceiveLibraryTimeout[_eid];\n timeout.lib = oldLib;\n timeout.expiry = block.number + _gracePeriod;\n emit DefaultReceiveLibraryTimeoutSet(_eid, oldLib, timeout.expiry);\n } else {\n // otherwise, remove the old configuration.\n delete defaultReceiveLibraryTimeout[_eid];\n emit DefaultReceiveLibraryTimeoutSet(_eid, oldLib, 0);\n }\n }\n\n /// @dev owner setting the defaultSendLibrary\n /// @dev must be a registered library (including blockLibrary) with the eid support enabled\n /// @dev can used to (1) extend the current configuration (2) force remove the current configuration (3) change to a new configuration\n /// @param _expiry the block number when lib expires\n function setDefaultReceiveLibraryTimeout(\n uint32 _eid,\n address _lib,\n uint256 _expiry\n ) external onlyRegistered(_lib) isReceiveLib(_lib) onlySupportedEid(_lib, _eid) onlyOwner {\n if (_expiry == 0) {\n // force remove the current configuration\n delete defaultReceiveLibraryTimeout[_eid];\n } else {\n // override it with new configuration\n if (_expiry <= block.number) revert Errors.LZ_InvalidExpiry();\n Timeout storage timeout = defaultReceiveLibraryTimeout[_eid];\n timeout.lib = _lib;\n timeout.expiry = _expiry;\n }\n emit DefaultReceiveLibraryTimeoutSet(_eid, _lib, _expiry);\n }\n\n /// @dev returns true only if both the default send/receive libraries are set\n function isSupportedEid(uint32 _eid) external view returns (bool) {\n return defaultSendLibrary[_eid] != address(0) && defaultReceiveLibrary[_eid] != address(0);\n }\n\n //------- OApp interfaces\n /// @dev Oapp setting the sendLibrary\n /// @dev must be a registered library (including blockLibrary) with the eid support enabled\n /// @dev authenticated by the Oapp\n function setSendLibrary(\n address _oapp,\n uint32 _eid,\n address _newLib\n ) external onlyRegisteredOrDefault(_newLib) isSendLib(_newLib) onlySupportedEid(_newLib, _eid) {\n _assertAuthorized(_oapp);\n\n // must provide a different value\n if (sendLibrary[_oapp][_eid] == _newLib) revert Errors.LZ_SameValue();\n sendLibrary[_oapp][_eid] = _newLib;\n emit SendLibrarySet(_oapp, _eid, _newLib);\n }\n\n /// @dev Oapp setting the receiveLibrary\n /// @dev must be a registered library (including blockLibrary) with the eid support enabled\n /// @dev in version migration, it can add a grace period to the old library. if the grace period is 0, it will delete the timeout configuration.\n /// @dev authenticated by the Oapp\n /// @param _gracePeriod the number of blocks from now until oldLib expires\n function setReceiveLibrary(\n address _oapp,\n uint32 _eid,\n address _newLib,\n uint256 _gracePeriod\n ) external onlyRegisteredOrDefault(_newLib) isReceiveLib(_newLib) onlySupportedEid(_newLib, _eid) {\n _assertAuthorized(_oapp);\n\n address oldLib = receiveLibrary[_oapp][_eid];\n // must provide new values\n if (oldLib == _newLib) revert Errors.LZ_SameValue();\n receiveLibrary[_oapp][_eid] = _newLib;\n emit ReceiveLibrarySet(_oapp, _eid, _newLib);\n\n if (_gracePeriod > 0) {\n // to simplify the logic, we only allow to set timeout if neither the new lib nor old lib is DEFAULT_LIB, which would should read the default timeout configurations\n // (1) if the Oapp wants to fall back to the DEFAULT, then set the newLib to DEFAULT with grace period == 0\n // (2) if the Oapp wants to change to a non DEFAULT from DEFAULT, then set the newLib to 'non-default' with _gracePeriod == 0, then use setReceiveLibraryTimeout() interface\n if (oldLib == DEFAULT_LIB || _newLib == DEFAULT_LIB) revert Errors.LZ_OnlyNonDefaultLib();\n\n // write to storage\n Timeout memory timeout = Timeout({ lib: oldLib, expiry: block.number + _gracePeriod });\n receiveLibraryTimeout[_oapp][_eid] = timeout;\n emit ReceiveLibraryTimeoutSet(_oapp, _eid, oldLib, timeout.expiry);\n } else {\n delete receiveLibraryTimeout[_oapp][_eid];\n emit ReceiveLibraryTimeoutSet(_oapp, _eid, oldLib, 0);\n }\n }\n\n /// @dev Oapp setting the defaultSendLibrary\n /// @dev must be a registered library (including blockLibrary) with the eid support enabled\n /// @dev can used to (1) extend the current configuration (2) force remove the current configuration (3) change to a new configuration\n /// @param _expiry the block number when lib expires\n function setReceiveLibraryTimeout(\n address _oapp,\n uint32 _eid,\n address _lib,\n uint256 _expiry\n ) external onlyRegistered(_lib) isReceiveLib(_lib) onlySupportedEid(_lib, _eid) {\n _assertAuthorized(_oapp);\n\n (, bool isDefault) = getReceiveLibrary(_oapp, _eid);\n // if current library is DEFAULT, Oapp cant set the timeout\n if (isDefault) revert Errors.LZ_OnlyNonDefaultLib();\n\n if (_expiry == 0) {\n // force remove the current configuration\n delete receiveLibraryTimeout[_oapp][_eid];\n } else {\n // override it with new configuration\n if (_expiry <= block.number) revert Errors.LZ_InvalidExpiry();\n Timeout storage timeout = receiveLibraryTimeout[_oapp][_eid];\n timeout.lib = _lib;\n timeout.expiry = _expiry;\n }\n emit ReceiveLibraryTimeoutSet(_oapp, _eid, _lib, _expiry);\n }\n\n //------- library config setter/getter. all pass-through functions to the msgLib\n\n /// @dev authenticated by the _oapp\n function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external onlyRegistered(_lib) {\n _assertAuthorized(_oapp);\n\n IMessageLib(_lib).setConfig(_oapp, _params);\n }\n\n /// @dev a view function to query the current configuration of the OApp\n function getConfig(\n address _oapp,\n address _lib,\n uint32 _eid,\n uint32 _configType\n ) external view onlyRegistered(_lib) returns (bytes memory config) {\n return IMessageLib(_lib).getConfig(_eid, _oapp, _configType);\n }\n\n function _assertAuthorized(address _oapp) internal virtual;\n}\n"
559
- },
560
- "contracts/MessagingChannel.sol": {
561
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { IMessagingChannel } from \"./interfaces/IMessagingChannel.sol\";\nimport { Errors } from \"./libs/Errors.sol\";\nimport { GUID } from \"./libs/GUID.sol\";\n\nabstract contract MessagingChannel is IMessagingChannel {\n bytes32 public constant EMPTY_PAYLOAD_HASH = bytes32(0);\n bytes32 public constant NIL_PAYLOAD_HASH = bytes32(type(uint256).max);\n\n // The universally unique id (UUID) of this deployed Endpoint\n uint32 public immutable eid;\n\n mapping(address receiver => mapping(uint32 srcEid => mapping(bytes32 sender => uint64 nonce)))\n public lazyInboundNonce;\n mapping(address receiver => mapping(uint32 srcEid => mapping(bytes32 sender => mapping(uint64 inboundNonce => bytes32 payloadHash))))\n public inboundPayloadHash;\n mapping(address sender => mapping(uint32 dstEid => mapping(bytes32 receiver => uint64 nonce))) public outboundNonce;\n\n /// @param _eid is the universally unique id (UUID) of this deployed Endpoint\n constructor(uint32 _eid) {\n eid = _eid;\n }\n\n /// @dev increase and return the next outbound nonce\n function _outbound(address _sender, uint32 _dstEid, bytes32 _receiver) internal returns (uint64 nonce) {\n unchecked {\n nonce = ++outboundNonce[_sender][_dstEid][_receiver];\n }\n }\n\n /// @dev inbound won't update the nonce eagerly to allow unordered verification\n /// @dev instead, it will update the nonce lazily when the message is received\n /// @dev messages can only be cleared in order to preserve censorship-resistance\n function _inbound(\n address _receiver,\n uint32 _srcEid,\n bytes32 _sender,\n uint64 _nonce,\n bytes32 _payloadHash\n ) internal {\n if (_payloadHash == EMPTY_PAYLOAD_HASH) revert Errors.LZ_InvalidPayloadHash();\n inboundPayloadHash[_receiver][_srcEid][_sender][_nonce] = _payloadHash;\n }\n\n /// @dev returns the max index of the longest gapless sequence of verified msg nonces.\n /// @dev the uninitialized value is 0. the first nonce is always 1\n /// @dev it starts from the lazyInboundNonce (last checkpoint) and iteratively check if the next nonce has been verified\n /// @dev this function can OOG if too many backlogs, but it can be trivially fixed by just clearing some prior messages\n /// @dev NOTE: Oapp explicitly skipped nonces count as \"verified\" for these purposes\n /// @dev eg. [1,2,3,4,6,7] => 4, [1,2,6,8,10] => 2, [1,3,4,5,6] => 1\n function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) public view returns (uint64) {\n uint64 nonceCursor = lazyInboundNonce[_receiver][_srcEid][_sender];\n\n // find the effective inbound currentNonce\n unchecked {\n while (_hasPayloadHash(_receiver, _srcEid, _sender, nonceCursor + 1)) {\n ++nonceCursor;\n }\n }\n return nonceCursor;\n }\n\n /// @dev checks if the storage slot is not initialized. Assumes computationally infeasible that payload can hash to 0\n function _hasPayloadHash(\n address _receiver,\n uint32 _srcEid,\n bytes32 _sender,\n uint64 _nonce\n ) internal view returns (bool) {\n return inboundPayloadHash[_receiver][_srcEid][_sender][_nonce] != EMPTY_PAYLOAD_HASH;\n }\n\n /// @dev the caller must provide _nonce to prevent skipping the unintended nonce\n /// @dev it could happen in some race conditions, e.g. to skip nonce 3, but nonce 3 was consumed first\n /// @dev usage: skipping the next nonce to prevent message verification, e.g. skip a message when Precrime throws alerts\n /// @dev if the Oapp wants to skip a verified message, it should call the clear() function instead\n /// @dev after skipping, the lazyInboundNonce is set to the provided nonce, which makes the inboundNonce also the provided nonce\n /// @dev ie. allows the Oapp to increment the lazyInboundNonce without having had that corresponding msg be verified\n function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external {\n _assertAuthorized(_oapp);\n\n if (_nonce != inboundNonce(_oapp, _srcEid, _sender) + 1) revert Errors.LZ_InvalidNonce(_nonce);\n lazyInboundNonce[_oapp][_srcEid][_sender] = _nonce;\n emit InboundNonceSkipped(_srcEid, _sender, _oapp, _nonce);\n }\n\n /// @dev Marks a packet as verified, but disallows execution until it is re-verified.\n /// @dev Reverts if the provided _payloadHash does not match the currently verified payload hash.\n /// @dev A non-verified nonce can be nilified by passing EMPTY_PAYLOAD_HASH for _payloadHash.\n /// @dev Assumes the computational intractability of finding a payload that hashes to bytes32.max.\n /// @dev Authenticated by the caller\n function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external {\n _assertAuthorized(_oapp);\n\n bytes32 curPayloadHash = inboundPayloadHash[_oapp][_srcEid][_sender][_nonce];\n if (curPayloadHash != _payloadHash) revert Errors.LZ_PayloadHashNotFound(curPayloadHash, _payloadHash);\n if (_nonce <= lazyInboundNonce[_oapp][_srcEid][_sender] && curPayloadHash == EMPTY_PAYLOAD_HASH)\n revert Errors.LZ_InvalidNonce(_nonce);\n // set it to nil\n inboundPayloadHash[_oapp][_srcEid][_sender][_nonce] = NIL_PAYLOAD_HASH;\n emit PacketNilified(_srcEid, _sender, _oapp, _nonce, _payloadHash);\n }\n\n /// @dev Marks a nonce as unexecutable and un-verifiable. The nonce can never be re-verified or executed.\n /// @dev Reverts if the provided _payloadHash does not match the currently verified payload hash.\n /// @dev Only packets with nonces less than or equal to the lazy inbound nonce can be burned.\n /// @dev Reverts if the nonce has already been executed.\n /// @dev Authenticated by the caller\n function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external {\n _assertAuthorized(_oapp);\n\n bytes32 curPayloadHash = inboundPayloadHash[_oapp][_srcEid][_sender][_nonce];\n if (curPayloadHash != _payloadHash) revert Errors.LZ_PayloadHashNotFound(curPayloadHash, _payloadHash);\n if (curPayloadHash == EMPTY_PAYLOAD_HASH || _nonce > lazyInboundNonce[_oapp][_srcEid][_sender])\n revert Errors.LZ_InvalidNonce(_nonce);\n delete inboundPayloadHash[_oapp][_srcEid][_sender][_nonce];\n emit PacketBurnt(_srcEid, _sender, _oapp, _nonce, _payloadHash);\n }\n\n /// @dev calling this function will clear the stored message and increment the lazyInboundNonce to the provided nonce\n /// @dev if a lot of messages are queued, the messages can be cleared with a smaller step size to prevent OOG\n /// @dev NOTE: this function does not change inboundNonce, it only changes the lazyInboundNonce up to the provided nonce\n function _clearPayload(\n address _receiver,\n uint32 _srcEid,\n bytes32 _sender,\n uint64 _nonce,\n bytes memory _payload\n ) internal returns (bytes32 actualHash) {\n uint64 currentNonce = lazyInboundNonce[_receiver][_srcEid][_sender];\n if (_nonce > currentNonce) {\n unchecked {\n // try to lazily update the inboundNonce till the _nonce\n for (uint64 i = currentNonce + 1; i <= _nonce; ++i) {\n if (!_hasPayloadHash(_receiver, _srcEid, _sender, i)) revert Errors.LZ_InvalidNonce(i);\n }\n lazyInboundNonce[_receiver][_srcEid][_sender] = _nonce;\n }\n }\n\n // check the hash of the payload to verify the executor has given the proper payload that has been verified\n actualHash = keccak256(_payload);\n bytes32 expectedHash = inboundPayloadHash[_receiver][_srcEid][_sender][_nonce];\n if (expectedHash != actualHash) revert Errors.LZ_PayloadHashNotFound(expectedHash, actualHash);\n\n // remove it from the storage\n delete inboundPayloadHash[_receiver][_srcEid][_sender][_nonce];\n }\n\n /// @dev returns the GUID for the next message given the path\n /// @dev the Oapp might want to include the GUID into the message in some cases\n function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32) {\n uint64 nextNonce = outboundNonce[_sender][_dstEid][_receiver] + 1;\n return GUID.generate(nextNonce, eid, _sender, _dstEid, _receiver);\n }\n\n function _assertAuthorized(address _oapp) internal virtual;\n}\n"
562
- },
563
- "contracts/MessagingComposer.sol": {
564
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { IMessagingComposer } from \"./interfaces/IMessagingComposer.sol\";\nimport { ILayerZeroComposer } from \"./interfaces/ILayerZeroComposer.sol\";\nimport { Errors } from \"./libs/Errors.sol\";\n\nabstract contract MessagingComposer is IMessagingComposer {\n bytes32 private constant NO_MESSAGE_HASH = bytes32(0);\n bytes32 private constant RECEIVED_MESSAGE_HASH = bytes32(uint256(1));\n\n mapping(address from => mapping(address to => mapping(bytes32 guid => mapping(uint16 index => bytes32 messageHash))))\n public composeQueue;\n\n /// @dev the Oapp sends the lzCompose message to the endpoint\n /// @dev the composer MUST assert the sender because anyone can send compose msg with this function\n /// @dev with the same GUID, the Oapp can send compose to multiple _composer at the same time\n /// @dev authenticated by the msg.sender\n /// @param _to the address which will receive the composed message\n /// @param _guid the message guid\n /// @param _message the message\n function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external {\n // must have not been sent before\n if (composeQueue[msg.sender][_to][_guid][_index] != NO_MESSAGE_HASH) revert Errors.LZ_ComposeExists();\n composeQueue[msg.sender][_to][_guid][_index] = keccak256(_message);\n emit ComposeSent(msg.sender, _to, _guid, _index, _message);\n }\n\n /// @dev execute a composed messages from the sender to the composer (receiver)\n /// @dev the execution provides the execution context (caller, extraData) to the receiver.\n /// the receiver can optionally assert the caller and validate the untrusted extraData\n /// @dev can not re-entrant\n /// @param _from the address which sends the composed message. in most cases, it is the Oapp's address.\n /// @param _to the address which receives the composed message\n /// @param _guid the message guid\n /// @param _message the message\n /// @param _extraData the extra data provided by the executor. this data is untrusted and should be validated.\n function lzCompose(\n address _from,\n address _to,\n bytes32 _guid,\n uint16 _index,\n bytes calldata _message,\n bytes calldata _extraData\n ) external payable {\n // assert the validity\n bytes32 expectedHash = composeQueue[_from][_to][_guid][_index];\n bytes32 actualHash = keccak256(_message);\n if (expectedHash != actualHash) revert Errors.LZ_ComposeNotFound(expectedHash, actualHash);\n\n // marks the message as received to prevent reentrancy\n // cannot just delete the value, otherwise the message can be sent again and could result in some undefined behaviour\n // even though the sender(composing Oapp) is implicitly fully trusted by the composer.\n // eg. sender may not even realize it has such a bug\n composeQueue[_from][_to][_guid][_index] = RECEIVED_MESSAGE_HASH;\n ILayerZeroComposer(_to).lzCompose{ value: msg.value }(_from, _guid, _message, msg.sender, _extraData);\n emit ComposeDelivered(_from, _to, _guid, _index);\n }\n\n /// @param _from the address which sends the composed message\n /// @param _to the address which receives the composed message\n /// @param _guid the message guid\n /// @param _message the message\n /// @param _extraData the extra data provided by the executor\n /// @param _reason the reason why the message is not received\n function lzComposeAlert(\n address _from,\n address _to,\n bytes32 _guid,\n uint16 _index,\n uint256 _gas,\n uint256 _value,\n bytes calldata _message,\n bytes calldata _extraData,\n bytes calldata _reason\n ) external {\n emit LzComposeAlert(_from, _to, msg.sender, _guid, _index, _gas, _value, _message, _extraData, _reason);\n }\n}\n"
565
- },
566
- "contracts/MessagingContext.sol": {
567
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { IMessagingContext } from \"./interfaces/IMessagingContext.sol\";\nimport { Errors } from \"./libs/Errors.sol\";\n\n/// this contract acts as a non-reentrancy guard and a source of messaging context\n/// the context includes the remote eid and the sender address\n/// it separates the send and receive context to allow messaging receipts (send back on receive())\nabstract contract MessagingContext is IMessagingContext {\n uint256 private constant NOT_ENTERED = 1;\n uint256 private _sendContext = NOT_ENTERED;\n\n /// @dev the sendContext is set to 8 bytes 0s + 4 bytes eid + 20 bytes sender\n modifier sendContext(uint32 _dstEid, address _sender) {\n if (_sendContext != NOT_ENTERED) revert Errors.LZ_SendReentrancy();\n _sendContext = (uint256(_dstEid) << 160) | uint160(_sender);\n _;\n _sendContext = NOT_ENTERED;\n }\n\n /// @dev returns true if sending message\n function isSendingMessage() public view returns (bool) {\n return _sendContext != NOT_ENTERED;\n }\n\n /// @dev returns (eid, sender) if sending message, (0, 0) otherwise\n function getSendContext() external view returns (uint32, address) {\n return isSendingMessage() ? _getSendContext(_sendContext) : (0, address(0));\n }\n\n function _getSendContext(uint256 _context) internal pure returns (uint32, address) {\n return (uint32(_context >> 160), address(uint160(_context)));\n }\n}\n"
568
- },
569
- "contracts/proxy/TransparentUpgradeableProxy.sol": {
570
- "content": "// SPDX-License-Identifier: MIT\n\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport { ERC1967Proxy } from \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @author OpenZeppelin. Modified from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.4/contracts/proxy/transparent/TransparentUpgradeableProxy.sol\n * to support custom errors.\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error indicating\n * the proxy admin cannot fallback to the target implementation.\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev The proxy caller is the current admin, and can't fallback to the proxy target.\n */\n error AdminAccessDenied();\n\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(address _logic, address admin_, bytes memory _data) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n */\n function changeAdmin(address newAdmin) external virtual ifAdmin {\n _changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n if (msg.sender == _getAdmin()) {\n revert AdminAccessDenied();\n }\n super._beforeFallback();\n }\n}\n"
571
- },
572
- "@layerzerolabs/lz-evm-messagelib-v2/contracts/libs/ExecutorOptions.sol": {
573
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport \"@layerzerolabs/lz-evm-protocol-v2/contracts/libs/CalldataBytesLib.sol\";\n\nlibrary ExecutorOptions {\n using CalldataBytesLib for bytes;\n\n uint8 internal constant WORKER_ID = 1;\n\n uint8 internal constant OPTION_TYPE_LZRECEIVE = 1;\n uint8 internal constant OPTION_TYPE_NATIVE_DROP = 2;\n uint8 internal constant OPTION_TYPE_LZCOMPOSE = 3;\n uint8 internal constant OPTION_TYPE_ORDERED_EXECUTION = 4;\n uint8 internal constant OPTION_TYPE_LZREAD = 5;\n\n error Executor_InvalidLzReceiveOption();\n error Executor_InvalidNativeDropOption();\n error Executor_InvalidLzComposeOption();\n error Executor_InvalidLzReadOption();\n\n /// @dev decode the next executor option from the options starting from the specified cursor\n /// @param _options [executor_id][executor_option][executor_id][executor_option]...\n /// executor_option = [option_size][option_type][option]\n /// option_size = len(option_type) + len(option)\n /// executor_id: uint8, option_size: uint16, option_type: uint8, option: bytes\n /// @param _cursor the cursor to start decoding from\n /// @return optionType the type of the option\n /// @return option the option of the executor\n /// @return cursor the cursor to start decoding the next executor option\n function nextExecutorOption(\n bytes calldata _options,\n uint256 _cursor\n ) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) {\n unchecked {\n // skip worker id\n cursor = _cursor + 1;\n\n // read option size\n uint16 size = _options.toU16(cursor);\n cursor += 2;\n\n // read option type\n optionType = _options.toU8(cursor);\n\n // startCursor and endCursor are used to slice the option from _options\n uint256 startCursor = cursor + 1; // skip option type\n uint256 endCursor = cursor + size;\n option = _options[startCursor:endCursor];\n cursor += size;\n }\n }\n\n function decodeLzReceiveOption(bytes calldata _option) internal pure returns (uint128 gas, uint128 value) {\n if (_option.length != 16 && _option.length != 32) revert Executor_InvalidLzReceiveOption();\n gas = _option.toU128(0);\n value = _option.length == 32 ? _option.toU128(16) : 0;\n }\n\n function decodeNativeDropOption(bytes calldata _option) internal pure returns (uint128 amount, bytes32 receiver) {\n if (_option.length != 48) revert Executor_InvalidNativeDropOption();\n amount = _option.toU128(0);\n receiver = _option.toB32(16);\n }\n\n function decodeLzComposeOption(\n bytes calldata _option\n ) internal pure returns (uint16 index, uint128 gas, uint128 value) {\n if (_option.length != 18 && _option.length != 34) revert Executor_InvalidLzComposeOption();\n index = _option.toU16(0);\n gas = _option.toU128(2);\n value = _option.length == 34 ? _option.toU128(18) : 0;\n }\n\n function decodeLzReadOption(\n bytes calldata _option\n ) internal pure returns (uint128 gas, uint32 calldataSize, uint128 value) {\n if (_option.length != 20 && _option.length != 36) revert Executor_InvalidLzReadOption();\n gas = _option.toU128(0);\n calldataSize = _option.toU32(16);\n value = _option.length == 36 ? _option.toU128(20) : 0;\n }\n\n function encodeLzReceiveOption(uint128 _gas, uint128 _value) internal pure returns (bytes memory) {\n return _value == 0 ? abi.encodePacked(_gas) : abi.encodePacked(_gas, _value);\n }\n\n function encodeNativeDropOption(uint128 _amount, bytes32 _receiver) internal pure returns (bytes memory) {\n return abi.encodePacked(_amount, _receiver);\n }\n\n function encodeLzComposeOption(uint16 _index, uint128 _gas, uint128 _value) internal pure returns (bytes memory) {\n return _value == 0 ? abi.encodePacked(_index, _gas) : abi.encodePacked(_index, _gas, _value);\n }\n\n function encodeLzReadOption(\n uint128 _gas,\n uint32 _calldataSize,\n uint128 _value\n ) internal pure returns (bytes memory) {\n return _value == 0 ? abi.encodePacked(_gas, _calldataSize) : abi.encodePacked(_gas, _calldataSize, _value);\n }\n}\n"
574
- },
575
- "@layerzerolabs/lz-evm-messagelib-v2/contracts/uln/libs/DVNOptions.sol": {
576
- "content": "// SPDX-License-Identifier: LZBL-1.2\n\npragma solidity ^0.8.20;\n\nimport { BytesLib } from \"solidity-bytes-utils/contracts/BytesLib.sol\";\n\nimport { BitMap256 } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/BitMaps.sol\";\nimport { CalldataBytesLib } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/libs/CalldataBytesLib.sol\";\n\nlibrary DVNOptions {\n using CalldataBytesLib for bytes;\n using BytesLib for bytes;\n\n uint8 internal constant WORKER_ID = 2;\n uint8 internal constant OPTION_TYPE_PRECRIME = 1;\n\n error DVN_InvalidDVNIdx();\n error DVN_InvalidDVNOptions(uint256 cursor);\n\n /// @dev group dvn options by its idx\n /// @param _options [dvn_id][dvn_option][dvn_id][dvn_option]...\n /// dvn_option = [option_size][dvn_idx][option_type][option]\n /// option_size = len(dvn_idx) + len(option_type) + len(option)\n /// dvn_id: uint8, dvn_idx: uint8, option_size: uint16, option_type: uint8, option: bytes\n /// @return dvnOptions the grouped options, still share the same format of _options\n /// @return dvnIndices the dvn indices\n function groupDVNOptionsByIdx(\n bytes memory _options\n ) internal pure returns (bytes[] memory dvnOptions, uint8[] memory dvnIndices) {\n if (_options.length == 0) return (dvnOptions, dvnIndices);\n\n uint8 numDVNs = getNumDVNs(_options);\n\n // if there is only 1 dvn, we can just return the whole options\n if (numDVNs == 1) {\n dvnOptions = new bytes[](1);\n dvnOptions[0] = _options;\n\n dvnIndices = new uint8[](1);\n dvnIndices[0] = _options.toUint8(3); // dvn idx\n return (dvnOptions, dvnIndices);\n }\n\n // otherwise, we need to group the options by dvn_idx\n dvnIndices = new uint8[](numDVNs);\n dvnOptions = new bytes[](numDVNs);\n unchecked {\n uint256 cursor = 0;\n uint256 start = 0;\n uint8 lastDVNIdx = 255; // 255 is an invalid dvn_idx\n\n while (cursor < _options.length) {\n ++cursor; // skip worker_id\n\n // optionLength asserted in getNumDVNs (skip check)\n uint16 optionLength = _options.toUint16(cursor);\n cursor += 2;\n\n // dvnIdx asserted in getNumDVNs (skip check)\n uint8 dvnIdx = _options.toUint8(cursor);\n\n // dvnIdx must equal to the lastDVNIdx for the first option\n // so it is always skipped in the first option\n // this operation slices out options whenever the scan finds a different lastDVNIdx\n if (lastDVNIdx == 255) {\n lastDVNIdx = dvnIdx;\n } else if (dvnIdx != lastDVNIdx) {\n uint256 len = cursor - start - 3; // 3 is for worker_id and option_length\n bytes memory opt = _options.slice(start, len);\n _insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, opt);\n\n // reset the start and lastDVNIdx\n start += len;\n lastDVNIdx = dvnIdx;\n }\n\n cursor += optionLength;\n }\n\n // skip check the cursor here because the cursor is asserted in getNumDVNs\n // if we have reached the end of the options, we need to process the last dvn\n uint256 size = cursor - start;\n bytes memory op = _options.slice(start, size);\n _insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, op);\n\n // revert dvnIndices to start from 0\n for (uint8 i = 0; i < numDVNs; ++i) {\n --dvnIndices[i];\n }\n }\n }\n\n function _insertDVNOptions(\n bytes[] memory _dvnOptions,\n uint8[] memory _dvnIndices,\n uint8 _dvnIdx,\n bytes memory _newOptions\n ) internal pure {\n // dvnIdx starts from 0 but default value of dvnIndices is 0,\n // so we tell if the slot is empty by adding 1 to dvnIdx\n if (_dvnIdx == 255) revert DVN_InvalidDVNIdx();\n uint8 dvnIdxAdj = _dvnIdx + 1;\n\n for (uint256 j = 0; j < _dvnIndices.length; ++j) {\n uint8 index = _dvnIndices[j];\n if (dvnIdxAdj == index) {\n _dvnOptions[j] = abi.encodePacked(_dvnOptions[j], _newOptions);\n break;\n } else if (index == 0) {\n // empty slot, that means it is the first time we see this dvn\n _dvnIndices[j] = dvnIdxAdj;\n _dvnOptions[j] = _newOptions;\n break;\n }\n }\n }\n\n /// @dev get the number of unique dvns\n /// @param _options the format is the same as groupDVNOptionsByIdx\n function getNumDVNs(bytes memory _options) internal pure returns (uint8 numDVNs) {\n uint256 cursor = 0;\n BitMap256 bitmap;\n\n // find number of unique dvn_idx\n unchecked {\n while (cursor < _options.length) {\n ++cursor; // skip worker_id\n\n uint16 optionLength = _options.toUint16(cursor);\n cursor += 2;\n if (optionLength < 2) revert DVN_InvalidDVNOptions(cursor); // at least 1 byte for dvn_idx and 1 byte for option_type\n\n uint8 dvnIdx = _options.toUint8(cursor);\n\n // if dvnIdx is not set, increment numDVNs\n // max num of dvns is 255, 255 is an invalid dvn_idx\n // The order of the dvnIdx is not required to be sequential, as enforcing the order may weaken\n // the composability of the options. e.g. if we refrain from enforcing the order, an OApp that has\n // already enforced certain options can append additional options to the end of the enforced\n // ones without restrictions.\n if (dvnIdx == 255) revert DVN_InvalidDVNIdx();\n if (!bitmap.get(dvnIdx)) {\n ++numDVNs;\n bitmap = bitmap.set(dvnIdx);\n }\n\n cursor += optionLength;\n }\n }\n if (cursor != _options.length) revert DVN_InvalidDVNOptions(cursor);\n }\n\n /// @dev decode the next dvn option from _options starting from the specified cursor\n /// @param _options the format is the same as groupDVNOptionsByIdx\n /// @param _cursor the cursor to start decoding\n /// @return optionType the type of the option\n /// @return option the option\n /// @return cursor the cursor to start decoding the next option\n function nextDVNOption(\n bytes calldata _options,\n uint256 _cursor\n ) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) {\n unchecked {\n // skip worker id\n cursor = _cursor + 1;\n\n // read option size\n uint16 size = _options.toU16(cursor);\n cursor += 2;\n\n // read option type\n optionType = _options.toU8(cursor + 1); // skip dvn_idx\n\n // startCursor and endCursor are used to slice the option from _options\n uint256 startCursor = cursor + 2; // skip option type and dvn_idx\n uint256 endCursor = cursor + size;\n option = _options[startCursor:endCursor];\n cursor += size;\n }\n }\n}\n"
577
- },
578
- "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol": {
579
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\n/**\n * @title ILayerZeroComposer\n */\ninterface ILayerZeroComposer {\n /**\n * @notice Composes a LayerZero message from an OApp.\n * @dev To ensure non-reentrancy, implementers of this interface MUST assert msg.sender is the corresponding EndpointV2 contract (i.e., onlyEndpointV2).\n * @param _from The address initiating the composition, typically the OApp where the lzReceive was called.\n * @param _guid The unique identifier for the corresponding LayerZero src/dst tx.\n * @param _message The composed message payload in bytes. NOT necessarily the same payload passed via lzReceive.\n * @param _executor The address of the executor for the composed message.\n * @param _extraData Additional arbitrary data in bytes passed by the entity who executes the lzCompose.\n */\n function lzCompose(\n address _from,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) external payable;\n}\n"
580
- },
581
- "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol": {
582
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\nimport { Origin } from \"./ILayerZeroEndpointV2.sol\";\n\ninterface ILayerZeroReceiver {\n function allowInitializePath(Origin calldata _origin) external view returns (bool);\n\n function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);\n\n function lzReceive(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) external payable;\n}\n"
583
- },
584
- "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
585
- "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n"
586
- },
587
- "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
588
- "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n"
589
- },
590
- "contracts/oapp/examples/CmdCodecV1Mock.sol": {
591
- "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport { EVMCallRequestV1, EVMCallComputeV1, ReadCmdCodecV1 } from \"../libs/ReadCmdCodecV1.sol\";\n\ncontract CmdCodecV1Mock {\n function decode(\n bytes calldata _cmd\n )\n external\n pure\n returns (uint16 appCmdLabel, EVMCallRequestV1[] memory evmRequests, EVMCallComputeV1 memory compute)\n {\n return ReadCmdCodecV1.decode(_cmd);\n }\n\n function encode(\n uint16 _appCmdLabel,\n EVMCallRequestV1[] calldata _evmRequests\n ) external pure returns (bytes memory) {\n return ReadCmdCodecV1.encode(_appCmdLabel, _evmRequests);\n }\n\n function encode(\n uint16 _appCmdLabel,\n EVMCallRequestV1[] calldata _evmRequests,\n EVMCallComputeV1 calldata _evmCompute\n ) external pure returns (bytes memory) {\n return ReadCmdCodecV1.encode(_appCmdLabel, _evmRequests, _evmCompute);\n }\n}\n"
592
- },
593
- "contracts/oapp/examples/LzReadCounter.sol": {
594
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { ILayerZeroEndpointV2, MessagingFee, MessagingReceipt, Origin } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\nimport { ReadCmdCodecV1, EVMCallComputeV1, EVMCallRequestV1 } from \"../libs/ReadCmdCodecV1.sol\";\nimport { IOAppComputer } from \"../interfaces/IOAppComputer.sol\";\n\nimport { OAppRead } from \"../OAppRead.sol\";\n\ncontract LzReadCounter is OAppRead, IOAppComputer {\n struct EvmReadRequest {\n uint16 appRequestLabel;\n uint32 targetEid;\n bool isBlockNum;\n uint64 blockNumOrTimestamp;\n uint16 confirmations;\n address to;\n uint256 countAddition; // addition to add to the count when reading\n }\n\n struct ComputeSetting {\n uint8 computeSetting;\n uint16 computeConfirmations;\n uint64 blockNumOrTimestamp;\n bool isBlockNum;\n }\n\n uint8 internal constant COMPUTE_SETTING_MAP_ONLY = 0;\n uint8 internal constant COMPUTE_SETTING_REDUCE_ONLY = 1;\n uint8 internal constant COMPUTE_SETTING_MAP_REDUCE = 2;\n uint8 internal constant COMPUTE_SETTING_NONE = 3;\n\n uint32 public immutable eid;\n uint256 public count;\n\n constructor(address _endpoint) OAppRead(_endpoint, msg.sender) {\n eid = ILayerZeroEndpointV2(_endpoint).eid();\n }\n\n // -------------------------------\n // Trigger Read\n function triggerRead(\n uint32 _channelId, // The read channel id\n uint16 _appLabel, // The cmd app label\n EvmReadRequest[] memory _requests,\n ComputeSetting memory _computeSetting,\n bytes calldata _options\n ) external payable returns (MessagingReceipt memory receipt) {\n bytes memory cmd = buildCmd(_appLabel, _requests, _computeSetting);\n count += 1; // increase the count, for pin block testing\n return _lzSend(_channelId, cmd, _options, MessagingFee(msg.value, 0), payable(msg.sender));\n }\n\n function clearCount() external {\n count = 0;\n }\n\n // -------------------------------\n // View\n function quote(\n uint32 _channelId,\n uint16 _appLabel,\n EvmReadRequest[] memory _requests,\n ComputeSetting memory _computeSetting,\n bytes calldata _options\n ) public view returns (uint256 nativeFee, uint256 lzTokenFee) {\n bytes memory cmd = buildCmd(_appLabel, _requests, _computeSetting);\n MessagingFee memory fee = _quote(_channelId, cmd, _options, false);\n return (fee.nativeFee, fee.lzTokenFee);\n }\n\n function buildCmd(\n uint16 appLabel,\n EvmReadRequest[] memory _readRequests,\n ComputeSetting memory _computeSetting\n ) public view returns (bytes memory) {\n require(_readRequests.length > 0, \"LzReadCounter: empty requests\");\n // build read requests\n EVMCallRequestV1[] memory readRequests = new EVMCallRequestV1[](_readRequests.length);\n for (uint256 i = 0; i < _readRequests.length; i++) {\n EvmReadRequest memory req = _readRequests[i];\n readRequests[i] = EVMCallRequestV1({\n appRequestLabel: req.appRequestLabel,\n targetEid: req.targetEid,\n isBlockNum: req.isBlockNum,\n blockNumOrTimestamp: req.blockNumOrTimestamp,\n confirmations: req.confirmations,\n to: req.to,\n callData: abi.encodeWithSelector(this.readCount.selector, req.countAddition)\n });\n }\n // build compute, on current contract\n require(_computeSetting.computeSetting <= COMPUTE_SETTING_NONE, \"LzReadCounter: invalid compute type\");\n EVMCallComputeV1 memory evmCompute = EVMCallComputeV1({\n computeSetting: _computeSetting.computeSetting,\n targetEid: _computeSetting.computeSetting == COMPUTE_SETTING_NONE ? 0 : eid, // 0(means no compute) for none, else use local eid\n isBlockNum: _computeSetting.isBlockNum,\n blockNumOrTimestamp: _computeSetting.blockNumOrTimestamp,\n confirmations: _computeSetting.computeConfirmations,\n to: address(this)\n });\n bytes memory cmd = ReadCmdCodecV1.encode(appLabel, readRequests, evmCompute);\n\n return cmd;\n }\n\n function readCount(uint256 countAddition) external view returns (uint256) {\n require(countAddition != 9, \"LzReadCounter: invalid count addition\"); // This is only for testing\n return count + countAddition;\n }\n\n function lzMap(bytes calldata _request, bytes calldata _response) external pure returns (bytes memory) {\n require(_response.length == 32, \"LzReadCounter: invalid response length\");\n uint16 requestId = ReadCmdCodecV1.decodeRequestV1AppRequestLabel(_request);\n uint256 countNum = abi.decode(_response, (uint256));\n return abi.encode(countNum + 100 + requestId * 1000); // map behavior\n }\n\n function lzReduce(bytes calldata _cmd, bytes[] calldata _responses) external pure returns (bytes memory) {\n uint256 total = 0;\n for (uint256 i = 0; i < _responses.length; i++) {\n require(_responses[i].length == 32, \"LzReadCounter: invalid response length\");\n uint256 countNum = abi.decode(_responses[i], (uint256));\n total += countNum;\n }\n total += 10000; // reduce behavior\n\n uint16 cmdAppLabel = ReadCmdCodecV1.decodeCmdAppLabel(_cmd);\n total += uint256(cmdAppLabel) * 100000; // cmdAppLabel behavior\n\n return abi.encode(total);\n }\n\n // -------------------------------\n function _lzReceive(\n Origin calldata /* _origin */,\n bytes32 /* _guid */,\n bytes calldata _message,\n address /*_executor*/,\n bytes calldata /*_extraData*/\n ) internal override {\n require(_message.length % 32 == 0, \"LzReadCounter: invalid message length\");\n uint256 total = 0;\n // loop read bytes32 of the message and decode it to uint256 then add it to the total\n for (uint256 i = 0; i < _message.length; i += 32) {\n total += abi.decode(_message[i:i + 32], (uint256));\n }\n // reset count if it's too large\n if (count >= 2 ** 128) {\n count = 0;\n }\n count += total;\n }\n\n // be able to receive ether\n receive() external payable virtual {}\n\n fallback() external payable {}\n}\n"
595
- },
596
- "contracts/oapp/examples/OmniCounter.sol": {
597
- "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.20;\n\n// @dev Oz5 implementation\n// import { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport { OmniCounterAbstract, MsgCodec } from \"./OmniCounterAbstract.sol\";\n\ncontract OmniCounter is OmniCounterAbstract {\n // @dev Oz4 implementation\n constructor(address _endpoint, address _delegate) OmniCounterAbstract(_endpoint, _delegate) {}\n\n // @dev Oz5 implementation\n // constructor(address _endpoint, address _delegate) OmniCounterAbstract(_endpoint, _delegate) Ownable(_delegate) {}\n}\n"
598
- },
599
- "contracts/oapp/examples/OmniCounterAbstract.sol": {
600
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { ILayerZeroEndpointV2, MessagingFee, MessagingReceipt, Origin } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\nimport { ILayerZeroComposer } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol\";\n\nimport { OApp } from \"../OApp.sol\";\nimport { OptionsBuilder } from \"../libs/OptionsBuilder.sol\";\nimport { OAppPreCrimeSimulator } from \"../../precrime/OAppPreCrimeSimulator.sol\";\n\nlibrary MsgCodec {\n uint8 internal constant VANILLA_TYPE = 1;\n uint8 internal constant COMPOSED_TYPE = 2;\n uint8 internal constant ABA_TYPE = 3;\n uint8 internal constant COMPOSED_ABA_TYPE = 4;\n\n uint8 internal constant MSG_TYPE_OFFSET = 0;\n uint8 internal constant SRC_EID_OFFSET = 1;\n uint8 internal constant VALUE_OFFSET = 5;\n\n function encode(uint8 _type, uint32 _srcEid) internal pure returns (bytes memory) {\n return abi.encodePacked(_type, _srcEid);\n }\n\n function encode(uint8 _type, uint32 _srcEid, uint256 _value) internal pure returns (bytes memory) {\n return abi.encodePacked(_type, _srcEid, _value);\n }\n\n function msgType(bytes calldata _message) internal pure returns (uint8) {\n return uint8(bytes1(_message[MSG_TYPE_OFFSET:SRC_EID_OFFSET]));\n }\n\n function srcEid(bytes calldata _message) internal pure returns (uint32) {\n return uint32(bytes4(_message[SRC_EID_OFFSET:VALUE_OFFSET]));\n }\n\n function value(bytes calldata _message) internal pure returns (uint256) {\n return uint256(bytes32(_message[VALUE_OFFSET:]));\n }\n}\n\n// @dev declared as abstract to provide backwards compatibility with Oz5/Oz4\nabstract contract OmniCounterAbstract is ILayerZeroComposer, OApp, OAppPreCrimeSimulator {\n using MsgCodec for bytes;\n using OptionsBuilder for bytes;\n\n uint256 public count;\n uint256 public composedCount;\n\n address public admin;\n uint32 public eid;\n\n mapping(uint32 srcEid => mapping(bytes32 sender => uint64 nonce)) private maxReceivedNonce;\n bool private orderedNonce;\n\n // for global assertions\n mapping(uint32 srcEid => uint256 count) public inboundCount;\n mapping(uint32 dstEid => uint256 count) public outboundCount;\n\n constructor(address _endpoint, address _delegate) OApp(_endpoint, _delegate) {\n admin = msg.sender;\n eid = ILayerZeroEndpointV2(_endpoint).eid();\n }\n\n modifier onlyAdmin() {\n require(msg.sender == admin, \"only admin\");\n _;\n }\n\n // -------------------------------\n // Only Admin\n function setAdmin(address _admin) external onlyAdmin {\n admin = _admin;\n }\n\n function withdraw(address payable _to, uint256 _amount) external onlyAdmin {\n (bool success, ) = _to.call{ value: _amount }(\"\");\n require(success, \"OmniCounter: withdraw failed\");\n }\n\n // -------------------------------\n // Send\n function increment(uint32 _eid, uint8 _type, bytes calldata _options) external payable {\n // bytes memory options = combineOptions(_eid, _type, _options);\n _lzSend(_eid, MsgCodec.encode(_type, eid), _options, MessagingFee(msg.value, 0), payable(msg.sender));\n _incrementOutbound(_eid);\n }\n\n // this is a broken function to skip incrementing outbound count\n // so that preCrime will fail\n function brokenIncrement(uint32 _eid, uint8 _type, bytes calldata _options) external payable onlyAdmin {\n // bytes memory options = combineOptions(_eid, _type, _options);\n _lzSend(_eid, MsgCodec.encode(_type, eid), _options, MessagingFee(msg.value, 0), payable(msg.sender));\n // _incrementOutbound(_eid); // mock method which intentionally does not increment outboundCount to cause a PreCrime Crime\n }\n\n function batchIncrement(\n uint32[] calldata _eids,\n uint8[] calldata _types,\n bytes[] calldata _options\n ) external payable {\n require(_eids.length == _options.length && _eids.length == _types.length, \"OmniCounter: length mismatch\");\n\n MessagingReceipt memory receipt;\n uint256 providedFee = msg.value;\n for (uint256 i = 0; i < _eids.length; i++) {\n address refundAddress = i == _eids.length - 1 ? msg.sender : address(this);\n uint32 dstEid = _eids[i];\n uint8 msgType = _types[i];\n // bytes memory options = combineOptions(dstEid, msgType, _options[i]);\n receipt = _lzSend(\n dstEid,\n MsgCodec.encode(msgType, eid),\n _options[i],\n MessagingFee(providedFee, 0),\n payable(refundAddress)\n );\n _incrementOutbound(dstEid);\n providedFee -= receipt.fee.nativeFee;\n }\n }\n\n // -------------------------------\n // View\n function quote(\n uint32 _eid,\n uint8 _type,\n bytes calldata _options\n ) public view returns (uint256 nativeFee, uint256 lzTokenFee) {\n // bytes memory options = combineOptions(_eid, _type, _options);\n MessagingFee memory fee = _quote(_eid, MsgCodec.encode(_type, eid), _options, false);\n return (fee.nativeFee, fee.lzTokenFee);\n }\n\n // @dev enables preCrime simulator\n // @dev routes the call down from the OAppPreCrimeSimulator, and up to the OApp\n function _lzReceiveSimulate(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) internal virtual override {\n _lzReceive(_origin, _guid, _message, _executor, _extraData);\n }\n\n // -------------------------------\n function _lzReceive(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address /*_executor*/,\n bytes calldata /*_extraData*/\n ) internal override {\n _acceptNonce(_origin.srcEid, _origin.sender, _origin.nonce);\n uint8 messageType = _message.msgType();\n\n if (messageType == MsgCodec.VANILLA_TYPE) {\n count++;\n\n //////////////////////////////// IMPORTANT //////////////////////////////////\n /// if you request for msg.value in the options, you should also encode it\n /// into your message and check the value received at destination (example below).\n /// if not, the executor could potentially provide less msg.value than you requested\n /// leading to unintended behavior. Another option is to assert the executor to be\n /// one that you trust.\n /////////////////////////////////////////////////////////////////////////////\n require(msg.value >= _message.value(), \"OmniCounter: insufficient value\");\n\n _incrementInbound(_origin.srcEid);\n } else if (messageType == MsgCodec.COMPOSED_TYPE || messageType == MsgCodec.COMPOSED_ABA_TYPE) {\n count++;\n _incrementInbound(_origin.srcEid);\n endpoint.sendCompose(address(this), _guid, 0, _message);\n } else if (messageType == MsgCodec.ABA_TYPE) {\n count++;\n _incrementInbound(_origin.srcEid);\n\n // send back to the sender\n _incrementOutbound(_origin.srcEid);\n bytes memory options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(200000, 10);\n _lzSend(\n _origin.srcEid,\n MsgCodec.encode(MsgCodec.VANILLA_TYPE, eid, 10),\n options,\n MessagingFee(msg.value, 0),\n payable(address(this))\n );\n } else {\n revert(\"invalid message type\");\n }\n }\n\n function _incrementInbound(uint32 _srcEid) internal {\n inboundCount[_srcEid]++;\n }\n\n function _incrementOutbound(uint32 _dstEid) internal {\n outboundCount[_dstEid]++;\n }\n\n function lzCompose(\n address _oApp,\n bytes32 /*_guid*/,\n bytes calldata _message,\n address,\n bytes calldata\n ) external payable override {\n require(_oApp == address(this), \"!oApp\");\n require(msg.sender == address(endpoint), \"!endpoint\");\n\n uint8 msgType = _message.msgType();\n if (msgType == MsgCodec.COMPOSED_TYPE) {\n composedCount += 1;\n } else if (msgType == MsgCodec.COMPOSED_ABA_TYPE) {\n composedCount += 1;\n\n uint32 srcEid = _message.srcEid();\n _incrementOutbound(srcEid);\n bytes memory options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(200000, 0);\n _lzSend(\n srcEid,\n MsgCodec.encode(MsgCodec.VANILLA_TYPE, eid),\n options,\n MessagingFee(msg.value, 0),\n payable(address(this))\n );\n } else {\n revert(\"invalid message type\");\n }\n }\n\n // -------------------------------\n // Ordered OApp\n // this demonstrates how to build an app that requires execution nonce ordering\n // normally an app should decide ordered or not on contract construction\n // this is just a demo\n function setOrderedNonce(bool _orderedNonce) external onlyOwner {\n orderedNonce = _orderedNonce;\n }\n\n function _acceptNonce(uint32 _srcEid, bytes32 _sender, uint64 _nonce) internal virtual {\n uint64 currentNonce = maxReceivedNonce[_srcEid][_sender];\n if (orderedNonce) {\n require(_nonce == currentNonce + 1, \"OApp: invalid nonce\");\n }\n // update the max nonce anyway. once the ordered mode is turned on, missing early nonces will be rejected\n if (_nonce > currentNonce) {\n maxReceivedNonce[_srcEid][_sender] = _nonce;\n }\n }\n\n function nextNonce(uint32 _srcEid, bytes32 _sender) public view virtual override returns (uint64) {\n if (orderedNonce) {\n return maxReceivedNonce[_srcEid][_sender] + 1;\n } else {\n return 0; // path nonce starts from 1. if 0 it means that there is no specific nonce enforcement\n }\n }\n\n // TODO should override oApp version with added ordered nonce increment\n // a governance function to skip nonce\n function skipInboundNonce(uint32 _srcEid, bytes32 _sender, uint64 _nonce) public virtual onlyOwner {\n endpoint.skip(address(this), _srcEid, _sender, _nonce);\n if (orderedNonce) {\n maxReceivedNonce[_srcEid][_sender]++;\n }\n }\n\n function isPeer(uint32 _eid, bytes32 _peer) public view override returns (bool) {\n return peers[_eid] == _peer;\n }\n\n // @dev Batch send requires overriding this function from OAppSender because the msg.value contains multiple fees\n function _payNative(uint256 _nativeFee) internal virtual override returns (uint256 nativeFee) {\n if (msg.value < _nativeFee) revert NotEnoughNative(msg.value);\n return _nativeFee;\n }\n\n // be able to receive ether\n receive() external payable virtual {}\n\n fallback() external payable {}\n}\n"
601
- },
602
- "contracts/oapp/examples/OmniCounterPreCrime.sol": {
603
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { PreCrime, PreCrimePeer } from \"../../precrime/PreCrime.sol\";\nimport { InboundPacket } from \"../../precrime/libs/Packet.sol\";\nimport { OmniCounter } from \"./OmniCounter.sol\";\n\ncontract OmniCounterPreCrime is PreCrime {\n struct ChainCount {\n uint32 remoteEid;\n uint256 inboundCount;\n uint256 outboundCount;\n }\n\n constructor(address _endpoint, address _counter) PreCrime(_endpoint, _counter) {}\n\n function buildSimulationResult() external view override returns (bytes memory) {\n address payable payableSimulator = payable(simulator);\n OmniCounter counter = OmniCounter(payableSimulator);\n ChainCount[] memory chainCounts = new ChainCount[](preCrimePeers.length);\n for (uint256 i = 0; i < preCrimePeers.length; i++) {\n uint32 remoteEid = preCrimePeers[i].eid;\n chainCounts[i] = ChainCount(remoteEid, counter.inboundCount(remoteEid), counter.outboundCount(remoteEid));\n }\n return abi.encode(chainCounts);\n }\n\n function _preCrime(\n InboundPacket[] memory /** _packets */,\n uint32[] memory _eids,\n bytes[] memory _simulations\n ) internal view override {\n uint32 localEid = _getLocalEid();\n ChainCount[] memory localChainCounts;\n\n // find local chain counts\n for (uint256 i = 0; i < _eids.length; i++) {\n if (_eids[i] == localEid) {\n localChainCounts = abi.decode(_simulations[i], (ChainCount[]));\n break;\n }\n }\n\n // local against remote\n for (uint256 i = 0; i < _eids.length; i++) {\n uint32 remoteEid = _eids[i];\n ChainCount[] memory remoteChainCounts = abi.decode(_simulations[i], (ChainCount[]));\n (uint256 _inboundCount, ) = _findChainCounts(localChainCounts, remoteEid);\n (, uint256 _outboundCount) = _findChainCounts(remoteChainCounts, localEid);\n if (_inboundCount > _outboundCount) {\n revert CrimeFound(\"inboundCount > outboundCount\");\n }\n }\n }\n\n function _findChainCounts(\n ChainCount[] memory _chainCounts,\n uint32 _remoteEid\n ) internal pure returns (uint256, uint256) {\n for (uint256 i = 0; i < _chainCounts.length; i++) {\n if (_chainCounts[i].remoteEid == _remoteEid) {\n return (_chainCounts[i].inboundCount, _chainCounts[i].outboundCount);\n }\n }\n return (0, 0);\n }\n\n function _getPreCrimePeers(\n InboundPacket[] memory _packets\n ) internal view override returns (PreCrimePeer[] memory peers) {\n PreCrimePeer[] memory allPeers = preCrimePeers;\n PreCrimePeer[] memory peersTmp = new PreCrimePeer[](_packets.length);\n\n int256 cursor = -1;\n for (uint256 i = 0; i < _packets.length; i++) {\n uint32 srcEid = _packets[i].origin.srcEid;\n\n // push src eid & peer\n int256 index = _indexOf(allPeers, srcEid);\n if (index >= 0 && _indexOf(peersTmp, srcEid) < 0) {\n cursor++;\n peersTmp[uint256(cursor)] = allPeers[uint256(index)];\n }\n }\n // copy to return\n if (cursor >= 0) {\n uint256 len = uint256(cursor) + 1;\n peers = new PreCrimePeer[](len);\n for (uint256 i = 0; i < len; i++) {\n peers[i] = peersTmp[i];\n }\n }\n }\n\n function _indexOf(PreCrimePeer[] memory _peers, uint32 _eid) internal pure returns (int256) {\n for (uint256 i = 0; i < _peers.length; i++) {\n if (_peers[i].eid == _eid) return int256(i);\n }\n return -1;\n }\n}\n"
604
- },
605
- "contracts/oapp/interfaces/IOAppComposer.sol": {
606
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { ILayerZeroComposer } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol\";\n\n/**\n * @title IOAppComposer\n * @dev This interface defines the OApp Composer, allowing developers to inherit only the OApp package without the protocol.\n */\n// solhint-disable-next-line no-empty-blocks\ninterface IOAppComposer is ILayerZeroComposer {}\n"
607
- },
608
- "contracts/oapp/interfaces/IOAppComputer.sol": {
609
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { IOAppComputerReduce } from \"./IOAppComputerReduce.sol\";\nimport { IOAppComputerMap } from \"./IOAppComputerMap.sol\";\n\ninterface IOAppComputer is IOAppComputerMap, IOAppComputerReduce {}\n"
610
- },
611
- "contracts/oapp/interfaces/IOAppComputerMap.sol": {
612
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\ninterface IOAppComputerMap {\n function lzMap(bytes calldata _request, bytes calldata _response) external view returns (bytes memory);\n}\n"
613
- },
614
- "contracts/oapp/interfaces/IOAppComputerReduce.sol": {
615
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\ninterface IOAppComputerReduce {\n function lzReduce(bytes calldata _cmd, bytes[] calldata _responses) external view returns (bytes memory);\n}\n"
616
- },
617
- "contracts/oapp/interfaces/IOAppCore.sol": {
618
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { ILayerZeroEndpointV2 } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\n\n/**\n * @title IOAppCore\n */\ninterface IOAppCore {\n // Custom error messages\n error OnlyPeer(uint32 eid, bytes32 sender);\n error NoPeer(uint32 eid);\n error InvalidEndpointCall();\n error InvalidDelegate();\n\n // Event emitted when a peer (OApp) is set for a corresponding endpoint\n event PeerSet(uint32 eid, bytes32 peer);\n\n /**\n * @notice Retrieves the OApp version information.\n * @return senderVersion The version of the OAppSender.sol contract.\n * @return receiverVersion The version of the OAppReceiver.sol contract.\n */\n function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion);\n\n /**\n * @notice Retrieves the LayerZero endpoint associated with the OApp.\n * @return iEndpoint The LayerZero endpoint as an interface.\n */\n function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint);\n\n /**\n * @notice Retrieves the peer (OApp) associated with a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @return peer The peer address (OApp instance) associated with the corresponding endpoint.\n */\n function peers(uint32 _eid) external view returns (bytes32 peer);\n\n /**\n * @notice Sets the peer address (OApp instance) for a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @param _peer The address of the peer to be associated with the corresponding endpoint.\n */\n function setPeer(uint32 _eid, bytes32 _peer) external;\n\n /**\n * @notice Sets the delegate address for the OApp Core.\n * @param _delegate The address of the delegate to be set.\n */\n function setDelegate(address _delegate) external;\n}\n"
619
- },
620
- "contracts/oapp/interfaces/IOAppMsgInspector.sol": {
621
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\n/**\n * @title IOAppMsgInspector\n * @dev Interface for the OApp Message Inspector, allowing examination of message and options contents.\n */\ninterface IOAppMsgInspector {\n // Custom error message for inspection failure\n error InspectionFailed(bytes message, bytes options);\n\n /**\n * @notice Allows the inspector to examine LayerZero message contents and optionally throw a revert if invalid.\n * @param _message The message payload to be inspected.\n * @param _options Additional options or parameters for inspection.\n * @return valid A boolean indicating whether the inspection passed (true) or failed (false).\n *\n * @dev Optionally done as a revert, OR use the boolean provided to handle the failure.\n */\n function inspect(bytes calldata _message, bytes calldata _options) external view returns (bool valid);\n}\n"
622
- },
623
- "contracts/oapp/interfaces/IOAppOptionsType3.sol": {
624
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Struct representing enforced option parameters.\n */\nstruct EnforcedOptionParam {\n uint32 eid; // Endpoint ID\n uint16 msgType; // Message Type\n bytes options; // Additional options\n}\n\n/**\n * @title IOAppOptionsType3\n * @dev Interface for the OApp with Type 3 Options, allowing the setting and combining of enforced options.\n */\ninterface IOAppOptionsType3 {\n // Custom error message for invalid options\n error InvalidOptions(bytes options);\n\n // Event emitted when enforced options are set\n event EnforcedOptionSet(EnforcedOptionParam[] _enforcedOptions);\n\n /**\n * @notice Sets enforced options for specific endpoint and message type combinations.\n * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.\n */\n function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) external;\n\n /**\n * @notice Combines options for a given endpoint and message type.\n * @param _eid The endpoint ID.\n * @param _msgType The OApp message type.\n * @param _extraOptions Additional options passed by the caller.\n * @return options The combination of caller specified options AND enforced options.\n */\n function combineOptions(\n uint32 _eid,\n uint16 _msgType,\n bytes calldata _extraOptions\n ) external view returns (bytes memory options);\n}\n"
625
- },
626
- "contracts/oapp/interfaces/IOAppReceiver.sol": {
627
- "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\nimport { ILayerZeroReceiver, Origin } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol\";\n\ninterface IOAppReceiver is ILayerZeroReceiver {\n /**\n * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.\n * @param _origin The origin information containing the source endpoint and sender address.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address on the src chain.\n * - nonce: The nonce of the message.\n * @param _message The lzReceive payload.\n * @param _sender The sender address.\n * @return isSender Is a valid sender.\n *\n * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer.\n * @dev The default sender IS the OAppReceiver implementer.\n */\n function isComposeMsgSender(\n Origin calldata _origin,\n bytes calldata _message,\n address _sender\n ) external view returns (bool isSender);\n}\n"
628
- },
629
- "contracts/oapp/libs/OAppOptionsType3.sol": {
630
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IOAppOptionsType3, EnforcedOptionParam } from \"../interfaces/IOAppOptionsType3.sol\";\n\n/**\n * @title OAppOptionsType3\n * @dev Abstract contract implementing the IOAppOptionsType3 interface with type 3 options.\n */\nabstract contract OAppOptionsType3 is IOAppOptionsType3, Ownable {\n uint16 internal constant OPTION_TYPE_3 = 3;\n\n // @dev The \"msgType\" should be defined in the child contract.\n mapping(uint32 eid => mapping(uint16 msgType => bytes enforcedOption)) public enforcedOptions;\n\n /**\n * @dev Sets the enforced options for specific endpoint and message type combinations.\n * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.\n *\n * @dev Only the owner/admin of the OApp can call this function.\n * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.\n * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.\n * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay\n * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().\n */\n function setEnforcedOptions(EnforcedOptionParam[] calldata _enforcedOptions) public virtual onlyOwner {\n _setEnforcedOptions(_enforcedOptions);\n }\n\n /**\n * @dev Sets the enforced options for specific endpoint and message type combinations.\n * @param _enforcedOptions An array of EnforcedOptionParam structures specifying enforced options.\n *\n * @dev Provides a way for the OApp to enforce things like paying for PreCrime, AND/OR minimum dst lzReceive gas amounts etc.\n * @dev These enforced options can vary as the potential options/execution on the remote may differ as per the msgType.\n * eg. Amount of lzReceive() gas necessary to deliver a lzCompose() message adds overhead you dont want to pay\n * if you are only making a standard LayerZero message ie. lzReceive() WITHOUT sendCompose().\n */\n function _setEnforcedOptions(EnforcedOptionParam[] memory _enforcedOptions) internal virtual {\n for (uint256 i = 0; i < _enforcedOptions.length; i++) {\n // @dev Enforced options are only available for optionType 3, as type 1 and 2 dont support combining.\n _assertOptionsType3(_enforcedOptions[i].options);\n enforcedOptions[_enforcedOptions[i].eid][_enforcedOptions[i].msgType] = _enforcedOptions[i].options;\n }\n\n emit EnforcedOptionSet(_enforcedOptions);\n }\n\n /**\n * @notice Combines options for a given endpoint and message type.\n * @param _eid The endpoint ID.\n * @param _msgType The OAPP message type.\n * @param _extraOptions Additional options passed by the caller.\n * @return options The combination of caller specified options AND enforced options.\n *\n * @dev If there is an enforced lzReceive option:\n * - {gasLimit: 200k, msg.value: 1 ether} AND a caller supplies a lzReceive option: {gasLimit: 100k, msg.value: 0.5 ether}\n * - The resulting options will be {gasLimit: 300k, msg.value: 1.5 ether} when the message is executed on the remote lzReceive() function.\n * @dev This presence of duplicated options is handled off-chain in the verifier/executor.\n */\n function combineOptions(\n uint32 _eid,\n uint16 _msgType,\n bytes calldata _extraOptions\n ) public view virtual returns (bytes memory) {\n bytes memory enforced = enforcedOptions[_eid][_msgType];\n\n // No enforced options, pass whatever the caller supplied, even if it's empty or legacy type 1/2 options.\n if (enforced.length == 0) return _extraOptions;\n\n // No caller options, return enforced\n if (_extraOptions.length == 0) return enforced;\n\n // @dev If caller provided _extraOptions, must be type 3 as its the ONLY type that can be combined.\n if (_extraOptions.length >= 2) {\n _assertOptionsType3(_extraOptions);\n // @dev Remove the first 2 bytes containing the type from the _extraOptions and combine with enforced.\n return bytes.concat(enforced, _extraOptions[2:]);\n }\n\n // No valid set of options was found.\n revert InvalidOptions(_extraOptions);\n }\n\n /**\n * @dev Internal function to assert that options are of type 3.\n * @param _options The options to be checked.\n */\n function _assertOptionsType3(bytes memory _options) internal pure virtual {\n uint16 optionsType;\n assembly {\n optionsType := mload(add(_options, 2))\n }\n if (optionsType != OPTION_TYPE_3) revert InvalidOptions(_options);\n }\n}\n"
631
- },
632
- "contracts/oapp/libs/OptionsBuilder.sol": {
633
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { BytesLib } from \"solidity-bytes-utils/contracts/BytesLib.sol\";\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport { ExecutorOptions } from \"@layerzerolabs/lz-evm-messagelib-v2/contracts/libs/ExecutorOptions.sol\";\nimport { DVNOptions } from \"@layerzerolabs/lz-evm-messagelib-v2/contracts/uln/libs/DVNOptions.sol\";\n\n/**\n * @title OptionsBuilder\n * @dev Library for building and encoding various message options.\n */\nlibrary OptionsBuilder {\n using SafeCast for uint256;\n using BytesLib for bytes;\n\n // Constants for options types\n uint16 internal constant TYPE_1 = 1; // legacy options type 1\n uint16 internal constant TYPE_2 = 2; // legacy options type 2\n uint16 internal constant TYPE_3 = 3;\n\n // Custom error message\n error InvalidSize(uint256 max, uint256 actual);\n error InvalidOptionType(uint16 optionType);\n\n // Modifier to ensure only options of type 3 are used\n modifier onlyType3(bytes memory _options) {\n if (_options.toUint16(0) != TYPE_3) revert InvalidOptionType(_options.toUint16(0));\n _;\n }\n\n /**\n * @dev Creates a new options container with type 3.\n * @return options The newly created options container.\n */\n function newOptions() internal pure returns (bytes memory) {\n return abi.encodePacked(TYPE_3);\n }\n\n /**\n * @dev Adds an executor LZ receive option to the existing options.\n * @param _options The existing options container.\n * @param _gas The gasLimit used on the lzReceive() function in the OApp.\n * @param _value The msg.value passed to the lzReceive() function in the OApp.\n * @return options The updated options container.\n *\n * @dev When multiples of this option are added, they are summed by the executor\n * eg. if (_gas: 200k, and _value: 1 ether) AND (_gas: 100k, _value: 0.5 ether) are sent in an option to the LayerZeroEndpoint,\n * that becomes (300k, 1.5 ether) when the message is executed on the remote lzReceive() function.\n */\n function addExecutorLzReceiveOption(\n bytes memory _options,\n uint128 _gas,\n uint128 _value\n ) internal pure onlyType3(_options) returns (bytes memory) {\n bytes memory option = ExecutorOptions.encodeLzReceiveOption(_gas, _value);\n return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_LZRECEIVE, option);\n }\n\n /**\n * @dev Adds an executor LZ read option to the existing options.\n * @param _options The existing options container.\n * @param _gas The gas limit used for the lzReceive() function in the ReadOApp.\n * @param _calldataSize The size of the payload for lzReceive() function in the ReadOApp.\n * @param _value The msg.value passed to the lzReceive() function in the ReadOApp.\n * @return options The updated options container.\n */\n function addExecutorLzReadOption(\n bytes memory _options,\n uint128 _gas,\n uint32 _calldataSize,\n uint128 _value\n ) internal pure onlyType3(_options) returns (bytes memory) {\n bytes memory option = ExecutorOptions.encodeLzReadOption(_gas, _calldataSize, _value);\n return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_LZREAD, option);\n }\n\n /**\n * @dev Adds an executor native drop option to the existing options.\n * @param _options The existing options container.\n * @param _amount The amount for the native value that is airdropped to the 'receiver'.\n * @param _receiver The receiver address for the native drop option.\n * @return options The updated options container.\n *\n * @dev When multiples of this option are added, they are summed by the executor on the remote chain.\n */\n function addExecutorNativeDropOption(\n bytes memory _options,\n uint128 _amount,\n bytes32 _receiver\n ) internal pure onlyType3(_options) returns (bytes memory) {\n bytes memory option = ExecutorOptions.encodeNativeDropOption(_amount, _receiver);\n return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_NATIVE_DROP, option);\n }\n\n /**\n * @dev Adds an executor LZ compose option to the existing options.\n * @param _options The existing options container.\n * @param _index The index for the lzCompose() function call.\n * @param _gas The gasLimit for the lzCompose() function call.\n * @param _value The msg.value for the lzCompose() function call.\n * @return options The updated options container.\n *\n * @dev When multiples of this option are added, they are summed PER index by the executor on the remote chain.\n * @dev If the OApp sends N lzCompose calls on the remote, you must provide N incremented indexes starting with 0.\n * ie. When your remote OApp composes (N = 3) messages, you must set this option for index 0,1,2\n */\n function addExecutorLzComposeOption(\n bytes memory _options,\n uint16 _index,\n uint128 _gas,\n uint128 _value\n ) internal pure onlyType3(_options) returns (bytes memory) {\n bytes memory option = ExecutorOptions.encodeLzComposeOption(_index, _gas, _value);\n return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_LZCOMPOSE, option);\n }\n\n /**\n * @dev Adds an executor ordered execution option to the existing options.\n * @param _options The existing options container.\n * @return options The updated options container.\n */\n function addExecutorOrderedExecutionOption(\n bytes memory _options\n ) internal pure onlyType3(_options) returns (bytes memory) {\n return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_ORDERED_EXECUTION, bytes(\"\"));\n }\n\n /**\n * @dev Adds a DVN pre-crime option to the existing options.\n * @param _options The existing options container.\n * @param _dvnIdx The DVN index for the pre-crime option.\n * @return options The updated options container.\n */\n function addDVNPreCrimeOption(\n bytes memory _options,\n uint8 _dvnIdx\n ) internal pure onlyType3(_options) returns (bytes memory) {\n return addDVNOption(_options, _dvnIdx, DVNOptions.OPTION_TYPE_PRECRIME, bytes(\"\"));\n }\n\n /**\n * @dev Adds an executor option to the existing options.\n * @param _options The existing options container.\n * @param _optionType The type of the executor option.\n * @param _option The encoded data for the executor option.\n * @return options The updated options container.\n */\n function addExecutorOption(\n bytes memory _options,\n uint8 _optionType,\n bytes memory _option\n ) internal pure onlyType3(_options) returns (bytes memory) {\n return\n abi.encodePacked(\n _options,\n ExecutorOptions.WORKER_ID,\n _option.length.toUint16() + 1, // +1 for optionType\n _optionType,\n _option\n );\n }\n\n /**\n * @dev Adds a DVN option to the existing options.\n * @param _options The existing options container.\n * @param _dvnIdx The DVN index for the DVN option.\n * @param _optionType The type of the DVN option.\n * @param _option The encoded data for the DVN option.\n * @return options The updated options container.\n */\n function addDVNOption(\n bytes memory _options,\n uint8 _dvnIdx,\n uint8 _optionType,\n bytes memory _option\n ) internal pure onlyType3(_options) returns (bytes memory) {\n return\n abi.encodePacked(\n _options,\n DVNOptions.WORKER_ID,\n _option.length.toUint16() + 2, // +2 for optionType and dvnIdx\n _dvnIdx,\n _optionType,\n _option\n );\n }\n\n /**\n * @dev Encodes legacy options of type 1.\n * @param _executionGas The gasLimit value passed to lzReceive().\n * @return legacyOptions The encoded legacy options.\n */\n function encodeLegacyOptionsType1(uint256 _executionGas) internal pure returns (bytes memory) {\n if (_executionGas > type(uint128).max) revert InvalidSize(type(uint128).max, _executionGas);\n return abi.encodePacked(TYPE_1, _executionGas);\n }\n\n /**\n * @dev Encodes legacy options of type 2.\n * @param _executionGas The gasLimit value passed to lzReceive().\n * @param _nativeForDst The amount of native air dropped to the receiver.\n * @param _receiver The _nativeForDst receiver address.\n * @return legacyOptions The encoded legacy options of type 2.\n */\n function encodeLegacyOptionsType2(\n uint256 _executionGas,\n uint256 _nativeForDst,\n bytes memory _receiver // @dev Use bytes instead of bytes32 in legacy type 2 for _receiver.\n ) internal pure returns (bytes memory) {\n if (_executionGas > type(uint128).max) revert InvalidSize(type(uint128).max, _executionGas);\n if (_nativeForDst > type(uint128).max) revert InvalidSize(type(uint128).max, _nativeForDst);\n if (_receiver.length > 32) revert InvalidSize(32, _receiver.length);\n return abi.encodePacked(TYPE_2, _executionGas, _nativeForDst, _receiver);\n }\n}\n"
634
- },
635
- "contracts/oapp/libs/ReadCmdCodecV1.sol": {
636
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nstruct EVMCallRequestV1 {\n uint16 appRequestLabel; // Label identifying the application or type of request (can be use in lzCompute)\n uint32 targetEid; // Target endpoint ID (representing a target blockchain)\n bool isBlockNum; // True if the request = block number, false if timestamp\n uint64 blockNumOrTimestamp; // Block number or timestamp to use in the request\n uint16 confirmations; // Number of block confirmations on top of the requested block number or timestamp before the view function can be called\n address to; // Address of the target contract on the target chain\n bytes callData; // Calldata for the contract call\n}\n\nstruct EVMCallComputeV1 {\n uint8 computeSetting; // Compute setting (0 = map only, 1 = reduce only, 2 = map reduce)\n uint32 targetEid; // Target endpoint ID (representing a target blockchain)\n bool isBlockNum; // True if the request = block number, false if timestamp\n uint64 blockNumOrTimestamp; // Block number or timestamp to use in the request\n uint16 confirmations; // Number of block confirmations on top of the requested block number or timestamp before the view function can be called\n address to; // Address of the target contract on the target chain\n}\n\nlibrary ReadCmdCodecV1 {\n using SafeCast for uint256;\n\n uint16 internal constant CMD_VERSION = 1;\n\n uint8 internal constant REQUEST_VERSION = 1;\n uint16 internal constant RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL = 1;\n\n uint8 internal constant COMPUTE_VERSION = 1;\n uint16 internal constant COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL = 1;\n\n error InvalidVersion();\n error InvalidType();\n\n function decode(\n bytes calldata _cmd\n )\n internal\n pure\n returns (uint16 appCmdLabel, EVMCallRequestV1[] memory evmCallRequests, EVMCallComputeV1 memory compute)\n {\n uint256 offset = 0;\n uint16 cmdVersion = uint16(bytes2(_cmd[offset:offset + 2]));\n offset += 2;\n if (cmdVersion != CMD_VERSION) revert InvalidVersion();\n\n appCmdLabel = uint16(bytes2(_cmd[offset:offset + 2]));\n offset += 2;\n\n (evmCallRequests, offset) = decodeRequestsV1(_cmd, offset);\n\n // decode the compute if it exists\n if (offset < _cmd.length) {\n (compute, ) = decodeEVMCallComputeV1(_cmd, offset);\n }\n }\n\n function decodeRequestsV1(\n bytes calldata _cmd,\n uint256 _offset\n ) internal pure returns (EVMCallRequestV1[] memory evmCallRequests, uint256 newOffset) {\n newOffset = _offset;\n uint16 requestCount = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n\n evmCallRequests = new EVMCallRequestV1[](requestCount);\n for (uint16 i = 0; i < requestCount; i++) {\n uint8 requestVersion = uint8(_cmd[newOffset]);\n newOffset += 1;\n if (requestVersion != REQUEST_VERSION) revert InvalidVersion();\n\n uint16 appRequestLabel = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n\n uint16 resolverType = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n\n if (resolverType == RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL) {\n (EVMCallRequestV1 memory request, uint256 nextOffset) = decodeEVMCallRequestV1(\n _cmd,\n newOffset,\n appRequestLabel\n );\n newOffset = nextOffset;\n evmCallRequests[i] = request;\n } else {\n revert InvalidType();\n }\n }\n }\n\n function decodeEVMCallRequestV1(\n bytes calldata _cmd,\n uint256 _offset,\n uint16 _appRequestLabel\n ) internal pure returns (EVMCallRequestV1 memory request, uint256 newOffset) {\n newOffset = _offset;\n request.appRequestLabel = _appRequestLabel;\n\n uint16 requestSize = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n request.targetEid = uint32(bytes4(_cmd[newOffset:newOffset + 4]));\n newOffset += 4;\n request.isBlockNum = uint8(_cmd[newOffset]) == 1;\n newOffset += 1;\n request.blockNumOrTimestamp = uint64(bytes8(_cmd[newOffset:newOffset + 8]));\n newOffset += 8;\n request.confirmations = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n request.to = address(bytes20(_cmd[newOffset:newOffset + 20]));\n newOffset += 20;\n uint16 callDataSize = requestSize - 35;\n request.callData = _cmd[newOffset:newOffset + callDataSize];\n newOffset += callDataSize;\n }\n\n function decodeEVMCallComputeV1(\n bytes calldata _cmd,\n uint256 _offset\n ) internal pure returns (EVMCallComputeV1 memory compute, uint256 newOffset) {\n newOffset = _offset;\n uint8 computeVersion = uint8(_cmd[newOffset]);\n newOffset += 1;\n if (computeVersion != COMPUTE_VERSION) revert InvalidVersion();\n uint16 computeType = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n if (computeType != COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL) revert InvalidType();\n\n compute.computeSetting = uint8(_cmd[newOffset]);\n newOffset += 1;\n compute.targetEid = uint32(bytes4(_cmd[newOffset:newOffset + 4]));\n newOffset += 4;\n compute.isBlockNum = uint8(_cmd[newOffset]) == 1;\n newOffset += 1;\n compute.blockNumOrTimestamp = uint64(bytes8(_cmd[newOffset:newOffset + 8]));\n newOffset += 8;\n compute.confirmations = uint16(bytes2(_cmd[newOffset:newOffset + 2]));\n newOffset += 2;\n compute.to = address(bytes20(_cmd[newOffset:newOffset + 20]));\n newOffset += 20;\n }\n\n function decodeCmdAppLabel(bytes calldata _cmd) internal pure returns (uint16) {\n uint256 offset = 0;\n uint16 cmdVersion = uint16(bytes2(_cmd[offset:offset + 2]));\n offset += 2;\n if (cmdVersion != CMD_VERSION) revert InvalidVersion();\n\n return uint16(bytes2(_cmd[offset:offset + 2]));\n }\n\n function decodeRequestV1AppRequestLabel(bytes calldata _request) internal pure returns (uint16) {\n uint256 offset = 0;\n uint8 requestVersion = uint8(_request[offset]);\n offset += 1;\n if (requestVersion != REQUEST_VERSION) revert InvalidVersion();\n\n return uint16(bytes2(_request[offset:offset + 2]));\n }\n\n function encode(\n uint16 _appCmdLabel,\n EVMCallRequestV1[] memory _evmCallRequests,\n EVMCallComputeV1 memory _evmCallCompute\n ) internal pure returns (bytes memory) {\n bytes memory cmd = encode(_appCmdLabel, _evmCallRequests);\n if (_evmCallCompute.targetEid != 0) {\n // if eid is 0, it means no compute\n cmd = appendEVMCallComputeV1(cmd, _evmCallCompute);\n }\n return cmd;\n }\n\n function encode(\n uint16 _appCmdLabel,\n EVMCallRequestV1[] memory _evmCallRequests\n ) internal pure returns (bytes memory) {\n bytes memory cmd = abi.encodePacked(CMD_VERSION, _appCmdLabel, _evmCallRequests.length.toUint16());\n for (uint256 i = 0; i < _evmCallRequests.length; i++) {\n cmd = appendEVMCallRequestV1(cmd, _evmCallRequests[i]);\n }\n return cmd;\n }\n\n // todo: optimize this with Buffer\n function appendEVMCallRequestV1(\n bytes memory _cmd,\n EVMCallRequestV1 memory _request\n ) internal pure returns (bytes memory) {\n bytes memory newCmd = abi.encodePacked(\n _cmd,\n REQUEST_VERSION,\n _request.appRequestLabel,\n RESOLVER_TYPE_SINGLE_VIEW_EVM_CALL,\n (_request.callData.length + 35).toUint16(),\n _request.targetEid\n );\n return\n abi.encodePacked(\n newCmd,\n _request.isBlockNum,\n _request.blockNumOrTimestamp,\n _request.confirmations,\n _request.to,\n _request.callData\n );\n }\n\n function appendEVMCallComputeV1(\n bytes memory _cmd,\n EVMCallComputeV1 memory _compute\n ) internal pure returns (bytes memory) {\n return\n abi.encodePacked(\n _cmd,\n COMPUTE_VERSION,\n COMPUTE_TYPE_SINGLE_VIEW_EVM_CALL,\n _compute.computeSetting,\n _compute.targetEid,\n _compute.isBlockNum,\n _compute.blockNumOrTimestamp,\n _compute.confirmations,\n _compute.to\n );\n }\n}\n"
637
- },
638
- "contracts/oapp/OApp.sol": {
639
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\n// @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers\n// solhint-disable-next-line no-unused-import\nimport { OAppSender, MessagingFee, MessagingReceipt } from \"./OAppSender.sol\";\n// @dev Import the 'Origin' so it's exposed to OApp implementers\n// solhint-disable-next-line no-unused-import\nimport { OAppReceiver, Origin } from \"./OAppReceiver.sol\";\nimport { OAppCore } from \"./OAppCore.sol\";\n\n/**\n * @title OApp\n * @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality.\n */\nabstract contract OApp is OAppSender, OAppReceiver {\n /**\n * @dev Constructor to initialize the OApp with the provided endpoint and owner.\n * @param _endpoint The address of the LOCAL LayerZero endpoint.\n * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.\n */\n constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {}\n\n /**\n * @notice Retrieves the OApp version information.\n * @return senderVersion The version of the OAppSender.sol implementation.\n * @return receiverVersion The version of the OAppReceiver.sol implementation.\n */\n function oAppVersion()\n public\n pure\n virtual\n override(OAppSender, OAppReceiver)\n returns (uint64 senderVersion, uint64 receiverVersion)\n {\n return (SENDER_VERSION, RECEIVER_VERSION);\n }\n}\n"
640
- },
641
- "contracts/oapp/OAppCore.sol": {
642
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IOAppCore, ILayerZeroEndpointV2 } from \"./interfaces/IOAppCore.sol\";\n\n/**\n * @title OAppCore\n * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations.\n */\nabstract contract OAppCore is IOAppCore, Ownable {\n // The LayerZero endpoint associated with the given OApp\n ILayerZeroEndpointV2 public immutable endpoint;\n\n // Mapping to store peers associated with corresponding endpoints\n mapping(uint32 eid => bytes32 peer) public peers;\n\n /**\n * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate.\n * @param _endpoint The address of the LOCAL Layer Zero endpoint.\n * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.\n *\n * @dev The delegate typically should be set as the owner of the contract.\n */\n constructor(address _endpoint, address _delegate) {\n endpoint = ILayerZeroEndpointV2(_endpoint);\n\n if (_delegate == address(0)) revert InvalidDelegate();\n endpoint.setDelegate(_delegate);\n }\n\n /**\n * @notice Sets the peer address (OApp instance) for a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @param _peer The address of the peer to be associated with the corresponding endpoint.\n *\n * @dev Only the owner/admin of the OApp can call this function.\n * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.\n * @dev Set this to bytes32(0) to remove the peer address.\n * @dev Peer is a bytes32 to accommodate non-evm chains.\n */\n function setPeer(uint32 _eid, bytes32 _peer) public virtual onlyOwner {\n _setPeer(_eid, _peer);\n }\n\n /**\n * @notice Sets the peer address (OApp instance) for a corresponding endpoint.\n * @param _eid The endpoint ID.\n * @param _peer The address of the peer to be associated with the corresponding endpoint.\n *\n * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp.\n * @dev Set this to bytes32(0) to remove the peer address.\n * @dev Peer is a bytes32 to accommodate non-evm chains.\n */\n function _setPeer(uint32 _eid, bytes32 _peer) internal virtual {\n peers[_eid] = _peer;\n emit PeerSet(_eid, _peer);\n }\n\n /**\n * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set.\n * ie. the peer is set to bytes32(0).\n * @param _eid The endpoint ID.\n * @return peer The address of the peer associated with the specified endpoint.\n */\n function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) {\n bytes32 peer = peers[_eid];\n if (peer == bytes32(0)) revert NoPeer(_eid);\n return peer;\n }\n\n /**\n * @notice Sets the delegate address for the OApp.\n * @param _delegate The address of the delegate to be set.\n *\n * @dev Only the owner/admin of the OApp can call this function.\n * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract.\n */\n function setDelegate(address _delegate) public onlyOwner {\n endpoint.setDelegate(_delegate);\n }\n}\n"
643
- },
644
- "contracts/oapp/OAppRead.sol": {
645
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { AddressCast } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/libs/AddressCast.sol\";\n\nimport { OApp } from \"./OApp.sol\";\n\nabstract contract OAppRead is OApp {\n\n constructor(address _endpoint, address _delegate) OApp(_endpoint, _delegate) {}\n\n // -------------------------------\n // Only Owner\n function setReadChannel(uint32 _channelId, bool _active) public virtual onlyOwner {\n _setPeer(_channelId, _active ? AddressCast.toBytes32(address(this)) : bytes32(0));\n }\n}\n"
646
- },
647
- "contracts/oapp/OAppReceiver.sol": {
648
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { IOAppReceiver, Origin } from \"./interfaces/IOAppReceiver.sol\";\nimport { OAppCore } from \"./OAppCore.sol\";\n\n/**\n * @title OAppReceiver\n * @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers.\n */\nabstract contract OAppReceiver is IOAppReceiver, OAppCore {\n // Custom error message for when the caller is not the registered endpoint/\n error OnlyEndpoint(address addr);\n\n // @dev The version of the OAppReceiver implementation.\n // @dev Version is bumped when changes are made to this contract.\n uint64 internal constant RECEIVER_VERSION = 2;\n\n /**\n * @notice Retrieves the OApp version information.\n * @return senderVersion The version of the OAppSender.sol contract.\n * @return receiverVersion The version of the OAppReceiver.sol contract.\n *\n * @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented.\n * ie. this is a RECEIVE only OApp.\n * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions.\n */\n function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {\n return (0, RECEIVER_VERSION);\n }\n\n /**\n * @notice Indicates whether an address is an approved composeMsg sender to the Endpoint.\n * @dev _origin The origin information containing the source endpoint and sender address.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address on the src chain.\n * - nonce: The nonce of the message.\n * @dev _message The lzReceive payload.\n * @param _sender The sender address.\n * @return isSender Is a valid sender.\n *\n * @dev Applications can optionally choose to implement separate composeMsg senders that are NOT the bridging layer.\n * @dev The default sender IS the OAppReceiver implementer.\n */\n function isComposeMsgSender(\n Origin calldata /*_origin*/,\n bytes calldata /*_message*/,\n address _sender\n ) public view virtual returns (bool) {\n return _sender == address(this);\n }\n\n /**\n * @notice Checks if the path initialization is allowed based on the provided origin.\n * @param origin The origin information containing the source endpoint and sender address.\n * @return Whether the path has been initialized.\n *\n * @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received.\n * @dev This defaults to assuming if a peer has been set, its initialized.\n * Can be overridden by the OApp if there is other logic to determine this.\n */\n function allowInitializePath(Origin calldata origin) public view virtual returns (bool) {\n return peers[origin.srcEid] == origin.sender;\n }\n\n /**\n * @notice Retrieves the next nonce for a given source endpoint and sender address.\n * @dev _srcEid The source endpoint ID.\n * @dev _sender The sender address.\n * @return nonce The next nonce.\n *\n * @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement.\n * @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered.\n * @dev This is also enforced by the OApp.\n * @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0.\n */\n function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) {\n return 0;\n }\n\n /**\n * @dev Entry point for receiving messages or packets from the endpoint.\n * @param _origin The origin information containing the source endpoint and sender address.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address on the src chain.\n * - nonce: The nonce of the message.\n * @param _guid The unique identifier for the received LayerZero message.\n * @param _message The payload of the received message.\n * @param _executor The address of the executor for the received message.\n * @param _extraData Additional arbitrary data provided by the corresponding executor.\n *\n * @dev Entry point for receiving msg/packet from the LayerZero endpoint.\n */\n function lzReceive(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) public payable virtual {\n // Ensures that only the endpoint can attempt to lzReceive() messages to this OApp.\n if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender);\n\n // Ensure that the sender matches the expected peer for the source endpoint.\n if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender);\n\n // Call the internal OApp implementation of lzReceive.\n _lzReceive(_origin, _guid, _message, _executor, _extraData);\n }\n\n /**\n * @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation.\n */\n function _lzReceive(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) internal virtual;\n}\n"
649
- },
650
- "contracts/oapp/OAppSender.sol": {
651
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { SafeERC20, IERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { MessagingParams, MessagingFee, MessagingReceipt } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\nimport { OAppCore } from \"./OAppCore.sol\";\n\n/**\n * @title OAppSender\n * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint.\n */\nabstract contract OAppSender is OAppCore {\n using SafeERC20 for IERC20;\n\n // Custom error messages\n error NotEnoughNative(uint256 msgValue);\n error LzTokenUnavailable();\n\n // @dev The version of the OAppSender implementation.\n // @dev Version is bumped when changes are made to this contract.\n uint64 internal constant SENDER_VERSION = 1;\n\n /**\n * @notice Retrieves the OApp version information.\n * @return senderVersion The version of the OAppSender.sol contract.\n * @return receiverVersion The version of the OAppReceiver.sol contract.\n *\n * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented.\n * ie. this is a SEND only OApp.\n * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions\n */\n function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) {\n return (SENDER_VERSION, 0);\n }\n\n /**\n * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation.\n * @param _dstEid The destination endpoint ID.\n * @param _message The message payload.\n * @param _options Additional options for the message.\n * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens.\n * @return fee The calculated MessagingFee for the message.\n * - nativeFee: The native fee for the message.\n * - lzTokenFee: The LZ token fee for the message.\n */\n function _quote(\n uint32 _dstEid,\n bytes memory _message,\n bytes memory _options,\n bool _payInLzToken\n ) internal view virtual returns (MessagingFee memory fee) {\n return\n endpoint.quote(\n MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken),\n address(this)\n );\n }\n\n /**\n * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message.\n * @param _dstEid The destination endpoint ID.\n * @param _message The message payload.\n * @param _options Additional options for the message.\n * @param _fee The calculated LayerZero fee for the message.\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n * @param _refundAddress The address to receive any excess fee values sent to the endpoint.\n * @return receipt The receipt for the sent message.\n * - guid: The unique identifier for the sent message.\n * - nonce: The nonce of the sent message.\n * - fee: The LayerZero fee incurred for the message.\n */\n function _lzSend(\n uint32 _dstEid,\n bytes memory _message,\n bytes memory _options,\n MessagingFee memory _fee,\n address _refundAddress\n ) internal virtual returns (MessagingReceipt memory receipt) {\n // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint.\n uint256 messageValue = _payNative(_fee.nativeFee);\n if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee);\n\n return\n // solhint-disable-next-line check-send-result\n endpoint.send{ value: messageValue }(\n MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0),\n _refundAddress\n );\n }\n\n /**\n * @dev Internal function to pay the native fee associated with the message.\n * @param _nativeFee The native fee to be paid.\n * @return nativeFee The amount of native currency paid.\n *\n * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction,\n * this will need to be overridden because msg.value would contain multiple lzFees.\n * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency.\n * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees.\n * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time.\n */\n function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) {\n if (msg.value != _nativeFee) revert NotEnoughNative(msg.value);\n return _nativeFee;\n }\n\n /**\n * @dev Internal function to pay the LZ token fee associated with the message.\n * @param _lzTokenFee The LZ token fee to be paid.\n *\n * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint.\n * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend().\n */\n function _payLzToken(uint256 _lzTokenFee) internal virtual {\n // @dev Cannot cache the token because it is not immutable in the endpoint.\n address lzToken = endpoint.lzToken();\n if (lzToken == address(0)) revert LzTokenUnavailable();\n\n // Pay LZ token fee by sending tokens to the endpoint.\n IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee);\n }\n}\n"
652
- },
653
- "contracts/oapp/utils/RateLimiter.sol": {
654
- "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title RateLimiter\n * @dev Abstract contract for implementing rate limiting functionality. This contract provides a basic framework for\n * rate limiting how often a function can be executed. It is designed to be inherited by other contracts requiring rate\n * limiting capabilities to protect resources or services from excessive use.\n *\n * Example 1: Max rate limit reached at beginning of window. As time continues the amount of in flights comes down.\n *\n * Rate Limit Config:\n * limit: 100 units\n * window: 60 seconds\n *\n * Amount in Flight (units) vs. Time Graph (seconds)\n *\n * 100 | * - (Max limit reached at beginning of window)\n * | *\n * | *\n * | *\n * 50 | * (After 30 seconds only 50 units in flight)\n * | *\n * | *\n * | *\n * 0 +--|---|---|---|---|-->(After 60 seconds 0 units are in flight)\n * 0 15 30 45 60 (seconds)\n *\n * Example 2: Max rate limit reached at beginning of window. As time continues the amount of in flights comes down\n * allowing for more to be sent. At the 90 second mark, more in flights come in.\n *\n * Rate Limit Config:\n * limit: 100 units\n * window: 60 seconds\n *\n * Amount in Flight (units) vs. Time Graph (seconds)\n *\n * 100 | * - (Max limit reached at beginning of window)\n * | *\n * | *\n * | *\n * 50 | * * (50 inflight)\n * | * *\n * | * *\n * | * *\n * 0 +--|--|--|--|--|--|--|--|--|--> Time\n * 0 15 30 45 60 75 90 105 120 (seconds)\n *\n * Example 3: Max rate limit reached at beginning of window. At the 15 second mark, the window gets updated to 60\n * seconds and the limit gets updated to 50 units. This scenario shows the direct depiction of \"in flight\" from the\n * previous window affecting the current window.\n *\n * Initial Rate Limit Config: For first 15 seconds\n * limit: 100 units\n * window: 30 seconds\n *\n * Updated Rate Limit Config: Updated at 15 second mark\n * limit: 50 units\n * window: 60 seconds\n *\n * Amount in Flight (units) vs. Time Graph (seconds)\n * 100 - *\n * |*\n * | *\n * | *\n * | *\n * | *\n * | *\n * 75 - | *\n * | *\n * | *\n * | *\n * | *\n * | *\n * | *\n * | *\n * 50 - | 𐫰 <--(Slope changes at the 15 second mark because of the update.\n * | ✧ * Window extended to 60 seconds and limit reduced to 50 units.\n * | ✧ ︎ * Because amountInFlight/lastUpdated do not reset, 50 units are\n * | ✧ * considered in flight from the previous window and the corresponding\n * | ✧ ︎ * decay from the previous rate.)\n * | ✧ *\n * 25 - | ✧ *\n * | ✧ *\n * | ✧ *\n * | ✧ *\n * | ✧ *\n * | ✧ *\n * | ✧ *\n * | ✧ *\n * 0 - +---|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----> Time\n * 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 (seconds)\n * [ Initial 30 Second Window ]\n * [ --------------- Extended 60 Second Window --------------- ]\n */\nabstract contract RateLimiter {\n /**\n * @notice Rate Limit struct.\n * @param amountInFlight The amount in the current window.\n * @param lastUpdated Timestamp representing the last time the rate limit was checked or updated.\n * @param limit This represents the maximum allowed amount within a given window.\n * @param window Defines the duration of the rate limiting window.\n */\n struct RateLimit {\n uint256 amountInFlight;\n uint256 lastUpdated;\n uint256 limit;\n uint256 window;\n }\n\n /**\n * @notice Rate Limit Configuration struct.\n * @param dstEid The destination endpoint id.\n * @param limit This represents the maximum allowed amount within a given window.\n * @param window Defines the duration of the rate limiting window.\n */\n struct RateLimitConfig {\n uint32 dstEid;\n uint256 limit;\n uint256 window;\n }\n\n /**\n * @dev Mapping from destination endpoint id to RateLimit Configurations.\n */\n mapping(uint32 dstEid => RateLimit limit) public rateLimits;\n\n /**\n * @notice Emitted when _setRateLimits occurs.\n * @param rateLimitConfigs An array of `RateLimitConfig` structs representing the rate limit configurations set.\n * - `dstEid`: The destination endpoint id.\n * - `limit`: This represents the maximum allowed amount within a given window.\n * - `window`: Defines the duration of the rate limiting window.\n */\n event RateLimitsChanged(RateLimitConfig[] rateLimitConfigs);\n\n /**\n * @notice Error that is thrown when an amount exceeds the rate_limit.\n */\n error RateLimitExceeded();\n\n /**\n * @notice Get the current amount that can be sent to this destination endpoint id for the given rate limit window.\n * @param _dstEid The destination endpoint id.\n * @return currentAmountInFlight The current amount that was sent.\n * @return amountCanBeSent The amount that can be sent.\n */\n function getAmountCanBeSent(\n uint32 _dstEid\n ) external view virtual returns (uint256 currentAmountInFlight, uint256 amountCanBeSent) {\n RateLimit memory rl = rateLimits[_dstEid];\n return _amountCanBeSent(rl.amountInFlight, rl.lastUpdated, rl.limit, rl.window);\n }\n\n /**\n * @notice Sets the Rate Limit.\n * @param _rateLimitConfigs A `RateLimitConfig` struct representing the rate limit configuration.\n * - `dstEid`: The destination endpoint id.\n * - `limit`: This represents the maximum allowed amount within a given window.\n * - `window`: Defines the duration of the rate limiting window.\n */\n function _setRateLimits(RateLimitConfig[] memory _rateLimitConfigs) internal virtual {\n unchecked {\n for (uint256 i = 0; i < _rateLimitConfigs.length; i++) {\n RateLimit storage rl = rateLimits[_rateLimitConfigs[i].dstEid];\n\n // @dev Ensure we checkpoint the existing rate limit as to not retroactively apply the new decay rate.\n _checkAndUpdateRateLimit(_rateLimitConfigs[i].dstEid, 0);\n\n // @dev Does NOT reset the amountInFlight/lastUpdated of an existing rate limit.\n rl.limit = _rateLimitConfigs[i].limit;\n rl.window = _rateLimitConfigs[i].window;\n }\n }\n emit RateLimitsChanged(_rateLimitConfigs);\n }\n\n /**\n * @notice Checks current amount in flight and amount that can be sent for a given rate limit window.\n * @param _amountInFlight The amount in the current window.\n * @param _lastUpdated Timestamp representing the last time the rate limit was checked or updated.\n * @param _limit This represents the maximum allowed amount within a given window.\n * @param _window Defines the duration of the rate limiting window.\n * @return currentAmountInFlight The amount in the current window.\n * @return amountCanBeSent The amount that can be sent.\n */\n function _amountCanBeSent(\n uint256 _amountInFlight,\n uint256 _lastUpdated,\n uint256 _limit,\n uint256 _window\n ) internal view virtual returns (uint256 currentAmountInFlight, uint256 amountCanBeSent) {\n uint256 timeSinceLastDeposit = block.timestamp - _lastUpdated;\n if (timeSinceLastDeposit >= _window) {\n currentAmountInFlight = 0;\n amountCanBeSent = _limit;\n } else {\n // @dev Presumes linear decay.\n uint256 decay = (_limit * timeSinceLastDeposit) / _window;\n currentAmountInFlight = _amountInFlight <= decay ? 0 : _amountInFlight - decay;\n // @dev In the event the _limit is lowered, and the 'in-flight' amount is higher than the _limit, set to 0.\n amountCanBeSent = _limit <= currentAmountInFlight ? 0 : _limit - currentAmountInFlight;\n }\n }\n\n /**\n * @notice Verifies whether the specified amount falls within the rate limit constraints for the targeted\n * endpoint ID. On successful verification, it updates amountInFlight and lastUpdated. If the amount exceeds\n * the rate limit, the operation reverts.\n * @param _dstEid The destination endpoint id.\n * @param _amount The amount to check for rate limit constraints.\n */\n function _checkAndUpdateRateLimit(uint32 _dstEid, uint256 _amount) internal virtual {\n // @dev By default dstEid that have not been explicitly set will return amountCanBeSent == 0.\n RateLimit storage rl = rateLimits[_dstEid];\n\n (uint256 currentAmountInFlight, uint256 amountCanBeSent) = _amountCanBeSent(\n rl.amountInFlight,\n rl.lastUpdated,\n rl.limit,\n rl.window\n );\n if (_amount > amountCanBeSent) revert RateLimitExceeded();\n\n // @dev Update the storage to contain the new amount and current timestamp.\n rl.amountInFlight = currentAmountInFlight + _amount;\n rl.lastUpdated = block.timestamp;\n }\n}\n"
655
- },
656
- "contracts/oft/interfaces/IOFT.sol": {
657
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { MessagingReceipt, MessagingFee } from \"../../oapp/OAppSender.sol\";\n\n/**\n * @dev Struct representing token parameters for the OFT send() operation.\n */\nstruct SendParam {\n uint32 dstEid; // Destination endpoint ID.\n bytes32 to; // Recipient address.\n uint256 amountLD; // Amount to send in local decimals.\n uint256 minAmountLD; // Minimum amount to send in local decimals.\n bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.\n bytes composeMsg; // The composed message for the send() operation.\n bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.\n}\n\n/**\n * @dev Struct representing OFT limit information.\n * @dev These amounts can change dynamically and are up the the specific oft implementation.\n */\nstruct OFTLimit {\n uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient.\n uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient.\n}\n\n/**\n * @dev Struct representing OFT receipt information.\n */\nstruct OFTReceipt {\n uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.\n // @dev In non-default implementations, the amountReceivedLD COULD differ from this value.\n uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.\n}\n\n/**\n * @dev Struct representing OFT fee details.\n * @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI.\n */\nstruct OFTFeeDetail {\n int256 feeAmountLD; // Amount of the fee in local decimals.\n string description; // Description of the fee.\n}\n\n/**\n * @title IOFT\n * @dev Interface for the OftChain (OFT) token.\n * @dev Does not inherit ERC20 to accommodate usage by OFTAdapter as well.\n * @dev This specific interface ID is '0x02e49c2c'.\n */\ninterface IOFT {\n // Custom error messages\n error InvalidLocalDecimals();\n error SlippageExceeded(uint256 amountLD, uint256 minAmountLD);\n\n // Events\n event OFTSent(\n bytes32 indexed guid, // GUID of the OFT message.\n uint32 dstEid, // Destination Endpoint ID.\n address indexed fromAddress, // Address of the sender on the src chain.\n uint256 amountSentLD, // Amount of tokens sent in local decimals.\n uint256 amountReceivedLD // Amount of tokens received in local decimals.\n );\n event OFTReceived(\n bytes32 indexed guid, // GUID of the OFT message.\n uint32 srcEid, // Source Endpoint ID.\n address indexed toAddress, // Address of the recipient on the dst chain.\n uint256 amountReceivedLD // Amount of tokens received in local decimals.\n );\n\n /**\n * @notice Retrieves interfaceID and the version of the OFT.\n * @return interfaceId The interface ID.\n * @return version The version.\n *\n * @dev interfaceId: This specific interface ID is '0x02e49c2c'.\n * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.\n * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.\n * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)\n */\n function oftVersion() external view returns (bytes4 interfaceId, uint64 version);\n\n /**\n * @notice Retrieves the address of the token associated with the OFT.\n * @return token The address of the ERC20 token implementation.\n */\n function token() external view returns (address);\n\n /**\n * @notice Indicates whether the OFT contract requires approval of the 'token()' to send.\n * @return requiresApproval Needs approval of the underlying token implementation.\n *\n * @dev Allows things like wallet implementers to determine integration requirements,\n * without understanding the underlying token implementation.\n */\n function approvalRequired() external view returns (bool);\n\n /**\n * @notice Retrieves the shared decimals of the OFT.\n * @return sharedDecimals The shared decimals of the OFT.\n */\n function sharedDecimals() external view returns (uint8);\n\n /**\n * @notice Provides a quote for OFT-related operations.\n * @param _sendParam The parameters for the send operation.\n * @return limit The OFT limit information.\n * @return oftFeeDetails The details of OFT fees.\n * @return receipt The OFT receipt information.\n */\n function quoteOFT(\n SendParam calldata _sendParam\n ) external view returns (OFTLimit memory, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory);\n\n /**\n * @notice Provides a quote for the send() operation.\n * @param _sendParam The parameters for the send() operation.\n * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.\n * @return fee The calculated LayerZero messaging fee from the send() operation.\n *\n * @dev MessagingFee: LayerZero msg fee\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n */\n function quoteSend(SendParam calldata _sendParam, bool _payInLzToken) external view returns (MessagingFee memory);\n\n /**\n * @notice Executes the send() operation.\n * @param _sendParam The parameters for the send operation.\n * @param _fee The fee information supplied by the caller.\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n * @param _refundAddress The address to receive any excess funds from fees etc. on the src.\n * @return receipt The LayerZero messaging receipt from the send() operation.\n * @return oftReceipt The OFT receipt information.\n *\n * @dev MessagingReceipt: LayerZero msg receipt\n * - guid: The unique identifier for the sent message.\n * - nonce: The nonce of the sent message.\n * - fee: The LayerZero fee incurred for the message.\n */\n function send(\n SendParam calldata _sendParam,\n MessagingFee calldata _fee,\n address _refundAddress\n ) external payable returns (MessagingReceipt memory, OFTReceipt memory);\n}\n"
658
- },
659
- "contracts/oft/libs/OFTComposeMsgCodec.sol": {
660
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nlibrary OFTComposeMsgCodec {\n // Offset constants for decoding composed messages\n uint8 private constant NONCE_OFFSET = 8;\n uint8 private constant SRC_EID_OFFSET = 12;\n uint8 private constant AMOUNT_LD_OFFSET = 44;\n uint8 private constant COMPOSE_FROM_OFFSET = 76;\n\n /**\n * @dev Encodes a OFT composed message.\n * @param _nonce The nonce value.\n * @param _srcEid The source endpoint ID.\n * @param _amountLD The amount in local decimals.\n * @param _composeMsg The composed message.\n * @return _msg The encoded Composed message.\n */\n function encode(\n uint64 _nonce,\n uint32 _srcEid,\n uint256 _amountLD,\n bytes memory _composeMsg // 0x[composeFrom][composeMsg]\n ) internal pure returns (bytes memory _msg) {\n _msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg);\n }\n\n /**\n * @dev Retrieves the nonce from the composed message.\n * @param _msg The message.\n * @return The nonce value.\n */\n function nonce(bytes calldata _msg) internal pure returns (uint64) {\n return uint64(bytes8(_msg[:NONCE_OFFSET]));\n }\n\n /**\n * @dev Retrieves the source endpoint ID from the composed message.\n * @param _msg The message.\n * @return The source endpoint ID.\n */\n function srcEid(bytes calldata _msg) internal pure returns (uint32) {\n return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET]));\n }\n\n /**\n * @dev Retrieves the amount in local decimals from the composed message.\n * @param _msg The message.\n * @return The amount in local decimals.\n */\n function amountLD(bytes calldata _msg) internal pure returns (uint256) {\n return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET]));\n }\n\n /**\n * @dev Retrieves the composeFrom value from the composed message.\n * @param _msg The message.\n * @return The composeFrom value.\n */\n function composeFrom(bytes calldata _msg) internal pure returns (bytes32) {\n return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]);\n }\n\n /**\n * @dev Retrieves the composed message.\n * @param _msg The message.\n * @return The composed message.\n */\n function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {\n return _msg[COMPOSE_FROM_OFFSET:];\n }\n\n /**\n * @dev Converts an address to bytes32.\n * @param _addr The address to convert.\n * @return The bytes32 representation of the address.\n */\n function addressToBytes32(address _addr) internal pure returns (bytes32) {\n return bytes32(uint256(uint160(_addr)));\n }\n\n /**\n * @dev Converts bytes32 to an address.\n * @param _b The bytes32 value to convert.\n * @return The address representation of bytes32.\n */\n function bytes32ToAddress(bytes32 _b) internal pure returns (address) {\n return address(uint160(uint256(_b)));\n }\n}\n"
661
- },
662
- "contracts/oft/libs/OFTMsgCodec.sol": {
663
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nlibrary OFTMsgCodec {\n // Offset constants for encoding and decoding OFT messages\n uint8 private constant SEND_TO_OFFSET = 32;\n uint8 private constant SEND_AMOUNT_SD_OFFSET = 40;\n\n /**\n * @dev Encodes an OFT LayerZero message.\n * @param _sendTo The recipient address.\n * @param _amountShared The amount in shared decimals.\n * @param _composeMsg The composed message.\n * @return _msg The encoded message.\n * @return hasCompose A boolean indicating whether the message has a composed payload.\n */\n function encode(\n bytes32 _sendTo,\n uint64 _amountShared,\n bytes memory _composeMsg\n ) internal view returns (bytes memory _msg, bool hasCompose) {\n hasCompose = _composeMsg.length > 0;\n // @dev Remote chains will want to know the composed function caller ie. msg.sender on the src.\n _msg = hasCompose\n ? abi.encodePacked(_sendTo, _amountShared, addressToBytes32(msg.sender), _composeMsg)\n : abi.encodePacked(_sendTo, _amountShared);\n }\n\n /**\n * @dev Checks if the OFT message is composed.\n * @param _msg The OFT message.\n * @return A boolean indicating whether the message is composed.\n */\n function isComposed(bytes calldata _msg) internal pure returns (bool) {\n return _msg.length > SEND_AMOUNT_SD_OFFSET;\n }\n\n /**\n * @dev Retrieves the recipient address from the OFT message.\n * @param _msg The OFT message.\n * @return The recipient address.\n */\n function sendTo(bytes calldata _msg) internal pure returns (bytes32) {\n return bytes32(_msg[:SEND_TO_OFFSET]);\n }\n\n /**\n * @dev Retrieves the amount in shared decimals from the OFT message.\n * @param _msg The OFT message.\n * @return The amount in shared decimals.\n */\n function amountSD(bytes calldata _msg) internal pure returns (uint64) {\n return uint64(bytes8(_msg[SEND_TO_OFFSET:SEND_AMOUNT_SD_OFFSET]));\n }\n\n /**\n * @dev Retrieves the composed message from the OFT message.\n * @param _msg The OFT message.\n * @return The composed message.\n */\n function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {\n return _msg[SEND_AMOUNT_SD_OFFSET:];\n }\n\n /**\n * @dev Converts an address to bytes32.\n * @param _addr The address to convert.\n * @return The bytes32 representation of the address.\n */\n function addressToBytes32(address _addr) internal pure returns (bytes32) {\n return bytes32(uint256(uint160(_addr)));\n }\n\n /**\n * @dev Converts bytes32 to an address.\n * @param _b The bytes32 value to convert.\n * @return The address representation of bytes32.\n */\n function bytes32ToAddress(bytes32 _b) internal pure returns (address) {\n return address(uint160(uint256(_b)));\n }\n}\n"
664
- },
665
- "contracts/oft/OFT.sol": {
666
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IOFT, OFTCore } from \"./OFTCore.sol\";\n\n/**\n * @title OFT Contract\n * @dev OFT is an ERC-20 token that extends the functionality of the OFTCore contract.\n */\nabstract contract OFT is OFTCore, ERC20 {\n /**\n * @dev Constructor for the OFT contract.\n * @param _name The name of the OFT.\n * @param _symbol The symbol of the OFT.\n * @param _lzEndpoint The LayerZero endpoint address.\n * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.\n */\n constructor(\n string memory _name,\n string memory _symbol,\n address _lzEndpoint,\n address _delegate\n ) ERC20(_name, _symbol) OFTCore(decimals(), _lzEndpoint, _delegate) {}\n\n /**\n * @dev Retrieves the address of the underlying ERC20 implementation.\n * @return The address of the OFT token.\n *\n * @dev In the case of OFT, address(this) and erc20 are the same contract.\n */\n function token() public view returns (address) {\n return address(this);\n }\n\n /**\n * @notice Indicates whether the OFT contract requires approval of the 'token()' to send.\n * @return requiresApproval Needs approval of the underlying token implementation.\n *\n * @dev In the case of OFT where the contract IS the token, approval is NOT required.\n */\n function approvalRequired() external pure virtual returns (bool) {\n return false;\n }\n\n /**\n * @dev Burns tokens from the sender's specified balance.\n * @param _from The address to debit the tokens from.\n * @param _amountLD The amount of tokens to send in local decimals.\n * @param _minAmountLD The minimum amount to send in local decimals.\n * @param _dstEid The destination chain ID.\n * @return amountSentLD The amount sent in local decimals.\n * @return amountReceivedLD The amount received in local decimals on the remote.\n */\n function _debit(\n address _from,\n uint256 _amountLD,\n uint256 _minAmountLD,\n uint32 _dstEid\n ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {\n (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid);\n\n // @dev In NON-default OFT, amountSentLD could be 100, with a 10% fee, the amountReceivedLD amount is 90,\n // therefore amountSentLD CAN differ from amountReceivedLD.\n\n // @dev Default OFT burns on src.\n _burn(_from, amountSentLD);\n }\n\n /**\n * @dev Credits tokens to the specified address.\n * @param _to The address to credit the tokens to.\n * @param _amountLD The amount of tokens to credit in local decimals.\n * @dev _srcEid The source chain ID.\n * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.\n */\n function _credit(\n address _to,\n uint256 _amountLD,\n uint32 /*_srcEid*/\n ) internal virtual override returns (uint256 amountReceivedLD) {\n if (_to == address(0x0)) _to = address(0xdead); // _mint(...) does not support address(0x0)\n // @dev Default OFT mints on dst.\n _mint(_to, _amountLD);\n // @dev In the case of NON-default OFT, the _amountLD MIGHT not be == amountReceivedLD.\n return _amountLD;\n }\n}\n"
667
- },
668
- "contracts/oft/OFTAdapter.sol": {
669
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { IERC20Metadata, IERC20 } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IOFT, OFTCore } from \"./OFTCore.sol\";\n\n/**\n * @title OFTAdapter Contract\n * @dev OFTAdapter is a contract that adapts an ERC-20 token to the OFT functionality.\n *\n * @dev For existing ERC20 tokens, this can be used to convert the token to crosschain compatibility.\n * @dev WARNING: ONLY 1 of these should exist for a given global mesh,\n * unless you make a NON-default implementation of OFT and needs to be done very carefully.\n * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.\n * IF the 'innerToken' applies something like a transfer fee, the default will NOT work...\n * a pre/post balance check will need to be done to calculate the amountSentLD/amountReceivedLD.\n */\nabstract contract OFTAdapter is OFTCore {\n using SafeERC20 for IERC20;\n\n IERC20 internal immutable innerToken;\n\n /**\n * @dev Constructor for the OFTAdapter contract.\n * @param _token The address of the ERC-20 token to be adapted.\n * @param _lzEndpoint The LayerZero endpoint address.\n * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.\n */\n constructor(\n address _token,\n address _lzEndpoint,\n address _delegate\n ) OFTCore(IERC20Metadata(_token).decimals(), _lzEndpoint, _delegate) {\n innerToken = IERC20(_token);\n }\n\n /**\n * @dev Retrieves the address of the underlying ERC20 implementation.\n * @return The address of the adapted ERC-20 token.\n *\n * @dev In the case of OFTAdapter, address(this) and erc20 are NOT the same contract.\n */\n function token() public view returns (address) {\n return address(innerToken);\n }\n\n /**\n * @notice Indicates whether the OFT contract requires approval of the 'token()' to send.\n * @return requiresApproval Needs approval of the underlying token implementation.\n *\n * @dev In the case of default OFTAdapter, approval is required.\n * @dev In non-default OFTAdapter contracts with something like mint and burn privileges, it would NOT need approval.\n */\n function approvalRequired() external pure virtual returns (bool) {\n return true;\n }\n\n /**\n * @dev Burns tokens from the sender's specified balance, ie. pull method.\n * @param _from The address to debit from.\n * @param _amountLD The amount of tokens to send in local decimals.\n * @param _minAmountLD The minimum amount to send in local decimals.\n * @param _dstEid The destination chain ID.\n * @return amountSentLD The amount sent in local decimals.\n * @return amountReceivedLD The amount received in local decimals on the remote.\n *\n * @dev msg.sender will need to approve this _amountLD of tokens to be locked inside of the contract.\n * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.\n * IF the 'innerToken' applies something like a transfer fee, the default will NOT work...\n * a pre/post balance check will need to be done to calculate the amountReceivedLD.\n */\n function _debit(\n address _from,\n uint256 _amountLD,\n uint256 _minAmountLD,\n uint32 _dstEid\n ) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {\n (amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid);\n // @dev Lock tokens by moving them into this contract from the caller.\n innerToken.safeTransferFrom(_from, address(this), amountSentLD);\n }\n\n /**\n * @dev Credits tokens to the specified address.\n * @param _to The address to credit the tokens to.\n * @param _amountLD The amount of tokens to credit in local decimals.\n * @dev _srcEid The source chain ID.\n * @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.\n *\n * @dev WARNING: The default OFTAdapter implementation assumes LOSSLESS transfers, ie. 1 token in, 1 token out.\n * IF the 'innerToken' applies something like a transfer fee, the default will NOT work...\n * a pre/post balance check will need to be done to calculate the amountReceivedLD.\n */\n function _credit(\n address _to,\n uint256 _amountLD,\n uint32 /*_srcEid*/\n ) internal virtual override returns (uint256 amountReceivedLD) {\n // @dev Unlock the tokens and transfer to the recipient.\n innerToken.safeTransfer(_to, _amountLD);\n // @dev In the case of NON-default OFTAdapter, the amountLD MIGHT not be == amountReceivedLD.\n return _amountLD;\n }\n}\n"
670
- },
671
- "contracts/oft/OFTCore.sol": {
672
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { OApp, Origin } from \"../oapp/OApp.sol\";\nimport { OAppOptionsType3 } from \"../oapp/libs/OAppOptionsType3.sol\";\nimport { IOAppMsgInspector } from \"../oapp/interfaces/IOAppMsgInspector.sol\";\n\nimport { OAppPreCrimeSimulator } from \"../precrime/OAppPreCrimeSimulator.sol\";\n\nimport { IOFT, SendParam, OFTLimit, OFTReceipt, OFTFeeDetail, MessagingReceipt, MessagingFee } from \"./interfaces/IOFT.sol\";\nimport { OFTMsgCodec } from \"./libs/OFTMsgCodec.sol\";\nimport { OFTComposeMsgCodec } from \"./libs/OFTComposeMsgCodec.sol\";\n\n/**\n * @title OFTCore\n * @dev Abstract contract for the OftChain (OFT) token.\n */\nabstract contract OFTCore is IOFT, OApp, OAppPreCrimeSimulator, OAppOptionsType3 {\n using OFTMsgCodec for bytes;\n using OFTMsgCodec for bytes32;\n\n // @notice Provides a conversion rate when swapping between denominations of SD and LD\n // - shareDecimals == SD == shared Decimals\n // - localDecimals == LD == local decimals\n // @dev Considers that tokens have different decimal amounts on various chains.\n // @dev eg.\n // For a token\n // - locally with 4 decimals --> 1.2345 => uint(12345)\n // - remotely with 2 decimals --> 1.23 => uint(123)\n // - The conversion rate would be 10 ** (4 - 2) = 100\n // @dev If you want to send 1.2345 -> (uint 12345), you CANNOT represent that value on the remote,\n // you can only display 1.23 -> uint(123).\n // @dev To preserve the dust that would otherwise be lost on that conversion,\n // we need to unify a denomination that can be represented on ALL chains inside of the OFT mesh\n uint256 public immutable decimalConversionRate;\n\n // @notice Msg types that are used to identify the various OFT operations.\n // @dev This can be extended in child contracts for non-default oft operations\n // @dev These values are used in things like combineOptions() in OAppOptionsType3.sol.\n uint16 public constant SEND = 1;\n uint16 public constant SEND_AND_CALL = 2;\n\n // Address of an optional contract to inspect both 'message' and 'options'\n address public msgInspector;\n event MsgInspectorSet(address inspector);\n\n /**\n * @dev Constructor.\n * @param _localDecimals The decimals of the token on the local chain (this chain).\n * @param _endpoint The address of the LayerZero endpoint.\n * @param _delegate The delegate capable of making OApp configurations inside of the endpoint.\n */\n constructor(uint8 _localDecimals, address _endpoint, address _delegate) OApp(_endpoint, _delegate) {\n if (_localDecimals < sharedDecimals()) revert InvalidLocalDecimals();\n decimalConversionRate = 10 ** (_localDecimals - sharedDecimals());\n }\n\n /**\n * @notice Retrieves interfaceID and the version of the OFT.\n * @return interfaceId The interface ID.\n * @return version The version.\n *\n * @dev interfaceId: This specific interface ID is '0x02e49c2c'.\n * @dev version: Indicates a cross-chain compatible msg encoding with other OFTs.\n * @dev If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented.\n * ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)\n */\n function oftVersion() external pure virtual returns (bytes4 interfaceId, uint64 version) {\n return (type(IOFT).interfaceId, 1);\n }\n\n /**\n * @dev Retrieves the shared decimals of the OFT.\n * @return The shared decimals of the OFT.\n *\n * @dev Sets an implicit cap on the amount of tokens, over uint64.max() will need some sort of outbound cap / totalSupply cap\n * Lowest common decimal denominator between chains.\n * Defaults to 6 decimal places to provide up to 18,446,744,073,709.551615 units (max uint64).\n * For tokens exceeding this totalSupply(), they will need to override the sharedDecimals function with something smaller.\n * ie. 4 sharedDecimals would be 1,844,674,407,370,955.1615\n */\n function sharedDecimals() public view virtual returns (uint8) {\n return 6;\n }\n\n /**\n * @dev Sets the message inspector address for the OFT.\n * @param _msgInspector The address of the message inspector.\n *\n * @dev This is an optional contract that can be used to inspect both 'message' and 'options'.\n * @dev Set it to address(0) to disable it, or set it to a contract address to enable it.\n */\n function setMsgInspector(address _msgInspector) public virtual onlyOwner {\n msgInspector = _msgInspector;\n emit MsgInspectorSet(_msgInspector);\n }\n\n /**\n * @notice Provides a quote for OFT-related operations.\n * @param _sendParam The parameters for the send operation.\n * @return oftLimit The OFT limit information.\n * @return oftFeeDetails The details of OFT fees.\n * @return oftReceipt The OFT receipt information.\n */\n function quoteOFT(\n SendParam calldata _sendParam\n )\n external\n view\n virtual\n returns (OFTLimit memory oftLimit, OFTFeeDetail[] memory oftFeeDetails, OFTReceipt memory oftReceipt)\n {\n uint256 minAmountLD = 0; // Unused in the default implementation.\n uint256 maxAmountLD = type(uint64).max; // Unused in the default implementation.\n oftLimit = OFTLimit(minAmountLD, maxAmountLD);\n\n // Unused in the default implementation; reserved for future complex fee details.\n oftFeeDetails = new OFTFeeDetail[](0);\n\n // @dev This is the same as the send() operation, but without the actual send.\n // - amountSentLD is the amount in local decimals that would be sent from the sender.\n // - amountReceivedLD is the amount in local decimals that will be credited to the recipient on the remote OFT instance.\n // @dev The amountSentLD MIGHT not equal the amount the user actually receives. HOWEVER, the default does.\n (uint256 amountSentLD, uint256 amountReceivedLD) = _debitView(\n _sendParam.amountLD,\n _sendParam.minAmountLD,\n _sendParam.dstEid\n );\n oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);\n }\n\n /**\n * @notice Provides a quote for the send() operation.\n * @param _sendParam The parameters for the send() operation.\n * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.\n * @return msgFee The calculated LayerZero messaging fee from the send() operation.\n *\n * @dev MessagingFee: LayerZero msg fee\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n */\n function quoteSend(\n SendParam calldata _sendParam,\n bool _payInLzToken\n ) external view virtual returns (MessagingFee memory msgFee) {\n // @dev mock the amount to receive, this is the same operation used in the send().\n // The quote is as similar as possible to the actual send() operation.\n (, uint256 amountReceivedLD) = _debitView(_sendParam.amountLD, _sendParam.minAmountLD, _sendParam.dstEid);\n\n // @dev Builds the options and OFT message to quote in the endpoint.\n (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);\n\n // @dev Calculates the LayerZero fee for the send() operation.\n return _quote(_sendParam.dstEid, message, options, _payInLzToken);\n }\n\n /**\n * @dev Executes the send operation.\n * @param _sendParam The parameters for the send operation.\n * @param _fee The calculated fee for the send() operation.\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n * @param _refundAddress The address to receive any excess funds.\n * @return msgReceipt The receipt for the send operation.\n * @return oftReceipt The OFT receipt information.\n *\n * @dev MessagingReceipt: LayerZero msg receipt\n * - guid: The unique identifier for the sent message.\n * - nonce: The nonce of the sent message.\n * - fee: The LayerZero fee incurred for the message.\n */\n function send(\n SendParam calldata _sendParam,\n MessagingFee calldata _fee,\n address _refundAddress\n ) external payable virtual returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) {\n // @dev Applies the token transfers regarding this send() operation.\n // - amountSentLD is the amount in local decimals that was ACTUALLY sent/debited from the sender.\n // - amountReceivedLD is the amount in local decimals that will be received/credited to the recipient on the remote OFT instance.\n (uint256 amountSentLD, uint256 amountReceivedLD) = _debit(\n msg.sender,\n _sendParam.amountLD,\n _sendParam.minAmountLD,\n _sendParam.dstEid\n );\n\n // @dev Builds the options and OFT message to quote in the endpoint.\n (bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);\n\n // @dev Sends the message to the LayerZero endpoint and returns the LayerZero msg receipt.\n msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress);\n // @dev Formulate the OFT receipt.\n oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);\n\n emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD);\n }\n\n /**\n * @dev Internal function to build the message and options.\n * @param _sendParam The parameters for the send() operation.\n * @param _amountLD The amount in local decimals.\n * @return message The encoded message.\n * @return options The encoded options.\n */\n function _buildMsgAndOptions(\n SendParam calldata _sendParam,\n uint256 _amountLD\n ) internal view virtual returns (bytes memory message, bytes memory options) {\n bool hasCompose;\n // @dev This generated message has the msg.sender encoded into the payload so the remote knows who the caller is.\n (message, hasCompose) = OFTMsgCodec.encode(\n _sendParam.to,\n _toSD(_amountLD),\n // @dev Must be include a non empty bytes if you want to compose, EVEN if you dont need it on the remote.\n // EVEN if you dont require an arbitrary payload to be sent... eg. '0x01'\n _sendParam.composeMsg\n );\n // @dev Change the msg type depending if its composed or not.\n uint16 msgType = hasCompose ? SEND_AND_CALL : SEND;\n // @dev Combine the callers _extraOptions with the enforced options via the OAppOptionsType3.\n options = combineOptions(_sendParam.dstEid, msgType, _sendParam.extraOptions);\n\n // @dev Optionally inspect the message and options depending if the OApp owner has set a msg inspector.\n // @dev If it fails inspection, needs to revert in the implementation. ie. does not rely on return boolean\n if (msgInspector != address(0)) IOAppMsgInspector(msgInspector).inspect(message, options);\n }\n\n /**\n * @dev Internal function to handle the receive on the LayerZero endpoint.\n * @param _origin The origin information.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address from the src chain.\n * - nonce: The nonce of the LayerZero message.\n * @param _guid The unique identifier for the received LayerZero message.\n * @param _message The encoded message.\n * @dev _executor The address of the executor.\n * @dev _extraData Additional data.\n */\n function _lzReceive(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address /*_executor*/, // @dev unused in the default implementation.\n bytes calldata /*_extraData*/ // @dev unused in the default implementation.\n ) internal virtual override {\n // @dev The src sending chain doesnt know the address length on this chain (potentially non-evm)\n // Thus everything is bytes32() encoded in flight.\n address toAddress = _message.sendTo().bytes32ToAddress();\n // @dev Credit the amountLD to the recipient and return the ACTUAL amount the recipient received in local decimals\n uint256 amountReceivedLD = _credit(toAddress, _toLD(_message.amountSD()), _origin.srcEid);\n\n if (_message.isComposed()) {\n // @dev Proprietary composeMsg format for the OFT.\n bytes memory composeMsg = OFTComposeMsgCodec.encode(\n _origin.nonce,\n _origin.srcEid,\n amountReceivedLD,\n _message.composeMsg()\n );\n\n // @dev Stores the lzCompose payload that will be executed in a separate tx.\n // Standardizes functionality for executing arbitrary contract invocation on some non-evm chains.\n // @dev The off-chain executor will listen and process the msg based on the src-chain-callers compose options passed.\n // @dev The index is used when a OApp needs to compose multiple msgs on lzReceive.\n // For default OFT implementation there is only 1 compose msg per lzReceive, thus its always 0.\n endpoint.sendCompose(toAddress, _guid, 0 /* the index of the composed message*/, composeMsg);\n }\n\n emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD);\n }\n\n /**\n * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.\n * @param _origin The origin information.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address from the src chain.\n * - nonce: The nonce of the LayerZero message.\n * @param _guid The unique identifier for the received LayerZero message.\n * @param _message The LayerZero message.\n * @param _executor The address of the off-chain executor.\n * @param _extraData Arbitrary data passed by the msg executor.\n *\n * @dev Enables the preCrime simulator to mock sending lzReceive() messages,\n * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.\n */\n function _lzReceiveSimulate(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) internal virtual override {\n _lzReceive(_origin, _guid, _message, _executor, _extraData);\n }\n\n /**\n * @dev Check if the peer is considered 'trusted' by the OApp.\n * @param _eid The endpoint ID to check.\n * @param _peer The peer to check.\n * @return Whether the peer passed is considered 'trusted' by the OApp.\n *\n * @dev Enables OAppPreCrimeSimulator to check whether a potential Inbound Packet is from a trusted source.\n */\n function isPeer(uint32 _eid, bytes32 _peer) public view virtual override returns (bool) {\n return peers[_eid] == _peer;\n }\n\n /**\n * @dev Internal function to remove dust from the given local decimal amount.\n * @param _amountLD The amount in local decimals.\n * @return amountLD The amount after removing dust.\n *\n * @dev Prevents the loss of dust when moving amounts between chains with different decimals.\n * @dev eg. uint(123) with a conversion rate of 100 becomes uint(100).\n */\n function _removeDust(uint256 _amountLD) internal view virtual returns (uint256 amountLD) {\n return (_amountLD / decimalConversionRate) * decimalConversionRate;\n }\n\n /**\n * @dev Internal function to convert an amount from shared decimals into local decimals.\n * @param _amountSD The amount in shared decimals.\n * @return amountLD The amount in local decimals.\n */\n function _toLD(uint64 _amountSD) internal view virtual returns (uint256 amountLD) {\n return _amountSD * decimalConversionRate;\n }\n\n /**\n * @dev Internal function to convert an amount from local decimals into shared decimals.\n * @param _amountLD The amount in local decimals.\n * @return amountSD The amount in shared decimals.\n */\n function _toSD(uint256 _amountLD) internal view virtual returns (uint64 amountSD) {\n return uint64(_amountLD / decimalConversionRate);\n }\n\n /**\n * @dev Internal function to mock the amount mutation from a OFT debit() operation.\n * @param _amountLD The amount to send in local decimals.\n * @param _minAmountLD The minimum amount to send in local decimals.\n * @dev _dstEid The destination endpoint ID.\n * @return amountSentLD The amount sent, in local decimals.\n * @return amountReceivedLD The amount to be received on the remote chain, in local decimals.\n *\n * @dev This is where things like fees would be calculated and deducted from the amount to be received on the remote.\n */\n function _debitView(\n uint256 _amountLD,\n uint256 _minAmountLD,\n uint32 /*_dstEid*/\n ) internal view virtual returns (uint256 amountSentLD, uint256 amountReceivedLD) {\n // @dev Remove the dust so nothing is lost on the conversion between chains with different decimals for the token.\n amountSentLD = _removeDust(_amountLD);\n // @dev The amount to send is the same as amount received in the default implementation.\n amountReceivedLD = amountSentLD;\n\n // @dev Check for slippage.\n if (amountReceivedLD < _minAmountLD) {\n revert SlippageExceeded(amountReceivedLD, _minAmountLD);\n }\n }\n\n /**\n * @dev Internal function to perform a debit operation.\n * @param _from The address to debit.\n * @param _amountLD The amount to send in local decimals.\n * @param _minAmountLD The minimum amount to send in local decimals.\n * @param _dstEid The destination endpoint ID.\n * @return amountSentLD The amount sent in local decimals.\n * @return amountReceivedLD The amount received in local decimals on the remote.\n *\n * @dev Defined here but are intended to be overriden depending on the OFT implementation.\n * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.\n */\n function _debit(\n address _from,\n uint256 _amountLD,\n uint256 _minAmountLD,\n uint32 _dstEid\n ) internal virtual returns (uint256 amountSentLD, uint256 amountReceivedLD);\n\n /**\n * @dev Internal function to perform a credit operation.\n * @param _to The address to credit.\n * @param _amountLD The amount to credit in local decimals.\n * @param _srcEid The source endpoint ID.\n * @return amountReceivedLD The amount ACTUALLY received in local decimals.\n *\n * @dev Defined here but are intended to be overriden depending on the OFT implementation.\n * @dev Depending on OFT implementation the _amountLD could differ from the amountReceivedLD.\n */\n function _credit(\n address _to,\n uint256 _amountLD,\n uint32 _srcEid\n ) internal virtual returns (uint256 amountReceivedLD);\n}\n"
673
- },
674
- "contracts/oft/OFTPrecrime.sol": {
675
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\n// import { IOApp } from \"../../interfaces/IOApp.sol\";\n// import { IOFT } from \"./interfaces/IOFT.sol\";\n// import { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n// import { OFTAdapter } from \"./OFTAdapter.sol\";\n\n//contract OFTPreCrime is PreCrime {\n// address public oft;\n// uint256 public EXPECTED_GLOBAL_SUPPLY;\n//\n// constructor(address _endpoint, address _oft) PreCrime(_endpoint) {\n// oft = _oft;\n// }\n//\n// struct SimulationResult {\n// uint256 totalSupplyLD;\n// bool isAdapter;\n// }\n//\n// // @dev only necessary when its exclusive 'OFT', NOT 'OFTAdapter' type\n// // sum of all tokens in the oft network, it can change, but this will need to be updated for pre-Crime to pass\n// function setGlobalSupply(uint256 _globalSupply) public onlyPreCrimeAdmin {\n// EXPECTED_GLOBAL_SUPPLY = _globalSupply;\n// }\n//\n// // -------------------------------\n// // PreCrime\n// function _receiver() internal view override returns (address) {\n// return address(oft);\n// }\n//\n// function _preCrime(bytes[] memory _simulation) internal view override returns (uint16 code, bytes memory reason) {\n// uint256 globalSupply;\n// uint256 expectedGlobalSupply = EXPECTED_GLOBAL_SUPPLY;\n//\n// // @dev indicates that there is an 'OFTAdapter' on one of the chains, not necessarily this local chain\n// bool isOFTAdapter;\n//\n// for (uint256 i = 0; i < _simulation.length; i++) {\n// SimulationResult memory result = abi.decode(_simulation[i], (SimulationResult));\n//\n// if (result.isAdapter) {\n// // @dev does not support multiple' 'OFTAdapter' contracts for a given oft mesh\n// if (isOFTAdapter) return (CODE_PRECRIME_FAILURE, \"OFTPreCrime: multiple OFTAdapters found\");\n// isOFTAdapter = true;\n//\n// expectedGlobalSupply = result.totalSupplyLD;\n// } else {\n// globalSupply += result.totalSupplyLD;\n// }\n// }\n//\n// if (isOFTAdapter && globalSupply > expectedGlobalSupply) {\n// // @dev expectedGlobal supply for an 'OFTAdapter' can be slightly higher due to users sending tokens direct\n// // to the OFTAdapter contract, cant check explicitly \"==\"\n// return (CODE_PRECRIME_FAILURE, \"OFTPreCrime: globalSupply > expectedGlobalSupply\");\n// } else if (globalSupply != expectedGlobalSupply) {\n// // @dev exclusively 'OFT', NOT 'OFTAdapter' instances, balances should be exactly \"==\"\n// return (CODE_PRECRIME_FAILURE, \"OFTPreCrime: globalSupply != expectedGlobalSupply\");\n// } else {\n// return (CODE_SUCCESS, \"\");\n// }\n// }\n//\n// function simulationCallback() external view override returns (bytes memory result) {\n// address token = IOFT(oft).token();\n//\n// // @dev checks if the corresponding _oft on this chain is an adapter version, or returns false if its regular 'OFT'\n// // eg. 'OFTAdapter' lock/unlock tokens from an external token contract, vs. regular 'OFT' mints/burns\n// bool isAdapter = token != oft;\n//\n// // @dev for 'OFTAdapter' the total supply is the total amount locked, otherwise its the totalSupply of oft tokens on the chain\n// uint256 totalSupply = isAdapter ? IERC20(token).balanceOf(oft) : IERC20(oft).totalSupply();\n//\n// return abi.encode(SimulationResult(totalSupply, isAdapter));\n// }\n//\n// function _simulate(Packet[] calldata _packets) internal override returns (uint16 code, bytes memory simulation) {\n// (bool success, bytes memory result) = oft.call{value: msg.value}(\n// abi.encodeWithSelector(IOApp.lzReceiveAndRevert.selector, _packets)\n// );\n// require(!success, \"OFTPreCrime: simulationCallback should be called via revert\");\n//\n// (, result) = _parseRevertResult(result, LzReceiveRevert.selector);\n// return (CODE_SUCCESS, result);\n// }\n//\n// // @dev need to ensure that all preCrimePeers are present inside of the results passed into _checkResultsCompleteness()\n// // when checking oft preCrime we always want every simulation/result from the remote peers\n// function _getPreCrimePeers(\n// Packet[] calldata /*_packets*/\n// ) internal view override returns (uint32[] memory eids, bytes32[] memory peers) {\n// // @dev assumes that the preCrimeEids is the full list of oft eids for this oft mesh\n// return (preCrimeEids, preCrimePeers);\n// }\n//}\n"
676
- },
677
- "contracts/precrime/extensions/PreCrimeE1.sol": {
678
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport { ILayerZeroEndpoint } from \"@layerzerolabs/lz-evm-v1-0.7/contracts/interfaces/ILayerZeroEndpoint.sol\";\n\nimport { PreCrime } from \"../PreCrime.sol\";\n\nabstract contract PreCrimeE1 is PreCrime {\n using SafeCast for uint32;\n\n uint32 internal immutable localEid;\n\n constructor(uint32 _localEid, address _endpoint, address _simulator) PreCrime(_endpoint, _simulator) {\n localEid = _localEid;\n }\n\n function _getLocalEid() internal view override returns (uint32) {\n return localEid;\n }\n\n function _getInboundNonce(uint32 _srcEid, bytes32 _sender) internal view override returns (uint64) {\n bytes memory path = _getPath(_srcEid, _sender);\n return ILayerZeroEndpoint(lzEndpoint).getInboundNonce(_srcEid.toUint16(), path);\n }\n\n function _getPath(uint32 _srcEid, bytes32 _sender) internal view virtual returns (bytes memory);\n}\n"
679
- },
680
- "contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol": {
681
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\n// @dev Import the Origin so it's exposed to OAppPreCrimeSimulator implementers.\n// solhint-disable-next-line no-unused-import\nimport { InboundPacket, Origin } from \"../libs/Packet.sol\";\n\n/**\n * @title IOAppPreCrimeSimulator Interface\n * @dev Interface for the preCrime simulation functionality in an OApp.\n */\ninterface IOAppPreCrimeSimulator {\n // @dev simulation result used in PreCrime implementation\n error SimulationResult(bytes result);\n error OnlySelf();\n\n /**\n * @dev Emitted when the preCrime contract address is set.\n * @param preCrimeAddress The address of the preCrime contract.\n */\n event PreCrimeSet(address preCrimeAddress);\n\n /**\n * @dev Retrieves the address of the preCrime contract implementation.\n * @return The address of the preCrime contract.\n */\n function preCrime() external view returns (address);\n\n /**\n * @dev Retrieves the address of the OApp contract.\n * @return The address of the OApp contract.\n */\n function oApp() external view returns (address);\n\n /**\n * @dev Sets the preCrime contract address.\n * @param _preCrime The address of the preCrime contract.\n */\n function setPreCrime(address _preCrime) external;\n\n /**\n * @dev Mocks receiving a packet, then reverts with a series of data to infer the state/result.\n * @param _packets An array of LayerZero InboundPacket objects representing received packets.\n */\n function lzReceiveAndRevert(InboundPacket[] calldata _packets) external payable;\n\n /**\n * @dev checks if the specified peer is considered 'trusted' by the OApp.\n * @param _eid The endpoint Id to check.\n * @param _peer The peer to check.\n * @return Whether the peer passed is considered 'trusted' by the OApp.\n */\n function isPeer(uint32 _eid, bytes32 _peer) external view returns (bool);\n}\n"
682
- },
683
- "contracts/precrime/interfaces/IPreCrime.sol": {
684
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\nstruct PreCrimePeer {\n uint32 eid;\n bytes32 preCrime;\n bytes32 oApp;\n}\n\n// TODO not done yet\ninterface IPreCrime {\n error OnlyOffChain();\n\n // for simulate()\n error PacketOversize(uint256 max, uint256 actual);\n error PacketUnsorted();\n error SimulationFailed(bytes reason);\n\n // for preCrime()\n error SimulationResultNotFound(uint32 eid);\n error InvalidSimulationResult(uint32 eid, bytes reason);\n error CrimeFound(bytes crime);\n\n function getConfig(bytes[] calldata _packets, uint256[] calldata _packetMsgValues) external returns (bytes memory);\n\n function simulate(\n bytes[] calldata _packets,\n uint256[] calldata _packetMsgValues\n ) external payable returns (bytes memory);\n\n function buildSimulationResult() external view returns (bytes memory);\n\n function preCrime(\n bytes[] calldata _packets,\n uint256[] calldata _packetMsgValues,\n bytes[] calldata _simulations\n ) external;\n\n function version() external view returns (uint64 major, uint8 minor);\n}\n"
685
- },
686
- "contracts/precrime/libs/Packet.sol": {
687
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { Origin } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\nimport { PacketV1Codec } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/PacketV1Codec.sol\";\n\n/**\n * @title InboundPacket\n * @dev Structure representing an inbound packet received by the contract.\n */\nstruct InboundPacket {\n Origin origin; // Origin information of the packet.\n uint32 dstEid; // Destination endpointId of the packet.\n address receiver; // Receiver address for the packet.\n bytes32 guid; // Unique identifier of the packet.\n uint256 value; // msg.value of the packet.\n address executor; // Executor address for the packet.\n bytes message; // Message payload of the packet.\n bytes extraData; // Additional arbitrary data for the packet.\n}\n\n/**\n * @title PacketDecoder\n * @dev Library for decoding LayerZero packets.\n */\nlibrary PacketDecoder {\n using PacketV1Codec for bytes;\n\n /**\n * @dev Decode an inbound packet from the given packet data.\n * @param _packet The packet data to decode.\n * @return packet An InboundPacket struct representing the decoded packet.\n */\n function decode(bytes calldata _packet) internal pure returns (InboundPacket memory packet) {\n packet.origin = Origin(_packet.srcEid(), _packet.sender(), _packet.nonce());\n packet.dstEid = _packet.dstEid();\n packet.receiver = _packet.receiverB20();\n packet.guid = _packet.guid();\n packet.message = _packet.message();\n }\n\n /**\n * @dev Decode multiple inbound packets from the given packet data and associated message values.\n * @param _packets An array of packet data to decode.\n * @param _packetMsgValues An array of associated message values for each packet.\n * @return packets An array of InboundPacket structs representing the decoded packets.\n */\n function decode(\n bytes[] calldata _packets,\n uint256[] memory _packetMsgValues\n ) internal pure returns (InboundPacket[] memory packets) {\n packets = new InboundPacket[](_packets.length);\n for (uint256 i = 0; i < _packets.length; i++) {\n bytes calldata packet = _packets[i];\n packets[i] = PacketDecoder.decode(packet);\n // @dev Allows the verifier to specify the msg.value that gets passed in lzReceive.\n packets[i].value = _packetMsgValues[i];\n }\n }\n}\n"
688
- },
689
- "contracts/precrime/OAppPreCrimeSimulator.sol": {
690
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IPreCrime } from \"./interfaces/IPreCrime.sol\";\nimport { IOAppPreCrimeSimulator, InboundPacket, Origin } from \"./interfaces/IOAppPreCrimeSimulator.sol\";\n\n/**\n * @title OAppPreCrimeSimulator\n * @dev Abstract contract serving as the base for preCrime simulation functionality in an OApp.\n */\nabstract contract OAppPreCrimeSimulator is IOAppPreCrimeSimulator, Ownable {\n // The address of the preCrime implementation.\n address public preCrime;\n\n /**\n * @dev Retrieves the address of the OApp contract.\n * @return The address of the OApp contract.\n *\n * @dev The simulator contract is the base contract for the OApp by default.\n * @dev If the simulator is a separate contract, override this function.\n */\n function oApp() external view virtual returns (address) {\n return address(this);\n }\n\n /**\n * @dev Sets the preCrime contract address.\n * @param _preCrime The address of the preCrime contract.\n */\n function setPreCrime(address _preCrime) public virtual onlyOwner {\n preCrime = _preCrime;\n emit PreCrimeSet(_preCrime);\n }\n\n /**\n * @dev Interface for pre-crime simulations. Always reverts at the end with the simulation results.\n * @param _packets An array of InboundPacket objects representing received packets to be delivered.\n *\n * @dev WARNING: MUST revert at the end with the simulation results.\n * @dev Gives the preCrime implementation the ability to mock sending packets to the lzReceive function,\n * WITHOUT actually executing them.\n */\n function lzReceiveAndRevert(InboundPacket[] calldata _packets) public payable virtual {\n for (uint256 i = 0; i < _packets.length; i++) {\n InboundPacket calldata packet = _packets[i];\n\n // Ignore packets that are not from trusted peers.\n if (!isPeer(packet.origin.srcEid, packet.origin.sender)) continue;\n\n // @dev Because a verifier is calling this function, it doesnt have access to executor params:\n // - address _executor\n // - bytes calldata _extraData\n // preCrime will NOT work for OApps that rely on these two parameters inside of their _lzReceive().\n // They are instead stubbed to default values, address(0) and bytes(\"\")\n // @dev Calling this.lzReceiveSimulate removes ability for assembly return 0 callstack exit,\n // which would cause the revert to be ignored.\n this.lzReceiveSimulate{ value: packet.value }(\n packet.origin,\n packet.guid,\n packet.message,\n packet.executor,\n packet.extraData\n );\n }\n\n // @dev Revert with the simulation results. msg.sender must implement IPreCrime.buildSimulationResult().\n revert SimulationResult(IPreCrime(msg.sender).buildSimulationResult());\n }\n\n /**\n * @dev Is effectively an internal function because msg.sender must be address(this).\n * Allows resetting the call stack for 'internal' calls.\n * @param _origin The origin information containing the source endpoint and sender address.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address on the src chain.\n * - nonce: The nonce of the message.\n * @param _guid The unique identifier of the packet.\n * @param _message The message payload of the packet.\n * @param _executor The executor address for the packet.\n * @param _extraData Additional data for the packet.\n */\n function lzReceiveSimulate(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) external payable virtual {\n // @dev Ensure ONLY can be called 'internally'.\n if (msg.sender != address(this)) revert OnlySelf();\n _lzReceiveSimulate(_origin, _guid, _message, _executor, _extraData);\n }\n\n /**\n * @dev Internal function to handle the OAppPreCrimeSimulator simulated receive.\n * @param _origin The origin information.\n * - srcEid: The source chain endpoint ID.\n * - sender: The sender address from the src chain.\n * - nonce: The nonce of the LayerZero message.\n * @param _guid The GUID of the LayerZero message.\n * @param _message The LayerZero message.\n * @param _executor The address of the off-chain executor.\n * @param _extraData Arbitrary data passed by the msg executor.\n *\n * @dev Enables the preCrime simulator to mock sending lzReceive() messages,\n * routes the msg down from the OAppPreCrimeSimulator, and back up to the OAppReceiver.\n */\n function _lzReceiveSimulate(\n Origin calldata _origin,\n bytes32 _guid,\n bytes calldata _message,\n address _executor,\n bytes calldata _extraData\n ) internal virtual;\n\n /**\n * @dev checks if the specified peer is considered 'trusted' by the OApp.\n * @param _eid The endpoint Id to check.\n * @param _peer The peer to check.\n * @return Whether the peer passed is considered 'trusted' by the OApp.\n */\n function isPeer(uint32 _eid, bytes32 _peer) public view virtual returns (bool);\n}\n"
691
- },
692
- "contracts/precrime/PreCrime.sol": {
693
- "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { BytesLib } from \"solidity-bytes-utils/contracts/BytesLib.sol\";\nimport { ILayerZeroEndpointV2 } from \"@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\";\n\nimport { IPreCrime, PreCrimePeer } from \"./interfaces/IPreCrime.sol\";\nimport { IOAppPreCrimeSimulator } from \"./interfaces/IOAppPreCrimeSimulator.sol\";\nimport { InboundPacket, PacketDecoder } from \"./libs/Packet.sol\";\n\nabstract contract PreCrime is Ownable, IPreCrime {\n using BytesLib for bytes;\n\n uint16 internal constant CONFIG_VERSION = 2;\n address internal constant OFF_CHAIN_CALLER = address(0xDEAD);\n\n address internal immutable lzEndpoint;\n address public immutable simulator;\n address public immutable oApp;\n\n // preCrime config\n uint64 public maxBatchSize;\n PreCrimePeer[] internal preCrimePeers;\n\n /// @dev getConfig(), simulate() and preCrime() are not view functions because it is more flexible to be able to\n /// update state for some complex logic. So onlyOffChain() modifier is to make sure they are only called\n /// by the off-chain.\n modifier onlyOffChain() {\n if (msg.sender != OFF_CHAIN_CALLER) revert OnlyOffChain();\n _;\n }\n\n constructor(address _endpoint, address _simulator) {\n lzEndpoint = _endpoint;\n simulator = _simulator;\n oApp = IOAppPreCrimeSimulator(_simulator).oApp();\n }\n\n function setMaxBatchSize(uint64 _maxBatchSize) external onlyOwner {\n maxBatchSize = _maxBatchSize;\n }\n\n function setPreCrimePeers(PreCrimePeer[] calldata _preCrimePeers) external onlyOwner {\n delete preCrimePeers;\n for (uint256 i = 0; i < _preCrimePeers.length; ++i) {\n preCrimePeers.push(_preCrimePeers[i]);\n }\n }\n\n function getPreCrimePeers() external view returns (PreCrimePeer[] memory) {\n return preCrimePeers;\n }\n\n function getConfig(\n bytes[] calldata _packets,\n uint256[] calldata _packetMsgValues\n ) external onlyOffChain returns (bytes memory) {\n bytes memory config = abi.encodePacked(CONFIG_VERSION, maxBatchSize);\n\n // if no packets, return config with all peers\n PreCrimePeer[] memory peers = _packets.length == 0\n ? preCrimePeers\n : _getPreCrimePeers(PacketDecoder.decode(_packets, _packetMsgValues));\n\n if (peers.length > 0) {\n uint16 size = uint16(peers.length);\n config = abi.encodePacked(config, size);\n\n for (uint256 i = 0; i < size; ++i) {\n config = abi.encodePacked(config, peers[i].eid, peers[i].preCrime, peers[i].oApp);\n }\n }\n\n return config;\n }\n\n // @dev _packetMsgValues refers to the 'lzReceive' option passed per packet\n function simulate(\n bytes[] calldata _packets,\n uint256[] calldata _packetMsgValues\n ) external payable override onlyOffChain returns (bytes memory) {\n InboundPacket[] memory packets = PacketDecoder.decode(_packets, _packetMsgValues);\n _checkPacketSizeAndOrder(packets);\n return _simulate(packets);\n }\n\n function preCrime(\n bytes[] calldata _packets,\n uint256[] calldata _packetMsgValues,\n bytes[] calldata _simulations\n ) external onlyOffChain {\n InboundPacket[] memory packets = PacketDecoder.decode(_packets, _packetMsgValues);\n uint32[] memory eids = new uint32[](_simulations.length);\n bytes[] memory simulations = new bytes[](_simulations.length);\n\n for (uint256 i = 0; i < _simulations.length; ++i) {\n bytes calldata simulation = _simulations[i];\n eids[i] = uint32(bytes4(simulation[0:4]));\n simulations[i] = simulation[4:];\n }\n _checkResultsCompleteness(packets, eids);\n\n _preCrime(packets, eids, simulations);\n }\n\n function version() external pure returns (uint64 major, uint8 minor) {\n return (2, 0);\n }\n\n function _checkResultsCompleteness(InboundPacket[] memory _packets, uint32[] memory _eids) internal {\n // check if all peers result included\n if (_packets.length > 0) {\n PreCrimePeer[] memory peers = _getPreCrimePeers(_packets);\n for (uint256 i = 0; i < peers.length; i++) {\n uint32 expectedEid = peers[i].eid;\n if (!_isContain(_eids, expectedEid)) revert SimulationResultNotFound(expectedEid);\n }\n }\n\n // check if local result included\n uint32 localEid = _getLocalEid();\n if (!_isContain(_eids, localEid)) revert SimulationResultNotFound(localEid);\n }\n\n function _isContain(uint32[] memory _array, uint32 _item) internal pure returns (bool) {\n for (uint256 i = 0; i < _array.length; i++) {\n if (_array[i] == _item) return true;\n }\n return false;\n }\n\n function _checkPacketSizeAndOrder(InboundPacket[] memory _packets) internal view {\n if (_packets.length > maxBatchSize) revert PacketOversize(maxBatchSize, _packets.length);\n\n // check packets nonce, sequence order\n // packets should ordered in ascending order by srcEid, sender, nonce\n if (_packets.length > 0) {\n uint32 srcEid;\n bytes32 sender;\n uint64 nonce;\n for (uint256 i = 0; i < _packets.length; i++) {\n InboundPacket memory packet = _packets[i];\n\n // skip if not from trusted peer\n if (!IOAppPreCrimeSimulator(simulator).isPeer(packet.origin.srcEid, packet.origin.sender)) continue;\n\n if (\n packet.origin.srcEid < srcEid || (packet.origin.srcEid == srcEid && packet.origin.sender < sender)\n ) {\n revert PacketUnsorted();\n } else if (packet.origin.srcEid != srcEid || packet.origin.sender != sender) {\n // start from a new chain or a new source oApp\n srcEid = packet.origin.srcEid;\n sender = packet.origin.sender;\n nonce = _getInboundNonce(srcEid, sender);\n }\n // TODO ??\n // Wont the nonce order not matter and enforced at the OApp level? the simulation will revert?\n\n // the following packet's nonce add 1 in order\n if (packet.origin.nonce != ++nonce) revert PacketUnsorted();\n }\n }\n }\n\n function _simulate(InboundPacket[] memory _packets) internal virtual returns (bytes memory) {\n (bool success, bytes memory returnData) = simulator.call{ value: msg.value }(\n abi.encodeWithSelector(IOAppPreCrimeSimulator.lzReceiveAndRevert.selector, _packets)\n );\n\n bytes memory result = _parseRevertResult(success, returnData);\n return abi.encodePacked(_getLocalEid(), result); // add localEid at the first of the result\n }\n\n function _parseRevertResult(bool _success, bytes memory _returnData) internal pure returns (bytes memory result) {\n // should always revert with LzReceiveRevert\n if (_success) revert SimulationFailed(\"no revert\");\n\n // if not expected selector, bubble up error\n if (bytes4(_returnData) != IOAppPreCrimeSimulator.SimulationResult.selector) {\n revert SimulationFailed(_returnData);\n }\n\n // Slice the sighash. Remove the selector which is the first 4 bytes\n result = _returnData.slice(4, _returnData.length - 4);\n result = abi.decode(result, (bytes));\n }\n\n // to be compatible with EndpointV1\n function _getLocalEid() internal view virtual returns (uint32) {\n return ILayerZeroEndpointV2(lzEndpoint).eid();\n }\n\n // to be compatible with EndpointV1\n function _getInboundNonce(uint32 _srcEid, bytes32 _sender) internal view virtual returns (uint64) {\n return ILayerZeroEndpointV2(lzEndpoint).inboundNonce(oApp, _srcEid, _sender);\n }\n\n // ----------------- to be implemented -----------------\n function buildSimulationResult() external view virtual override returns (bytes memory);\n\n function _getPreCrimePeers(InboundPacket[] memory _packets) internal virtual returns (PreCrimePeer[] memory peers);\n\n function _preCrime(\n InboundPacket[] memory _packets,\n uint32[] memory _eids,\n bytes[] memory _simulations\n ) internal virtual;\n}\n"
694
489
  }
695
490
  },
696
- "language": "Solidity"
491
+ "settings": {
492
+ "optimizer": {
493
+ "enabled": true,
494
+ "runs": 20000
495
+ },
496
+ "evmVersion": "paris",
497
+ "outputSelection": {
498
+ "*": {
499
+ "*": [
500
+ "abi",
501
+ "evm.bytecode",
502
+ "evm.deployedBytecode",
503
+ "evm.methodIdentifiers",
504
+ "metadata",
505
+ "devdoc",
506
+ "userdoc",
507
+ "storageLayout",
508
+ "evm.gasEstimates"
509
+ ],
510
+ "": [
511
+ "ast"
512
+ ]
513
+ }
514
+ },
515
+ "metadata": {
516
+ "useLiteralContent": true
517
+ }
518
+ }
697
519
  }
698
520
  }