@layerzerolabs/lz-evm-sdk-v1 3.0.112 → 3.0.113-verify.0
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.
- package/artifacts/verification-data.json +329 -0
- package/artifacts-tron/verification-data.json +284 -0
- package/artifacts-zk/verification-data.json +233 -0
- package/deployments/arbitrum-sandbox-local/DefaultProxyAdmin.json +7 -7
- package/deployments/arbitrum-sandbox-local/Endpoint.json +5 -5
- package/deployments/arbitrum-sandbox-local/FPValidator.json +3 -3
- package/deployments/arbitrum-sandbox-local/MPTValidator01.json +3 -3
- package/deployments/arbitrum-sandbox-local/NonceContract.json +3 -3
- package/deployments/arbitrum-sandbox-local/RelayerV2.json +11 -11
- package/deployments/arbitrum-sandbox-local/RelayerV2_Implementation.json +3 -3
- package/deployments/arbitrum-sandbox-local/RelayerV2_Proxy.json +11 -11
- package/deployments/arbitrum-sandbox-local/TreasuryV2.json +5 -5
- package/deployments/arbitrum-sandbox-local/UltraLightNode.json +5 -5
- package/deployments/arbitrum-sandbox-local/UltraLightNodeV2.json +5 -5
- package/deployments/bsc-sandbox-local/DefaultProxyAdmin.json +7 -7
- package/deployments/bsc-sandbox-local/Endpoint.json +5 -5
- package/deployments/bsc-sandbox-local/FPValidator.json +3 -3
- package/deployments/bsc-sandbox-local/MPTValidator01.json +3 -3
- package/deployments/bsc-sandbox-local/NonceContract.json +3 -3
- package/deployments/bsc-sandbox-local/RelayerV2.json +11 -11
- package/deployments/bsc-sandbox-local/RelayerV2_Implementation.json +3 -3
- package/deployments/bsc-sandbox-local/RelayerV2_Proxy.json +11 -11
- package/deployments/bsc-sandbox-local/TreasuryV2.json +5 -5
- package/deployments/bsc-sandbox-local/UltraLightNode.json +5 -5
- package/deployments/bsc-sandbox-local/UltraLightNodeV2.json +5 -5
- package/deployments/ethereum-sandbox-local/DefaultProxyAdmin.json +10 -10
- package/deployments/ethereum-sandbox-local/Endpoint.json +7 -7
- package/deployments/ethereum-sandbox-local/FPValidator.json +4 -4
- package/deployments/ethereum-sandbox-local/MPTValidator01.json +4 -4
- package/deployments/ethereum-sandbox-local/NonceContract.json +4 -4
- package/deployments/ethereum-sandbox-local/RelayerV2.json +16 -16
- package/deployments/ethereum-sandbox-local/RelayerV2_Implementation.json +4 -4
- package/deployments/ethereum-sandbox-local/RelayerV2_Proxy.json +16 -16
- package/deployments/ethereum-sandbox-local/TreasuryV2.json +7 -7
- package/deployments/ethereum-sandbox-local/UltraLightNode.json +7 -7
- package/deployments/ethereum-sandbox-local/UltraLightNodeV2.json +7 -7
- package/deployments/polygon-sandbox-local/DefaultProxyAdmin.json +10 -10
- package/deployments/polygon-sandbox-local/Endpoint.json +7 -7
- package/deployments/polygon-sandbox-local/FPValidator.json +4 -4
- package/deployments/polygon-sandbox-local/MPTValidator01.json +4 -4
- package/deployments/polygon-sandbox-local/NonceContract.json +4 -4
- package/deployments/polygon-sandbox-local/RelayerV2.json +16 -16
- package/deployments/polygon-sandbox-local/RelayerV2_Implementation.json +4 -4
- package/deployments/polygon-sandbox-local/RelayerV2_Proxy.json +16 -16
- package/deployments/polygon-sandbox-local/TreasuryV2.json +7 -7
- package/deployments/polygon-sandbox-local/UltraLightNode.json +7 -7
- package/deployments/polygon-sandbox-local/UltraLightNodeV2.json +7 -7
- package/deployments/tron-sandbox-local/DefaultProxyAdmin.json +14 -14
- package/deployments/tron-sandbox-local/Endpoint.json +10 -10
- package/deployments/tron-sandbox-local/FPValidator.json +6 -6
- package/deployments/tron-sandbox-local/MPTValidator01.json +6 -6
- package/deployments/tron-sandbox-local/NonceContract.json +7 -7
- package/deployments/tron-sandbox-local/RelayerV2.json +31 -31
- package/deployments/tron-sandbox-local/RelayerV2_Implementation.json +6 -6
- package/deployments/tron-sandbox-local/RelayerV2_Proxy.json +28 -28
- package/deployments/tron-sandbox-local/TreasuryV2.json +11 -11
- package/deployments/tron-sandbox-local/UltraLightNode.json +11 -11
- package/deployments/tron-sandbox-local/UltraLightNodeV2.json +12 -12
- package/package.json +13 -9
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
{
|
|
2
|
+
"solcLongVersion": "0.7.6+commit.7338295f",
|
|
3
|
+
"input": {
|
|
4
|
+
"sources": {
|
|
5
|
+
"contracts/arbitrum/interfaces/ArbSys.sol": {
|
|
6
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.4.21 <0.9.0;\n\n/**\n * @title Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. Exposes a variety of system-level functionality.\n */\ninterface ArbSys {\n /**\n * @notice Get internal version number identifying an ArbOS build\n * @return version number as int\n */\n function arbOSVersion() external pure returns (uint);\n\n function arbChainID() external view returns (uint);\n\n /**\n * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)\n * @return block number as int\n */\n function arbBlockNumber() external view returns (uint);\n\n /**\n * @notice Send given amount of Eth to dest from sender.\n * This is a convenience function, which is equivalent to calling sendTxToL1 with empty calldataForL1.\n * @param destination recipient address on L1\n * @return unique identifier for this L2-to-L1 transaction.\n */\n function withdrawEth(address destination) external payable returns (uint);\n\n /**\n * @notice Send a transaction to L1\n * @param destination recipient address on L1\n * @param calldataForL1 (optional) calldata for L1 contract call\n * @return a unique identifier for this L2-to-L1 transaction.\n */\n function sendTxToL1(address destination, bytes calldata calldataForL1) external payable returns (uint);\n\n /**\n * @notice get the number of transactions issued by the given external account or the account sequence number of the given contract\n * @param account target account\n * @return the number of transactions issued by the given external account or the account sequence number of the given contract\n */\n function getTransactionCount(address account) external view returns (uint256);\n\n /**\n * @notice get the value of target L2 storage slot\n * This function is only callable from address 0 to prevent contracts from being able to call it\n * @param account target account\n * @param index target index of storage slot\n * @return stotage value for the given account at the given index\n */\n function getStorageAt(address account, uint256 index) external view returns (uint256);\n\n /**\n * @notice check if current call is coming from l1\n * @return true if the caller of this was called directly from L1\n */\n function isTopLevelCall() external view returns (bool);\n\n /**\n * @notice check if the caller (of this caller of this) is an aliased L1 contract address\n * @return true iff the caller's address is an alias for an L1 contract address\n */\n function wasMyCallersAddressAliased() external view returns (bool);\n\n /**\n * @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing\n * @return address of the caller's caller, without applying L1 contract address aliasing\n */\n function myCallersAddressWithoutAliasing() external view returns (address);\n\n /**\n * @notice map L1 sender contract address to its L2 alias\n * @param sender sender address\n * @param dest destination address\n * @return aliased sender address\n */\n function mapL1SenderContractAddressToL2Alias(address sender, address dest) external pure returns (address);\n\n /**\n * @notice get the caller's amount of available storage gas\n * @return amount of storage gas available to the caller\n */\n function getStorageGasAvailable() external view returns (uint);\n\n event L2ToL1Transaction(\n address caller,\n address indexed destination,\n uint indexed uniqueId,\n uint indexed batchNumber,\n uint indexInBatch,\n uint arbBlockNum,\n uint ethBlockNum,\n uint timestamp,\n uint callvalue,\n bytes data\n );\n}\n"
|
|
7
|
+
},
|
|
8
|
+
"contracts/mocks/ContractOne.sol": {
|
|
9
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\ncontract ContractOne {\n uint x;\n\n function setIt(uint _x) external {\n x = _x;\n }\n}\n"
|
|
10
|
+
},
|
|
11
|
+
"contracts/mocks/IsContract.sol": {
|
|
12
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\ncontract IsContract {\n function isAddressContract(address addr) external view returns (bool) {\n // check if the toAddress is a contract. We are not concerned about addresses that pretend to be wallets. because worst case we just delete their payload if being malicious\n // we can guarantee that if a size > 0, then the contract is definitely a contract address in this context\n uint size;\n assembly {\n size := extcodesize(addr)\n }\n return size != 0;\n }\n}\n"
|
|
13
|
+
},
|
|
14
|
+
"contracts/precrime/example/inherit/CounterI.sol": {
|
|
15
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"./CounterPrecrime.sol\";\n\ncontract CounterI is CounterPrecrime {\n // keep track of how many messages have been received from other chains\n uint public totalCount;\n mapping(uint32 => uint) public inboundCount;\n mapping(uint32 => uint) public outboundCount;\n\n event Send(uint16 dstChainId);\n event Receive(uint16 srcChainId);\n\n uint16 public chainId;\n\n constructor(uint16 _chainId) CounterPrecrime(_chainId) {\n chainId = _chainId;\n }\n\n function lzReceive(uint16 _srcChainId) public {\n inboundCount[_srcChainId]++;\n totalCount++;\n\n emit Receive(_srcChainId);\n }\n\n function increment(uint16 _dstChainId) external {\n outboundCount[_dstChainId]++;\n\n emit Send(_dstChainId);\n }\n\n function brokeIncrement(uint16 _dstChainId) external {\n emit Send(_dstChainId);\n }\n\n function brokeTotalCount() external {\n totalCount++;\n }\n\n function getInboundNonce(uint32 _chainId) public view returns (uint) {\n // in reality, this would be a call to the LayerZero endpoint\n return inboundCount[_chainId];\n }\n\n // ------------- precrime -----------------\n function _lzReceiveByPacket(Packet calldata _packet) internal virtual override {\n lzReceive(uint16(_packet.srcChainId));\n }\n\n function getCountState(uint16[] memory peers) public view virtual override returns (CountState memory) {\n ChainPathCount[] memory chainPathCounts = new ChainPathCount[](peers.length);\n for (uint i = 0; i < peers.length; i++) {\n uint16 peer = peers[i];\n chainPathCounts[i] = ChainPathCount({\n eid: peer,\n inboundCount: inboundCount[peer],\n outboundCount: outboundCount[peer]\n });\n }\n\n CountState memory countState = CountState({totalCount: totalCount, chainPathCounts: chainPathCounts});\n\n return countState;\n }\n\n function _getInboundNonce(Packet memory packet) internal view override returns (uint64) {\n // in reality, this would be a call to the LayerZero endpoint\n return uint64(inboundCount[packet.srcChainId]);\n }\n}\n"
|
|
16
|
+
},
|
|
17
|
+
"contracts/precrime/example/inherit/CounterPrecrime.sol": {
|
|
18
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"../../PreCrime.sol\";\n\nabstract contract CounterPrecrime is PreCrime {\n uint16[] public remoteChainIds;\n bytes32[] public remotePrecrimeAddresses;\n\n struct SimulationResult {\n uint16 chainId;\n CountState countState;\n }\n\n struct CountState {\n uint totalCount;\n ChainPathCount[] chainPathCounts;\n }\n\n struct ChainPathCount {\n uint16 eid;\n uint inboundCount;\n uint outboundCount;\n }\n\n constructor(uint16 _localChainId) PreCrime(_localChainId) {\n maxBatchSize = 10;\n }\n\n function setRemotePrecrimeAddresses(\n uint16[] memory _remoteChainIds,\n bytes32[] memory _remotePrecrimeAddresses\n ) public onlyPrecrimeAdmin {\n require(_remoteChainIds.length == _remotePrecrimeAddresses.length, \"Precrime: invalid size\");\n remoteChainIds = _remoteChainIds;\n remotePrecrimeAddresses = _remotePrecrimeAddresses;\n }\n\n function _simulate(Packet[] calldata _packets) internal override returns (uint16 code, bytes memory data) {\n // simulate\n for (uint256 i = 0; i < _packets.length; i++) {\n _lzReceiveByPacket(_packets[i]);\n }\n\n // return simulation result\n bytes memory result = abi.encode(\n SimulationResult({chainId: localChainId, countState: getCountState(remoteChainIds)})\n );\n return (CODE_SUCCESS, result);\n }\n\n function _precrime(\n bytes[] memory _simulation\n ) internal view virtual override returns (uint16 code, bytes memory reason) {\n (SimulationResult memory localResult, SimulationResult[] memory results) = _getLocalSimulateResult(_simulation);\n\n uint sumOutboundCount = 0;\n // for each chainPathCount, find the chainPathCount and check the counts\n for (uint256 j = 0; j < localResult.countState.chainPathCounts.length; j++) {\n ChainPathCount memory cpCount = localResult.countState.chainPathCounts[j];\n // find remote to local count state\n // should provide all peers simulated results\n ChainPathCount memory remoteCp = _getRemoteCpCount(results, cpCount.eid);\n (code, reason) = _assertChainPathCount(cpCount, remoteCp);\n if (code != CODE_SUCCESS) {\n return (code, reason);\n }\n sumOutboundCount += remoteCp.outboundCount; // remote to local outbound count\n }\n (code, reason) = _assertTotalCount(localResult.countState, sumOutboundCount);\n if (code != CODE_SUCCESS) {\n return (code, reason);\n }\n\n return (CODE_SUCCESS, \"\");\n }\n\n function _lzReceiveByPacket(Packet calldata _packet) internal virtual;\n\n /**\n * @notice Get the count states for a list of peers\n * @param peers - the list of remote chainId to get counts for\n * @return counts - the CountState with the total count and the chain path counts\n */\n function getCountState(uint16[] memory peers) public view virtual returns (CountState memory);\n\n function _getRemoteCpCount(\n SimulationResult[] memory _results,\n uint16 _remoteId\n ) internal view returns (ChainPathCount memory) {\n uint localEid = localChainId;\n for (uint256 i = 0; i < _results.length; i++) {\n SimulationResult memory remoteResult = _results[i];\n if (remoteResult.chainId == _remoteId) {\n for (uint256 j = 0; j < remoteResult.countState.chainPathCounts.length; j++) {\n ChainPathCount memory cpCount = remoteResult.countState.chainPathCounts[j];\n if (cpCount.eid == localEid) {\n // find to localEid path\n return cpCount;\n }\n }\n }\n }\n revert(\"Precrime: countState not found, are you missing a simulation?\");\n }\n\n function _getLocalSimulateResult(\n bytes[] memory _simulation\n ) internal view returns (SimulationResult memory localResult, SimulationResult[] memory results) {\n // decode results\n results = new SimulationResult[](_simulation.length);\n for (uint256 i = 0; i < _simulation.length; i++) {\n bytes memory result = _simulation[i];\n results[i] = abi.decode(result, (SimulationResult));\n if (results[i].chainId == localChainId) {\n localResult = results[i];\n }\n }\n }\n\n function _assertChainPathCount(\n ChainPathCount memory _localCpCount,\n ChainPathCount memory _remoteCpCount\n ) internal pure returns (uint16 code, bytes memory reason) {\n if (_localCpCount.inboundCount > _remoteCpCount.outboundCount) {\n return (CODE_PRECRIME_FAILURE, \"Precrime: inboundCount > outboundCount\");\n }\n if (_localCpCount.outboundCount > _remoteCpCount.inboundCount) {\n return (CODE_PRECRIME_FAILURE, \"Precrime: outboundCount > inboundCount\");\n }\n return (CODE_SUCCESS, \"\");\n }\n\n function _assertTotalCount(\n CountState memory _localCount,\n uint _sumOutbound\n ) internal pure returns (uint16 code, bytes memory reason) {\n if (_localCount.totalCount > _sumOutbound) {\n return (CODE_PRECRIME_FAILURE, \"Precrime: totalCount > sum outboundCount\");\n }\n }\n\n function _remotePrecrimeAddress(\n Packet[] calldata _packets\n ) internal view override returns (uint16[] memory chainIds, bytes32[] memory precrimeAddresses) {\n if (_packets.length == 0) {\n return (remoteChainIds, remotePrecrimeAddresses);\n }\n\n // only return related remotes\n uint16 size = _getRelatedRemoteSize(_packets);\n if (size > 0) {\n chainIds = new uint16[](size);\n uint256 k = 0;\n precrimeAddresses = new bytes32[](size);\n for (uint16 i = 0; i < remoteChainIds.length; i++) {\n for (uint16 j = 0; j < _packets.length; j++) {\n uint16 srcChainId = _packets[j].srcChainId;\n if (remoteChainIds[i] == srcChainId) {\n chainIds[k] = srcChainId;\n precrimeAddresses[k] = remotePrecrimeAddresses[i];\n k++;\n break;\n }\n }\n }\n }\n }\n\n function _getRelatedRemoteSize(Packet[] memory _packets) internal view returns (uint16 size) {\n for (uint16 i = 0; i < remoteChainIds.length; i++) {\n for (uint16 j = 0; j < _packets.length; j++) {\n if (remoteChainIds[i] == _packets[j].srcChainId) {\n size++;\n break;\n }\n }\n }\n }\n}\n"
|
|
19
|
+
},
|
|
20
|
+
"contracts/precrime/example/view/CounterPrecrimeView.sol": {
|
|
21
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"../../PreCrimeView.sol\";\nimport \"./CounterView.sol\";\nimport \"./CounterV.sol\";\n\ncontract CounterPrecrimeView is PreCrimeView {\n CounterView public counterView;\n\n uint16[] public remoteChainIds;\n bytes32[] public remotePrecrimeAddresses;\n\n struct SimulationResult {\n uint16 chainId;\n CounterView.CountState countState;\n }\n\n constructor(uint16 _localChainId, address _counterView) PreCrimeView(_localChainId) {\n counterView = CounterView(_counterView);\n maxBatchSize = 10;\n }\n\n function setRemotePrecrimeAddresses(\n uint16[] memory _remoteChainIds,\n bytes32[] memory _remotePrecrimeAddresses\n ) public onlyPrecrimeAdmin {\n require(_remoteChainIds.length == _remotePrecrimeAddresses.length, \"Precrime: invalid size\");\n remoteChainIds = _remoteChainIds;\n remotePrecrimeAddresses = _remotePrecrimeAddresses;\n }\n\n function setCounterView(address _counterView) public onlyPrecrimeAdmin {\n counterView = CounterView(_counterView);\n }\n\n function _simulate(Packet[] calldata _packets) internal view override returns (uint16 code, bytes memory data) {\n // get state from counter\n CounterView.CountState memory countState = counterView.getCountState(remoteChainIds);\n\n // simulate\n for (uint256 i = 0; i < _packets.length; i++) {\n Packet memory packet = _packets[i];\n countState = counterView.lzReceive(countState, packet.srcChainId);\n }\n\n // return simulation result\n return (CODE_SUCCESS, abi.encode(SimulationResult({chainId: localChainId, countState: countState})));\n }\n\n function _precrime(\n bytes[] memory _simulation\n ) internal view virtual override returns (uint16 code, bytes memory reason) {\n (SimulationResult memory localResult, SimulationResult[] memory results) = _getLocalSimulateResult(_simulation);\n\n uint sumOutboundCount = 0;\n // for each chainPathCount, find the chainPathCount and check the counts\n for (uint256 j = 0; j < localResult.countState.chainPathCounts.length; j++) {\n CounterView.ChainPathCount memory cpCount = localResult.countState.chainPathCounts[j];\n // find remote to local count state\n // should provide all peers simulated results\n CounterView.ChainPathCount memory remoteCp = _getRemoteCpCount(results, cpCount.eid);\n (code, reason) = _assertChainPathCount(cpCount, remoteCp);\n if (code != CODE_SUCCESS) {\n return (code, reason);\n }\n sumOutboundCount += remoteCp.outboundCount; // remote to local outbound count\n }\n (code, reason) = _assertTotalCount(localResult.countState, sumOutboundCount);\n if (code != CODE_SUCCESS) {\n return (code, reason);\n }\n\n return (CODE_SUCCESS, \"\");\n }\n\n function _getRemoteCpCount(\n SimulationResult[] memory _results,\n uint16 _remoteId\n ) internal view returns (CounterView.ChainPathCount memory) {\n uint localEid = localChainId;\n for (uint256 i = 0; i < _results.length; i++) {\n SimulationResult memory remoteResult = _results[i];\n if (remoteResult.chainId == _remoteId) {\n for (uint256 j = 0; j < remoteResult.countState.chainPathCounts.length; j++) {\n CounterView.ChainPathCount memory cpCount = remoteResult.countState.chainPathCounts[j];\n if (cpCount.eid == localEid) {\n // find to localEid path\n return cpCount;\n }\n }\n }\n }\n revert(\"Precrime: count state not found\");\n }\n\n function _getLocalSimulateResult(\n bytes[] memory _simulation\n ) internal view returns (SimulationResult memory localResult, SimulationResult[] memory results) {\n // decode results\n results = new SimulationResult[](_simulation.length);\n for (uint256 i = 0; i < _simulation.length; i++) {\n results[i] = abi.decode(_simulation[i], (SimulationResult));\n if (results[i].chainId == localChainId) {\n localResult = results[i];\n }\n }\n }\n\n function _assertChainPathCount(\n CounterView.ChainPathCount memory _localCpCount,\n CounterView.ChainPathCount memory _remoteCpCount\n ) internal pure returns (uint16 code, bytes memory reason) {\n if (_localCpCount.inboundCount > _remoteCpCount.outboundCount) {\n return (CODE_PRECRIME_FAILURE, \"Precrime: inboundCount > outboundCount\");\n }\n if (_localCpCount.outboundCount > _remoteCpCount.inboundCount) {\n return (CODE_PRECRIME_FAILURE, \"Precrime: outboundCount > inboundCount\");\n }\n return (CODE_SUCCESS, \"\");\n }\n\n function _assertTotalCount(\n CounterView.CountState memory _localCount,\n uint _sumOutbound\n ) internal pure returns (uint16 code, bytes memory reason) {\n if (_localCount.totalCount > _sumOutbound) {\n return (CODE_PRECRIME_FAILURE, \"Precrime: totalCount > sum outboundCount\");\n }\n return (CODE_SUCCESS, \"\");\n }\n\n function _remotePrecrimeAddress(\n Packet[] calldata _packets\n ) internal view override returns (uint16[] memory chainIds, bytes32[] memory precrimeAddresses) {\n if (_packets.length == 0) {\n return (remoteChainIds, remotePrecrimeAddresses);\n }\n\n // only return related remotes\n uint16 size = _getRelatedRemoteSize(_packets);\n if (size > 0) {\n chainIds = new uint16[](size);\n uint256 k = 0;\n precrimeAddresses = new bytes32[](size);\n for (uint16 i = 0; i < remoteChainIds.length; i++) {\n for (uint16 j = 0; j < _packets.length; j++) {\n uint16 srcChainId = _packets[j].srcChainId;\n if (remoteChainIds[i] == srcChainId) {\n chainIds[k] = srcChainId;\n precrimeAddresses[k] = remotePrecrimeAddresses[i];\n k++;\n break;\n }\n }\n }\n }\n }\n\n function _getRelatedRemoteSize(Packet[] memory _packets) internal view returns (uint16 size) {\n for (uint16 i = 0; i < remoteChainIds.length; i++) {\n for (uint16 j = 0; j < _packets.length; j++) {\n if (remoteChainIds[i] == _packets[j].srcChainId) {\n size++;\n break;\n }\n }\n }\n }\n\n function _getInboundNonce(Packet memory packet) internal view override returns (uint64) {\n CounterV counter = counterView.counter();\n return counter.getInboundNonce(packet.srcChainId);\n }\n}\n"
|
|
22
|
+
},
|
|
23
|
+
"contracts/precrime/example/view/CounterV.sol": {
|
|
24
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\ncontract CounterV {\n // keep track of how many messages have been received from other chains\n uint public totalCount;\n mapping(uint32 => uint) public inboundCount;\n mapping(uint32 => uint) public outboundCount;\n\n event Send(uint16 dstChainId);\n event Receive(uint16 srcChainId);\n\n uint16 public chainId;\n\n constructor(uint16 _chainId) {\n chainId = _chainId;\n }\n\n function lzReceive(uint16 _srcChainId) external {\n inboundCount[_srcChainId]++;\n totalCount++;\n\n emit Receive(_srcChainId);\n }\n\n function increment(uint16 _dstChainId) external {\n outboundCount[_dstChainId]++;\n\n emit Send(_dstChainId);\n }\n\n function brokeIncrement(uint16 _dstChainId) external {\n emit Send(_dstChainId);\n }\n\n function brokeTotalCount() external {\n totalCount++;\n }\n\n function getInboundNonce(uint16 _chainId) public view returns (uint64) {\n // in reality, this would be a call to the LayerZero endpoint\n return uint64(inboundCount[_chainId]);\n }\n}\n"
|
|
25
|
+
},
|
|
26
|
+
"contracts/precrime/example/view/CounterView.sol": {
|
|
27
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"./CounterV.sol\";\n\ncontract CounterView {\n struct CountState {\n uint totalCount;\n ChainPathCount[] chainPathCounts;\n }\n\n struct ChainPathCount {\n uint16 eid;\n uint inboundCount;\n uint outboundCount;\n }\n\n CounterV public counter;\n\n constructor(address _counter) {\n counter = CounterV(_counter);\n }\n\n function lzReceive(CountState memory countState, uint16 _srcChainId) public pure returns (CountState memory) {\n // do receive logic\n for (uint i = 0; i < countState.chainPathCounts.length; i++) {\n ChainPathCount memory chainPathCount = countState.chainPathCounts[i];\n if (chainPathCount.eid == _srcChainId) {\n countState.totalCount++;\n chainPathCount.inboundCount++;\n countState.chainPathCounts[i] = chainPathCount;\n break;\n }\n }\n return countState;\n }\n\n /**\n * @notice Get the count states for a list of peers\n * @param peers - the list of remote chainId to get counts for\n * @return counts - the CountState with the total count and the chain path counts\n */\n function getCountState(uint16[] calldata peers) public view returns (CountState memory) {\n ChainPathCount[] memory chainPathCounts = new ChainPathCount[](peers.length);\n\n for (uint i = 0; i < peers.length; i++) {\n uint16 peer = peers[i];\n chainPathCounts[i] = ChainPathCount({\n eid: peer,\n inboundCount: counter.inboundCount(peer),\n outboundCount: counter.outboundCount(peer)\n });\n }\n\n CountState memory countState = CountState({totalCount: counter.totalCount(), chainPathCounts: chainPathCounts});\n\n return countState;\n }\n}\n"
|
|
28
|
+
},
|
|
29
|
+
"contracts/precrime/interfaces/IPreCrime.sol": {
|
|
30
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.7.0;\n\nimport \"./IPreCrimeBase.sol\";\n\ninterface IPreCrime is IPreCrimeBase {\n /**\n * @dev simulate run cross chain packets and get a simulation result for precrime later\n * @param _packets packets, the packets item should group by srcChainId, srcAddress, then sort by nonce\n * @return code simulation result code; see the error code defination\n * @return result the result is use for precrime params\n */\n function simulate(Packet[] calldata _packets) external returns (uint16 code, bytes memory result);\n}\n"
|
|
31
|
+
},
|
|
32
|
+
"contracts/precrime/interfaces/IPreCrimeBase.sol": {
|
|
33
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.7.0;\n\ninterface IPreCrimeBase {\n struct Packet {\n uint16 srcChainId; // source chain id\n bytes32 srcAddress; // srouce UA address\n uint64 nonce;\n bytes payload;\n }\n\n /**\n * @dev get precrime config,\n * @param _packets packets\n * @return bytes of [maxBatchSize, remotePrecrimes]\n */\n function getConfig(Packet[] calldata _packets) external view returns (bytes memory);\n\n /**\n * @dev\n * @param _simulation all simulation results from difference chains\n * @return code precrime result code; check out the error code defination\n * @return reason error reason\n */\n function precrime(\n Packet[] calldata _packets,\n bytes[] calldata _simulation\n ) external view returns (uint16 code, bytes memory reason);\n\n /**\n * @dev protocol version\n */\n function version() external view returns (uint16);\n}\n"
|
|
34
|
+
},
|
|
35
|
+
"contracts/precrime/interfaces/IPreCrimeView.sol": {
|
|
36
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.7.0;\n\nimport \"./IPreCrimeBase.sol\";\n\ninterface IPreCrimeView is IPreCrimeBase {\n /**\n * @dev simulate run cross chain packets and get a simulation result for precrime later\n * @param _packets packets, the packets item should group by srcChainId, srcAddress, then sort by nonce\n * @return code simulation result code; see the error code defination\n * @return result the result is use for precrime params\n */\n function simulate(Packet[] calldata _packets) external view returns (uint16 code, bytes memory result);\n}\n"
|
|
37
|
+
},
|
|
38
|
+
"contracts/precrime/PreCrime.sol": {
|
|
39
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"./interfaces/IPreCrime.sol\";\nimport \"./PreCrimeBase.sol\";\n\nabstract contract PreCrime is PreCrimeBase, IPreCrime {\n bytes4 private constant SIMULATE_REVERT_SELECTOR = bytes4(keccak256(\"SimulateRevert(uint16,bytes)\"));\n\n /**\n * @dev 10000 - 20000 is for view mode, 20000 - 30000 is for precrime inherit mode\n */\n uint16 public constant PRECRIME_VERSION = 20001;\n\n constructor(uint16 _localChainId) PreCrimeBase(_localChainId) {}\n\n /**\n * @dev simulate run cross chain packets and get a simulation result for precrime later\n * @param _packets packets, the packets item should group by srcChainId, srcAddress, then sort by nonce\n * @return code simulation result code; see the error code defination\n * @return data the result is use for precrime params\n */\n function simulate(Packet[] calldata _packets) external override returns (uint16 code, bytes memory data) {\n // params check\n (code, data) = _checkPacketsMaxSizeAndNonceOrder(_packets);\n if (code != CODE_SUCCESS) {\n return (code, data);\n }\n\n (bool success, bytes memory result) = address(this).call(\n abi.encodeWithSelector(this._simulateAndRevert.selector, _packets)\n );\n require(!success, \"simulate should never return success\");\n\n // parse code and data\n (code, data) = _parseRevertResult(result);\n if (code == CODE_SUCCESS) {\n data = abi.encode(localChainId, data); // add localChainId to the header\n }\n }\n\n function _parseRevertResult(bytes memory result) internal pure returns (uint16 code, bytes memory data) {\n // check revert selector\n bytes4 selector;\n assembly {\n selector := mload(add(result, 0x20)) // skip the length and get bytes4 selector\n }\n if (selector != SIMULATE_REVERT_SELECTOR) {\n // bubble up the internal error\n assembly {\n revert(add(result, 0x20), mload(result))\n }\n }\n\n // parse code and result\n assembly {\n // Slice the sighash. Remove the selector which is the first 4 bytes\n result := add(result, 0x04)\n }\n return abi.decode(result, (uint16, bytes));\n }\n\n /**\n * @dev internal function, no one should call\n * @param _packets packets\n */\n function _simulateAndRevert(Packet[] calldata _packets) external virtual {\n require(msg.sender == address(this));\n (uint16 code, bytes memory simulation) = _simulate(_packets);\n // equal to: revert SimulateRevert(code, result);\n bytes memory revertData = abi.encodePacked(SIMULATE_REVERT_SELECTOR, abi.encode(code, simulation));\n assembly {\n revert(add(revertData, 32), mload(revertData))\n }\n }\n\n /**\n * @dev UA execute the logic by _packets, and return simulation result for precrime. would revert state after returned result.\n * @param _packets packets\n * @return code\n * @return result\n */\n function _simulate(Packet[] calldata _packets) internal virtual returns (uint16 code, bytes memory result);\n\n function version() external pure override returns (uint16) {\n return PRECRIME_VERSION;\n }\n}\n"
|
|
40
|
+
},
|
|
41
|
+
"contracts/precrime/PreCrimeBase.sol": {
|
|
42
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"./interfaces/IPreCrime.sol\";\n\nabstract contract PreCrimeBase is IPreCrimeBase {\n uint16 public constant CONFIG_VERSION = 1;\n\n //---------------- error code ----------------------\n // --- UA scope code ---\n uint16 public constant CODE_SUCCESS = 0; // success\n uint16 public constant CODE_PRECRIME_FAILURE = 1; // !!! crimes found\n\n // --- protocol scope error code ---\n // simualte\n uint16 public constant CODE_PACKETS_OVERSIZE = 2; // packets number bigger then max size\n uint16 public constant CODE_PACKETS_UNSORTED = 3; // packets are unsorted, need backfill and keep order\n // precrime\n uint16 public constant CODE_MISS_SIMULATE_RESULT = 4; // miss simulation result\n\n uint16 public immutable localChainId;\n uint64 public maxBatchSize;\n address public precrimeAdmin;\n\n modifier onlyPrecrimeAdmin() {\n require(msg.sender == precrimeAdmin, \"only admin\");\n _;\n }\n\n constructor(uint16 _localChainId) {\n localChainId = _localChainId;\n precrimeAdmin = msg.sender;\n }\n\n function setPrecrimeAdmin(address _precrimeAdmin) external onlyPrecrimeAdmin {\n precrimeAdmin = _precrimeAdmin;\n }\n\n function setMaxBatchSize(uint64 _maxBatchSize) external onlyPrecrimeAdmin {\n maxBatchSize = _maxBatchSize;\n }\n\n /**\n * @dev get precrime config,\n * @param _packets packets\n * @return configation bytes\n */\n function getConfig(Packet[] calldata _packets) external view virtual override returns (bytes memory) {\n (uint16[] memory remoteChains, bytes32[] memory remoteAddresses) = _remotePrecrimeAddress(_packets);\n return\n abi.encodePacked(\n CONFIG_VERSION,\n //---- max packets size for simulate batch ---\n maxBatchSize,\n //------------- remote precrimes -------------\n remoteChains.length,\n remoteChains,\n remoteAddresses\n );\n }\n\n /**\n * @dev\n * @param _simulation all simulation results from difference chains\n * @return code precrime result code; check out the error code definition\n * @return reason error reason\n */\n function precrime(\n Packet[] calldata _packets,\n bytes[] calldata _simulation\n ) external view override returns (uint16 code, bytes memory reason) {\n bytes[] memory originSimulateResult = new bytes[](_simulation.length);\n uint16[] memory chainIds = new uint16[](_simulation.length);\n for (uint256 i = 0; i < _simulation.length; i++) {\n (uint16 chainId, bytes memory simulateResult) = abi.decode(_simulation[i], (uint16, bytes));\n chainIds[i] = chainId;\n originSimulateResult[i] = simulateResult;\n }\n\n (code, reason) = _checkResultsCompleteness(_packets, chainIds);\n if (code != CODE_SUCCESS) {\n return (code, reason);\n }\n\n (code, reason) = _precrime(originSimulateResult);\n }\n\n function _checkPacketsMaxSizeAndNonceOrder(\n Packet[] calldata _packets\n ) internal view returns (uint16 code, bytes memory reason) {\n if (_packets.length > maxBatchSize) {\n return (CODE_PACKETS_OVERSIZE, abi.encodePacked(\"packets size exceed limited\"));\n }\n\n // check packets nonce, sequence order\n // packets should group by srcChainId and srcAddress, then sort by nonce ascending\n if (_packets.length > 0) {\n uint16 srcChainId;\n bytes32 srcAddress;\n uint64 nonce;\n for (uint256 i = 0; i < _packets.length; i++) {\n Packet memory packet = _packets[i];\n // start from a new chain packet or a new source UA\n if (packet.srcChainId != srcChainId || packet.srcAddress != srcAddress) {\n srcChainId = packet.srcChainId;\n srcAddress = packet.srcAddress;\n nonce = packet.nonce;\n uint64 nextInboundNonce = _getInboundNonce(packet) + 1;\n // the first packet's nonce must equal to dst InboundNonce+1\n if (nonce != nextInboundNonce) {\n return (CODE_PACKETS_UNSORTED, abi.encodePacked(\"skipped inboundNonce forbidden\"));\n }\n } else {\n // the following packet's nonce add 1 in order\n if (packet.nonce != ++nonce) {\n return (CODE_PACKETS_UNSORTED, abi.encodePacked(\"unsorted packets\"));\n }\n }\n }\n }\n return (CODE_SUCCESS, \"\");\n }\n\n function _checkResultsCompleteness(\n Packet[] calldata _packets,\n uint16[] memory _resultChainIds\n ) internal view returns (uint16 code, bytes memory reason) {\n // check if all remote result included\n if (_packets.length > 0) {\n (uint16[] memory remoteChains, ) = _remotePrecrimeAddress(_packets);\n for (uint256 i = 0; i < remoteChains.length; i++) {\n bool resultChainIdChecked;\n for (uint256 j = 0; j < _resultChainIds.length; j++) {\n if (_resultChainIds[j] == remoteChains[i]) {\n resultChainIdChecked = true;\n break;\n }\n }\n if (!resultChainIdChecked) {\n return (CODE_MISS_SIMULATE_RESULT, \"missing remote simulation result\");\n }\n }\n }\n // check if local result included\n bool localChainIdResultChecked;\n for (uint256 j = 0; j < _resultChainIds.length; j++) {\n if (_resultChainIds[j] == localChainId) {\n localChainIdResultChecked = true;\n break;\n }\n }\n if (!localChainIdResultChecked) {\n return (CODE_MISS_SIMULATE_RESULT, \"missing local simulation result\");\n }\n\n return (CODE_SUCCESS, \"\");\n }\n\n /**\n * @dev\n * @param _simulation all simulation results from difference chains\n * @return code precrime result code; check out the error code defination\n * @return reason error reason\n */\n function _precrime(bytes[] memory _simulation) internal view virtual returns (uint16 code, bytes memory reason);\n\n /**\n * @dev UA return trusted remote precrimes by packets\n * @param _packets packets\n * @return\n */\n function _remotePrecrimeAddress(\n Packet[] calldata _packets\n ) internal view virtual returns (uint16[] memory, bytes32[] memory);\n\n /**\n * get srcChain & srcAddress InboundNonce by packet\n */\n function _getInboundNonce(Packet memory packet) internal view virtual returns (uint64 nonce);\n}\n"
|
|
43
|
+
},
|
|
44
|
+
"contracts/precrime/PreCrimeView.sol": {
|
|
45
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"./interfaces/IPreCrimeView.sol\";\nimport \"./PreCrimeBase.sol\";\n\nabstract contract PreCrimeView is PreCrimeBase, IPreCrimeView {\n /**\n * @dev 10000 - 20000 is for view mode, 20000 - 30000 is for precrime inherit mode\n */\n uint16 public constant PRECRIME_VERSION = 10001;\n\n constructor(uint16 _localChainId) PreCrimeBase(_localChainId) {}\n\n /**\n * @dev simulate run cross chain packets and get a simulation result for precrime later\n * @param _packets packets, the packets item should group by srcChainId, srcAddress, then sort by nonce\n * @return code simulation result code; see the error code defination\n * @return data the result is use for precrime params\n */\n function simulate(Packet[] calldata _packets) external view override returns (uint16 code, bytes memory data) {\n // params check\n (code, data) = _checkPacketsMaxSizeAndNonceOrder(_packets);\n if (code != CODE_SUCCESS) {\n return (code, data);\n }\n\n (code, data) = _simulate(_packets);\n if (code == CODE_SUCCESS) {\n data = abi.encode(localChainId, data); // add localChainId to the header\n }\n }\n\n /**\n * @dev UA execute the logic by _packets, and return simulation result for precrime. would revert state after returned result.\n * @param _packets packets\n * @return code\n * @return result\n */\n function _simulate(Packet[] calldata _packets) internal view virtual returns (uint16 code, bytes memory result);\n\n function version() external pure override returns (uint16) {\n return PRECRIME_VERSION;\n }\n}\n"
|
|
46
|
+
},
|
|
47
|
+
"contracts/mocks/PacketData.sol": {
|
|
48
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\ncontract PacketData {\n event Packet(uint16 chainId, bytes payload);\n event Packet(bytes payload);\n\n function emitPacketV1(\n uint64 nonce,\n address ua,\n uint16 dstChainId,\n address dstAddress,\n bytes calldata payload\n ) public {\n bytes memory encodedPayload = abi.encodePacked(nonce, ua, dstAddress, payload);\n emit Packet(dstChainId, encodedPayload);\n }\n\n function emitPacketV2(\n uint64 nonce,\n uint16 localChainId,\n address ua,\n uint16 dstChainId,\n address dstAddress,\n bytes calldata payload\n ) public {\n bytes memory encodedPayload = abi.encodePacked(nonce, localChainId, ua, dstChainId, dstAddress, payload);\n emit Packet(encodedPayload);\n }\n}\n"
|
|
49
|
+
},
|
|
50
|
+
"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
|
|
51
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\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"
|
|
52
|
+
},
|
|
53
|
+
"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": {
|
|
54
|
+
"content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n"
|
|
55
|
+
},
|
|
56
|
+
"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
|
|
57
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n"
|
|
58
|
+
},
|
|
59
|
+
"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
|
|
60
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\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[50] private __gap;\n}\n"
|
|
61
|
+
},
|
|
62
|
+
"@openzeppelin/contracts/access/Ownable.sol": {
|
|
63
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n"
|
|
64
|
+
},
|
|
65
|
+
"@openzeppelin/contracts/math/SafeMath.sol": {
|
|
66
|
+
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n"
|
|
67
|
+
},
|
|
68
|
+
"@openzeppelin/contracts/proxy/Proxy.sol": {
|
|
69
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overridden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n"
|
|
70
|
+
},
|
|
71
|
+
"@openzeppelin/contracts/proxy/UpgradeableProxy.sol": {
|
|
72
|
+
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\nimport \"./Proxy.sol\";\nimport \"../utils/Address.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n *\n * Upgradeability is only provided internally through {_upgradeTo}. For an externally upgradeable proxy see\n * {TransparentUpgradeableProxy}.\n */\ncontract UpgradeableProxy is Proxy {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n _setImplementation(_logic);\n if(_data.length > 0) {\n Address.functionDelegateCall(_logic, _data);\n }\n }\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n bytes32 slot = _IMPLEMENTATION_SLOT;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n impl := sload(slot)\n }\n }\n\n /**\n * @dev Upgrades the proxy to a new implementation.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal virtual {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"UpgradeableProxy: new implementation is not a contract\");\n\n bytes32 slot = _IMPLEMENTATION_SLOT;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(slot, newImplementation)\n }\n }\n}\n"
|
|
73
|
+
},
|
|
74
|
+
"@openzeppelin/contracts/token/ERC20/ERC20.sol": {
|
|
75
|
+
"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"
|
|
76
|
+
},
|
|
77
|
+
"@openzeppelin/contracts/token/ERC20/IERC20.sol": {
|
|
78
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
|
|
79
|
+
},
|
|
80
|
+
"@openzeppelin/contracts/token/ERC20/SafeERC20.sol": {
|
|
81
|
+
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n"
|
|
82
|
+
},
|
|
83
|
+
"@openzeppelin/contracts/utils/Address.sol": {
|
|
84
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n"
|
|
85
|
+
},
|
|
86
|
+
"@openzeppelin/contracts/utils/Context.sol": {
|
|
87
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n"
|
|
88
|
+
},
|
|
89
|
+
"@openzeppelin/contracts/utils/ReentrancyGuard.sol": {
|
|
90
|
+
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor () {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and make it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"
|
|
91
|
+
},
|
|
92
|
+
"contracts/Endpoint.sol": {
|
|
93
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"./interfaces/ILayerZeroReceiver.sol\";\nimport \"./interfaces/ILayerZeroEndpoint.sol\";\nimport \"./interfaces/ILayerZeroMessagingLibrary.sol\";\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract Endpoint is Ownable, ILayerZeroEndpoint {\n uint16 public immutable chainId;\n\n // installed libraries and reserved versions\n uint16 public constant BLOCK_VERSION = 65535;\n uint16 public constant DEFAULT_VERSION = 0;\n uint16 public latestVersion;\n mapping(uint16 => ILayerZeroMessagingLibrary) public libraryLookup; // version -> ILayerZeroEndpointLibrary\n\n // default send/receive libraries\n uint16 public defaultSendVersion;\n uint16 public defaultReceiveVersion;\n ILayerZeroMessagingLibrary public defaultSendLibrary;\n address public defaultReceiveLibraryAddress;\n\n struct LibraryConfig {\n uint16 sendVersion;\n uint16 receiveVersion;\n address receiveLibraryAddress;\n ILayerZeroMessagingLibrary sendLibrary;\n }\n\n struct StoredPayload {\n uint64 payloadLength;\n address dstAddress;\n bytes32 payloadHash;\n }\n\n // user app config = [uaAddress]\n mapping(address => LibraryConfig) public uaConfigLookup;\n // inboundNonce = [srcChainId][srcAddress].\n mapping(uint16 => mapping(bytes => uint64)) public inboundNonce;\n // outboundNonce = [dstChainId][srcAddress].\n mapping(uint16 => mapping(address => uint64)) public outboundNonce;\n // storedPayload = [srcChainId][srcAddress]\n mapping(uint16 => mapping(bytes => StoredPayload)) public storedPayload;\n\n // library versioning events\n event NewLibraryVersionAdded(uint16 version);\n event DefaultSendVersionSet(uint16 version);\n event DefaultReceiveVersionSet(uint16 version);\n event UaSendVersionSet(address ua, uint16 version);\n event UaReceiveVersionSet(address ua, uint16 version);\n event UaForceResumeReceive(uint16 chainId, bytes srcAddress);\n // payload events\n event PayloadCleared(uint16 srcChainId, bytes srcAddress, uint64 nonce, address dstAddress);\n event PayloadStored(\n uint16 srcChainId,\n bytes srcAddress,\n address dstAddress,\n uint64 nonce,\n bytes payload,\n bytes reason\n );\n\n constructor(uint16 _chainId) {\n chainId = _chainId;\n }\n\n //---------------------------------------------------------------------------\n // send and receive nonreentrant lock\n uint8 internal constant _NOT_ENTERED = 1;\n uint8 internal constant _ENTERED = 2;\n uint8 internal _send_entered_state = 1;\n uint8 internal _receive_entered_state = 1;\n\n modifier sendNonReentrant() {\n require(_send_entered_state == _NOT_ENTERED, \"LayerZero: no send reentrancy\");\n _send_entered_state = _ENTERED;\n _;\n _send_entered_state = _NOT_ENTERED;\n }\n modifier receiveNonReentrant() {\n require(_receive_entered_state == _NOT_ENTERED, \"LayerZero: no receive reentrancy\");\n _receive_entered_state = _ENTERED;\n _;\n _receive_entered_state = _NOT_ENTERED;\n }\n\n // BLOCK_VERSION is also a valid version\n modifier validVersion(uint16 _version) {\n require(_version <= latestVersion || _version == BLOCK_VERSION, \"LayerZero: invalid messaging library version\");\n _;\n }\n\n //---------------------------------------------------------------------------\n // User Application Calls - Endpoint Interface\n\n function send(\n uint16 _dstChainId,\n bytes calldata _destination,\n bytes calldata _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable override sendNonReentrant {\n LibraryConfig storage uaConfig = uaConfigLookup[msg.sender];\n uint64 nonce = ++outboundNonce[_dstChainId][msg.sender];\n _getSendLibrary(uaConfig).send{value: msg.value}(\n msg.sender,\n nonce,\n _dstChainId,\n _destination,\n _payload,\n _refundAddress,\n _zroPaymentAddress,\n _adapterParams\n );\n }\n\n //---------------------------------------------------------------------------\n // authenticated Library (msg.sender) Calls to pass through Endpoint to UA (dstAddress)\n function receivePayload(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n address _dstAddress,\n uint64 _nonce,\n uint _gasLimit,\n bytes calldata _payload\n ) external override receiveNonReentrant {\n // assert and increment the nonce. no message shuffling\n require(_nonce == ++inboundNonce[_srcChainId][_srcAddress], \"LayerZero: wrong nonce\");\n\n LibraryConfig storage uaConfig = uaConfigLookup[_dstAddress];\n\n // authentication to prevent cross-version message validation\n // protects against a malicious library from passing arbitrary data\n if (uaConfig.receiveVersion == DEFAULT_VERSION) {\n require(defaultReceiveLibraryAddress == msg.sender, \"LayerZero: invalid default library\");\n } else {\n require(uaConfig.receiveLibraryAddress == msg.sender, \"LayerZero: invalid library\");\n }\n\n // block if any message blocking\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n require(sp.payloadHash == bytes32(0), \"LayerZero: in message blocking\");\n\n try ILayerZeroReceiver(_dstAddress).lzReceive{gas: _gasLimit}(_srcChainId, _srcAddress, _nonce, _payload) {\n // success, do nothing, end of the message delivery\n } catch (bytes memory reason) {\n // revert nonce if any uncaught errors/exceptions if the ua chooses the blocking mode\n storedPayload[_srcChainId][_srcAddress] = StoredPayload(\n uint64(_payload.length),\n _dstAddress,\n keccak256(_payload)\n );\n emit PayloadStored(_srcChainId, _srcAddress, _dstAddress, _nonce, _payload, reason);\n }\n }\n\n function retryPayload(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n bytes calldata _payload\n ) external override receiveNonReentrant {\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n require(sp.payloadHash != bytes32(0), \"LayerZero: no stored payload\");\n require(\n _payload.length == sp.payloadLength && keccak256(_payload) == sp.payloadHash,\n \"LayerZero: invalid payload\"\n );\n\n address dstAddress = sp.dstAddress;\n // empty the storedPayload\n sp.payloadLength = 0;\n sp.dstAddress = address(0);\n sp.payloadHash = bytes32(0);\n\n uint64 nonce = inboundNonce[_srcChainId][_srcAddress];\n\n ILayerZeroReceiver(dstAddress).lzReceive(_srcChainId, _srcAddress, nonce, _payload);\n emit PayloadCleared(_srcChainId, _srcAddress, nonce, dstAddress);\n }\n\n //---------------------------------------------------------------------------\n // Owner Calls, only new library version upgrade (3 steps)\n\n // note libraryLookup[0] = 0x0, no library implementation\n // LIBRARY UPGRADE step 1: set _newLayerZeroLibraryAddress be the new version\n function newVersion(address _newLayerZeroLibraryAddress) external onlyOwner {\n require(_newLayerZeroLibraryAddress != address(0x0), \"LayerZero: new version cannot be zero address\");\n require(latestVersion < 65535, \"LayerZero: can not add new messaging library\");\n latestVersion++;\n libraryLookup[latestVersion] = ILayerZeroMessagingLibrary(_newLayerZeroLibraryAddress);\n emit NewLibraryVersionAdded(latestVersion);\n }\n\n // LIBRARY UPGRADE step 2: stop sending messages from the old version\n function setDefaultSendVersion(\n uint16 _newDefaultSendVersion\n ) external onlyOwner validVersion(_newDefaultSendVersion) {\n require(_newDefaultSendVersion != DEFAULT_VERSION, \"LayerZero: default send version must > 0\");\n defaultSendVersion = _newDefaultSendVersion;\n defaultSendLibrary = libraryLookup[defaultSendVersion];\n emit DefaultSendVersionSet(_newDefaultSendVersion);\n }\n\n // LIBRARY UPGRADE step 3: stop receiving messages from the old version\n function setDefaultReceiveVersion(\n uint16 _newDefaultReceiveVersion\n ) external onlyOwner validVersion(_newDefaultReceiveVersion) {\n require(_newDefaultReceiveVersion != DEFAULT_VERSION, \"LayerZero: default receive version must > 0\");\n defaultReceiveVersion = _newDefaultReceiveVersion;\n defaultReceiveLibraryAddress = address(libraryLookup[defaultReceiveVersion]);\n emit DefaultReceiveVersionSet(_newDefaultReceiveVersion);\n }\n\n //---------------------------------------------------------------------------\n // User Application Calls - UA set/get Interface\n\n function setConfig(\n uint16 _version,\n uint16 _chainId,\n uint _configType,\n bytes calldata _config\n ) external override validVersion(_version) {\n if (_version == DEFAULT_VERSION) {\n require(\n defaultSendVersion == defaultReceiveVersion,\n \"LayerZero: can not set Config during DEFAULT migration\"\n );\n _version = defaultSendVersion;\n }\n require(_version != BLOCK_VERSION, \"LayerZero: can not set config for BLOCK_VERSION\");\n libraryLookup[_version].setConfig(_chainId, msg.sender, _configType, _config);\n }\n\n // Migration step 1: set the send version\n // Define what library the UA points too\n function setSendVersion(uint16 _newVersion) external override validVersion(_newVersion) {\n // write into config\n LibraryConfig storage uaConfig = uaConfigLookup[msg.sender];\n uaConfig.sendVersion = _newVersion;\n // the libraryLookup[BLOCK_VERSION || DEFAULT_VERSION] = 0x0\n uaConfig.sendLibrary = libraryLookup[_newVersion];\n emit UaSendVersionSet(msg.sender, _newVersion);\n }\n\n // Migration step 2: set the receive version\n // after all messages sent from the old version are received\n // the UA can now safely switch to the new receive version\n // it is the UA's responsibility make sure all messages from the old version are processed\n function setReceiveVersion(uint16 _newVersion) external override validVersion(_newVersion) {\n // write into config\n LibraryConfig storage uaConfig = uaConfigLookup[msg.sender];\n uaConfig.receiveVersion = _newVersion;\n // the libraryLookup[BLOCK_VERSION || DEFAULT_VERSION] = 0x0\n uaConfig.receiveLibraryAddress = address(libraryLookup[_newVersion]);\n emit UaReceiveVersionSet(msg.sender, _newVersion);\n }\n\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override {\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n // revert if no messages are cached. safeguard malicious UA behaviour\n require(sp.payloadHash != bytes32(0), \"LayerZero: no stored payload\");\n require(sp.dstAddress == msg.sender, \"LayerZero: invalid caller\");\n\n // empty the storedPayload\n sp.payloadLength = 0;\n sp.dstAddress = address(0);\n sp.payloadHash = bytes32(0);\n\n // emit the event with the new nonce\n emit UaForceResumeReceive(_srcChainId, _srcAddress);\n }\n\n //---------------------------------------------------------------------------\n // view helper function\n\n function estimateFees(\n uint16 _dstChainId,\n address _userApplication,\n bytes calldata _payload,\n bool _payInZRO,\n bytes calldata _adapterParams\n ) external view override returns (uint nativeFee, uint zroFee) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n ILayerZeroMessagingLibrary lib = uaConfig.sendVersion == DEFAULT_VERSION\n ? defaultSendLibrary\n : uaConfig.sendLibrary;\n return lib.estimateFees(_dstChainId, _userApplication, _payload, _payInZRO, _adapterParams);\n }\n\n function _getSendLibrary(LibraryConfig storage uaConfig) internal view returns (ILayerZeroMessagingLibrary) {\n if (uaConfig.sendVersion == DEFAULT_VERSION) {\n // check if the in send-blocking upgrade\n require(defaultSendVersion != BLOCK_VERSION, \"LayerZero: default in BLOCK_VERSION\");\n return defaultSendLibrary;\n } else {\n // check if the in send-blocking upgrade\n require(uaConfig.sendVersion != BLOCK_VERSION, \"LayerZero: in BLOCK_VERSION\");\n return uaConfig.sendLibrary;\n }\n }\n\n function getSendLibraryAddress(\n address _userApplication\n ) external view override returns (address sendLibraryAddress) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n uint16 sendVersion = uaConfig.sendVersion;\n require(sendVersion != BLOCK_VERSION, \"LayerZero: send version is BLOCK_VERSION\");\n if (sendVersion == DEFAULT_VERSION) {\n require(defaultSendVersion != BLOCK_VERSION, \"LayerZero: send version (default) is BLOCK_VERSION\");\n sendLibraryAddress = address(defaultSendLibrary);\n } else {\n sendLibraryAddress = address(uaConfig.sendLibrary);\n }\n }\n\n function getReceiveLibraryAddress(\n address _userApplication\n ) external view override returns (address receiveLibraryAddress) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n uint16 receiveVersion = uaConfig.receiveVersion;\n require(receiveVersion != BLOCK_VERSION, \"LayerZero: receive version is BLOCK_VERSION\");\n if (receiveVersion == DEFAULT_VERSION) {\n require(defaultReceiveVersion != BLOCK_VERSION, \"LayerZero: receive version (default) is BLOCK_VERSION\");\n receiveLibraryAddress = defaultReceiveLibraryAddress;\n } else {\n receiveLibraryAddress = uaConfig.receiveLibraryAddress;\n }\n }\n\n function isSendingPayload() external view override returns (bool) {\n return _send_entered_state == _ENTERED;\n }\n\n function isReceivingPayload() external view override returns (bool) {\n return _receive_entered_state == _ENTERED;\n }\n\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view override returns (uint64) {\n return inboundNonce[_srcChainId][_srcAddress];\n }\n\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view override returns (uint64) {\n return outboundNonce[_dstChainId][_srcAddress];\n }\n\n function getChainId() external view override returns (uint16) {\n return chainId;\n }\n\n function getSendVersion(address _userApplication) external view override returns (uint16) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n return uaConfig.sendVersion == DEFAULT_VERSION ? defaultSendVersion : uaConfig.sendVersion;\n }\n\n function getReceiveVersion(address _userApplication) external view override returns (uint16) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n return uaConfig.receiveVersion == DEFAULT_VERSION ? defaultReceiveVersion : uaConfig.receiveVersion;\n }\n\n function getConfig(\n uint16 _version,\n uint16 _chainId,\n address _userApplication,\n uint _configType\n ) external view override validVersion(_version) returns (bytes memory) {\n if (_version == DEFAULT_VERSION) {\n require(defaultSendVersion == defaultReceiveVersion, \"LayerZero: no DEFAULT config while migration\");\n _version = defaultSendVersion;\n }\n require(_version != BLOCK_VERSION, \"LayerZero: can not get config for BLOCK_VERSION\");\n return libraryLookup[_version].getConfig(_chainId, _userApplication, _configType);\n }\n\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view override returns (bool) {\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n return sp.payloadHash != bytes32(0);\n }\n}\n"
|
|
94
|
+
},
|
|
95
|
+
"contracts/EndpointLite.sol": {
|
|
96
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\n\nimport \"./interfaces/ILayerZeroReceiver.sol\";\nimport \"./interfaces/ILayerZeroEndpoint.sol\";\nimport \"./interfaces/ILayerZeroMessagingLibrary.sol\";\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract EndpointLite is Ownable, ILayerZeroEndpoint {\n uint16 public immutable chainId;\n\n // installed libraries and reserved versions\n uint16 public constant BLOCK_VERSION = 65535;\n uint16 public constant DEFAULT_VERSION = 0;\n uint16 public latestVersion;\n mapping(uint16 => ILayerZeroMessagingLibrary) public libraryLookup; // version -> ILayerZeroEndpointLibrary\n\n // default send/receive libraries\n uint16 public defaultSendVersion;\n uint16 public defaultReceiveVersion;\n ILayerZeroMessagingLibrary public defaultSendLibrary;\n address public defaultReceiveLibraryAddress;\n\n struct LibraryConfig {\n uint16 sendVersion;\n uint16 receiveVersion;\n address receiveLibraryAddress;\n ILayerZeroMessagingLibrary sendLibrary;\n }\n\n struct StoredPayload {\n uint64 payloadLength;\n address dstAddress;\n bytes32 payloadHash;\n }\n\n // user app config = [uaAddress]\n mapping(address => LibraryConfig) public uaConfigLookup;\n // inboundNonce = [srcChainId][srcAddress].\n mapping(uint16 => mapping(bytes => uint64)) public inboundNonce;\n // storedPayload = [srcChainId][srcAddress]\n mapping(uint16 => mapping(bytes => StoredPayload)) public storedPayload;\n\n // library versioning events\n event NewLibraryVersionAdded(uint16 version);\n event DefaultSendVersionSet(uint16 version);\n event DefaultReceiveVersionSet(uint16 version);\n event UaSendVersionSet(address ua, uint16 version);\n event UaReceiveVersionSet(address ua, uint16 version);\n event UaForceResumeReceive(uint16 chainId, bytes srcAddress);\n // payload events\n event PayloadCleared(uint16 srcChainId, bytes srcAddress, uint64 nonce, address dstAddress);\n event PayloadStored(\n uint16 srcChainId,\n bytes srcAddress,\n address dstAddress,\n uint64 nonce,\n bytes payload,\n bytes reason\n );\n\n constructor(uint16 _chainId) {\n chainId = _chainId;\n }\n\n //---------------------------------------------------------------------------\n // send and receive nonreentrant lock\n uint8 internal constant _NOT_ENTERED = 1;\n uint8 internal constant _ENTERED = 2;\n uint8 internal _send_entered_state = 1;\n uint8 internal _receive_entered_state = 1;\n\n modifier sendNonReentrant() {\n require(_send_entered_state == _NOT_ENTERED, \"LayerZero: no send reentrancy\");\n _send_entered_state = _ENTERED;\n _;\n _send_entered_state = _NOT_ENTERED;\n }\n modifier receiveNonReentrant() {\n require(_receive_entered_state == _NOT_ENTERED, \"LayerZero: no receive reentrancy\");\n _receive_entered_state = _ENTERED;\n _;\n _receive_entered_state = _NOT_ENTERED;\n }\n\n // BLOCK_VERSION is also a valid version\n modifier validVersion(uint16 _version) {\n require(_version <= latestVersion || _version == BLOCK_VERSION, \"LayerZero: invalid messaging library version\");\n _;\n }\n\n //---------------------------------------------------------------------------\n // User Application Calls - Endpoint Interface\n\n function send(\n uint16 _dstChainId,\n bytes calldata _destination,\n bytes calldata _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable override sendNonReentrant {\n LibraryConfig storage uaConfig = uaConfigLookup[msg.sender];\n _getSendLibrary(uaConfig).send{value: msg.value}(\n msg.sender,\n 0,\n _dstChainId,\n _destination,\n _payload,\n _refundAddress,\n _zroPaymentAddress,\n _adapterParams\n );\n }\n\n //---------------------------------------------------------------------------\n // authenticated Library (msg.sender) Calls to pass through Endpoint to UA (dstAddress)\n function receivePayload(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n address _dstAddress,\n uint64 _nonce,\n uint _gasLimit,\n bytes calldata _payload\n ) external override receiveNonReentrant {\n // assert and increment the nonce. no message shuffling\n require(_nonce == ++inboundNonce[_srcChainId][_srcAddress], \"LayerZero: wrong nonce\");\n\n LibraryConfig storage uaConfig = uaConfigLookup[_dstAddress];\n\n // authentication to prevent cross-version message validation\n // protects against a malicious library from passing arbitrary data\n if (uaConfig.receiveVersion == DEFAULT_VERSION) {\n require(defaultReceiveLibraryAddress == msg.sender, \"LayerZero: invalid default library\");\n } else {\n require(uaConfig.receiveLibraryAddress == msg.sender, \"LayerZero: invalid library\");\n }\n\n // block if any message blocking\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n require(sp.payloadHash == bytes32(0), \"LayerZero: in message blocking\");\n\n try ILayerZeroReceiver(_dstAddress).lzReceive{gas: _gasLimit}(_srcChainId, _srcAddress, _nonce, _payload) {\n // success, do nothing, end of the message delivery\n } catch (bytes memory reason) {\n // revert nonce if any uncaught errors/exceptions if the ua chooses the blocking mode\n storedPayload[_srcChainId][_srcAddress] = StoredPayload(\n uint64(_payload.length),\n _dstAddress,\n keccak256(_payload)\n );\n emit PayloadStored(_srcChainId, _srcAddress, _dstAddress, _nonce, _payload, reason);\n }\n }\n\n function retryPayload(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n bytes calldata _payload\n ) external override receiveNonReentrant {\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n require(sp.payloadHash != bytes32(0), \"LayerZero: no stored payload\");\n require(\n _payload.length == sp.payloadLength && keccak256(_payload) == sp.payloadHash,\n \"LayerZero: invalid payload\"\n );\n\n address dstAddress = sp.dstAddress;\n // empty the storedPayload\n sp.payloadLength = 0;\n sp.dstAddress = address(0);\n sp.payloadHash = bytes32(0);\n\n uint64 nonce = inboundNonce[_srcChainId][_srcAddress];\n\n ILayerZeroReceiver(dstAddress).lzReceive(_srcChainId, _srcAddress, nonce, _payload);\n emit PayloadCleared(_srcChainId, _srcAddress, nonce, dstAddress);\n }\n\n //---------------------------------------------------------------------------\n // Owner Calls, only new library version upgrade (3 steps)\n\n // note libraryLookup[0] = 0x0, no library implementation\n // LIBRARY UPGRADE step 1: set _newLayerZeroLibraryAddress be the new version\n function newVersion(address _newLayerZeroLibraryAddress) external onlyOwner {\n require(_newLayerZeroLibraryAddress != address(0x0), \"LayerZero: new version cannot be zero address\");\n require(latestVersion < 65535, \"LayerZero: can not add new messaging library\");\n latestVersion++;\n libraryLookup[latestVersion] = ILayerZeroMessagingLibrary(_newLayerZeroLibraryAddress);\n emit NewLibraryVersionAdded(latestVersion);\n }\n\n // LIBRARY UPGRADE step 2: stop sending messages from the old version\n function setDefaultSendVersion(\n uint16 _newDefaultSendVersion\n ) external onlyOwner validVersion(_newDefaultSendVersion) {\n require(_newDefaultSendVersion != DEFAULT_VERSION, \"LayerZero: default send version must > 0\");\n defaultSendVersion = _newDefaultSendVersion;\n defaultSendLibrary = libraryLookup[defaultSendVersion];\n emit DefaultSendVersionSet(_newDefaultSendVersion);\n }\n\n // LIBRARY UPGRADE step 3: stop receiving messages from the old version\n function setDefaultReceiveVersion(\n uint16 _newDefaultReceiveVersion\n ) external onlyOwner validVersion(_newDefaultReceiveVersion) {\n require(_newDefaultReceiveVersion != DEFAULT_VERSION, \"LayerZero: default receive version must > 0\");\n defaultReceiveVersion = _newDefaultReceiveVersion;\n defaultReceiveLibraryAddress = address(libraryLookup[defaultReceiveVersion]);\n emit DefaultReceiveVersionSet(_newDefaultReceiveVersion);\n }\n\n //---------------------------------------------------------------------------\n // User Application Calls - UA set/get Interface\n\n function setConfig(\n uint16 _version,\n uint16 _chainId,\n uint _configType,\n bytes calldata _config\n ) external override validVersion(_version) {\n if (_version == DEFAULT_VERSION) {\n require(\n defaultSendVersion == defaultReceiveVersion,\n \"LayerZero: can not set Config during DEFAULT migration\"\n );\n _version = defaultSendVersion;\n }\n require(_version != BLOCK_VERSION, \"LayerZero: can not set config for BLOCK_VERSION\");\n libraryLookup[_version].setConfig(_chainId, msg.sender, _configType, _config);\n }\n\n // Migration step 1: set the send version\n // Define what library the UA points too\n function setSendVersion(uint16 _newVersion) external override validVersion(_newVersion) {\n // write into config\n LibraryConfig storage uaConfig = uaConfigLookup[msg.sender];\n uaConfig.sendVersion = _newVersion;\n // the libraryLookup[BLOCK_VERSION || DEFAULT_VERSION] = 0x0\n uaConfig.sendLibrary = libraryLookup[_newVersion];\n emit UaSendVersionSet(msg.sender, _newVersion);\n }\n\n // Migration step 2: set the receive version\n // after all messages sent from the old version are received\n // the UA can now safely switch to the new receive version\n // it is the UA's responsibility make sure all messages from the old version are processed\n function setReceiveVersion(uint16 _newVersion) external override validVersion(_newVersion) {\n // write into config\n LibraryConfig storage uaConfig = uaConfigLookup[msg.sender];\n uaConfig.receiveVersion = _newVersion;\n // the libraryLookup[BLOCK_VERSION || DEFAULT_VERSION] = 0x0\n uaConfig.receiveLibraryAddress = address(libraryLookup[_newVersion]);\n emit UaReceiveVersionSet(msg.sender, _newVersion);\n }\n\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override {\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n // revert if no messages are cached. safeguard malicious UA behaviour\n require(sp.payloadHash != bytes32(0), \"LayerZero: no stored payload\");\n require(sp.dstAddress == msg.sender, \"LayerZero: invalid caller\");\n\n // empty the storedPayload\n sp.payloadLength = 0;\n sp.dstAddress = address(0);\n sp.payloadHash = bytes32(0);\n\n // emit the event with the new nonce\n emit UaForceResumeReceive(_srcChainId, _srcAddress);\n }\n\n //---------------------------------------------------------------------------\n // view helper function\n\n function estimateFees(\n uint16 _dstChainId,\n address _userApplication,\n bytes calldata _payload,\n bool _payInZRO,\n bytes calldata _adapterParams\n ) external view override returns (uint nativeFee, uint zroFee) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n ILayerZeroMessagingLibrary lib = uaConfig.sendVersion == DEFAULT_VERSION\n ? defaultSendLibrary\n : uaConfig.sendLibrary;\n return lib.estimateFees(_dstChainId, _userApplication, _payload, _payInZRO, _adapterParams);\n }\n\n function _getSendLibrary(LibraryConfig storage uaConfig) internal view returns (ILayerZeroMessagingLibrary) {\n if (uaConfig.sendVersion == DEFAULT_VERSION) {\n // check if the in send-blocking upgrade\n require(defaultSendVersion != BLOCK_VERSION, \"LayerZero: default in BLOCK_VERSION\");\n return defaultSendLibrary;\n } else {\n // check if the in send-blocking upgrade\n require(uaConfig.sendVersion != BLOCK_VERSION, \"LayerZero: in BLOCK_VERSION\");\n return uaConfig.sendLibrary;\n }\n }\n\n function getSendLibraryAddress(\n address _userApplication\n ) external view override returns (address sendLibraryAddress) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n uint16 sendVersion = uaConfig.sendVersion;\n require(sendVersion != BLOCK_VERSION, \"LayerZero: send version is BLOCK_VERSION\");\n if (sendVersion == DEFAULT_VERSION) {\n require(defaultSendVersion != BLOCK_VERSION, \"LayerZero: send version (default) is BLOCK_VERSION\");\n sendLibraryAddress = address(defaultSendLibrary);\n } else {\n sendLibraryAddress = address(uaConfig.sendLibrary);\n }\n }\n\n function getReceiveLibraryAddress(\n address _userApplication\n ) external view override returns (address receiveLibraryAddress) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n uint16 receiveVersion = uaConfig.receiveVersion;\n require(receiveVersion != BLOCK_VERSION, \"LayerZero: receive version is BLOCK_VERSION\");\n if (receiveVersion == DEFAULT_VERSION) {\n require(defaultReceiveVersion != BLOCK_VERSION, \"LayerZero: receive version (default) is BLOCK_VERSION\");\n receiveLibraryAddress = defaultReceiveLibraryAddress;\n } else {\n receiveLibraryAddress = uaConfig.receiveLibraryAddress;\n }\n }\n\n function isSendingPayload() external view override returns (bool) {\n return _send_entered_state == _ENTERED;\n }\n\n function isReceivingPayload() external view override returns (bool) {\n return _receive_entered_state == _ENTERED;\n }\n\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view override returns (uint64) {\n return inboundNonce[_srcChainId][_srcAddress];\n }\n\n function getOutboundNonce(uint16, address) external pure override returns (uint64) {\n revert(\"LayerZero: no outbound nonce at endpoint\");\n }\n\n function getChainId() external view override returns (uint16) {\n return chainId;\n }\n\n function getSendVersion(address _userApplication) external view override returns (uint16) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n return uaConfig.sendVersion == DEFAULT_VERSION ? defaultSendVersion : uaConfig.sendVersion;\n }\n\n function getReceiveVersion(address _userApplication) external view override returns (uint16) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n return uaConfig.receiveVersion == DEFAULT_VERSION ? defaultReceiveVersion : uaConfig.receiveVersion;\n }\n\n function getConfig(\n uint16 _version,\n uint16 _chainId,\n address _userApplication,\n uint _configType\n ) external view override validVersion(_version) returns (bytes memory) {\n if (_version == DEFAULT_VERSION) {\n require(defaultSendVersion == defaultReceiveVersion, \"LayerZero: no DEFAULT config while migration\");\n _version = defaultSendVersion;\n }\n require(_version != BLOCK_VERSION, \"LayerZero: can not get config for BLOCK_VERSION\");\n return libraryLookup[_version].getConfig(_chainId, _userApplication, _configType);\n }\n\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view override returns (bool) {\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n return sp.payloadHash != bytes32(0);\n }\n}\n"
|
|
97
|
+
},
|
|
98
|
+
"contracts/example/AltTokenUA.sol": {
|
|
99
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.7.6;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../interfaces/ILayerZeroEndpoint.sol\";\nimport \"../interfaces/ILayerZeroReceiver.sol\";\n\n// An example UA running on Shrapnel using ERC20 as payment token\n// To demonstrate how feeToken payment needs to be atomic with layerzero send\ncontract AltTokenUA is ILayerZeroReceiver {\n ILayerZeroEndpoint public endpoint;\n IERC20 public feeToken;\n address public feeHandler;\n\n constructor(address _endpoint, address _feeToken, address _feeHandler) {\n endpoint = ILayerZeroEndpoint(_endpoint);\n feeToken = IERC20(_feeToken);\n feeHandler = _feeHandler;\n }\n\n function send(\n uint16 _dstChainId,\n address _dstAddress,\n bytes memory _payload,\n bytes memory _adapterParams,\n uint _fee\n ) public payable {\n feeToken.transferFrom(msg.sender, feeHandler, _fee);\n\n bytes memory path = abi.encodePacked(_dstAddress, address(this));\n endpoint.send(_dstChainId, path, _payload, msg.sender, address(0), _adapterParams);\n }\n\n function lzReceive(\n uint16 _srcChainId,\n bytes memory _fromAddress,\n uint64 /*_nonce*/,\n bytes memory _payload\n ) external virtual override {\n //do nothing\n }\n}\n"
|
|
100
|
+
},
|
|
101
|
+
"contracts/FeeHandler.sol": {
|
|
102
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract FeeHandler is Ownable {\n using SafeERC20 for IERC20;\n\n IERC20 public feeToken;\n mapping(address => bool) public approved;\n\n constructor() {}\n\n function setFeeToken(address _feeToken) external onlyOwner {\n require(address(feeToken) == address(0x0), \"FeeHandler: feeToken already set\");\n feeToken = IERC20(_feeToken);\n }\n\n function approve(address _uln) external onlyOwner {\n approved[_uln] = true;\n }\n\n function creditFee(address[] calldata _receivers, uint[] calldata _amounts, address _refundAddress) external {\n require(_receivers.length == _amounts.length, \"FeeHandler: invalid parameters\");\n require(approved[msg.sender], \"FeeHandler: not approved\");\n\n for (uint i = 0; i < _receivers.length; i++) {\n feeToken.safeTransfer(_receivers[i], _amounts[i]);\n }\n uint remaining = feeToken.balanceOf(address(this));\n if (remaining > 0) {\n feeToken.safeTransfer(_refundAddress, remaining);\n }\n }\n}\n"
|
|
103
|
+
},
|
|
104
|
+
"contracts/interfaces/IContractOne.sol": {
|
|
105
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface IContractOne {\n function setIt(uint x) external;\n}\n"
|
|
106
|
+
},
|
|
107
|
+
"contracts/interfaces/ILayerZeroEndpoint.sol": {
|
|
108
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(\n uint16 _dstChainId,\n bytes calldata _destination,\n bytes calldata _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n address _dstAddress,\n uint64 _nonce,\n uint _gasLimit,\n bytes calldata _payload\n ) external;\n\n // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(\n uint16 _dstChainId,\n address _userApplication,\n bytes calldata _payload,\n bool _payInZRO,\n bytes calldata _adapterParam\n ) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(\n uint16 _version,\n uint16 _chainId,\n address _userApplication,\n uint _configType\n ) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n"
|
|
109
|
+
},
|
|
110
|
+
"contracts/interfaces/ILayerZeroMessagingLibrary.sol": {
|
|
111
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.8.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroMessagingLibrary {\n // send(), messages will be inflight.\n function send(\n address _userApplication,\n uint64 _lastNonce,\n uint16 _chainId,\n bytes calldata _destination,\n bytes calldata _payload,\n address payable refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable;\n\n // estimate native fee at the send side\n function estimateFees(\n uint16 _chainId,\n address _userApplication,\n bytes calldata _payload,\n bool _payInZRO,\n bytes calldata _adapterParam\n ) external view returns (uint nativeFee, uint zroFee);\n\n //---------------------------------------------------------------------------\n // setConfig / getConfig are User Application (UA) functions to specify Oracle, Relayer, blockConfirmations, libraryVersion\n function setConfig(uint16 _chainId, address _userApplication, uint _configType, bytes calldata _config) external;\n\n function getConfig(\n uint16 _chainId,\n address _userApplication,\n uint _configType\n ) external view returns (bytes memory);\n}\n"
|
|
112
|
+
},
|
|
113
|
+
"contracts/interfaces/ILayerZeroMessagingLibraryV2.sol": {
|
|
114
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.8.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\nimport \"./ILayerZeroMessagingLibrary.sol\";\n\ninterface ILayerZeroMessagingLibraryV2 is ILayerZeroMessagingLibrary {\n function getOutboundNonce(uint16 _chainId, bytes calldata _path) external view returns (uint64);\n}\n"
|
|
115
|
+
},
|
|
116
|
+
"contracts/interfaces/ILayerZeroOracle.sol": {
|
|
117
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.7.0;\n\ninterface ILayerZeroOracle {\n // @notice query the oracle price for relaying block information to the destination chain\n // @param _dstChainId the destination endpoint identifier\n // @param _outboundProofType the proof type identifier to specify the data to be relayed\n function getPrice(uint16 _dstChainId, uint16 _outboundProofType) external view returns (uint price);\n\n // @notice Ultra-Light Node notifies the Oracle of a new block information relaying request\n // @param _dstChainId the destination endpoint identifier\n // @param _outboundProofType the proof type identifier to specify the data to be relayed\n // @param _outboundBlockConfirmations the number of source chain block confirmation needed\n function notifyOracle(uint16 _dstChainId, uint16 _outboundProofType, uint64 _outboundBlockConfirmations) external;\n\n // @notice query if the address is an approved actor for privileges like data submission and fee withdrawal etc.\n // @param _address the address to be checked\n function isApproved(address _address) external view returns (bool approved);\n}\n"
|
|
118
|
+
},
|
|
119
|
+
"contracts/interfaces/ILayerZeroOracleV2.sol": {
|
|
120
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.8.0;\n\ninterface ILayerZeroOracleV2 {\n // @notice query price and assign jobs at the same time\n // @param _dstChainId - the destination endpoint identifier\n // @param _outboundProofType - the proof type identifier to specify proof to be relayed\n // @param _outboundBlockConfirmation - block confirmation delay before relaying blocks\n // @param _userApplication - the source sending contract address\n function assignJob(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n uint64 _outboundBlockConfirmation,\n address _userApplication\n ) external returns (uint price);\n\n // @notice query the oracle price for relaying block information to the destination chain\n // @param _dstChainId the destination endpoint identifier\n // @param _outboundProofType the proof type identifier to specify the data to be relayed\n // @param _outboundBlockConfirmation - block confirmation delay before relaying blocks\n // @param _userApplication - the source sending contract address\n function getFee(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n uint64 _outboundBlockConfirmation,\n address _userApplication\n ) external view returns (uint price);\n\n // @notice withdraw the accrued fee in ultra light node\n // @param _to - the fee receiver\n // @param _amount - the withdrawal amount\n function withdrawFee(address payable _to, uint _amount) external;\n}\n"
|
|
121
|
+
},
|
|
122
|
+
"contracts/interfaces/ILayerZeroPriceFeed.sol": {
|
|
123
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.8.0;\n\ninterface ILayerZeroPriceFeed {\n /**\n * @dev\n * priceRatio: (USD price of 1 unit of remote native token in unit of local native token) * PRICE_RATIO_DENOMINATOR\n */\n\n struct Price {\n uint128 priceRatio; // float value * 10 ^ 10, decimal awared. for aptos to evm, the basis would be (10^18 / 10^8) * 10 ^10 = 10 ^ 20.\n uint64 gasPriceInUnit; // for evm, it is in wei, for aptos, it is in octas.\n uint32 gasPerByte;\n }\n\n struct UpdatePrice {\n uint16 chainId;\n Price price;\n }\n\n /**\n * @dev\n * ArbGasInfo.go:GetPricesInArbGas\n *\n */\n struct ArbitrumPriceExt {\n uint64 gasPerL2Tx; // L2 overhead\n uint32 gasPerL1CallDataByte;\n }\n\n struct UpdatePriceExt {\n uint16 chainId;\n Price price;\n ArbitrumPriceExt extend;\n }\n\n function getPrice(uint16 _dstChainId) external view returns (Price memory);\n\n function getPriceRatioDenominator() external view returns (uint128);\n\n function estimateFeeByChain(\n uint16 _dstChainId,\n uint _callDataSize,\n uint _gas\n ) external view returns (uint fee, uint128 priceRatio);\n\n function nativeTokenPriceUSD() external view returns (uint128);\n}\n"
|
|
124
|
+
},
|
|
125
|
+
"contracts/interfaces/ILayerZeroPriceFeedV2.sol": {
|
|
126
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.8.0;\n\n// copy of \"@layerzerolabs/lz-evm-messagelib-v2/contracts/interfaces/ILayerZeroPriceFeed.sol\"\ninterface ILayerZeroPriceFeedV2 {\n /**\n * @dev\n * priceRatio: (USD price of 1 unit of remote native token in unit of local native token) * PRICE_RATIO_DENOMINATOR\n */\n\n struct Price {\n uint128 priceRatio; // float value * 10 ^ 20, decimal awared. for aptos to evm, the basis would be (10^18 / 10^8) * 10 ^20 = 10 ^ 30.\n uint64 gasPriceInUnit; // for evm, it is in wei, for aptos, it is in octas.\n uint32 gasPerByte;\n }\n\n struct UpdatePrice {\n uint32 eid;\n Price price;\n }\n\n /**\n * @dev\n * ArbGasInfo.go:GetPricesInArbGas\n *\n */\n struct ArbitrumPriceExt {\n uint64 gasPerL2Tx; // L2 overhead\n uint32 gasPerL1CallDataByte;\n }\n\n struct UpdatePriceExt {\n uint32 eid;\n Price price;\n ArbitrumPriceExt extend;\n }\n\n function getPrice(uint32 _dstEid) external view returns (Price memory);\n\n function getPriceRatioDenominator() external view returns (uint128);\n\n function estimateFeeByEid(\n uint32 _dstEid,\n uint _callDataSize,\n uint _gas\n ) external view returns (uint fee, uint128 priceRatio, uint128 priceRatioDenominator, uint128 nativePriceUSD);\n}\n"
|
|
127
|
+
},
|
|
128
|
+
"contracts/interfaces/ILayerZeroReceiver.sol": {
|
|
129
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n"
|
|
130
|
+
},
|
|
131
|
+
"contracts/interfaces/ILayerZeroRelayer.sol": {
|
|
132
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.7.0;\n\ninterface ILayerZeroRelayer {\n // @notice query the relayer price for relaying the payload and its proof to the destination chain\n // @param _dstChainId - the destination endpoint identifier\n // @param _outboundProofType - the proof type identifier to specify proof to be relayed\n // @param _userApplication - the source sending contract address. relayers may apply price discrimination to user apps\n // @param _payloadSize - the length of the payload. it is an indicator of gas usage for relaying cross-chain messages\n // @param _adapterParams - optional parameters for extra service plugins, e.g. sending dust tokens at the destination chain\n function getPrice(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n address _userApplication,\n uint _payloadSize,\n bytes calldata _adapterParams\n ) external view returns (uint price);\n\n // @notice Ultra-Light Node notifies the Oracle of a new block information relaying request\n // @param _dstChainId - the destination endpoint identifier\n // @param _outboundProofType - the proof type identifier to specify the data to be relayed\n // @param _adapterParams - optional parameters for extra service plugins, e.g. sending dust tokens at the destination chain\n function notifyRelayer(uint16 _dstChainId, uint16 _outboundProofType, bytes calldata _adapterParams) external;\n\n // @notice query if the address is an approved actor for privileges like data submission and fee withdrawal etc.\n // @param _address - the address to be checked\n function isApproved(address _address) external view returns (bool approved);\n}\n"
|
|
133
|
+
},
|
|
134
|
+
"contracts/interfaces/ILayerZeroRelayerV2.sol": {
|
|
135
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.8.0;\n\ninterface ILayerZeroRelayerV2 {\n // @notice query price and assign jobs at the same time\n // @param _dstChainId - the destination endpoint identifier\n // @param _outboundProofType - the proof type identifier to specify proof to be relayed\n // @param _userApplication - the source sending contract address. relayers may apply price discrimination to user apps\n // @param _payloadSize - the length of the payload. it is an indicator of gas usage for relaying cross-chain messages\n // @param _adapterParams - optional parameters for extra service plugins, e.g. sending dust tokens at the destination chain\n function assignJob(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n address _userApplication,\n uint _payloadSize,\n bytes calldata _adapterParams\n ) external returns (uint price);\n\n // @notice query the relayer price for relaying the payload and its proof to the destination chain\n // @param _dstChainId - the destination endpoint identifier\n // @param _outboundProofType - the proof type identifier to specify proof to be relayed\n // @param _userApplication - the source sending contract address. relayers may apply price discrimination to user apps\n // @param _payloadSize - the length of the payload. it is an indicator of gas usage for relaying cross-chain messages\n // @param _adapterParams - optional parameters for extra service plugins, e.g. sending dust tokens at the destination chain\n function getFee(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n address _userApplication,\n uint _payloadSize,\n bytes calldata _adapterParams\n ) external view returns (uint price);\n\n // @notice withdraw the accrued fee in ultra light node\n // @param _to - the fee receiver\n // @param _amount - the withdrawal amount\n function withdrawFee(address payable _to, uint _amount) external;\n}\n"
|
|
136
|
+
},
|
|
137
|
+
"contracts/interfaces/ILayerZeroRelayerV2PriceData.sol": {
|
|
138
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.7.0;\n\npragma abicoder v2;\n\ninterface ILayerZeroRelayerV2PriceData {\n struct DstPrice {\n uint128 dstPriceRatio; // 10^10\n uint128 dstGasPriceInWei;\n }\n\n struct DstConfig {\n uint128 dstNativeAmtCap;\n uint64 baseGas;\n uint64 gasPerByte;\n }\n\n function dstPriceLookup(uint16 _chainId) external view returns (DstPrice memory);\n\n function dstConfigLookup(uint16 _chainId, uint16 _outboundProofType) external view returns (DstConfig memory);\n}\n"
|
|
139
|
+
},
|
|
140
|
+
"contracts/interfaces/ILayerZeroTreasury.sol": {
|
|
141
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroTreasury {\n function getFees(bool payInZro, uint relayerFee, uint oracleFee) external view returns (uint);\n}\n"
|
|
142
|
+
},
|
|
143
|
+
"contracts/interfaces/ILayerZeroUltraLightNodeV1.sol": {
|
|
144
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.7.0;\n\ninterface ILayerZeroUltraLightNodeV1 {\n // a Relayer can execute the validateTransactionProof()\n function validateTransactionProof(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _lookupHash,\n bytes calldata _transactionProof\n ) external;\n\n // an Oracle delivers the block data using updateHash()\n function updateHash(uint16 _remoteChainId, bytes32 _lookupHash, uint _confirmations, bytes32 _data) external;\n\n // can only withdraw the receivable of the msg.sender\n function withdrawNative(uint8 _type, address _owner, address payable _to, uint _amount) external;\n\n function withdrawZRO(address _to, uint _amount) external;\n\n // view functions\n function oracleQuotedAmount(address _oracle) external view returns (uint);\n\n function relayerQuotedAmount(address _relayer) external view returns (uint);\n}\n"
|
|
145
|
+
},
|
|
146
|
+
"contracts/interfaces/ILayerZeroUltraLightNodeV2.sol": {
|
|
147
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.8.0;\n\ninterface ILayerZeroUltraLightNodeV2 {\n // Relayer functions\n function validateTransactionProof(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _lookupHash,\n bytes32 _blockData,\n bytes calldata _transactionProof\n ) external;\n\n // an Oracle delivers the block data using updateHash()\n function updateHash(uint16 _srcChainId, bytes32 _lookupHash, uint _confirmations, bytes32 _blockData) external;\n\n // can only withdraw the receivable of the msg.sender\n function withdrawNative(address payable _to, uint _amount) external;\n\n function withdrawZRO(address _to, uint _amount) external;\n\n // view functions\n function getAppConfig(\n uint16 _remoteChainId,\n address _userApplicationAddress\n ) external view returns (ApplicationConfiguration memory);\n\n function accruedNativeFee(address _address) external view returns (uint);\n\n struct ApplicationConfiguration {\n uint16 inboundProofLibraryVersion;\n uint64 inboundBlockConfirmations;\n address relayer;\n uint16 outboundProofType;\n uint64 outboundBlockConfirmations;\n address oracle;\n }\n\n event HashReceived(\n uint16 indexed srcChainId,\n address indexed oracle,\n bytes32 lookupHash,\n bytes32 blockData,\n uint confirmations\n );\n event RelayerParams(bytes adapterParams, uint16 outboundProofType);\n event Packet(bytes payload);\n event InvalidDst(\n uint16 indexed srcChainId,\n bytes srcAddress,\n address indexed dstAddress,\n uint64 nonce,\n bytes32 payloadHash\n );\n event PacketReceived(\n uint16 indexed srcChainId,\n bytes srcAddress,\n address indexed dstAddress,\n uint64 nonce,\n bytes32 payloadHash\n );\n event AppConfigUpdated(address indexed userApplication, uint indexed configType, bytes newConfig);\n event AddInboundProofLibraryForChain(uint16 indexed chainId, address lib);\n event EnableSupportedOutboundProof(uint16 indexed chainId, uint16 proofType);\n event SetChainAddressSize(uint16 indexed chainId, uint size);\n event SetDefaultConfigForChainId(\n uint16 indexed chainId,\n uint16 inboundProofLib,\n uint64 inboundBlockConfirm,\n address relayer,\n uint16 outboundProofType,\n uint64 outboundBlockConfirm,\n address oracle\n );\n event SetDefaultAdapterParamsForChainId(uint16 indexed chainId, uint16 indexed proofType, bytes adapterParams);\n event SetLayerZeroToken(address indexed tokenAddress);\n event SetRemoteUln(uint16 indexed chainId, bytes32 uln);\n event SetTreasury(address indexed treasuryAddress);\n event WithdrawZRO(address indexed msgSender, address indexed to, uint amount);\n event WithdrawNative(address indexed msgSender, address indexed to, uint amount);\n}\n"
|
|
148
|
+
},
|
|
149
|
+
"contracts/interfaces/ILayerZeroUserApplicationConfig.sol": {
|
|
150
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n"
|
|
151
|
+
},
|
|
152
|
+
"contracts/interfaces/ILayerZeroValidationLibrary.sol": {
|
|
153
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.8.0;\n\nimport \"../proof/utility/LayerZeroPacket.sol\";\n\ninterface ILayerZeroValidationLibrary {\n function validateProof(\n bytes32 blockData,\n bytes calldata _data,\n uint _remoteAddressSize\n ) external returns (LayerZeroPacket.Packet memory packet);\n}\n"
|
|
154
|
+
},
|
|
155
|
+
"contracts/interfaces/IValidationLibraryHelper.sol": {
|
|
156
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.8.0;\n\nimport \"../proof/utility/LayerZeroPacket.sol\";\nimport \"./ILayerZeroValidationLibrary.sol\";\n\ninterface IValidationLibraryHelper {\n struct ULNLog {\n bytes32 contractAddress;\n bytes32 topicZeroSig;\n bytes data;\n }\n\n function getVerifyLog(\n bytes32 hashRoot,\n uint[] memory receiptSlotIndex,\n uint logIndex,\n bytes[] memory proof\n ) external pure returns (ULNLog memory);\n\n function getPacket(\n bytes memory data,\n uint16 srcChain,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) external pure returns (LayerZeroPacket.Packet memory);\n\n function getUtilsVersion() external view returns (uint8);\n}\n"
|
|
157
|
+
},
|
|
158
|
+
"contracts/interfaces/IValidationLibraryHelperV2.sol": {
|
|
159
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.8.0;\n\nimport \"../proof/utility/LayerZeroPacket.sol\";\n\ninterface IValidationLibraryHelperV2 {\n struct ULNLog {\n bytes32 contractAddress;\n bytes32 topicZeroSig;\n bytes data;\n }\n\n function getVerifyLog(\n bytes32 hashRoot,\n uint[] calldata receiptSlotIndex,\n uint logIndex,\n bytes[] calldata proof\n ) external pure returns (ULNLog memory);\n\n function getPacket(\n bytes calldata data,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) external pure returns (LayerZeroPacket.Packet memory);\n\n function getUtilsVersion() external view returns (uint8);\n\n function getProofType() external view returns (uint8);\n}\n"
|
|
160
|
+
},
|
|
161
|
+
"contracts/libs/RateLimiter.sol": {
|
|
162
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n// Copyright 2023 LayerZero Labs Ltd.\n// You may obtain a copy of the License at\n// https://github.com/LayerZero-Labs/license/blob/main/LICENSE-LZBL-1.1\n\npragma solidity ^0.7.6;\n\nlibrary RateLimiter {\n struct Info {\n // capacity of the token bucket. This is the maximum number of tokens that the bucket can hold at any given time\n uint64 capacity;\n // current number of tokens in the bucket\n uint64 tokens;\n // number of tokens refilled per second\n uint64 rate;\n // timestamp of last refill\n uint64 lastRefillTime;\n }\n\n function setCapacity(Info storage _self, uint64 _capacity) internal {\n _self.capacity = _capacity;\n _self.tokens = _capacity;\n _self.lastRefillTime = uint64(block.timestamp);\n }\n\n function setRate(Info storage _self, uint64 _rate) internal {\n refill(_self, 0);\n _self.rate = _rate;\n }\n\n function tryConsume(Info storage _self, uint64 _amount) internal returns (uint64) {\n refill(_self, 0);\n\n uint64 tokens = _self.tokens;\n require(tokens >= _amount, \"RelayerV2: out of counters - try again later!\");\n\n uint64 newTokens = tokens - _amount;\n _self.tokens = newTokens;\n return newTokens;\n }\n\n function refill(Info storage _self, uint64 _extraTokens) internal {\n uint newTokens = _extraTokens;\n\n uint64 currentTime = uint64(block.timestamp);\n if (currentTime > _self.lastRefillTime) {\n uint timeElapsedInSeconds = currentTime - _self.lastRefillTime;\n newTokens += timeElapsedInSeconds * _self.rate;\n }\n\n if (newTokens > 0) {\n newTokens += _self.tokens;\n _self.tokens = newTokens > _self.capacity ? _self.capacity : uint64(newTokens);\n }\n\n _self.lastRefillTime = currentTime;\n }\n}\n"
|
|
163
|
+
},
|
|
164
|
+
"contracts/mocks/ContractTwo.sol": {
|
|
165
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\nimport \"../interfaces/IContractOne.sol\";\n\ncontract ContractTwo {\n address contractOne;\n\n constructor(address _contractOne) {\n contractOne = _contractOne;\n }\n\n function callSetIt(uint _gasLimit) external {\n IContractOne(contractOne).setIt{gas: _gasLimit}(1);\n }\n}\n"
|
|
166
|
+
},
|
|
167
|
+
"contracts/mocks/GIN.sol": {
|
|
168
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\nimport \"../interfaces/ILayerZeroReceiver.sol\";\nimport \"../interfaces/ILayerZeroEndpoint.sol\";\n\ncontract GIN is ILayerZeroReceiver {\n bool public messageComplete;\n ILayerZeroEndpoint public endpoint;\n\n event Message(bytes32 indexed message);\n\n constructor(address _endpoint) {\n endpoint = ILayerZeroEndpoint(_endpoint);\n }\n\n function lzReceive(uint16, bytes memory /*_fromAddress*/, uint64, bytes memory _payload) external override {\n require(msg.sender == address(endpoint));\n bytes32 message;\n assembly {\n message := mload(add(_payload, 32))\n }\n emit Message(message);\n messageComplete = true;\n }\n\n function sendFirstMessage(\n uint gasAmountForDst,\n uint16[] calldata chainIds,\n bytes[] calldata dstAddresses\n ) external payable {\n require(!messageComplete, \"The first message of LayerZero has already been sent\");\n uint16 version = 1;\n bytes memory _relayerParams = abi.encodePacked(version, gasAmountForDst);\n\n bytes32 message = \"GIN\";\n bytes memory messageString = bytes(abi.encodePacked(message));\n uint length = chainIds.length;\n uint fee = msg.value / length;\n for (uint i = 0; i < length; i++) {\n endpoint.send{value: fee}(\n chainIds[i],\n dstAddresses[i],\n messageString,\n payable(msg.sender),\n address(0x0),\n _relayerParams\n );\n }\n }\n}\n"
|
|
169
|
+
},
|
|
170
|
+
"contracts/mocks/LayerZeroOracleBadMock.sol": {
|
|
171
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\n\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/ILayerZeroOracle.sol\";\nimport \"../interfaces/ILayerZeroUltraLightNodeV1.sol\";\nimport \"../interfaces/ILayerZeroEndpoint.sol\";\n\n// mock is designed to try and send the msg it just received again to trigger a revert\ncontract LayerZeroOracleBadMock is ILayerZeroOracle, Ownable, ReentrancyGuard {\n mapping(address => bool) public approvedAddresses;\n mapping(uint16 => mapping(uint16 => uint)) public chainPriceLookup;\n uint public fee;\n ILayerZeroUltraLightNodeV1 public uln; // ultraLightNode instance\n ILayerZeroEndpoint public endpoint; // for bad oracles trying to talk to endpoint\n\n event OracleNotified(uint16 dstChainId, uint16 _outboundProofType, uint blockConfirmations);\n event Withdraw(address to, uint amount);\n\n constructor() {\n approvedAddresses[msg.sender] = true;\n }\n\n function notifyOracle(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n uint64 _outboundBlockConfirmations\n ) external override {\n // oracle is set to do bad things and try to call send again, this should revert\n endpoint.send(_dstChainId, \"0x\", \"0x\", address(0), address(0), \"0x\");\n emit OracleNotified(_dstChainId, _outboundProofType, _outboundBlockConfirmations);\n }\n\n function updateHash(uint16 _remoteChainId, bytes32 _blockHash, uint _confirmations, bytes32 _data) external {\n require(approvedAddresses[msg.sender], \"LayerZeroOracleMock: caller must be approved\");\n uln.updateHash(_remoteChainId, _blockHash, _confirmations, _data);\n }\n\n function withdraw(address payable _to, uint _amount) public onlyOwner nonReentrant {\n (bool success, ) = _to.call{value: _amount}(\"\");\n require(success, \"failed to withdraw\");\n emit Withdraw(_to, _amount);\n }\n\n // owner can set uln\n function setUln(address ulnAddress) external onlyOwner {\n uln = ILayerZeroUltraLightNodeV1(ulnAddress);\n }\n\n // owner can set uln\n function setEndpoint(address endpointAddress) external onlyOwner {\n endpoint = ILayerZeroEndpoint(endpointAddress);\n }\n\n // mock, doesnt do anything\n function setJob(uint16 _chain, address _oracle, bytes32 _id, uint _fee) public onlyOwner {}\n\n // mocked for now\n function assignJob(\n uint16 _dstChainId,\n uint16 /*_outboundProofType*/,\n uint64 /*_outboundBlockConfirmation*/,\n address\n ) external returns (uint price) {\n // oracle is set to do bad things and try to call send again, this should revert\n endpoint.send(_dstChainId, \"0x\", \"0x\", address(0), address(0), \"0x\");\n return 1;\n }\n\n function setDeliveryAddress(uint16 _dstChainId, address _deliveryAddress) public onlyOwner {}\n\n function setPrice(uint16 _destinationChainId, uint16 _outboundProofType, uint _price) external onlyOwner {\n chainPriceLookup[_outboundProofType][_destinationChainId] = _price;\n }\n\n function setApprovedAddress(address _oracleAddress, bool _approve) external {\n approvedAddresses[_oracleAddress] = _approve;\n }\n\n function isApproved(address _relayerAddress) public view override returns (bool) {\n return approvedAddresses[_relayerAddress];\n }\n\n function getPrice(uint16 _destinationChainId, uint16 _outboundProofType) external view override returns (uint) {\n return chainPriceLookup[_outboundProofType][_destinationChainId];\n }\n\n fallback() external payable {}\n\n receive() external payable {}\n}\n"
|
|
172
|
+
},
|
|
173
|
+
"contracts/mocks/LayerZeroOracleMock.sol": {
|
|
174
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\n\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/ILayerZeroOracle.sol\";\nimport \"../interfaces/ILayerZeroUltraLightNodeV1.sol\";\n\ncontract LayerZeroOracleMock is ILayerZeroOracle, Ownable, ReentrancyGuard {\n mapping(address => bool) public approvedAddresses;\n mapping(uint16 => mapping(uint16 => uint)) public chainPriceLookup;\n uint public fee;\n ILayerZeroUltraLightNodeV1 public uln; // ultraLightNode instance\n\n event OracleNotified(uint16 dstChainId, uint16 _outboundProofType, uint blockConfirmations);\n event Withdraw(address to, uint amount);\n\n constructor() {\n approvedAddresses[msg.sender] = true;\n }\n\n function notifyOracle(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n uint64 _outboundBlockConfirmations\n ) external override {\n emit OracleNotified(_dstChainId, _outboundProofType, _outboundBlockConfirmations);\n }\n\n function updateHash(uint16 _remoteChainId, bytes32 _blockHash, uint _confirmations, bytes32 _data) external {\n require(approvedAddresses[msg.sender], \"LayerZeroOracleMock: caller must be approved\");\n uln.updateHash(_remoteChainId, _blockHash, _confirmations, _data);\n }\n\n function withdraw(address payable _to, uint _amount) public onlyOwner nonReentrant {\n (bool success, ) = _to.call{value: _amount}(\"\");\n require(success, \"failed to withdraw\");\n emit Withdraw(_to, _amount);\n }\n\n // owner can set uln\n function setUln(address ulnAddress) external onlyOwner {\n uln = ILayerZeroUltraLightNodeV1(ulnAddress);\n }\n\n // mock, doesnt do anything\n function setJob(uint16 _chain, address _oracle, bytes32 _id, uint _fee) public onlyOwner {}\n\n function setDeliveryAddress(uint16 _dstChainId, address _deliveryAddress) public onlyOwner {}\n\n function setPrice(uint16 _destinationChainId, uint16 _outboundProofType, uint _price) external onlyOwner {\n chainPriceLookup[_outboundProofType][_destinationChainId] = _price;\n }\n\n function setApprovedAddress(address _oracleAddress, bool _approve) external {\n approvedAddresses[_oracleAddress] = _approve;\n }\n\n function isApproved(address _relayerAddress) public view override returns (bool) {\n return approvedAddresses[_relayerAddress];\n }\n\n function getPrice(uint16 _destinationChainId, uint16 _outboundProofType) external view override returns (uint) {\n return chainPriceLookup[_outboundProofType][_destinationChainId];\n }\n\n fallback() external payable {}\n\n receive() external payable {}\n}\n"
|
|
175
|
+
},
|
|
176
|
+
"contracts/mocks/LayerZeroOracleMockV2.sol": {
|
|
177
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/ILayerZeroOracleV2.sol\";\nimport \"../interfaces/ILayerZeroUltraLightNodeV2.sol\";\n\ncontract LayerZeroOracleMockV2 is ILayerZeroOracleV2, Ownable, ReentrancyGuard {\n mapping(address => bool) public approvedAddresses;\n mapping(uint16 => mapping(uint16 => uint)) public chainPriceLookup;\n mapping(uint16 => mapping(uint16 => uint64)) public jobs; // mocked, not used for anything yet\n uint public fee;\n ILayerZeroUltraLightNodeV2 public uln; // ultraLightNode instance\n\n event OracleNotified(uint16 dstChainId, uint16 _outboundProofType, uint blockConfirmations);\n event Withdraw(address to, uint amount);\n\n constructor() {\n approvedAddresses[msg.sender] = true;\n }\n\n // mocked for now, will auto accept the job, and return the price at the same time\n function assignJob(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n uint64 _outboundBlockConfirmation,\n address\n ) external override returns (uint price) {\n jobs[_dstChainId][_outboundProofType] = _outboundBlockConfirmation;\n return chainPriceLookup[_outboundProofType][_dstChainId];\n }\n\n function getFee(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n uint64 /*_outboundBlockConfirmation*/,\n address\n ) external view override returns (uint) {\n return chainPriceLookup[_outboundProofType][_dstChainId];\n }\n\n function withdrawFee(address payable _to, uint _amount) public override onlyOwner nonReentrant {\n (bool success, ) = _to.call{value: _amount}(\"\");\n require(success, \"failed to withdraw\");\n emit Withdraw(_to, _amount);\n }\n\n function updateHash(uint16 _remoteChainId, bytes32 _blockHash, uint _confirmations, bytes32 _data) external {\n require(approvedAddresses[msg.sender], \"LayerZeroOracleMock: caller must be approved\");\n uln.updateHash(_remoteChainId, _blockHash, _confirmations, _data);\n }\n\n function setUln(address ulnAddress) external onlyOwner {\n uln = ILayerZeroUltraLightNodeV2(ulnAddress);\n }\n\n function setDeliveryAddress(uint16 _dstChainId, address _deliveryAddress) public onlyOwner {}\n\n function setPrice(uint16 _destinationChainId, uint16 _outboundProofType, uint _price) external onlyOwner {\n chainPriceLookup[_outboundProofType][_destinationChainId] = _price;\n }\n\n function setApprovedAddress(address _oracleAddress, bool _approve) external {\n approvedAddresses[_oracleAddress] = _approve;\n }\n\n function isApproved(address _relayerAddress) public view returns (bool) {\n return approvedAddresses[_relayerAddress];\n }\n\n fallback() external payable {}\n\n receive() external payable {}\n}\n"
|
|
178
|
+
},
|
|
179
|
+
"contracts/mocks/LayerZeroTokenMock.sol": {
|
|
180
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract LayerZeroTokenMock is ERC20 {\n constructor() ERC20(\"LayerZeroTokenMock\", \"LZTM\") {\n _mint(msg.sender, 1_000_000 * 10 ** 18);\n }\n}\n"
|
|
181
|
+
},
|
|
182
|
+
"contracts/mocks/MockToken.sol": {
|
|
183
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n// this is a MOCK\ncontract MockToken is ERC20 {\n // this is a MOCK\n constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {\n _mint(msg.sender, 1000000000000000000000);\n }\n\n // this is a MOCK\n function mint(address _to, uint _amount) public {\n _mint(_to, _amount);\n }\n\n //Mocked to imitate what happens if a transfer fails\n function transfer(address recipient, uint amount) public virtual override returns (bool) {\n require(recipient != address(0x1));\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n}\n"
|
|
184
|
+
},
|
|
185
|
+
"contracts/mocks/OmniCounter.sol": {
|
|
186
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../interfaces/ILayerZeroReceiver.sol\";\nimport \"../interfaces/ILayerZeroEndpoint.sol\";\nimport \"../interfaces/ILayerZeroUserApplicationConfig.sol\";\n\ncontract OmniCounter is Ownable, ILayerZeroReceiver, ILayerZeroUserApplicationConfig {\n // keep track of how many messages have been received from other chains\n uint public messageCounter;\n mapping(address => uint) public remoteAddressCounter;\n // required: the LayerZero endpoint which is passed in the constructor\n ILayerZeroEndpoint public endpoint;\n bool public payInZRO;\n\n mapping(uint16 => bytes) public trustedRemoteLookup;\n\n constructor(address _endpoint) {\n endpoint = ILayerZeroEndpoint(_endpoint);\n }\n\n function getCounter() public view returns (uint) {\n return messageCounter;\n }\n\n // overrides lzReceive function in ILayerZeroReceiver.\n // automatically invoked on the receiving chain after the source chain calls endpoint.send(...)\n function lzReceive(\n uint16 _srcChainId,\n bytes memory _fromAddress,\n uint64 /*_nonce*/,\n bytes memory _payload\n ) external virtual override {\n require(msg.sender == address(endpoint));\n _verifySourceAddress(_srcChainId, _fromAddress);\n\n address fromAddress;\n assembly {\n fromAddress := mload(add(_fromAddress, 20))\n }\n\n // used for testing reentrant, retry sending the payload through the relayer before the initial receive has been resolved\n // ff == '0x6666' on the payload side\n if (\n keccak256(abi.encodePacked((_payload))) == keccak256(abi.encodePacked((bytes2(\"ff\")))) ||\n keccak256(abi.encodePacked((_payload))) == keccak256(abi.encodePacked((bytes10(\"ff\"))))\n ) {\n endpoint.receivePayload(1, bytes(\"\"), address(0x0), 1, 1, bytes(\"\"));\n }\n\n remoteAddressCounter[fromAddress] += 1;\n messageCounter += 1;\n }\n\n function incrementCounter(\n uint16 _dstChainId,\n bytes calldata _adapterParams,\n bytes calldata payload\n ) public payable {\n address zroPaymentAddress = payInZRO ? address(this) : address(0x0);\n _incrementCounter(_dstChainId, payload, payable(msg.sender), zroPaymentAddress, _adapterParams);\n }\n\n // call send() to multiple destinations in the same transaction!\n function multiIncrementCounter(\n uint16[] calldata _dstChainIds,\n bytes calldata _adapterParams,\n bytes calldata payload\n ) public payable {\n // send() each chainId + dst address pair\n uint16[] memory dstChainIds = _dstChainIds;\n bytes memory adapterParams = _adapterParams;\n\n uint _refund = msg.value;\n // send() each chainId + dst address pair\n for (uint i = 0; i < dstChainIds.length; ++i) {\n (uint valueToSend, ) = endpoint.estimateFees(\n dstChainIds[i],\n address(this),\n payload,\n payInZRO,\n adapterParams\n );\n _refund -= valueToSend;\n // a Communicator.sol instance is the 'endpoint'\n // .send() each payload to the destination chainId + UA destination address\n address zroPaymentAddress = payInZRO ? address(this) : address(0x0);\n _incrementCounter(_dstChainIds[i], payload, payable(msg.sender), zroPaymentAddress, adapterParams);\n }\n // refund eth if too much was sent into this contract call\n payable(msg.sender).transfer(_refund);\n }\n\n function _incrementCounter(\n uint16 _dstChainId,\n bytes memory _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes memory _adapterParams\n ) public payable {\n bytes memory trustedRemote = trustedRemoteLookup[_dstChainId];\n require(trustedRemote.length > 0, \"*** trustedRemote cant be 0x \");\n endpoint.send{value: msg.value}(\n _dstChainId,\n trustedRemote,\n _payload,\n _refundAddress,\n _zroPaymentAddress,\n _adapterParams\n );\n }\n\n function setConfig(\n uint16 /*_version*/,\n uint16 _chainId,\n uint _configType,\n bytes calldata _config\n ) external override {\n endpoint.setConfig(endpoint.getSendVersion(address(this)), _chainId, _configType, _config);\n }\n\n function getConfig(uint16, uint16 _chainId, address, uint _configType) external view returns (bytes memory) {\n return endpoint.getConfig(endpoint.getSendVersion(address(this)), _chainId, address(this), _configType);\n }\n\n function setSendVersion(uint16 version) external override {\n endpoint.setSendVersion(version);\n }\n\n function setReceiveVersion(uint16 version) external override {\n endpoint.setReceiveVersion(version);\n }\n\n function getSendVersion() external view returns (uint16) {\n return endpoint.getSendVersion(address(this));\n }\n\n function getReceiveVersion() external view returns (uint16) {\n return endpoint.getReceiveVersion(address(this));\n }\n\n function setOutboundBlockConfirmations(uint16 dstChainId, uint64 confirmations) external {\n // should technically be onlyOwner but this is a mock\n uint TYPE_OUTBOUND_BLOCK_CONFIRMATIONS = 6;\n endpoint.setConfig(\n endpoint.getSendVersion(address(this)),\n dstChainId,\n TYPE_OUTBOUND_BLOCK_CONFIRMATIONS,\n abi.encodePacked(confirmations)\n );\n }\n\n function getOutboundBlockConfirmations(uint16 remoteChainId) external view returns (bytes memory _confirmations) {\n return endpoint.getConfig(endpoint.getSendVersion(address(this)), remoteChainId, address(this), 5);\n }\n\n // set the Oracle to be used by this UA for LayerZero messages\n function setOracle(uint16 dstChainId, address oracle) external {\n // should technically be onlyOwner but this is a mock\n uint TYPE_ORACLE = 6; // from UltraLightNode\n // set the Oracle\n // uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config\n endpoint.setConfig(endpoint.getSendVersion(address(this)), dstChainId, TYPE_ORACLE, abi.encode(oracle));\n }\n\n // get the configured oracle\n function getOracle(uint16 remoteChainId) external view returns (address _oracle) {\n bytes memory bytesOracle = endpoint.getConfig(\n endpoint.getSendVersion(address(this)),\n remoteChainId,\n address(this),\n 6\n );\n assembly {\n _oracle := mload(add(bytesOracle, 32))\n }\n }\n\n // set the Relayer to be used by this UA for LayerZero messages\n function setRelayer(uint16 dstChainId, address relayer) external {\n uint TYPE_RELAYER = 3;\n endpoint.setConfig(endpoint.getSendVersion(address(this)), dstChainId, TYPE_RELAYER, abi.encode(relayer));\n }\n\n // set the inbound block confirmations\n function setInboundConfirmations(uint16 remoteChainId, uint16 confirmations) external {\n endpoint.setConfig(\n endpoint.getSendVersion(address(this)),\n remoteChainId,\n 2, // CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS\n abi.encode(confirmations)\n );\n }\n\n // set outbound block confirmations\n function setOutboundConfirmations(uint16 remoteChainId, uint16 confirmations) external {\n endpoint.setConfig(\n endpoint.getSendVersion(address(this)),\n remoteChainId,\n 5, // CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS\n abi.encode(confirmations)\n );\n }\n\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override {\n // ignored for this contract\n }\n\n function setPayInZRO(bool _payInZRO) external onlyOwner {\n payInZRO = _payInZRO;\n }\n\n function approveTokenSpender(address token, address spender, uint amount) external onlyOwner {\n IERC20(token).approve(spender, amount);\n }\n\n // allow this contract to receive ether\n fallback() external payable {}\n\n receive() external payable {\n // Mock the ability to reject payments\n require(\n msg.value < 1000 && msg.value != 10,\n \"Did you mean to send a blocked amount - check receive() / fallback()\"\n );\n }\n\n // allow owner to set it multiple times.\n function setTrustedRemote(uint16 _srcChainId, bytes calldata _srcAddress) external onlyOwner {\n trustedRemoteLookup[_srcChainId] = _srcAddress;\n }\n\n function _verifySourceAddress(uint16 _srcChainId, bytes memory _fromAddress) internal view {\n bytes memory trustedRemote = trustedRemoteLookup[_srcChainId];\n require(\n trustedRemote.length != 0 && keccak256(_fromAddress) == keccak256(trustedRemote),\n \"source counter is not trusted\"\n );\n }\n}\n"
|
|
187
|
+
},
|
|
188
|
+
"contracts/mocks/PingPong.sol": {
|
|
189
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\n//\n// Note: you will need to fund each deployed contract with gas\n//\n// PingPong sends a LayerZero message back and forth between chains until stopped!\n//\n// Demonstrates:\n// 1. a recursive feature of calling send() from inside lzReceive()\n// 2. how to `estimateFees` for a send()'ing a LayerZero message\n// 3. the contract pays the message fee\n\npragma solidity ^0.8.17;\n\nimport \"../interfaces/ILayerZeroReceiver.sol\";\nimport \"../interfaces/ILayerZeroEndpoint.sol\";\nimport \"../interfaces/ILayerZeroUserApplicationConfig.sol\";\n\ncontract PingPong is ILayerZeroReceiver, ILayerZeroUserApplicationConfig {\n // the LayerZero endpoint calls .send() to send a cross chain message\n ILayerZeroEndpoint public endpoint;\n // whether PingPong is ping-ponging\n bool public pingsEnabled;\n // event emitted every ping() to keep track of consecutive pings count\n event Ping(uint pings);\n // the maxPings before ending the loop\n uint public maxPings;\n // keep track of the totalPings sent\n uint public numPings;\n bool public isUlnV2;\n\n // constructor requires the LayerZero endpoint for this chain\n constructor(address _layerZeroEndpoint, bool _isUlnV2) {\n pingsEnabled = true;\n endpoint = ILayerZeroEndpoint(_layerZeroEndpoint);\n maxPings = 5;\n isUlnV2 = _isUlnV2;\n }\n\n // disable ping-ponging\n function disable() external {\n pingsEnabled = false;\n }\n\n // pings the destination chain, along with the current number of pings sent\n function ping(\n uint16 _dstChainId, // send a ping to this destination chainId\n address _dstPingPongAddr, // destination address of PingPong contract\n uint pings // the uint to start at. use 0 as a default\n ) public {\n require(address(this).balance > 0, \"the balance of this contract is 0. pls send gas for message fees\");\n require(pingsEnabled, \"pingsEnabled is false. messages stopped\");\n require(maxPings > pings, \"maxPings has been reached, no more looping\");\n\n emit Ping(pings);\n\n // abi.encode() the payload with the number of pings sent\n bytes memory payload = abi.encode(pings);\n\n // encode adapterParams to specify more gas for the destination\n uint16 version = 1;\n uint gasForDestinationLzReceive = 350000;\n bytes memory adapterParams = abi.encodePacked(version, gasForDestinationLzReceive);\n\n // get the fees we need to pay to LayerZero + Relayer to cover message delivery\n // see Communicator.sol's .estimateNativeFees() function for more details.\n (uint messageFee, ) = endpoint.estimateFees(_dstChainId, address(this), payload, false, adapterParams);\n require(\n address(this).balance >= messageFee,\n \"address(this).balance < messageFee. pls send gas for message fees\"\n );\n\n bytes memory path = isUlnV2\n ? abi.encodePacked(_dstPingPongAddr, address(this))\n : abi.encodePacked(_dstPingPongAddr);\n\n // send LayerZero message\n endpoint.send{value: messageFee}( // {value: messageFee} will be paid out of this contract!\n _dstChainId, // destination chainId\n path,\n payload, // abi.encode()'ed bytes\n payable(this), // (msg.sender will be this contract) refund address (LayerZero will refund any extra gas back to caller of send()\n address(0x0), // 'zroPaymentAddress' unused for this mock/example\n adapterParams // 'adapterParams' unused for this mock/example\n );\n }\n\n // receive the bytes payload from the source chain via LayerZero\n // _srcChainId: the chainId that we are receiving the message from.\n // _fromAddress: the source PingPong address\n function lzReceive(\n uint16 _srcChainId,\n bytes memory _fromAddress,\n uint64 /*_nonce*/,\n bytes memory _payload\n ) external override {\n require(msg.sender == address(endpoint)); // boilerplate! lzReceive must be called by the endpoint for security\n\n // use assembly to extract the address from the bytes memory parameter\n address fromAddress;\n assembly {\n fromAddress := mload(add(_fromAddress, 20))\n }\n\n // decode the number of pings sent thus far\n uint pings = abi.decode(_payload, (uint));\n\n // \"recursively\" call ping in order to *pong* (and increment pings)\n ++pings;\n numPings = pings;\n\n ping(_srcChainId, fromAddress, pings);\n }\n\n function setConfig(\n uint16 /*_version*/,\n uint16 _dstChainId,\n uint _configType,\n bytes memory _config\n ) external override {\n endpoint.setConfig(_dstChainId, endpoint.getSendVersion(address(this)), _configType, _config);\n }\n\n function getConfig(\n uint16 /*_dstChainId*/,\n uint16 _chainId,\n address,\n uint _configType\n ) external view returns (bytes memory) {\n return endpoint.getConfig(endpoint.getSendVersion(address(this)), _chainId, address(this), _configType);\n }\n\n function setSendVersion(uint16 version) external override {\n endpoint.setSendVersion(version);\n }\n\n function setReceiveVersion(uint16 version) external override {\n endpoint.setReceiveVersion(version);\n }\n\n function getSendVersion() external view returns (uint16) {\n return endpoint.getSendVersion(address(this));\n }\n\n function getReceiveVersion() external view returns (uint16) {\n return endpoint.getReceiveVersion(address(this));\n }\n\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override {\n // do nth\n }\n\n // allow this contract to receive ether\n fallback() external payable {}\n\n receive() external payable {}\n}\n"
|
|
190
|
+
},
|
|
191
|
+
"contracts/mocks/PriceFeedV2Mock.sol": {
|
|
192
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"../interfaces/ILayerZeroPriceFeedV2.sol\";\n\n// PriceFeed is updated based on v1 eids\n// v2 eids will fall to the convention of v1 eid + 30,000\ncontract PriceFeedV2Mock is ILayerZeroPriceFeedV2, OwnableUpgradeable {\n uint128 internal PRICE_RATIO_DENOMINATOR;\n\n // sets pricing\n mapping(address => bool) public priceUpdater;\n\n mapping(uint32 => Price) public defaultModelPrice;\n ArbitrumPriceExt public arbitrumPriceExt;\n\n uint128 public nativeTokenPriceUSD; // uses PRICE_RATIO_DENOMINATOR\n\n // upgrade: arbitrum compression - percentage of callDataSize after brotli compression\n uint128 public ARBITRUM_COMPRESSION_PERCENT;\n\n // ============================ Constructor ===================================\n\n function initialize(address _priceUpdater) public initializer {\n __Ownable_init();\n priceUpdater[_priceUpdater] = true;\n PRICE_RATIO_DENOMINATOR = 1e20;\n ARBITRUM_COMPRESSION_PERCENT = 47;\n }\n\n // ============================ Modifier ======================================\n\n // owner is always approved\n modifier onlyPriceUpdater() {\n if (owner() != msg.sender) {\n require(priceUpdater[msg.sender], \"PriceFeed: not price updater\");\n }\n _;\n }\n\n // ============================ OnlyOwner =====================================\n\n function setPriceUpdater(address _addr, bool _active) external onlyOwner {\n priceUpdater[_addr] = _active;\n }\n\n function setPriceRatioDenominator(uint128 _denominator) external onlyOwner {\n PRICE_RATIO_DENOMINATOR = _denominator;\n }\n\n function setArbitrumCompressionPercent(uint128 _compressionPercent) external onlyOwner {\n ARBITRUM_COMPRESSION_PERCENT = _compressionPercent;\n }\n\n // ============================ OnlyPriceUpdater =====================================\n\n function setPrice(UpdatePrice[] calldata _price) external onlyPriceUpdater {\n for (uint i = 0; i < _price.length; i++) {\n UpdatePrice calldata _update = _price[i];\n _setPrice(_update.eid, _update.price);\n }\n }\n\n function setPriceForArbitrum(UpdatePriceExt calldata _update) external onlyPriceUpdater {\n _setPrice(_update.eid, _update.price);\n\n uint64 gasPerL2Tx = _update.extend.gasPerL2Tx;\n uint32 gasPerL1CalldataByte = _update.extend.gasPerL1CallDataByte;\n\n arbitrumPriceExt.gasPerL2Tx = gasPerL2Tx;\n arbitrumPriceExt.gasPerL1CallDataByte = gasPerL1CalldataByte;\n }\n\n function setNativeTokenPriceUSD(uint128 _nativeTokenPriceUSD) external onlyPriceUpdater {\n nativeTokenPriceUSD = _nativeTokenPriceUSD;\n }\n\n // ============================ Internal ==========================================\n function _setPrice(uint32 _dstEid, Price memory _price) internal {\n uint128 priceRatio = _price.priceRatio;\n uint64 gasPriceInUnit = _price.gasPriceInUnit;\n uint32 gasPerByte = _price.gasPerByte;\n defaultModelPrice[_dstEid] = Price(priceRatio, gasPriceInUnit, gasPerByte);\n }\n\n function _getL1LookupId(uint32 _l2Eid) internal pure returns (uint32) {\n uint32 l2Eid = _l2Eid % 30_000;\n if (l2Eid == 111) {\n return 101;\n } else if (l2Eid == 10132) {\n return 10121; // ethereum-goerli\n } else if (l2Eid == 20132) {\n return 20121; // ethereum-goerli\n } else {\n revert(\"PriceFeed: unknown l2 chain id\");\n }\n }\n\n // ============================ View ==========================================\n\n function getPrice(uint32 _dstEid) external view override returns (Price memory price) {\n price = defaultModelPrice[_dstEid];\n }\n\n function getPriceRatioDenominator() external view override returns (uint128) {\n return PRICE_RATIO_DENOMINATOR;\n }\n\n function estimateFeeByEid(\n uint32 _dstEid,\n uint _callDataSize,\n uint _gas\n )\n external\n view\n override\n returns (uint fee, uint128 priceRatio, uint128 priceRatioDenominator, uint128 nativePriceUSD)\n {\n uint32 dstEid = _dstEid % 30_000;\n if (dstEid == 110 || dstEid == 10143 || dstEid == 20143) {\n (fee, priceRatio) = _estimateFeeWithArbitrumModel(dstEid, _callDataSize, _gas);\n } else if (dstEid == 111 || dstEid == 10132 || dstEid == 20132) {\n (fee, priceRatio) = _estimateFeeWithOptimismModel(dstEid, _callDataSize, _gas);\n } else {\n (fee, priceRatio) = _estimateFeeWithDefaultModel(dstEid, _callDataSize, _gas);\n }\n priceRatioDenominator = PRICE_RATIO_DENOMINATOR;\n nativePriceUSD = nativeTokenPriceUSD;\n }\n\n function _estimateFeeWithDefaultModel(\n uint32 _dstEid,\n uint _callDataSize,\n uint _gas\n ) internal view returns (uint fee, uint128 priceRatio) {\n Price storage remotePrice = defaultModelPrice[_dstEid];\n\n // assuming the _gas includes (1) the 21,000 overhead and (2) not the calldata gas\n uint gasForCallData = _callDataSize * remotePrice.gasPerByte;\n uint remoteFee = (gasForCallData + _gas) * remotePrice.gasPriceInUnit;\n return ((remoteFee * remotePrice.priceRatio) / PRICE_RATIO_DENOMINATOR, remotePrice.priceRatio);\n }\n\n function _estimateFeeWithOptimismModel(\n uint32 _dstEid,\n uint _callDataSize,\n uint _gas\n ) internal view returns (uint fee, uint128 priceRatio) {\n uint32 ethereumId = _getL1LookupId(_dstEid);\n\n // L1 fee\n Price storage ethereumPrice = defaultModelPrice[ethereumId];\n uint gasForL1CallData = (_callDataSize * ethereumPrice.gasPerByte) + 3188; // 2100 + 68 * 16\n uint l1Fee = gasForL1CallData * ethereumPrice.gasPriceInUnit;\n\n // L2 fee\n Price storage optimismPrice = defaultModelPrice[_dstEid];\n uint gasForL2CallData = _callDataSize * optimismPrice.gasPerByte;\n uint l2Fee = (gasForL2CallData + _gas) * optimismPrice.gasPriceInUnit;\n\n uint l1FeeInSrcPrice = (l1Fee * ethereumPrice.priceRatio) / PRICE_RATIO_DENOMINATOR;\n uint l2FeeInSrcPrice = (l2Fee * optimismPrice.priceRatio) / PRICE_RATIO_DENOMINATOR;\n uint gasFee = l1FeeInSrcPrice + l2FeeInSrcPrice;\n return (gasFee, optimismPrice.priceRatio);\n }\n\n function _estimateFeeWithArbitrumModel(\n uint32 _dstEid,\n uint _callDataSize,\n uint _gas\n ) internal view returns (uint fee, uint128 priceRatio) {\n Price storage arbitrumPrice = defaultModelPrice[_dstEid];\n\n // L1 fee\n uint gasForL1CallData = ((_callDataSize * ARBITRUM_COMPRESSION_PERCENT) / 100) *\n arbitrumPriceExt.gasPerL1CallDataByte;\n // L2 Fee\n uint gasForL2CallData = _callDataSize * arbitrumPrice.gasPerByte;\n uint gasFee = (_gas + arbitrumPriceExt.gasPerL2Tx + gasForL1CallData + gasForL2CallData) *\n arbitrumPrice.gasPriceInUnit;\n\n return ((gasFee * arbitrumPrice.priceRatio) / PRICE_RATIO_DENOMINATOR, arbitrumPrice.priceRatio);\n }\n}\n"
|
|
193
|
+
},
|
|
194
|
+
"contracts/mocks/Token.sol": {
|
|
195
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract Token is ERC20 {\n event tried();\n event caught();\n\n constructor() ERC20(\"test\", \"test\") {\n _mint(msg.sender, 10_000_000_000 * 10 ** 18);\n }\n\n // not supported by zksync\n // function selfDestruct() public {\n // selfdestruct(payable(address(0x0)));\n // }\n\n function tryCatch(address _tokenAddress) public {\n try ERC20(_tokenAddress).totalSupply() {\n emit tried();\n } catch {\n emit caught();\n }\n }\n}\n"
|
|
196
|
+
},
|
|
197
|
+
"contracts/mocks/UltraLightNodeV2Mock.sol": {
|
|
198
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"../interfaces/ILayerZeroUltraLightNodeV2.sol\";\n\ncontract UltraLightNodeV2Mock is ILayerZeroUltraLightNodeV2 {\n event executed();\n event paidTo(address _to, uint _amount);\n\n mapping(address => mapping(uint16 => mapping(bytes32 => mapping(bytes32 => uint)))) public hashLookup; //[oracle][srcChainId][blockhash][datahash] -> confirmation\n\n // Mock version of uln for testing the withdraw fee function. If we need to use this again we can expand on it.\n // Relayer functions\n function validateTransactionProof(uint16, address, uint, bytes32, bytes32, bytes calldata) external override {\n emit executed();\n }\n\n // an Oracle delivers the block data using updateHash()\n function updateHash(uint16, bytes32, uint, bytes32) external override {\n emit executed();\n }\n\n // can only withdraw the receivable of the msg.sender\n function withdrawNative(address payable _to, uint _amount) external override {\n (bool success, ) = _to.call{value: _amount}(\"\");\n require(success);\n emit paidTo(_to, _amount);\n }\n\n function withdrawZRO(address, uint) external override {\n emit executed();\n }\n\n // view functions\n function getAppConfig(uint16, address) external view override returns (ApplicationConfiguration memory) {}\n\n function accruedNativeFee(address _address) external view override returns (uint) {}\n\n receive() external payable {}\n}\n"
|
|
199
|
+
},
|
|
200
|
+
"contracts/NonceContract.sol": {
|
|
201
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"./interfaces/ILayerZeroEndpoint.sol\";\n\ncontract NonceContract {\n ILayerZeroEndpoint public immutable endpoint;\n // outboundNonce = [dstChainId][remoteAddress + localAddress]\n mapping(uint16 => mapping(bytes => uint64)) public outboundNonce;\n\n constructor(address _endpoint) {\n endpoint = ILayerZeroEndpoint(_endpoint);\n }\n\n function increment(uint16 _chainId, address _ua, bytes calldata _path) external returns (uint64) {\n require(\n endpoint.getSendLibraryAddress(_ua) == msg.sender,\n \"NonceContract: msg.sender is not valid sendlibrary\"\n );\n return ++outboundNonce[_chainId][_path];\n }\n}\n"
|
|
202
|
+
},
|
|
203
|
+
"contracts/NonceContractRadar.sol": {
|
|
204
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\n\nimport \"./interfaces/ILayerZeroEndpoint.sol\";\n\ncontract NonceContractRadar {\n ILayerZeroEndpoint public immutable endpoint;\n address public immutable ulnv2Radar;\n // outboundNonce = [dstChainId][remoteAddress + localAddress]\n mapping(uint16 => mapping(bytes => uint64)) public outboundNonce;\n\n constructor(address _endpoint, address _ulnv2Radar) {\n endpoint = ILayerZeroEndpoint(_endpoint);\n ulnv2Radar = _ulnv2Radar;\n }\n\n function increment(uint16 _chainId, address _ua, bytes calldata _path) external returns (uint64) {\n require(\n endpoint.getSendLibraryAddress(_ua) == msg.sender,\n \"NonceContract: msg.sender is not valid sendlibrary\"\n );\n return ++outboundNonce[_chainId][_path];\n }\n\n // only ulnv2Radar can call this function\n function initRadarOutboundNonce(uint16 _dstChainId, bytes calldata _path, uint64 _nonce) external {\n require(msg.sender == ulnv2Radar, \"NonceContract: only ulnv2Radar\");\n outboundNonce[_dstChainId][_path] = _nonce;\n }\n}\n"
|
|
205
|
+
},
|
|
206
|
+
"contracts/PriceFeed.sol": {
|
|
207
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"hardhat-deploy/solc_0.8/proxy/Proxied.sol\";\nimport \"./interfaces/ILayerZeroPriceFeed.sol\";\n\ncontract PriceFeed is ILayerZeroPriceFeed, OwnableUpgradeable, Proxied {\n uint128 public PRICE_RATIO_DENOMINATOR;\n\n // sets pricing\n mapping(address => bool) public priceUpdater;\n\n // [_chainId]\n mapping(uint16 => Price) public defaultModelPrice;\n ArbitrumPriceExt public arbitrumPriceExt;\n\n uint128 public override nativeTokenPriceUSD; // uses PRICE_RATIO_DENOMINATOR\n\n // upgrade: arbitrum compression - percentage of callDataSize after brotli compression\n uint128 public ARBITRUM_COMPRESSION_PERCENT;\n\n // ============================ Constructor ===================================\n\n function initialize(address _priceUpdater) public proxied initializer {\n __Ownable_init();\n priceUpdater[_priceUpdater] = true;\n PRICE_RATIO_DENOMINATOR = 1e10;\n ARBITRUM_COMPRESSION_PERCENT = 47;\n }\n\n function onUpgrade() public proxied {\n PRICE_RATIO_DENOMINATOR = 1e10;\n ARBITRUM_COMPRESSION_PERCENT = 47;\n }\n\n // ============================ Modifier ======================================\n\n // owner is always approved\n modifier onlyPriceUpdater() {\n if (owner() != msg.sender) {\n require(priceUpdater[msg.sender], \"PriceFeed: not price updater\");\n }\n _;\n }\n\n // ============================ OnlyOwner =====================================\n\n function setPriceUpdater(address _addr, bool _active) external onlyOwner {\n priceUpdater[_addr] = _active;\n }\n\n function setPriceRatioDenominator(uint128 _denominator) external onlyOwner {\n PRICE_RATIO_DENOMINATOR = _denominator;\n }\n\n function setArbitrumCompressionPercent(uint128 _compressionPercent) external onlyOwner {\n ARBITRUM_COMPRESSION_PERCENT = _compressionPercent;\n }\n\n // ============================ OnlyPriceUpdater =====================================\n\n function setPrice(UpdatePrice[] calldata _price) external onlyPriceUpdater {\n for (uint i = 0; i < _price.length; i++) {\n UpdatePrice calldata _update = _price[i];\n _setPrice(_update.chainId, _update.price);\n }\n }\n\n function setPriceForArbitrum(UpdatePriceExt[] calldata _price) external onlyPriceUpdater {\n for (uint i = 0; i < _price.length; i++) {\n UpdatePriceExt calldata _update = _price[i];\n\n _setPrice(_update.chainId, _update.price);\n\n uint64 gasPerL2Tx = _update.extend.gasPerL2Tx;\n uint32 gasPerL1CalldataByte = _update.extend.gasPerL1CallDataByte;\n\n arbitrumPriceExt.gasPerL2Tx = gasPerL2Tx;\n arbitrumPriceExt.gasPerL1CallDataByte = gasPerL1CalldataByte;\n }\n }\n\n function setNativeTokenPriceUSD(uint128 _nativeTokenPriceUSD) external onlyPriceUpdater {\n nativeTokenPriceUSD = _nativeTokenPriceUSD;\n }\n\n // ============================ Internal ==========================================\n function _setPrice(uint16 chainId, Price memory _price) internal {\n uint128 priceRatio = _price.priceRatio;\n uint64 gasPriceInUnit = _price.gasPriceInUnit;\n uint32 gasPerByte = _price.gasPerByte;\n defaultModelPrice[chainId] = Price(priceRatio, gasPriceInUnit, gasPerByte);\n }\n\n // For optimism l1 gas price lookup\n function _getL1LookupId(uint16 _l2ChainId) internal pure returns (uint16) {\n if (_l2ChainId == 111) {\n return 101;\n } else if (_l2ChainId == 10132) {\n return 10121; // ethereum-goerli\n } else if (_l2ChainId == 20132) {\n return 20121; // ethereum-goerli\n } else {\n revert(\"PriceFeed: unknown l2 chain id\");\n }\n }\n\n // ============================ View ==========================================\n\n function getPrice(uint16 _dstChainId) external view override returns (Price memory price) {\n price = defaultModelPrice[_dstChainId];\n }\n\n function getPriceRatioDenominator() external view override returns (uint128) {\n return PRICE_RATIO_DENOMINATOR;\n }\n\n function estimateFeeByChain(\n uint16 _dstChainId,\n uint _callDataSize,\n uint _gas\n ) external view override returns (uint fee, uint128 priceRatio) {\n if (_dstChainId == 110 || _dstChainId == 10143 || _dstChainId == 20143) {\n return estimateFeeWithArbitrumModel(_dstChainId, _callDataSize, _gas);\n } else if (_dstChainId == 111 || _dstChainId == 10132 || _dstChainId == 20132) {\n return estimateFeeWithOptimismModel(_dstChainId, _callDataSize, _gas);\n } else {\n return estimateFeeWithDefaultModel(_dstChainId, _callDataSize, _gas);\n }\n }\n\n function estimateFeeWithDefaultModel(\n uint16 _dstChainId,\n uint _callDataSize,\n uint _gas\n ) public view returns (uint fee, uint128 priceRatio) {\n Price storage remotePrice = defaultModelPrice[_dstChainId];\n\n // assuming the _gas includes (1) the 21,000 overhead and (2) not the calldata gas\n uint gasForCallData = _callDataSize * remotePrice.gasPerByte;\n uint remoteFee = (gasForCallData + _gas) * remotePrice.gasPriceInUnit;\n return ((remoteFee * remotePrice.priceRatio) / PRICE_RATIO_DENOMINATOR, remotePrice.priceRatio);\n }\n\n function estimateFeeWithOptimismModel(\n uint16 _dstChainId,\n uint _callDataSize,\n uint _gas\n ) public view returns (uint fee, uint128 priceRatio) {\n uint16 ethereumId = _getL1LookupId(_dstChainId);\n\n // L1 fee\n Price storage ethereumPrice = defaultModelPrice[ethereumId];\n uint gasForL1CallData = (_callDataSize * ethereumPrice.gasPerByte) + 3188; // 2100 + 68 * 16\n uint l1Fee = gasForL1CallData * ethereumPrice.gasPriceInUnit;\n\n // L2 fee\n Price storage optimismPrice = defaultModelPrice[_dstChainId];\n uint gasForL2CallData = _callDataSize * optimismPrice.gasPerByte;\n uint l2Fee = (gasForL2CallData + _gas) * optimismPrice.gasPriceInUnit;\n\n uint l1FeeInSrcPrice = (l1Fee * ethereumPrice.priceRatio) / PRICE_RATIO_DENOMINATOR;\n uint l2FeeInSrcPrice = (l2Fee * optimismPrice.priceRatio) / PRICE_RATIO_DENOMINATOR;\n uint gasFee = l1FeeInSrcPrice + l2FeeInSrcPrice;\n return (gasFee, optimismPrice.priceRatio);\n }\n\n function estimateFeeWithArbitrumModel(\n uint16 _dstChainId,\n uint _callDataSize,\n uint _gas\n ) public view returns (uint fee, uint128 priceRatio) {\n Price storage arbitrumPrice = defaultModelPrice[_dstChainId];\n\n // L1 fee\n uint gasForL1CallData = ((_callDataSize * ARBITRUM_COMPRESSION_PERCENT) / 100) *\n arbitrumPriceExt.gasPerL1CallDataByte;\n // L2 Fee\n uint gasForL2CallData = _callDataSize * arbitrumPrice.gasPerByte;\n uint gasFee = (_gas + arbitrumPriceExt.gasPerL2Tx + gasForL1CallData + gasForL2CallData) *\n arbitrumPrice.gasPriceInUnit;\n\n return ((gasFee * arbitrumPrice.priceRatio) / PRICE_RATIO_DENOMINATOR, arbitrumPrice.priceRatio);\n }\n}\n"
|
|
208
|
+
},
|
|
209
|
+
"contracts/proof/FPValidator.sol": {
|
|
210
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"../interfaces/ILayerZeroValidationLibrary.sol\";\nimport \"../interfaces/IValidationLibraryHelperV2.sol\";\n\ninterface IStargate {\n // Stargate objects for abi encoding / decoding\n struct SwapObj {\n uint amount;\n uint eqFee;\n uint eqReward;\n uint lpFee;\n uint protocolFee;\n uint lkbRemove;\n }\n\n struct CreditObj {\n uint credits;\n uint idealBalance;\n }\n}\n\ncontract FPValidator is ILayerZeroValidationLibrary, IValidationLibraryHelperV2 {\n uint8 public proofType = 2;\n uint8 public utilsVersion = 1;\n\n address public immutable stargateBridgeAddress;\n address public immutable stargateTokenAddress;\n\n constructor(address _stargateBridgeAddress, address _stargateTokenAddress) {\n stargateBridgeAddress = _stargateBridgeAddress;\n stargateTokenAddress = _stargateTokenAddress;\n }\n\n function validateProof(\n bytes32 _packetHash,\n bytes calldata _transactionProof,\n uint _remoteAddressSize\n ) external view override returns (LayerZeroPacket.Packet memory packet) {\n require(_remoteAddressSize > 0, \"ProofLib: invalid address size\");\n // _transactionProof = srcUlnAddress (32 bytes) + lzPacket\n require(\n _transactionProof.length > 32 && keccak256(_transactionProof) == _packetHash,\n \"ProofLib: invalid transaction proof\"\n );\n\n bytes memory ulnAddressBytes = bytes(_transactionProof[0:32]);\n bytes32 ulnAddress;\n assembly {\n ulnAddress := mload(add(ulnAddressBytes, 32))\n }\n packet = LayerZeroPacket.getPacketV3(_transactionProof[32:], _remoteAddressSize, ulnAddress);\n\n if (packet.dstAddress == stargateBridgeAddress) packet.payload = _secureStgPayload(packet.payload);\n if (packet.dstAddress == stargateTokenAddress) packet.payload = _secureStgTokenPayload(packet.payload);\n\n return packet;\n }\n\n function _secureStgTokenPayload(bytes memory _payload) internal pure returns (bytes memory) {\n (bytes memory toAddressBytes, uint qty) = abi.decode(_payload, (bytes, uint));\n\n address toAddress = address(0);\n if (toAddressBytes.length > 0) {\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n if (toAddress == address(0)) {\n address deadAddress = address(0x000000000000000000000000000000000000dEaD);\n bytes memory newToAddressBytes = abi.encodePacked(deadAddress);\n return abi.encode(newToAddressBytes, qty);\n }\n\n // default to return the original payload\n return _payload;\n }\n\n function _secureStgPayload(bytes memory _payload) internal view returns (bytes memory) {\n // functionType is uint8 even though the encoding will take up the side of uint256\n uint8 functionType;\n assembly {\n functionType := mload(add(_payload, 32))\n }\n\n // TYPE_SWAP_REMOTE == 1 && only if the payload has a payload\n // only swapRemote inside of stargate can call sgReceive on an user supplied to address\n // thus we do not care about the other type functions even if the toAddress is overly long.\n if (functionType == 1) {\n // decode the _payload with its types\n (\n ,\n uint srcPoolId,\n uint dstPoolId,\n uint dstGasForCall,\n IStargate.CreditObj memory c,\n IStargate.SwapObj memory s,\n bytes memory toAddressBytes,\n bytes memory contractCallPayload\n ) = abi.decode(_payload, (uint8, uint, uint, uint, IStargate.CreditObj, IStargate.SwapObj, bytes, bytes));\n\n // if contractCallPayload.length > 0 need to check if the to address is a contract or not\n if (contractCallPayload.length > 0) {\n // otherwise, need to check if the payload can be delivered to the toAddress\n address toAddress = address(0);\n if (toAddressBytes.length > 0) {\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n // check if the toAddress is a contract. We are not concerned about addresses that pretend to be wallets. because worst case we just delete their payload if being malicious\n // we can guarantee that if a size > 0, then the contract is definitely a contract address in this context\n uint size;\n assembly {\n size := extcodesize(toAddress)\n }\n\n if (size == 0) {\n // size == 0 indicates its not a contract, payload wont be delivered\n // secure the _payload to make sure funds can be delivered to the toAddress\n bytes memory newToAddressBytes = abi.encodePacked(toAddress);\n bytes memory securePayload = abi.encode(\n functionType,\n srcPoolId,\n dstPoolId,\n dstGasForCall,\n c,\n s,\n newToAddressBytes,\n bytes(\"\")\n );\n return securePayload;\n }\n }\n }\n\n // default to return the original payload\n return _payload;\n }\n\n function secureStgTokenPayload(bytes memory _payload) external pure returns (bytes memory) {\n return _secureStgTokenPayload(_payload);\n }\n\n function secureStgPayload(bytes memory _payload) external view returns (bytes memory) {\n return _secureStgPayload(_payload);\n }\n\n function getUtilsVersion() external view override returns (uint8) {\n return utilsVersion;\n }\n\n function getProofType() external view override returns (uint8) {\n return proofType;\n }\n\n function getVerifyLog(\n bytes32,\n uint[] calldata,\n uint,\n bytes[] calldata proof\n ) external pure override returns (ULNLog memory log) {}\n\n function getPacket(\n bytes memory data,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) external pure override returns (LayerZeroPacket.Packet memory) {\n return LayerZeroPacket.getPacketV3(data, sizeOfSrcAddress, ulnAddress);\n }\n}\n"
|
|
211
|
+
},
|
|
212
|
+
"contracts/proof/MPTValidator.sol": {
|
|
213
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"./utility/Buffer.sol\";\nimport \"../interfaces/ILayerZeroValidationLibrary.sol\";\nimport \"./utility/UltraLightNodeEVMDecoder.sol\";\n\ncontract MPTValidator is ILayerZeroValidationLibrary {\n using RLPDecode for RLPDecode.RLPItem;\n using RLPDecode for RLPDecode.Iterator;\n using Buffer for Buffer.buffer;\n using SafeMath for uint;\n\n bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;\n\n struct ULNLog {\n bytes32 contractAddress;\n bytes32 topicZeroSig;\n bytes data;\n }\n\n function validateProof(\n bytes32 _receiptsRoot,\n bytes calldata _transactionProof,\n uint _remoteAddressSize\n ) external pure override returns (LayerZeroPacket.Packet memory packet) {\n (uint16 remoteChainId, bytes[] memory proof, uint[] memory pointers, uint receiptIndex, uint logIndex) = abi\n .decode(_transactionProof, (uint16, bytes[], uint[], uint, uint));\n\n ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptIndex, logIndex, proof, pointers);\n require(log.topicZeroSig == PACKET_SIGNATURE, \"LayerZero: packet not recognized\"); //data\n\n return getPacket(log.data, remoteChainId, _remoteAddressSize, log.contractAddress);\n }\n\n function _getVerifiedLog(\n bytes32 hashRoot,\n uint receiptSlotIndex,\n uint logIndex,\n bytes[] memory proof,\n uint[] memory pointers\n ) internal pure returns (ULNLog memory) {\n // walk and assert the hash links of MPT\n uint pointer;\n bytes memory proofBytes;\n for (uint i = 0; i < proof.length; i++) {\n proofBytes = proof[i];\n require(hashRoot == keccak256(proofBytes), \"LayerZero: invalid hashlink\");\n if (i < pointers.length) {\n pointer = pointers[i];\n assembly {\n hashRoot := mload(add(add(proofBytes, pointer), 32))\n }\n }\n }\n\n // build the iterator for the proofBytes\n RLPDecode.Iterator memory it = RLPDecode.toRlpItem(proofBytes).iterator();\n\n // get the receipt item from either branch or leaf node\n RLPDecode.RLPItem memory receiptItem = it.item.getItemByIndex(receiptSlotIndex);\n // it = targetReceiptIter\n it = receiptItem.typeOffset().iterator();\n it.next(); // status\n it.next(); // gasUsed\n it.next(); // logBloom\n\n // it = targetLogIter\n it = it.next().getItemByIndex(logIndex).iterator();\n ULNLog memory log;\n log.contractAddress = bytes32(it.next().toUint());\n log.topicZeroSig = bytes32(it.next().getItemByIndex(0).toUint());\n log.data = it.next().toBytes();\n\n return log;\n }\n\n // profiling and test\n function getVerifyLog(\n bytes32 hashRoot,\n uint receiptSlotIndex,\n uint logIndex,\n bytes[] memory proof,\n uint[] memory pointers\n ) external pure returns (ULNLog memory) {\n return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof, pointers);\n }\n\n function getPacket(\n bytes memory data,\n uint16 srcChain,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) internal pure returns (LayerZeroPacket.Packet memory) {\n uint16 dstChainId;\n address dstAddress;\n uint size;\n uint64 nonce;\n\n // The log consists of the destination chain id and then a bytes payload\n // 0--------------------------------------------31\n // 0 | destination chain id\n // 32 | defines bytes array\n // 64 |\n // 96 | bytes array size\n // 128 | payload\n assembly {\n dstChainId := mload(add(data, 32))\n size := mload(add(data, 96)) /// size of the byte array\n nonce := mload(add(data, 104)) // offset to convert to uint64 128 is index -24\n dstAddress := mload(add(data, sub(add(128, sizeOfSrcAddress), 4))) // offset to convert to address 12 -8\n }\n\n Buffer.buffer memory srcAddressBuffer;\n srcAddressBuffer.init(sizeOfSrcAddress);\n srcAddressBuffer.writeRawBytes(0, data, 136, sizeOfSrcAddress); // 128 + 8\n\n uint payloadSize = size.sub(20).sub(sizeOfSrcAddress);\n Buffer.buffer memory payloadBuffer;\n payloadBuffer.init(payloadSize);\n payloadBuffer.writeRawBytes(0, data, sizeOfSrcAddress.add(156), payloadSize); // 148 + 8\n return\n LayerZeroPacket.Packet(\n srcChain,\n dstChainId,\n nonce,\n address(dstAddress),\n srcAddressBuffer.buf,\n ulnAddress,\n payloadBuffer.buf\n );\n }\n}\n"
|
|
214
|
+
},
|
|
215
|
+
"contracts/proof/MPTValidator01.sol": {
|
|
216
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"./utility/UltraLightNodeEVMDecoder.sol\";\nimport \"../interfaces/IValidationLibraryHelperV2.sol\";\nimport \"../interfaces/ILayerZeroValidationLibrary.sol\";\n\ninterface IStargate {\n // Stargate objects for abi encoding / decoding\n struct SwapObj {\n uint amount;\n uint eqFee;\n uint eqReward;\n uint lpFee;\n uint protocolFee;\n uint lkbRemove;\n }\n\n struct CreditObj {\n uint credits;\n uint idealBalance;\n }\n}\n\ncontract MPTValidator01 is ILayerZeroValidationLibrary, IValidationLibraryHelperV2 {\n using RLPDecode for RLPDecode.RLPItem;\n using RLPDecode for RLPDecode.Iterator;\n\n uint8 public proofType = 1;\n uint8 public utilsVersion = 4;\n bytes32 public constant PACKET_SIGNATURE = 0xe9bded5f24a4168e4f3bf44e00298c993b22376aad8c58c7dda9718a54cbea82;\n\n address public immutable stargateBridgeAddress;\n address public immutable stargateTokenAddress;\n\n constructor(address _stargateBridgeAddress, address _stargateTokenAddress) {\n stargateBridgeAddress = _stargateBridgeAddress;\n stargateTokenAddress = _stargateTokenAddress;\n }\n\n function validateProof(\n bytes32 _receiptsRoot,\n bytes calldata _transactionProof,\n uint _remoteAddressSize\n ) external view override returns (LayerZeroPacket.Packet memory packet) {\n require(_remoteAddressSize > 0, \"ProofLib: invalid address size\");\n (bytes[] memory proof, uint[] memory receiptSlotIndex, uint logIndex) = abi.decode(\n _transactionProof,\n (bytes[], uint[], uint)\n );\n\n ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptSlotIndex, logIndex, proof);\n require(log.topicZeroSig == PACKET_SIGNATURE, \"ProofLib: packet not recognized\"); //data\n\n packet = LayerZeroPacket.getPacketV2(log.data, _remoteAddressSize, log.contractAddress);\n\n if (packet.dstAddress == stargateBridgeAddress) packet.payload = _secureStgPayload(packet.payload);\n\n if (packet.dstAddress == stargateTokenAddress) packet.payload = _secureStgTokenPayload(packet.payload);\n\n return packet;\n }\n\n function _secureStgTokenPayload(bytes memory _payload) internal pure returns (bytes memory) {\n (bytes memory toAddressBytes, uint qty) = abi.decode(_payload, (bytes, uint));\n\n address toAddress = address(0);\n if (toAddressBytes.length > 0) {\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n if (toAddress == address(0)) {\n address deadAddress = address(0x000000000000000000000000000000000000dEaD);\n bytes memory newToAddressBytes = abi.encodePacked(deadAddress);\n return abi.encode(newToAddressBytes, qty);\n }\n\n // default to return the original payload\n return _payload;\n }\n\n function _secureStgPayload(bytes memory _payload) internal view returns (bytes memory) {\n // functionType is uint8 even though the encoding will take up the side of uint256\n uint8 functionType;\n assembly {\n functionType := mload(add(_payload, 32))\n }\n\n // TYPE_SWAP_REMOTE == 1 && only if the payload has a payload\n // only swapRemote inside of stargate can call sgReceive on an user supplied to address\n // thus we do not care about the other type functions even if the toAddress is overly long.\n if (functionType == 1) {\n // decode the _payload with its types\n (\n ,\n uint srcPoolId,\n uint dstPoolId,\n uint dstGasForCall,\n IStargate.CreditObj memory c,\n IStargate.SwapObj memory s,\n bytes memory toAddressBytes,\n bytes memory contractCallPayload\n ) = abi.decode(_payload, (uint8, uint, uint, uint, IStargate.CreditObj, IStargate.SwapObj, bytes, bytes));\n\n // if contractCallPayload.length > 0 need to check if the to address is a contract or not\n if (contractCallPayload.length > 0) {\n // otherwise, need to check if the payload can be delivered to the toAddress\n address toAddress = address(0);\n if (toAddressBytes.length > 0) {\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n // check if the toAddress is a contract. We are not concerned about addresses that pretend to be wallets. because worst case we just delete their payload if being malicious\n // we can guarantee that if a size > 0, then the contract is definitely a contract address in this context\n uint size;\n assembly {\n size := extcodesize(toAddress)\n }\n\n if (size == 0) {\n // size == 0 indicates its not a contract, payload wont be delivered\n // secure the _payload to make sure funds can be delivered to the toAddress\n bytes memory newToAddressBytes = abi.encodePacked(toAddress);\n bytes memory securePayload = abi.encode(\n functionType,\n srcPoolId,\n dstPoolId,\n dstGasForCall,\n c,\n s,\n newToAddressBytes,\n bytes(\"\")\n );\n return securePayload;\n }\n }\n }\n\n // default to return the original payload\n return _payload;\n }\n\n function secureStgTokenPayload(bytes memory _payload) external pure returns (bytes memory) {\n return _secureStgTokenPayload(_payload);\n }\n\n function secureStgPayload(bytes memory _payload) external view returns (bytes memory) {\n return _secureStgPayload(_payload);\n }\n\n function _getVerifiedLog(\n bytes32 hashRoot,\n uint[] memory paths,\n uint logIndex,\n bytes[] memory proof\n ) internal pure returns (ULNLog memory) {\n require(paths.length == proof.length, \"ProofLib: invalid proof size\");\n require(proof.length > 0, \"ProofLib: proof size must > 0\");\n RLPDecode.RLPItem memory item;\n bytes memory proofBytes;\n\n for (uint i = 0; i < proof.length; i++) {\n proofBytes = proof[i];\n require(hashRoot == keccak256(proofBytes), \"ProofLib: invalid hashlink\");\n item = RLPDecode.toRlpItem(proofBytes).safeGetItemByIndex(paths[i]);\n if (i < proof.length - 1) hashRoot = bytes32(item.toUint());\n }\n\n // burning status + gasUsed + logBloom\n RLPDecode.RLPItem memory logItem = item.typeOffset().safeGetItemByIndex(3);\n RLPDecode.Iterator memory it = logItem.safeGetItemByIndex(logIndex).iterator();\n ULNLog memory log;\n log.contractAddress = bytes32(it.next().toUint());\n log.topicZeroSig = bytes32(it.next().safeGetItemByIndex(0).toUint());\n log.data = it.next().toBytes();\n\n return log;\n }\n\n function getUtilsVersion() external view override returns (uint8) {\n return utilsVersion;\n }\n\n function getProofType() external view override returns (uint8) {\n return proofType;\n }\n\n function getVerifyLog(\n bytes32 hashRoot,\n uint[] memory receiptSlotIndex,\n uint logIndex,\n bytes[] memory proof\n ) external pure override returns (ULNLog memory) {\n return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof);\n }\n\n function getPacket(\n bytes memory data,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) external pure override returns (LayerZeroPacket.Packet memory) {\n return LayerZeroPacket.getPacketV2(data, sizeOfSrcAddress, ulnAddress);\n }\n}\n"
|
|
217
|
+
},
|
|
218
|
+
"contracts/proof/MPTValidatorStgV3.sol": {
|
|
219
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"./utility/Buffer.sol\";\nimport \"../interfaces/ILayerZeroValidationLibrary.sol\";\nimport \"./utility/UltraLightNodeEVMDecoder.sol\";\n\ncontract MPTValidatorStgV3 is ILayerZeroValidationLibrary {\n using RLPDecode for RLPDecode.RLPItem;\n using RLPDecode for RLPDecode.Iterator;\n using Buffer for Buffer.buffer;\n using SafeMath for uint;\n\n bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;\n\n address public immutable stargateBridgeAddress;\n address public immutable stgTokenAddress;\n uint16 public immutable localChainId;\n\n constructor(address _stargateBridgeAddress, address _stgTokenAddress, uint16 _localChainId) {\n stargateBridgeAddress = _stargateBridgeAddress;\n stgTokenAddress = _stgTokenAddress;\n localChainId = _localChainId;\n }\n\n struct ULNLog {\n bytes32 contractAddress;\n bytes32 topicZeroSig;\n bytes data;\n }\n\n // Stargate objects for abi encoding / decoding\n struct SwapObj {\n uint amount;\n uint eqFee;\n uint eqReward;\n uint lpFee;\n uint protocolFee;\n uint lkbRemove;\n }\n\n struct CreditObj {\n uint credits;\n uint idealBalance;\n }\n\n function validateProof(\n bytes32 _receiptsRoot,\n bytes calldata _transactionProof,\n uint _remoteAddressSize\n ) external view override returns (LayerZeroPacket.Packet memory) {\n (uint16 remoteChainId, bytes[] memory proof, uint[] memory receiptSlotIndex, uint logIndex) = abi.decode(\n _transactionProof,\n (uint16, bytes[], uint[], uint)\n );\n\n ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptSlotIndex, logIndex, proof);\n require(log.topicZeroSig == PACKET_SIGNATURE, \"ProofLib: packet not recognized\"); //data\n\n LayerZeroPacket.Packet memory packet = _getPacket(\n log.data,\n remoteChainId,\n _remoteAddressSize,\n log.contractAddress\n );\n\n require(packet.dstChainId == localChainId, \"ProofLib: invalid destination chain ID\");\n\n if (packet.dstAddress == stargateBridgeAddress) packet.payload = _secureStgPayload(packet.payload);\n\n if (packet.dstAddress == stgTokenAddress) packet.payload = _secureStgTokenPayload(packet.payload);\n\n return packet;\n }\n\n function _secureStgTokenPayload(bytes memory _payload) internal pure returns (bytes memory) {\n (bytes memory toAddressBytes, uint qty) = abi.decode(_payload, (bytes, uint));\n\n address toAddress = address(0);\n if (toAddressBytes.length > 0) {\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n if (toAddress == address(0)) {\n address deadAddress = address(0x000000000000000000000000000000000000dEaD);\n bytes memory newToAddressBytes = abi.encodePacked(deadAddress);\n return abi.encode(newToAddressBytes, qty);\n }\n\n // default to return the original payload\n return _payload;\n }\n\n function _secureStgPayload(bytes memory _payload) internal view returns (bytes memory) {\n // functionType is uint8 even though the encoding will take up the side of uint256\n uint8 functionType;\n assembly {\n functionType := mload(add(_payload, 32))\n }\n\n // TYPE_SWAP_REMOTE == 1 && only if the payload has a payload\n // only swapRemote inside of stargate can call sgReceive on an user supplied to address\n // thus we do not care about the other type functions even if the toAddress is overly long.\n if (functionType == 1) {\n // decode the _payload with its types\n (\n ,\n uint srcPoolId,\n uint dstPoolId,\n uint dstGasForCall,\n CreditObj memory c,\n SwapObj memory s,\n bytes memory toAddressBytes,\n bytes memory contractCallPayload\n ) = abi.decode(_payload, (uint8, uint, uint, uint, CreditObj, SwapObj, bytes, bytes));\n\n // if contractCallPayload.length > 0 need to check if the to address is a contract or not\n if (contractCallPayload.length > 0) {\n // otherwise, need to check if the payload can be delivered to the toAddress\n address toAddress = address(0);\n if (toAddressBytes.length > 0) {\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n // check if the toAddress is a contract. We are not concerned about addresses that pretend to be wallets. because worst case we just delete their payload if being malicious\n // we can guarantee that if a size > 0, then the contract is definitely a contract address in this context\n uint size;\n assembly {\n size := extcodesize(toAddress)\n }\n\n if (size == 0) {\n // size == 0 indicates its not a contract, payload wont be delivered\n // secure the _payload to make sure funds can be delivered to the toAddress\n bytes memory newToAddressBytes = abi.encodePacked(toAddress);\n bytes memory securePayload = abi.encode(\n functionType,\n srcPoolId,\n dstPoolId,\n dstGasForCall,\n c,\n s,\n newToAddressBytes,\n bytes(\"\")\n );\n return securePayload;\n }\n }\n }\n\n // default to return the original payload\n return _payload;\n }\n\n function secureStgTokenPayload(bytes memory _payload) external pure returns (bytes memory) {\n return _secureStgTokenPayload(_payload);\n }\n\n function secureStgPayload(bytes memory _payload) external view returns (bytes memory) {\n return _secureStgPayload(_payload);\n }\n\n function _getVerifiedLog(\n bytes32 hashRoot,\n uint[] memory paths,\n uint logIndex,\n bytes[] memory proof\n ) internal pure returns (ULNLog memory) {\n require(paths.length == proof.length, \"ProofLib: invalid proof size\");\n\n RLPDecode.RLPItem memory item;\n bytes memory proofBytes;\n\n for (uint i = 0; i < proof.length; i++) {\n proofBytes = proof[i];\n require(hashRoot == keccak256(proofBytes), \"ProofLib: invalid hashlink\");\n item = RLPDecode.toRlpItem(proofBytes).safeGetItemByIndex(paths[i]);\n if (i < proof.length - 1) hashRoot = bytes32(item.toUint());\n }\n\n // burning status + gasUsed + logBloom\n RLPDecode.RLPItem memory logItem = item.typeOffset().safeGetItemByIndex(3);\n RLPDecode.Iterator memory it = logItem.safeGetItemByIndex(logIndex).iterator();\n ULNLog memory log;\n log.contractAddress = bytes32(it.next().toUint());\n log.topicZeroSig = bytes32(it.next().getItemByIndex(0).toUint());\n log.data = it.next().toBytes();\n\n return log;\n }\n\n // profiling and test\n function getVerifyLog(\n bytes32 hashRoot,\n uint[] memory receiptSlotIndex,\n uint logIndex,\n bytes[] memory proof\n ) external pure returns (ULNLog memory) {\n return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof);\n }\n\n function getPacket(\n bytes memory data,\n uint16 srcChain,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) external pure returns (LayerZeroPacket.Packet memory) {\n return _getPacket(data, srcChain, sizeOfSrcAddress, ulnAddress);\n }\n\n function _getPacket(\n bytes memory data,\n uint16 srcChain,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) internal pure returns (LayerZeroPacket.Packet memory) {\n uint16 dstChainId;\n address dstAddress;\n uint size;\n uint64 nonce;\n\n // The log consists of the destination chain id and then a bytes payload\n // 0--------------------------------------------31\n // 0 | destination chain id\n // 32 | defines bytes array\n // 64 |\n // 96 | bytes array size\n // 128 | payload\n assembly {\n dstChainId := mload(add(data, 32))\n size := mload(add(data, 96)) /// size of the byte array\n nonce := mload(add(data, 104)) // offset to convert to uint64 128 is index -24\n dstAddress := mload(add(data, sub(add(128, sizeOfSrcAddress), 4))) // offset to convert to address 12 -8\n }\n\n Buffer.buffer memory srcAddressBuffer;\n srcAddressBuffer.init(sizeOfSrcAddress);\n srcAddressBuffer.writeRawBytes(0, data, 136, sizeOfSrcAddress); // 128 + 8\n\n uint payloadSize = size.sub(20).sub(sizeOfSrcAddress);\n Buffer.buffer memory payloadBuffer;\n payloadBuffer.init(payloadSize);\n payloadBuffer.writeRawBytes(0, data, sizeOfSrcAddress.add(156), payloadSize); // 148 + 8\n return\n LayerZeroPacket.Packet(\n srcChain,\n dstChainId,\n nonce,\n dstAddress,\n srcAddressBuffer.buf,\n ulnAddress,\n payloadBuffer.buf\n );\n }\n}\n"
|
|
220
|
+
},
|
|
221
|
+
"contracts/proof/MPTValidatorV2.sol": {
|
|
222
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"./utility/Buffer.sol\";\nimport \"../interfaces/ILayerZeroValidationLibrary.sol\";\nimport \"./utility/UltraLightNodeEVMDecoder.sol\";\n\ncontract MPTValidatorV2 is ILayerZeroValidationLibrary {\n using RLPDecode for RLPDecode.RLPItem;\n using RLPDecode for RLPDecode.Iterator;\n using Buffer for Buffer.buffer;\n using SafeMath for uint;\n\n bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;\n\n struct ULNLog {\n bytes32 contractAddress;\n bytes32 topicZeroSig;\n bytes data;\n }\n\n function validateProof(\n bytes32 _receiptsRoot,\n bytes calldata _transactionProof,\n uint _remoteAddressSize\n ) external pure override returns (LayerZeroPacket.Packet memory packet) {\n (uint16 remoteChainId, bytes[] memory proof, uint[] memory receiptSlotIndex, uint logIndex) = abi.decode(\n _transactionProof,\n (uint16, bytes[], uint[], uint)\n );\n\n ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptSlotIndex, logIndex, proof);\n require(log.topicZeroSig == PACKET_SIGNATURE, \"ProofLib: packet not recognized\"); //data\n\n return _getPacket(log.data, remoteChainId, _remoteAddressSize, log.contractAddress);\n }\n\n function _getVerifiedLog(\n bytes32 hashRoot,\n uint[] memory paths,\n uint logIndex,\n bytes[] memory proof\n ) internal pure returns (ULNLog memory) {\n require(paths.length == proof.length, \"ProofLib: invalid proof size\");\n\n RLPDecode.RLPItem memory item;\n bytes memory proofBytes;\n\n for (uint i = 0; i < proof.length; i++) {\n proofBytes = proof[i];\n require(hashRoot == keccak256(proofBytes), \"ProofLib: invalid hashlink\");\n item = RLPDecode.toRlpItem(proofBytes).safeGetItemByIndex(paths[i]);\n if (i < proof.length - 1) hashRoot = bytes32(item.toUint());\n }\n\n // burning status + gasUsed + logBloom\n RLPDecode.RLPItem memory logItem = item.typeOffset().safeGetItemByIndex(3);\n RLPDecode.Iterator memory it = logItem.safeGetItemByIndex(logIndex).iterator();\n ULNLog memory log;\n log.contractAddress = bytes32(it.next().toUint());\n log.topicZeroSig = bytes32(it.next().getItemByIndex(0).toUint());\n log.data = it.next().toBytes();\n\n return log;\n }\n\n // profiling and test\n function getVerifyLog(\n bytes32 hashRoot,\n uint[] memory receiptSlotIndex,\n uint logIndex,\n bytes[] memory proof\n ) external pure returns (ULNLog memory) {\n return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof);\n }\n\n function getPacket(\n bytes memory data,\n uint16 srcChain,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) external pure returns (LayerZeroPacket.Packet memory) {\n return _getPacket(data, srcChain, sizeOfSrcAddress, ulnAddress);\n }\n\n function _getPacket(\n bytes memory data,\n uint16 srcChain,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) internal pure returns (LayerZeroPacket.Packet memory) {\n uint16 dstChainId;\n address dstAddress;\n uint size;\n uint64 nonce;\n\n // The log consists of the destination chain id and then a bytes payload\n // 0--------------------------------------------31\n // 0 | destination chain id\n // 32 | defines bytes array\n // 64 |\n // 96 | bytes array size\n // 128 | payload\n assembly {\n dstChainId := mload(add(data, 32))\n size := mload(add(data, 96)) /// size of the byte array\n nonce := mload(add(data, 104)) // offset to convert to uint64 128 is index -24\n dstAddress := mload(add(data, sub(add(128, sizeOfSrcAddress), 4))) // offset to convert to address 12 -8\n }\n\n Buffer.buffer memory srcAddressBuffer;\n srcAddressBuffer.init(sizeOfSrcAddress);\n srcAddressBuffer.writeRawBytes(0, data, 136, sizeOfSrcAddress); // 128 + 8\n\n uint payloadSize = size.sub(20).sub(sizeOfSrcAddress);\n Buffer.buffer memory payloadBuffer;\n payloadBuffer.init(payloadSize);\n payloadBuffer.writeRawBytes(0, data, sizeOfSrcAddress.add(156), payloadSize); // 148 + 8\n return\n LayerZeroPacket.Packet(\n srcChain,\n dstChainId,\n nonce,\n dstAddress,\n srcAddressBuffer.buf,\n ulnAddress,\n payloadBuffer.buf\n );\n }\n}\n"
|
|
223
|
+
},
|
|
224
|
+
"contracts/proof/MPTValidatorV4.sol": {
|
|
225
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"../interfaces/IValidationLibraryHelper.sol\";\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"./utility/UltraLightNodeEVMDecoder.sol\";\n\ninterface IUltraLightNode {\n struct BlockData {\n uint confirmations;\n bytes32 data;\n }\n\n struct ApplicationConfiguration {\n uint16 inboundProofLibraryVersion;\n uint64 inboundBlockConfirmations;\n address relayer;\n uint16 outboundProofType;\n uint64 outboundBlockConfirmations;\n address oracle;\n }\n\n function getAppConfig(\n uint16 _chainId,\n address userApplicationAddress\n ) external view returns (ApplicationConfiguration memory);\n\n function getBlockHeaderData(\n address _oracle,\n uint16 _remoteChainId,\n bytes32 _lookupHash\n ) external view returns (BlockData memory blockData);\n}\n\ninterface IStargate {\n // Stargate objects for abi encoding / decoding\n struct SwapObj {\n uint amount;\n uint eqFee;\n uint eqReward;\n uint lpFee;\n uint protocolFee;\n uint lkbRemove;\n }\n\n struct CreditObj {\n uint credits;\n uint idealBalance;\n }\n}\n\ncontract MPTValidatorV4 is ILayerZeroValidationLibrary, IValidationLibraryHelper {\n using RLPDecode for RLPDecode.RLPItem;\n using RLPDecode for RLPDecode.Iterator;\n using LayerZeroPacket for bytes;\n\n uint8 public utilsVersion = 3;\n bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;\n\n address public immutable stargateBridgeAddress;\n address public immutable stgTokenAddress;\n uint16 public immutable localChainId;\n IUltraLightNode public immutable uln;\n\n constructor(address _stargateBridgeAddress, address _stgTokenAddress, uint16 _localChainId, address _ulnAddress) {\n stargateBridgeAddress = _stargateBridgeAddress;\n stgTokenAddress = _stgTokenAddress;\n localChainId = _localChainId;\n uln = IUltraLightNode(_ulnAddress);\n }\n\n function validateProof(\n bytes32 _receiptsRoot,\n bytes calldata _transactionProof,\n uint _remoteAddressSize\n ) external view override returns (LayerZeroPacket.Packet memory) {\n require(_remoteAddressSize > 0, \"ProofLib: invalid address size\");\n\n (\n uint16 remoteChainId,\n bytes32 blockHash,\n bytes[] memory proof,\n uint[] memory receiptSlotIndex,\n uint logIndex\n ) = abi.decode(_transactionProof, (uint16, bytes32, bytes[], uint[], uint));\n\n ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptSlotIndex, logIndex, proof);\n require(log.topicZeroSig == PACKET_SIGNATURE, \"ProofLib: packet not recognized\"); //data\n\n LayerZeroPacket.Packet memory packet = log.data.getPacket(\n remoteChainId,\n _remoteAddressSize,\n log.contractAddress\n );\n\n _assertMessagePath(packet, blockHash, _receiptsRoot);\n\n if (packet.dstAddress == stargateBridgeAddress) packet.payload = _secureStgPayload(packet.payload);\n\n if (packet.dstAddress == stgTokenAddress) packet.payload = _secureStgTokenPayload(packet.payload);\n\n return packet;\n }\n\n function _assertMessagePath(\n LayerZeroPacket.Packet memory packet,\n bytes32 blockHash,\n bytes32 receiptsRoot\n ) internal view {\n require(packet.dstChainId == localChainId, \"ProofLib: invalid destination chain ID\");\n\n IUltraLightNode.ApplicationConfiguration memory appConfig = uln.getAppConfig(\n packet.srcChainId,\n packet.dstAddress\n );\n IUltraLightNode.BlockData memory blockData = uln.getBlockHeaderData(\n appConfig.oracle,\n packet.srcChainId,\n blockHash\n );\n\n require(blockData.data == receiptsRoot, \"ProofLib: invalid receipt root\");\n\n require(\n blockData.confirmations >= appConfig.inboundBlockConfirmations,\n \"ProofLib: not enough block confirmations\"\n );\n }\n\n function _secureStgTokenPayload(bytes memory _payload) internal pure returns (bytes memory) {\n (bytes memory toAddressBytes, uint qty) = abi.decode(_payload, (bytes, uint));\n\n address toAddress = address(0);\n if (toAddressBytes.length > 0) {\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n if (toAddress == address(0)) {\n address deadAddress = address(0x000000000000000000000000000000000000dEaD);\n bytes memory newToAddressBytes = abi.encodePacked(deadAddress);\n return abi.encode(newToAddressBytes, qty);\n }\n\n // default to return the original payload\n return _payload;\n }\n\n function _secureStgPayload(bytes memory _payload) internal view returns (bytes memory) {\n // functionType is uint8 even though the encoding will take up the side of uint256\n uint8 functionType;\n assembly {\n functionType := mload(add(_payload, 32))\n }\n\n // TYPE_SWAP_REMOTE == 1 && only if the payload has a payload\n // only swapRemote inside of stargate can call sgReceive on an user supplied to address\n // thus we do not care about the other type functions even if the toAddress is overly long.\n if (functionType == 1) {\n // decode the _payload with its types\n (\n ,\n uint srcPoolId,\n uint dstPoolId,\n uint dstGasForCall,\n IStargate.CreditObj memory c,\n IStargate.SwapObj memory s,\n bytes memory toAddressBytes,\n bytes memory contractCallPayload\n ) = abi.decode(_payload, (uint8, uint, uint, uint, IStargate.CreditObj, IStargate.SwapObj, bytes, bytes));\n\n // if contractCallPayload.length > 0 need to check if the to address is a contract or not\n if (contractCallPayload.length > 0) {\n // otherwise, need to check if the payload can be delivered to the toAddress\n address toAddress = address(0);\n if (toAddressBytes.length > 0) {\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n // check if the toAddress is a contract. We are not concerned about addresses that pretend to be wallets. because worst case we just delete their payload if being malicious\n // we can guarantee that if a size > 0, then the contract is definitely a contract address in this context\n uint size;\n assembly {\n size := extcodesize(toAddress)\n }\n\n if (size == 0) {\n // size == 0 indicates its not a contract, payload wont be delivered\n // secure the _payload to make sure funds can be delivered to the toAddress\n bytes memory newToAddressBytes = abi.encodePacked(toAddress);\n bytes memory securePayload = abi.encode(\n functionType,\n srcPoolId,\n dstPoolId,\n dstGasForCall,\n c,\n s,\n newToAddressBytes,\n bytes(\"\")\n );\n return securePayload;\n }\n }\n }\n\n // default to return the original payload\n return _payload;\n }\n\n function secureStgTokenPayload(bytes memory _payload) external pure returns (bytes memory) {\n return _secureStgTokenPayload(_payload);\n }\n\n function secureStgPayload(bytes memory _payload) external view returns (bytes memory) {\n return _secureStgPayload(_payload);\n }\n\n function _getVerifiedLog(\n bytes32 hashRoot,\n uint[] memory paths,\n uint logIndex,\n bytes[] memory proof\n ) internal pure returns (ULNLog memory) {\n require(paths.length == proof.length, \"ProofLib: invalid proof size\");\n require(proof.length > 0, \"ProofLib: proof size must > 0\");\n RLPDecode.RLPItem memory item;\n bytes memory proofBytes;\n\n for (uint i = 0; i < proof.length; i++) {\n proofBytes = proof[i];\n require(hashRoot == keccak256(proofBytes), \"ProofLib: invalid hashlink\");\n item = RLPDecode.toRlpItem(proofBytes).safeGetItemByIndex(paths[i]);\n if (i < proof.length - 1) hashRoot = bytes32(item.toUint());\n }\n\n // burning status + gasUsed + logBloom\n RLPDecode.RLPItem memory logItem = item.typeOffset().safeGetItemByIndex(3);\n RLPDecode.Iterator memory it = logItem.safeGetItemByIndex(logIndex).iterator();\n ULNLog memory log;\n log.contractAddress = bytes32(it.next().toUint());\n log.topicZeroSig = bytes32(it.next().safeGetItemByIndex(0).toUint());\n log.data = it.next().toBytes();\n\n return log;\n }\n\n function getUtilsVersion() external view override returns (uint8) {\n return utilsVersion;\n }\n\n function getVerifyLog(\n bytes32 hashRoot,\n uint[] memory receiptSlotIndex,\n uint logIndex,\n bytes[] memory proof\n ) external pure override returns (ULNLog memory) {\n return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof);\n }\n\n function getPacket(\n bytes memory data,\n uint16 srcChain,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) external pure override returns (LayerZeroPacket.Packet memory) {\n return data.getPacket(srcChain, sizeOfSrcAddress, ulnAddress);\n }\n\n // profiling and test\n function assertMessagePath(\n LayerZeroPacket.Packet memory packet,\n bytes32 blockHash,\n bytes32 receiptsRoot\n ) external view {\n _assertMessagePath(packet, blockHash, receiptsRoot);\n }\n}\n"
|
|
226
|
+
},
|
|
227
|
+
"contracts/proof/MPTValidatorV5.sol": {
|
|
228
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"../interfaces/IValidationLibraryHelper.sol\";\nimport \"./utility/LayerZeroPacket.sol\";\nimport \"./utility/UltraLightNodeEVMDecoder.sol\";\n\ninterface IUltraLightNode {\n struct BlockData {\n uint confirmations;\n bytes32 data;\n }\n\n struct ApplicationConfiguration {\n uint16 inboundProofLibraryVersion;\n uint64 inboundBlockConfirmations;\n address relayer;\n uint16 outboundProofType;\n uint64 outboundBlockConfirmations;\n address oracle;\n }\n\n function getAppConfig(\n uint16 _chainId,\n address userApplicationAddress\n ) external view returns (ApplicationConfiguration memory);\n\n function getBlockHeaderData(\n address _oracle,\n uint16 _remoteChainId,\n bytes32 _lookupHash\n ) external view returns (BlockData memory blockData);\n}\n\ninterface IStargate {\n // Stargate objects for abi encoding / decoding\n struct SwapObj {\n uint amount;\n uint eqFee;\n uint eqReward;\n uint lpFee;\n uint protocolFee;\n uint lkbRemove;\n }\n\n struct CreditObj {\n uint credits;\n uint idealBalance;\n }\n}\n\ncontract MPTValidatorV5 is ILayerZeroValidationLibrary, IValidationLibraryHelper {\n using RLPDecode for RLPDecode.RLPItem;\n using RLPDecode for RLPDecode.Iterator;\n using LayerZeroPacket for bytes;\n\n uint8 public utilsVersion = 3;\n bytes32 public constant PACKET_SIGNATURE = 0xe8d23d927749ec8e512eb885679c2977d57068839d8cca1a85685dbbea0648f6;\n\n address public immutable stargateBridgeAddress;\n address public immutable stgTokenAddress;\n address public immutable relayerAddress;\n uint16 public immutable localChainId;\n IUltraLightNode public immutable uln;\n\n constructor(\n address _stargateBridgeAddress,\n address _stgTokenAddress,\n uint16 _localChainId,\n address _ulnAddress,\n address _relayerAddress\n ) {\n stargateBridgeAddress = _stargateBridgeAddress;\n stgTokenAddress = _stgTokenAddress;\n localChainId = _localChainId;\n uln = IUltraLightNode(_ulnAddress);\n relayerAddress = _relayerAddress;\n }\n\n function validateProof(\n bytes32 _receiptsRoot,\n bytes calldata _transactionProof,\n uint _remoteAddressSize\n ) external view override returns (LayerZeroPacket.Packet memory) {\n require(_remoteAddressSize > 0, \"ProofLib: invalid address size\");\n\n (\n uint16 remoteChainId,\n bytes32 blockHash,\n bytes[] memory proof,\n uint[] memory receiptSlotIndex,\n uint logIndex\n ) = abi.decode(_transactionProof, (uint16, bytes32, bytes[], uint[], uint));\n\n ULNLog memory log = _getVerifiedLog(_receiptsRoot, receiptSlotIndex, logIndex, proof);\n require(log.topicZeroSig == PACKET_SIGNATURE, \"ProofLib: packet not recognized\"); //data\n\n LayerZeroPacket.Packet memory packet = log.data.getPacket(\n remoteChainId,\n _remoteAddressSize,\n log.contractAddress\n );\n\n _assertMessagePath(packet, blockHash, _receiptsRoot);\n\n if (packet.dstAddress == stargateBridgeAddress) packet.payload = _secureStgPayload(packet.payload);\n\n if (packet.dstAddress == stgTokenAddress) packet.payload = _secureStgTokenPayload(packet.payload);\n\n return packet;\n }\n\n function _assertMessagePath(\n LayerZeroPacket.Packet memory packet,\n bytes32 blockHash,\n bytes32 receiptsRoot\n ) internal view {\n require(packet.dstChainId == localChainId, \"ProofLib: invalid destination chain ID\");\n\n IUltraLightNode.ApplicationConfiguration memory appConfig = uln.getAppConfig(\n packet.srcChainId,\n packet.dstAddress\n );\n IUltraLightNode.BlockData memory blockData = uln.getBlockHeaderData(\n appConfig.oracle,\n packet.srcChainId,\n blockHash\n );\n require(appConfig.relayer == relayerAddress, \"ProofLib: invalid relayer\");\n\n require(blockData.data == receiptsRoot, \"ProofLib: invalid receipt root\");\n\n require(\n blockData.confirmations >= appConfig.inboundBlockConfirmations,\n \"ProofLib: not enough block confirmations\"\n );\n }\n\n function _secureStgTokenPayload(bytes memory _payload) internal pure returns (bytes memory) {\n (bytes memory toAddressBytes, uint qty) = abi.decode(_payload, (bytes, uint));\n\n address toAddress = address(0);\n if (toAddressBytes.length > 0) {\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n if (toAddress == address(0)) {\n address deadAddress = address(0x000000000000000000000000000000000000dEaD);\n bytes memory newToAddressBytes = abi.encodePacked(deadAddress);\n return abi.encode(newToAddressBytes, qty);\n }\n\n // default to return the original payload\n return _payload;\n }\n\n function _secureStgPayload(bytes memory _payload) internal view returns (bytes memory) {\n // functionType is uint8 even though the encoding will take up the side of uint256\n uint8 functionType;\n assembly {\n functionType := mload(add(_payload, 32))\n }\n\n // TYPE_SWAP_REMOTE == 1 && only if the payload has a payload\n // only swapRemote inside of stargate can call sgReceive on an user supplied to address\n // thus we do not care about the other type functions even if the toAddress is overly long.\n if (functionType == 1) {\n // decode the _payload with its types\n (\n ,\n uint srcPoolId,\n uint dstPoolId,\n uint dstGasForCall,\n IStargate.CreditObj memory c,\n IStargate.SwapObj memory s,\n bytes memory toAddressBytes,\n bytes memory contractCallPayload\n ) = abi.decode(_payload, (uint8, uint, uint, uint, IStargate.CreditObj, IStargate.SwapObj, bytes, bytes));\n\n // if contractCallPayload.length > 0 need to check if the to address is a contract or not\n if (contractCallPayload.length > 0) {\n // otherwise, need to check if the payload can be delivered to the toAddress\n address toAddress = address(0);\n if (toAddressBytes.length > 0) {\n assembly {\n toAddress := mload(add(toAddressBytes, 20))\n }\n }\n\n // check if the toAddress is a contract. We are not concerned about addresses that pretend to be wallets. because worst case we just delete their payload if being malicious\n // we can guarantee that if a size > 0, then the contract is definitely a contract address in this context\n uint size;\n assembly {\n size := extcodesize(toAddress)\n }\n\n if (size == 0) {\n // size == 0 indicates its not a contract, payload wont be delivered\n // secure the _payload to make sure funds can be delivered to the toAddress\n bytes memory newToAddressBytes = abi.encodePacked(toAddress);\n bytes memory securePayload = abi.encode(\n functionType,\n srcPoolId,\n dstPoolId,\n dstGasForCall,\n c,\n s,\n newToAddressBytes,\n bytes(\"\")\n );\n return securePayload;\n }\n }\n }\n\n // default to return the original payload\n return _payload;\n }\n\n function secureStgTokenPayload(bytes memory _payload) external pure returns (bytes memory) {\n return _secureStgTokenPayload(_payload);\n }\n\n function secureStgPayload(bytes memory _payload) external view returns (bytes memory) {\n return _secureStgPayload(_payload);\n }\n\n function _getVerifiedLog(\n bytes32 hashRoot,\n uint[] memory paths,\n uint logIndex,\n bytes[] memory proof\n ) internal pure returns (ULNLog memory) {\n require(paths.length == proof.length, \"ProofLib: invalid proof size\");\n require(proof.length > 0, \"ProofLib: proof size must > 0\");\n RLPDecode.RLPItem memory item;\n bytes memory proofBytes;\n\n for (uint i = 0; i < proof.length; i++) {\n proofBytes = proof[i];\n require(hashRoot == keccak256(proofBytes), \"ProofLib: invalid hashlink\");\n item = RLPDecode.toRlpItem(proofBytes).safeGetItemByIndex(paths[i]);\n if (i < proof.length - 1) hashRoot = bytes32(item.toUint());\n }\n\n // burning status + gasUsed + logBloom\n RLPDecode.RLPItem memory logItem = item.typeOffset().safeGetItemByIndex(3);\n RLPDecode.Iterator memory it = logItem.safeGetItemByIndex(logIndex).iterator();\n ULNLog memory log;\n log.contractAddress = bytes32(it.next().toUint());\n log.topicZeroSig = bytes32(it.next().safeGetItemByIndex(0).toUint());\n log.data = it.next().toBytes();\n\n return log;\n }\n\n function getUtilsVersion() external view override returns (uint8) {\n return utilsVersion;\n }\n\n function getVerifyLog(\n bytes32 hashRoot,\n uint[] memory receiptSlotIndex,\n uint logIndex,\n bytes[] memory proof\n ) external pure override returns (ULNLog memory) {\n return _getVerifiedLog(hashRoot, receiptSlotIndex, logIndex, proof);\n }\n\n function getPacket(\n bytes memory data,\n uint16 srcChain,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) external pure override returns (LayerZeroPacket.Packet memory) {\n return data.getPacket(srcChain, sizeOfSrcAddress, ulnAddress);\n }\n\n // profiling and test\n function assertMessagePath(\n LayerZeroPacket.Packet memory packet,\n bytes32 blockHash,\n bytes32 receiptsRoot\n ) external view {\n _assertMessagePath(packet, blockHash, receiptsRoot);\n }\n}\n"
|
|
229
|
+
},
|
|
230
|
+
"contracts/proof/utility/Buffer.sol": {
|
|
231
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\n// https://github.com/ensdomains/buffer\n\npragma solidity ^0.8.0;\n\n/**\n * @dev A library for working with mutable byte buffers in Solidity.\n *\n * Byte buffers are mutable and expandable, and provide a variety of primitives\n * for writing to them. At any time you can fetch a bytes object containing the\n * current contents of the buffer. The bytes object should not be stored between\n * operations, as it may change due to resizing of the buffer.\n */\nlibrary Buffer {\n /**\n * @dev Represents a mutable buffer. Buffers have a current value (buf) and\n * a capacity. The capacity may be longer than the current value, in\n * which case it can be extended without the need to allocate more memory.\n */\n struct buffer {\n bytes buf;\n uint capacity;\n }\n\n /**\n * @dev Initializes a buffer with an initial capacity.a co\n * @param buf The buffer to initialize.\n * @param capacity The number of bytes of space to allocate the buffer.\n * @return The buffer, for chaining.\n */\n function init(buffer memory buf, uint capacity) internal pure returns (buffer memory) {\n if (capacity % 32 != 0) {\n capacity += 32 - (capacity % 32);\n }\n // Allocate space for the buffer data\n buf.capacity = capacity;\n assembly {\n let ptr := mload(0x40)\n mstore(buf, ptr)\n mstore(ptr, 0)\n mstore(0x40, add(32, add(ptr, capacity)))\n }\n return buf;\n }\n\n /**\n * @dev Writes a byte string to a buffer. Resizes if doing so would exceed\n * the capacity of the buffer.\n * @param buf The buffer to append to.\n * @param off The start offset to write to.\n * @param rawData The data to append.\n * @param len The number of bytes to copy.\n * @return The original buffer, for chaining.\n */\n function writeRawBytes(\n buffer memory buf,\n uint off,\n bytes memory rawData,\n uint offData,\n uint len\n ) internal pure returns (buffer memory) {\n if (off + len > buf.capacity) {\n resize(buf, max(buf.capacity, len + off) * 2);\n }\n\n uint dest;\n uint src;\n assembly {\n // Memory address of the buffer data\n let bufptr := mload(buf)\n // Length of existing buffer data\n let buflen := mload(bufptr)\n // Start address = buffer address + offset + sizeof(buffer length)\n dest := add(add(bufptr, 32), off)\n // Update buffer length if we're extending it\n if gt(add(len, off), buflen) {\n mstore(bufptr, add(len, off))\n }\n src := add(rawData, offData)\n }\n\n // Copy word-length chunks while possible\n for (; len >= 32; len -= 32) {\n assembly {\n mstore(dest, mload(src))\n }\n dest += 32;\n src += 32;\n }\n\n // Copy remaining bytes\n unchecked {\n uint mask = 256 ** (32 - len) - 1;\n assembly {\n let srcpart := and(mload(src), not(mask))\n let destpart := and(mload(dest), mask)\n mstore(dest, or(destpart, srcpart))\n }\n\n return buf;\n }\n }\n\n /**\n * @dev Writes a byte string to a buffer. Resizes if doing so would exceed\n * the capacity of the buffer.\n * @param buf The buffer to append to.\n * @param off The start offset to write to.\n * @param data The data to append.\n * @param len The number of bytes to copy.\n * @return The original buffer, for chaining.\n */\n function write(buffer memory buf, uint off, bytes memory data, uint len) internal pure returns (buffer memory) {\n require(len <= data.length);\n\n if (off + len > buf.capacity) {\n resize(buf, max(buf.capacity, len + off) * 2);\n }\n\n uint dest;\n uint src;\n assembly {\n // Memory address of the buffer data\n let bufptr := mload(buf)\n // Length of existing buffer data\n let buflen := mload(bufptr)\n // Start address = buffer address + offset + sizeof(buffer length)\n dest := add(add(bufptr, 32), off)\n // Update buffer length if we're extending it\n if gt(add(len, off), buflen) {\n mstore(bufptr, add(len, off))\n }\n src := add(data, 32)\n }\n\n // Copy word-length chunks while possible\n for (; len >= 32; len -= 32) {\n assembly {\n mstore(dest, mload(src))\n }\n dest += 32;\n src += 32;\n }\n\n // Copy remaining bytes\n unchecked {\n uint mask = 256 ** (32 - len) - 1;\n assembly {\n let srcpart := and(mload(src), not(mask))\n let destpart := and(mload(dest), mask)\n mstore(dest, or(destpart, srcpart))\n }\n }\n\n return buf;\n }\n\n function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\n return write(buf, buf.buf.length, data, data.length);\n }\n\n function resize(buffer memory buf, uint capacity) private pure {\n bytes memory oldbuf = buf.buf;\n init(buf, capacity);\n append(buf, oldbuf);\n }\n\n function max(uint a, uint b) private pure returns (uint) {\n if (a > b) {\n return a;\n }\n return b;\n }\n}\n"
|
|
232
|
+
},
|
|
233
|
+
"contracts/proof/utility/LayerZeroPacket.sol": {
|
|
234
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"./Buffer.sol\";\n\nlibrary LayerZeroPacket {\n using Buffer for Buffer.buffer;\n\n struct Packet {\n uint16 srcChainId;\n uint16 dstChainId;\n uint64 nonce;\n address dstAddress;\n bytes srcAddress;\n bytes32 ulnAddress;\n bytes payload;\n }\n\n function getPacket(\n bytes memory data,\n uint16 srcChain,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) internal pure returns (LayerZeroPacket.Packet memory) {\n uint16 dstChainId;\n address dstAddress;\n uint size;\n uint64 nonce;\n\n // The log consists of the destination chain id and then a bytes payload\n // 0--------------------------------------------31\n // 0 | total bytes size\n // 32 | destination chain id\n // 64 | bytes offset\n // 96 | bytes array size\n // 128 | payload\n assembly {\n dstChainId := mload(add(data, 32))\n size := mload(add(data, 96)) /// size of the byte array\n nonce := mload(add(data, 104)) // offset to convert to uint64 128 is index -24\n dstAddress := mload(add(data, sub(add(128, sizeOfSrcAddress), 4))) // offset to convert to address 12 -8\n }\n\n Buffer.buffer memory srcAddressBuffer;\n srcAddressBuffer.init(sizeOfSrcAddress);\n srcAddressBuffer.writeRawBytes(0, data, 136, sizeOfSrcAddress); // 128 + 8\n\n uint payloadSize = size - 28 - sizeOfSrcAddress;\n Buffer.buffer memory payloadBuffer;\n payloadBuffer.init(payloadSize);\n payloadBuffer.writeRawBytes(0, data, sizeOfSrcAddress + 156, payloadSize); // 148 + 8\n return\n LayerZeroPacket.Packet(\n srcChain,\n dstChainId,\n nonce,\n dstAddress,\n srcAddressBuffer.buf,\n ulnAddress,\n payloadBuffer.buf\n );\n }\n\n function getPacketV2(\n bytes memory data,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) internal pure returns (LayerZeroPacket.Packet memory) {\n // packet def: abi.encodePacked(nonce, srcChain, srcAddress, dstChain, dstAddress, payload);\n // data def: abi.encode(packet) = offset(32) + length(32) + packet\n // if from EVM\n // 0 - 31 0 - 31 | total bytes size\n // 32 - 63 32 - 63 | location\n // 64 - 95 64 - 95 | size of the packet\n // 96 - 103 96 - 103 | nonce\n // 104 - 105 104 - 105 | srcChainId\n // 106 - P 106 - 125 | srcAddress, where P = 106 + sizeOfSrcAddress - 1,\n // P+1 - P+2 126 - 127 | dstChainId\n // P+3 - P+22 128 - 147 | dstAddress\n // P+23 - END 148 - END | payload\n\n // decode the packet\n uint256 realSize;\n uint64 nonce;\n uint16 srcChain;\n uint16 dstChain;\n address dstAddress;\n assembly {\n realSize := mload(add(data, 64))\n nonce := mload(add(data, 72)) // 104 - 32\n srcChain := mload(add(data, 74)) // 106 - 32\n dstChain := mload(add(data, add(76, sizeOfSrcAddress))) // P + 3 - 32 = 105 + size + 3 - 32 = 76 + size\n dstAddress := mload(add(data, add(96, sizeOfSrcAddress))) // P + 23 - 32 = 105 + size + 23 - 32 = 96 + size\n }\n\n require(srcChain != 0, \"LayerZeroPacket: invalid packet\");\n\n Buffer.buffer memory srcAddressBuffer;\n srcAddressBuffer.init(sizeOfSrcAddress);\n srcAddressBuffer.writeRawBytes(0, data, 106, sizeOfSrcAddress);\n\n uint nonPayloadSize = sizeOfSrcAddress + 32; // 2 + 2 + 8 + 20, 32 + 20 = 52 if sizeOfSrcAddress == 20\n uint payloadSize = realSize - nonPayloadSize;\n Buffer.buffer memory payloadBuffer;\n payloadBuffer.init(payloadSize);\n payloadBuffer.writeRawBytes(0, data, nonPayloadSize + 96, payloadSize);\n\n return\n LayerZeroPacket.Packet(\n srcChain,\n dstChain,\n nonce,\n dstAddress,\n srcAddressBuffer.buf,\n ulnAddress,\n payloadBuffer.buf\n );\n }\n\n function getPacketV3(\n bytes memory data,\n uint sizeOfSrcAddress,\n bytes32 ulnAddress\n ) internal pure returns (LayerZeroPacket.Packet memory) {\n // data def: abi.encodePacked(nonce, srcChain, srcAddress, dstChain, dstAddress, payload);\n // if from EVM\n // 0 - 31 0 - 31 | total bytes size\n // 32 - 39 32 - 39 | nonce\n // 40 - 41 40 - 41 | srcChainId\n // 42 - P 42 - 61 | srcAddress, where P = 41 + sizeOfSrcAddress,\n // P+1 - P+2 62 - 63 | dstChainId\n // P+3 - P+22 64 - 83 | dstAddress\n // P+23 - END 84 - END | payload\n\n // decode the packet\n uint256 realSize = data.length;\n uint nonPayloadSize = sizeOfSrcAddress + 32; // 2 + 2 + 8 + 20, 32 + 20 = 52 if sizeOfSrcAddress == 20\n require(realSize >= nonPayloadSize, \"LayerZeroPacket: invalid packet\");\n uint payloadSize = realSize - nonPayloadSize;\n\n uint64 nonce;\n uint16 srcChain;\n uint16 dstChain;\n address dstAddress;\n assembly {\n nonce := mload(add(data, 8)) // 40 - 32\n srcChain := mload(add(data, 10)) // 42 - 32\n dstChain := mload(add(data, add(12, sizeOfSrcAddress))) // P + 3 - 32 = 41 + size + 3 - 32 = 12 + size\n dstAddress := mload(add(data, add(32, sizeOfSrcAddress))) // P + 23 - 32 = 41 + size + 23 - 32 = 32 + size\n }\n\n require(srcChain != 0, \"LayerZeroPacket: invalid packet\");\n\n Buffer.buffer memory srcAddressBuffer;\n srcAddressBuffer.init(sizeOfSrcAddress);\n srcAddressBuffer.writeRawBytes(0, data, 42, sizeOfSrcAddress);\n\n Buffer.buffer memory payloadBuffer;\n if (payloadSize > 0) {\n payloadBuffer.init(payloadSize);\n payloadBuffer.writeRawBytes(0, data, nonPayloadSize + 32, payloadSize);\n }\n\n return\n LayerZeroPacket.Packet(\n srcChain,\n dstChain,\n nonce,\n dstAddress,\n srcAddressBuffer.buf,\n ulnAddress,\n payloadBuffer.buf\n );\n }\n}\n"
|
|
235
|
+
},
|
|
236
|
+
"contracts/proof/utility/RLPDecode.sol": {
|
|
237
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\n// https://github.com/hamdiallam/solidity-rlp\n\npragma solidity ^0.8.0;\n\nlibrary RLPDecode {\n uint8 constant STRING_SHORT_START = 0x80;\n uint8 constant STRING_LONG_START = 0xb8;\n uint8 constant LIST_SHORT_START = 0xc0;\n uint8 constant LIST_LONG_START = 0xf8;\n uint8 constant WORD_SIZE = 32;\n\n struct RLPItem {\n uint len;\n uint memPtr;\n }\n\n struct Iterator {\n RLPItem item; // Item that's being iterated over.\n uint nextPtr; // Position of the next item in the list.\n }\n\n /*\n * @dev Returns the next element in the iteration. Reverts if it has not next element.\n * @param self The iterator.\n * @return The next element in the iteration.\n */\n function next(Iterator memory self) internal pure returns (RLPItem memory) {\n require(hasNext(self), \"RLPDecoder iterator has no next\");\n\n uint ptr = self.nextPtr;\n uint itemLength = _itemLength(ptr);\n self.nextPtr = ptr + itemLength;\n\n return RLPItem(itemLength, ptr);\n }\n\n /*\n * @dev Returns true if the iteration has more elements.\n * @param self The iterator.\n * @return true if the iteration has more elements.\n */\n function hasNext(Iterator memory self) internal pure returns (bool) {\n RLPItem memory item = self.item;\n return self.nextPtr < item.memPtr + item.len;\n }\n\n /*\n * @param item RLP encoded bytes\n */\n\n function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) {\n uint memPtr;\n assembly {\n memPtr := add(item, 0x20)\n }\n // offset the pointer if the first byte\n\n uint8 byte0;\n assembly {\n byte0 := byte(0, mload(memPtr))\n }\n uint len = item.length;\n if (len > 0 && byte0 < LIST_SHORT_START) {\n assembly {\n memPtr := add(memPtr, 0x01)\n }\n len -= 1;\n }\n return RLPItem(len, memPtr);\n }\n\n /*\n * @dev Create an iterator. Reverts if item is not a list.\n * @param self The RLP item.\n * @return An 'Iterator' over the item.\n */\n function iterator(RLPItem memory self) internal pure returns (Iterator memory) {\n require(isList(self), \"RLPDecoder iterator is not list\");\n\n uint ptr = self.memPtr + _payloadOffset(self.memPtr);\n return Iterator(self, ptr);\n }\n\n /*\n * @param item RLP encoded bytes\n */\n function rlpLen(RLPItem memory item) internal pure returns (uint) {\n return item.len;\n }\n\n /*\n * @param item RLP encoded bytes\n */\n function payloadLen(RLPItem memory item) internal pure returns (uint) {\n uint offset = _payloadOffset(item.memPtr);\n require(item.len >= offset, \"RLPDecoder: invalid uint RLP item offset size\");\n return item.len - offset;\n }\n\n /*\n * @param item RLP encoded list in bytes\n */\n function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) {\n require(isList(item), \"RLPDecoder iterator is not a list\");\n\n uint items = numItems(item);\n RLPItem[] memory result = new RLPItem[](items);\n\n uint memPtr = item.memPtr + _payloadOffset(item.memPtr);\n uint dataLen;\n for (uint i = 0; i < items; i++) {\n dataLen = _itemLength(memPtr);\n result[i] = RLPItem(dataLen, memPtr);\n memPtr = memPtr + dataLen;\n }\n\n return result;\n }\n\n /*\n * @param get the RLP item by index. save gas.\n */\n function getItemByIndex(RLPItem memory item, uint idx) internal pure returns (RLPItem memory) {\n require(isList(item), \"RLPDecoder iterator is not a list\");\n\n uint memPtr = item.memPtr + _payloadOffset(item.memPtr);\n uint dataLen;\n for (uint i = 0; i < idx; i++) {\n dataLen = _itemLength(memPtr);\n memPtr = memPtr + dataLen;\n }\n dataLen = _itemLength(memPtr);\n return RLPItem(dataLen, memPtr);\n }\n\n /*\n * @param get the RLP item by index. save gas.\n */\n function safeGetItemByIndex(RLPItem memory item, uint idx) internal pure returns (RLPItem memory) {\n require(isList(item), \"RLPDecoder iterator is not a list\");\n require(idx < numItems(item), \"RLP item out of bounds\");\n uint endPtr = item.memPtr + item.len;\n\n uint memPtr = item.memPtr + _payloadOffset(item.memPtr);\n uint dataLen;\n for (uint i = 0; i < idx; i++) {\n dataLen = _itemLength(memPtr);\n memPtr = memPtr + dataLen;\n }\n dataLen = _itemLength(memPtr);\n\n require(memPtr + dataLen <= endPtr, \"RLP item overflow\");\n return RLPItem(dataLen, memPtr);\n }\n\n /*\n * @param offset the receipt bytes item\n */\n function typeOffset(RLPItem memory item) internal pure returns (RLPItem memory) {\n uint offset = _payloadOffset(item.memPtr);\n uint8 byte0;\n uint memPtr = item.memPtr;\n uint len = item.len;\n assembly {\n memPtr := add(memPtr, offset)\n byte0 := byte(0, mload(memPtr))\n }\n if (len > 0 && byte0 < LIST_SHORT_START) {\n assembly {\n memPtr := add(memPtr, 0x01)\n }\n len -= 1;\n }\n return RLPItem(len, memPtr);\n }\n\n // @return indicator whether encoded payload is a list. negate this function call for isData.\n function isList(RLPItem memory item) internal pure returns (bool) {\n if (item.len == 0) return false;\n\n uint8 byte0;\n uint memPtr = item.memPtr;\n assembly {\n byte0 := byte(0, mload(memPtr))\n }\n\n if (byte0 < LIST_SHORT_START) return false;\n return true;\n }\n\n /** RLPItem conversions into data types **/\n\n // @returns raw rlp encoding in bytes\n function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) {\n bytes memory result = new bytes(item.len);\n if (result.length == 0) return result;\n\n uint ptr;\n assembly {\n ptr := add(0x20, result)\n }\n\n copy(item.memPtr, ptr, item.len);\n return result;\n }\n\n // any non-zero byte except \"0x80\" is considered true\n function toBoolean(RLPItem memory item) internal pure returns (bool) {\n require(item.len == 1, \"RLPDecoder toBoolean invalid length\");\n uint result;\n uint memPtr = item.memPtr;\n assembly {\n result := byte(0, mload(memPtr))\n }\n\n // SEE Github Issue #5.\n // Summary: Most commonly used RLP libraries (i.e Geth) will encode\n // \"0\" as \"0x80\" instead of as \"0\". We handle this edge case explicitly\n // here.\n if (result == 0 || result == STRING_SHORT_START) {\n return false;\n } else {\n return true;\n }\n }\n\n function toAddress(RLPItem memory item) internal pure returns (address) {\n // 1 byte for the length prefix\n require(item.len == 21, \"RLPDecoder toAddress invalid length\");\n\n return address(uint160(toUint(item)));\n }\n\n function toUint(RLPItem memory item) internal pure returns (uint) {\n require(item.len > 0 && item.len <= 33, \"RLPDecoder toUint invalid length\");\n\n uint offset = _payloadOffset(item.memPtr);\n require(item.len >= offset, \"RLPDecoder: invalid RLP item offset size\");\n uint len = item.len - offset;\n\n uint result;\n uint memPtr = item.memPtr + offset;\n assembly {\n result := mload(memPtr)\n\n // shift to the correct location if necessary\n if lt(len, 32) {\n result := div(result, exp(256, sub(32, len)))\n }\n }\n\n return result;\n }\n\n // enforces 32 byte length\n function toUintStrict(RLPItem memory item) internal pure returns (uint) {\n // one byte prefix\n require(item.len == 33, \"RLPDecoder toUintStrict invalid length\");\n\n uint result;\n uint memPtr = item.memPtr + 1;\n assembly {\n result := mload(memPtr)\n }\n\n return result;\n }\n\n function toBytes(RLPItem memory item) internal pure returns (bytes memory) {\n require(item.len > 0, \"RLPDecoder toBytes invalid length\");\n\n uint offset = _payloadOffset(item.memPtr);\n require(item.len >= offset, \"RLPDecoder: invalid RLP item offset size\");\n uint len = item.len - offset; // data length\n bytes memory result = new bytes(len);\n\n uint destPtr;\n assembly {\n destPtr := add(0x20, result)\n }\n\n copy(item.memPtr + offset, destPtr, len);\n return result;\n }\n\n /*\n * Private Helpers\n */\n\n // @return number of payload items inside an encoded list.\n function numItems(RLPItem memory item) internal pure returns (uint) {\n if (item.len == 0) return 0;\n\n uint count = 0;\n uint currPtr = item.memPtr + _payloadOffset(item.memPtr);\n uint endPtr = item.memPtr + item.len;\n while (currPtr < endPtr) {\n currPtr = currPtr + _itemLength(currPtr); // skip over an item\n count++;\n }\n\n return count;\n }\n\n // @return entire rlp item byte length\n function _itemLength(uint memPtr) private pure returns (uint) {\n uint itemLen;\n uint byte0;\n assembly {\n byte0 := byte(0, mload(memPtr))\n }\n\n if (byte0 < STRING_SHORT_START) itemLen = 1;\n else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1;\n else if (byte0 < LIST_SHORT_START) {\n assembly {\n let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is\n memPtr := add(memPtr, 1) // skip over the first byte\n\n /* 32 byte word size */\n let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len\n itemLen := add(dataLen, add(byteLen, 1))\n }\n } else if (byte0 < LIST_LONG_START) {\n itemLen = byte0 - LIST_SHORT_START + 1;\n } else {\n assembly {\n let byteLen := sub(byte0, 0xf7)\n memPtr := add(memPtr, 1)\n\n let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length\n itemLen := add(dataLen, add(byteLen, 1))\n }\n }\n\n return itemLen;\n }\n\n // @return number of bytes until the data\n function _payloadOffset(uint memPtr) private pure returns (uint) {\n uint byte0;\n assembly {\n byte0 := byte(0, mload(memPtr))\n }\n\n if (byte0 < STRING_SHORT_START) return 0;\n else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1;\n else if (byte0 < LIST_SHORT_START)\n // being explicit\n return byte0 - (STRING_LONG_START - 1) + 1;\n else return byte0 - (LIST_LONG_START - 1) + 1;\n }\n\n /*\n * @param src Pointer to source\n * @param dest Pointer to destination\n * @param len Amount of memory to copy from the source\n */\n function copy(uint src, uint dest, uint len) private pure {\n if (len == 0) return;\n\n // copy as many word sizes as possible\n for (; len >= WORD_SIZE; len -= WORD_SIZE) {\n assembly {\n mstore(dest, mload(src))\n }\n\n src += WORD_SIZE;\n dest += WORD_SIZE;\n }\n\n // left over bytes. Mask is used to remove unwanted bytes from the word\n unchecked {\n uint mask = 256 ** (WORD_SIZE - len) - 1;\n assembly {\n let srcpart := and(mload(src), not(mask)) // zero out src\n let destpart := and(mload(dest), mask) // retrieve the bytes\n mstore(dest, or(destpart, srcpart))\n }\n }\n }\n}\n"
|
|
238
|
+
},
|
|
239
|
+
"contracts/proof/utility/UltraLightNodeEVMDecoder.sol": {
|
|
240
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.0;\n\nimport \"./RLPDecode.sol\";\n\nlibrary UltraLightNodeEVMDecoder {\n using RLPDecode for RLPDecode.RLPItem;\n using RLPDecode for RLPDecode.Iterator;\n\n struct Log {\n address contractAddress;\n bytes32 topicZero;\n bytes data;\n }\n\n function getReceiptLog(bytes memory data, uint logIndex) internal pure returns (Log memory) {\n RLPDecode.Iterator memory it = RLPDecode.toRlpItem(data).iterator();\n uint idx;\n while (it.hasNext()) {\n if (idx == 3) {\n return toReceiptLog(it.next().getItemByIndex(logIndex).toRlpBytes());\n } else it.next();\n idx++;\n }\n revert(\"no log index in receipt\");\n }\n\n function toReceiptLog(bytes memory data) internal pure returns (Log memory) {\n RLPDecode.Iterator memory it = RLPDecode.toRlpItem(data).iterator();\n Log memory log;\n\n uint idx;\n while (it.hasNext()) {\n if (idx == 0) {\n log.contractAddress = it.next().toAddress();\n } else if (idx == 1) {\n RLPDecode.RLPItem memory item = it.next().getItemByIndex(0);\n log.topicZero = bytes32(item.toUint());\n } else if (idx == 2) log.data = it.next().toBytes();\n else it.next();\n idx++;\n }\n return log;\n }\n}\n"
|
|
241
|
+
},
|
|
242
|
+
"contracts/proxy/DefaultProxyAdmin.sol": {
|
|
243
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.7.0;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./TransparentUpgradeableProxy.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract DefaultProxyAdmin is Ownable {\n constructor(address initialOwner) {\n transferOwnership(initialOwner);\n }\n\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n TransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n"
|
|
244
|
+
},
|
|
245
|
+
"contracts/proxy/TransparentUpgradeableProxy.sol": {
|
|
246
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\n\n/**\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 that says\n * \"admin cannot fallback to proxy target\".\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 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 require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n}\n"
|
|
247
|
+
},
|
|
248
|
+
"contracts/Relayer.sol": {
|
|
249
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.7.6;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"hardhat-deploy/solc_0.7/proxy/Proxied.sol\";\n\nimport \"./interfaces/ILayerZeroRelayer.sol\";\nimport \"./interfaces/ILayerZeroUltraLightNodeV1.sol\";\n\ncontract Relayer is ILayerZeroRelayer, ReentrancyGuard, OwnableUpgradeable, Proxied {\n using SafeERC20 for IERC20;\n using SafeMath for uint;\n using SafeMath for uint128;\n using SafeMath for uint64;\n\n ILayerZeroUltraLightNodeV1 public uln;\n\n struct DstPrice {\n uint128 dstPriceRatio; // 10^10\n uint128 dstGasPriceInWei;\n }\n\n struct DstConfig {\n uint128 dstNativeAmtCap;\n uint64 baseGas;\n uint64 gasPerByte;\n }\n\n // [_chainId] => DstPriceData. change often\n mapping(uint16 => DstPrice) public dstPriceLookup;\n // [_chainId][_outboundProofType] => DstConfig. change much less often\n mapping(uint16 => mapping(uint16 => DstConfig)) public dstConfigLookup;\n mapping(address => bool) public approvedAddresses;\n\n event WithdrawTokens(address token, address to, uint amount);\n event Withdraw(address to, uint amount);\n event ApproveAddress(address addr, bool approved);\n\n address public stargateBridgeAddress;\n\n event InvalidPayloadSize(uint indexed payloadSize);\n event ValueTransferFailed(address indexed to, uint indexed quantity);\n\n //----------------------------------------------------------------------------------\n // Relayer Interface V2 Change\n\n event AssignJob(uint16 dstChainId, uint16 outboundProofType, address userApplication, uint totalFee);\n event Ulnv2Set(address ulnv2);\n\n // new pauseable relayer\n bool public paused;\n\n // owner is always approved\n modifier onlyApproved() {\n if (owner() != msg.sender) {\n require(isApproved(msg.sender), \"Relayer: not approved \");\n }\n _;\n }\n\n function initialize(address _uln) public proxied initializer {\n __Ownable_init();\n uln = ILayerZeroUltraLightNodeV1(_uln);\n setApprovedAddress(address(this), true);\n }\n\n //----------------------------------------------------------------------------------\n // onlyApproved\n function validateTransactionProofV2(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _blockHash,\n bytes calldata _transactionProof,\n address payable _to\n ) external payable onlyApproved nonReentrant {\n (bool sent, ) = _to.call{value: msg.value}(\"\");\n //require(sent, \"Relayer: failed to send ether\");\n if (!sent) {\n emit ValueTransferFailed(_to, msg.value);\n }\n uln.validateTransactionProof(_srcChainId, _dstAddress, _gasLimit, _blockHash, _transactionProof);\n }\n\n function validateTransactionProofV1(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _blockHash,\n bytes calldata _transactionProof\n ) external onlyApproved nonReentrant {\n uln.validateTransactionProof(_srcChainId, _dstAddress, _gasLimit, _blockHash, _transactionProof);\n }\n\n function setDstPrice(uint16 _chainId, uint128 _dstPriceRatio, uint128 _dstGasPriceInWei) external onlyApproved {\n dstPriceLookup[_chainId] = DstPrice(_dstPriceRatio, _dstGasPriceInWei);\n }\n\n function setDstConfig(\n uint16 _chainId,\n uint16 _outboundProofType,\n uint128 _dstNativeAmtCap,\n uint64 _baseGas,\n uint64 _gasPerByte\n ) external onlyApproved {\n dstConfigLookup[_chainId][_outboundProofType] = DstConfig(_dstNativeAmtCap, _baseGas, _gasPerByte);\n }\n\n // other relayer fees are withdrawn through the RelayerFee interface\n // uint8 public constant WITHDRAW_TYPE_RELAYER_QUOTED_FEES = 2;\n function withdrawQuotedFromULN(address payable _to, uint _amount) external onlyApproved {\n uln.withdrawNative(2, address(0x0), _to, _amount);\n }\n\n //----------------------------------------------------------------------------------\n // onlyOwner\n\n function setApprovedAddress(address _relayerAddress, bool _approve) public onlyOwner {\n approvedAddresses[_relayerAddress] = _approve;\n emit ApproveAddress(_relayerAddress, _approve);\n }\n\n function setPause(bool _paused) public onlyOwner {\n paused = _paused;\n }\n\n //----------------------------------------------------------------------------------\n // view functions\n\n // txType 1\n // bytes [2 32 ]\n // fields [txType extraGas]\n // txType 2\n // bytes [2 32 32 bytes[] ]\n // fields [txType extraGas dstNativeAmt dstNativeAddress]\n // User App Address is not used in this version\n function _getPrices(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n address,\n bytes memory _adapterParameters\n ) internal view returns (uint basePrice, uint pricePerByte) {\n require(!paused, \"Admin: paused\");\n // decoding the _adapterParameters - reverts if type 2 and there is no dstNativeAddress\n require(\n _adapterParameters.length == 34 || _adapterParameters.length > 66,\n \"Relayer: wrong _adapterParameters size\"\n );\n uint16 txType;\n uint extraGas;\n assembly {\n txType := mload(add(_adapterParameters, 2))\n extraGas := mload(add(_adapterParameters, 34))\n }\n require(extraGas > 0, \"Relayer: gas too low\");\n require(txType == 1 || txType == 2, \"Relayer: unsupported txType\");\n\n DstPrice storage dstPrice = dstPriceLookup[_dstChainId];\n DstConfig storage dstConfig = dstConfigLookup[_dstChainId][_outboundProofType];\n\n uint totalRemoteToken; // = baseGas + extraGas + requiredNativeAmount\n if (txType == 2) {\n uint dstNativeAmt;\n assembly {\n dstNativeAmt := mload(add(_adapterParameters, 66))\n }\n require(dstConfig.dstNativeAmtCap >= dstNativeAmt, \"Relayer: dstNativeAmt too large \");\n totalRemoteToken = totalRemoteToken.add(dstNativeAmt);\n }\n // remoteGasTotal = dstGasPriceInWei * (baseGas + extraGas)\n uint remoteGasTotal = dstPrice.dstGasPriceInWei.mul(dstConfig.baseGas.add(extraGas));\n\n totalRemoteToken = totalRemoteToken.add(remoteGasTotal);\n\n // tokenConversionRate = dstPrice / localPrice\n // basePrice = totalRemoteToken * tokenConversionRate\n basePrice = totalRemoteToken.mul(dstPrice.dstPriceRatio).div(10 ** 10);\n\n // pricePerByte = (dstGasPriceInWei * gasPerBytes) * tokenConversionRate\n pricePerByte = dstPrice.dstGasPriceInWei.mul(dstConfig.gasPerByte).mul(dstPrice.dstPriceRatio).div(10 ** 10);\n }\n\n function notifyRelayer(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n bytes calldata _adapterParams\n ) external override {\n //do nothing\n }\n\n function getPrice(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n address _userApplication,\n uint payloadSize,\n bytes calldata _adapterParams\n ) external view override returns (uint) {\n (uint basePrice, uint pricePerByte) = _getPrices(\n _dstChainId,\n _outboundProofType,\n _userApplication,\n _adapterParams\n );\n return basePrice.add(payloadSize.mul(pricePerByte));\n }\n\n function isApproved(address _relayerAddress) public view override returns (bool) {\n return approvedAddresses[_relayerAddress];\n }\n}\n"
|
|
250
|
+
},
|
|
251
|
+
"contracts/RelayerV2.sol": {
|
|
252
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"hardhat-deploy/solc_0.8/proxy/Proxied.sol\";\n\nimport \"./interfaces/ILayerZeroRelayerV2.sol\";\nimport \"./interfaces/ILayerZeroUltraLightNodeV2.sol\";\nimport \"./interfaces/ILayerZeroPriceFeedV2.sol\";\n\ncontract RelayerV2 is ReentrancyGuard, OwnableUpgradeable, Proxied, ILayerZeroRelayerV2 {\n using SafeERC20 for IERC20;\n\n ILayerZeroUltraLightNodeV2 public uln;\n address public stargateBridgeAddress;\n uint public constant AIRDROP_GAS_LIMIT = 150000; // 150k\n\n struct DstPrice {\n uint128 dstPriceRatio; // 10^10\n uint128 dstGasPriceInWei;\n }\n\n struct DstConfig {\n uint128 dstNativeAmtCap;\n uint64 baseGas;\n uint64 gasPerByte;\n }\n\n struct DstMultiplier {\n uint16 chainId;\n uint128 multiplier;\n }\n\n struct DstFloorMargin {\n uint16 chainId;\n uint128 floorMargin;\n }\n\n // [_chainId] => DstPriceData. change often\n mapping(uint16 => DstPrice) public dstPriceLookupOld;\n // [_chainId][_outboundProofType] => DstConfig. change much less often\n mapping(uint16 => mapping(uint16 => DstConfig)) public dstConfigLookup;\n mapping(address => bool) public approvedAddresses;\n\n event Withdraw(address to, uint amount);\n event ApproveAddress(address addr, bool approved);\n event SetPriceConfigUpdater(address priceConfigUpdater, bool allow);\n event AssignJob(uint totalFee);\n event ValueTransferFailed(address indexed to, uint indexed quantity);\n event SetDstPrice(uint16 chainId, uint128 dstPriceRatio, uint128 dstGasPriceInWei);\n event SetDstConfig(\n uint16 chainId,\n uint16 outboundProofType,\n uint128 dstNativeAmtCap,\n uint64 baseGas,\n uint64 gasPerByte\n );\n\n // new pauseable relayer\n bool public paused;\n\n // Update for Price Feed\n ILayerZeroPriceFeedV2 public priceFeed;\n // multipler for airdrop\n uint128 public multiplierBps;\n\n // PriceFeedContract Upgrade\n // all encoded param bytes except for proof for validateTransactionProofV1\n uint16 public validateProofBytes;\n uint16 public fpBytes;\n uint16 public mptOverhead;\n\n // [chainId] => [multiplier]\n mapping(uint16 => uint128) public dstMultipliers;\n // [chainId] => [floor margin in USD]\n mapping(uint16 => uint128) public dstFloorMarginsUSD;\n mapping(address => bool) public priceConfigUpdaters;\n\n uint256 public nativeDecimalsRate;\n\n // owner is always approved\n modifier onlyApproved() {\n if (owner() != msg.sender) {\n require(isApproved(msg.sender), \"Relayer: not approved\");\n }\n _;\n }\n\n modifier onlyPriceConfigUpdater() {\n if (owner() != msg.sender && !approvedAddresses[msg.sender]) {\n require(priceConfigUpdaters[msg.sender], \"Relayer: not updater\");\n }\n _;\n }\n\n function initialize(address _uln, address _priceFeed, uint256 _nativeDecimalsRate) public proxied initializer {\n __Ownable_init();\n uln = ILayerZeroUltraLightNodeV2(_uln);\n setApprovedAddress(address(this), true);\n multiplierBps = 12000;\n priceFeed = ILayerZeroPriceFeedV2(_priceFeed);\n validateProofBytes = 164;\n fpBytes = 160;\n mptOverhead = 500;\n nativeDecimalsRate = _nativeDecimalsRate;\n }\n\n function onUpgrade(uint256 _nativeDecimalsRate) public proxied {\n nativeDecimalsRate = nativeDecimalsRate;\n }\n\n //----------------------------------------------------------------------------------\n // onlyApproved\n\n function setDstPrice(uint16 _chainId, uint128 _dstPriceRatio, uint128 _dstGasPriceInWei) external onlyApproved {\n // No longer used: Write prices in PriceFeed.\n }\n\n function setPriceFeed(address _priceFeed) external onlyApproved {\n priceFeed = ILayerZeroPriceFeedV2(_priceFeed);\n }\n\n function setPriceMultiplierBps(uint128 _multiplierBps) external onlyApproved {\n multiplierBps = _multiplierBps;\n }\n\n function setDstPriceMultipliers(DstMultiplier[] calldata _multipliers) external onlyPriceConfigUpdater {\n for (uint i = 0; i < _multipliers.length; i++) {\n DstMultiplier calldata _data = _multipliers[i];\n dstMultipliers[_data.chainId] = _data.multiplier;\n }\n }\n\n function setDstFloorMarginsUSD(DstFloorMargin[] calldata _margins) external onlyPriceConfigUpdater {\n for (uint i = 0; i < _margins.length; i++) {\n DstFloorMargin calldata _data = _margins[i];\n dstFloorMarginsUSD[_data.chainId] = _data.floorMargin;\n }\n }\n\n function setDstConfig(\n uint16 _chainId,\n uint16 _outboundProofType,\n uint128 _dstNativeAmtCap,\n uint64 _baseGas,\n uint64 _gasPerByte\n ) external onlyApproved {\n dstConfigLookup[_chainId][_outboundProofType] = DstConfig(_dstNativeAmtCap, _baseGas, _gasPerByte);\n emit SetDstConfig(_chainId, _outboundProofType, _dstNativeAmtCap, _baseGas, _gasPerByte);\n }\n\n function setStargateAddress(address _stargateAddress) external onlyApproved {\n stargateBridgeAddress = _stargateAddress;\n }\n\n //----------------------------------------------------------------------------------\n // onlyOwner\n\n function setApprovedAddress(address _relayerAddress, bool _approve) public onlyOwner {\n approvedAddresses[_relayerAddress] = _approve;\n emit ApproveAddress(_relayerAddress, _approve);\n }\n\n function setPriceConfigUpdater(address _priceConfigUpdater, bool _allow) public onlyOwner {\n priceConfigUpdaters[_priceConfigUpdater] = _allow;\n emit SetPriceConfigUpdater(_priceConfigUpdater, _allow);\n }\n\n function setPause(bool _paused) public onlyOwner {\n paused = _paused;\n }\n\n // txType 1\n // bytes [2 32 ]\n // fields [txType extraGas]\n // txType 2\n // bytes [2 32 32 bytes[] ]\n // fields [txType extraGas dstNativeAmt dstNativeAddress]\n // User App Address is not used in this version\n function _getPrices(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n address,\n uint _payloadSize,\n bytes memory _adapterParameters\n ) internal view returns (uint) {\n require(!paused, \"Admin: paused\");\n // decoding the _adapterParameters - reverts if type 2 and there is no dstNativeAddress\n require(\n _adapterParameters.length == 34 || _adapterParameters.length > 66,\n \"Relayer: wrong _adapterParameters size\"\n );\n uint16 txType;\n uint extraGas;\n assembly {\n txType := mload(add(_adapterParameters, 2))\n extraGas := mload(add(_adapterParameters, 34))\n }\n require(extraGas > 0, \"Relayer: gas too low\");\n require(txType == 1 || txType == 2, \"Relayer: unsupported txType\");\n\n DstConfig storage dstConfig = dstConfigLookup[_dstChainId][_outboundProofType];\n\n // validateTransactionProof bytes = fixedBytes + proofBytes\n // V2 has an extra 32 bytes for payable address\n uint totalFixedBytes = txType == 2 ? uint(validateProofBytes) + 32 : validateProofBytes;\n uint proofBytes = _outboundProofType == 2 ? _payloadSize + fpBytes : _payloadSize + mptOverhead;\n\n uint16 dstChainId = _dstChainId; // stack too deep\n (uint fee, uint128 priceRatio, uint128 priceRatioDenominator, uint128 nativePriceUSD) = priceFeed\n .estimateFeeByEid(dstChainId, totalFixedBytes + proofBytes, dstConfig.baseGas + extraGas);\n\n uint dstNativeAmt = 0;\n if (txType == 2) {\n assembly {\n dstNativeAmt := mload(add(_adapterParameters, 66))\n }\n require(dstConfig.dstNativeAmtCap >= dstNativeAmt, \"Relayer: dstNativeAmt too large\");\n }\n uint airdropAmount = 0;\n if (dstNativeAmt > 0) {\n airdropAmount = (((dstNativeAmt * priceRatio) / priceRatioDenominator) * multiplierBps) / 10000;\n }\n\n return _getDstTxCost(dstChainId, fee, nativePriceUSD) + airdropAmount;\n }\n\n function _getDstTxCost(uint16 _dstChainId, uint _fee, uint128 nativeTokenPriceUSD) private view returns (uint) {\n uint128 _dstMultiplier = dstMultipliers[_dstChainId];\n if (_dstMultiplier == 0) {\n _dstMultiplier = multiplierBps;\n }\n uint dstTxCostWithMultiplier = (_fee * _dstMultiplier) / 10000;\n\n if (nativeTokenPriceUSD == 0) {\n return dstTxCostWithMultiplier;\n }\n\n uint dstTxCostWithMargin = _fee + (dstFloorMarginsUSD[_dstChainId] * nativeDecimalsRate) / nativeTokenPriceUSD;\n\n return dstTxCostWithMargin > dstTxCostWithMultiplier ? dstTxCostWithMargin : dstTxCostWithMultiplier;\n }\n\n function getFee(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n address _userApplication,\n uint _payloadSize,\n bytes calldata _adapterParams\n ) external view override returns (uint) {\n require(_payloadSize <= 10000, \"Relayer: _payloadSize tooooo big\");\n return _getPrices(_dstChainId, _outboundProofType, _userApplication, _payloadSize, _adapterParams);\n }\n\n // view function to convert pricefeed price to current price (for backwards compatibility)\n function dstPriceLookup(uint16 _dstChainId) public view returns (DstPrice memory) {\n ILayerZeroPriceFeedV2.Price memory price = priceFeed.getPrice(_dstChainId);\n return DstPrice(price.priceRatio, price.gasPriceInUnit);\n }\n\n function isApproved(address _relayerAddress) public view returns (bool) {\n return approvedAddresses[_relayerAddress];\n }\n\n function assignJob(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n address _userApplication,\n uint _payloadSize,\n bytes calldata _adapterParams\n ) external override returns (uint fee) {\n require(msg.sender == address(uln), \"Relayer: invalid uln\");\n require(_payloadSize <= 10000, \"Relayer: _payloadSize tooooo big\");\n fee = _getPrices(_dstChainId, _outboundProofType, _userApplication, _payloadSize, _adapterParams);\n emit AssignJob(fee);\n }\n\n function withdrawFee(address payable _to, uint _amount) external override onlyApproved {\n uint totalFee = uln.accruedNativeFee(address(this));\n require(_amount <= totalFee, \"Relayer: not enough fee for withdrawal\");\n uln.withdrawNative(_to, _amount);\n }\n\n function withdrawToken(address _token, address _to, uint _amount) external onlyApproved {\n if (_token == address(0)) {\n uint total = address(this).balance;\n require(_amount <= total, \"Relayer: not enough native fee for withdrawal\");\n (bool sent, ) = payable(_to).call{ value: _amount }(\"\");\n require(sent, \"Relayer: failed to send ether\");\n } else {\n uint total = IERC20(_token).balanceOf(address(this));\n require(_amount <= total, \"Relayer: not enough fee for withdrawal\");\n IERC20(_token).safeTransfer(_to, _amount);\n }\n }\n\n function validateTransactionProofV2(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _blockHash,\n bytes32 _data,\n bytes calldata _transactionProof,\n address payable _to\n ) external payable onlyApproved nonReentrant {\n (bool sent, ) = _to.call{ gas: AIRDROP_GAS_LIMIT, value: msg.value }(\"\");\n //require(sent, \"Relayer: failed to send ether\");\n if (!sent) {\n emit ValueTransferFailed(_to, msg.value);\n }\n uln.validateTransactionProof(_srcChainId, _dstAddress, _gasLimit, _blockHash, _data, _transactionProof);\n }\n\n function validateTransactionProofV2WithGasLimit(\n uint16 _srcChainId,\n address _dstAddress,\n uint _executeGasLimit,\n uint _airdropGasLimit,\n bytes32 _blockHash,\n bytes32 _data,\n bytes calldata _transactionProof,\n address payable _to\n ) external payable onlyApproved nonReentrant {\n (bool sent, ) = _to.call{ gas: _airdropGasLimit, value: msg.value }(\"\");\n if (!sent) {\n emit ValueTransferFailed(_to, msg.value);\n }\n uln.validateTransactionProof(_srcChainId, _dstAddress, _executeGasLimit, _blockHash, _data, _transactionProof);\n }\n\n function validateTransactionProofV1(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _blockHash,\n bytes32 _data,\n bytes calldata _transactionProof\n ) external onlyApproved nonReentrant {\n uln.validateTransactionProof(_srcChainId, _dstAddress, _gasLimit, _blockHash, _data, _transactionProof);\n }\n}\n"
|
|
253
|
+
},
|
|
254
|
+
"contracts/RelayerV2Radar.sol": {
|
|
255
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.7.6;\n\npragma abicoder v2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"hardhat-deploy/solc_0.7/proxy/Proxied.sol\";\n\nimport \"./interfaces/ILayerZeroRelayerV2.sol\";\nimport \"./interfaces/ILayerZeroRelayerV2PriceData.sol\";\nimport \"./interfaces/ILayerZeroUltraLightNodeV2.sol\";\nimport \"./interfaces/ILayerZeroPriceFeed.sol\";\n\n// RelayerV2Radar has an instance of RelayerV2.\n// It does not need to set prices.\n// it has view functions that use the internal RelayerV2 price data.\ncontract RelayerV2Radar is\n ReentrancyGuard,\n OwnableUpgradeable,\n Proxied,\n ILayerZeroRelayerV2,\n ILayerZeroRelayerV2PriceData\n{\n using SafeERC20 for IERC20;\n using SafeMath for uint;\n using SafeMath for uint128;\n using SafeMath for uint64;\n\n ILayerZeroUltraLightNodeV2 public uln; // UltraLightNodeV2Radar\n ILayerZeroRelayerV2PriceData public relayerV2;\n\n address public stargateBridgeAddress;\n\n // struct DstPrice {\n // uint128 dstPriceRatio; // 10^10\n // uint128 dstGasPriceInWei;\n // }\n //\n // struct DstConfig {\n // uint128 dstNativeAmtCap;\n // uint64 baseGas;\n // uint64 gasPerByte;\n // }\n\n // // [_chainId] => DstPriceData. change often\n // mapping(uint16 => RelayerV2.DstPrice) public dstPriceLookup;\n // // [_chainId][_outboundProofType] => DstConfig. change much less often\n // mapping(uint16 => mapping(uint16 => RelayerV2.DstConfig)) public dstConfigLookup;\n mapping(address => bool) public approvedAddresses;\n\n event Withdraw(address to, uint amount);\n event ApproveAddress(address addr, bool approved);\n event AssignJob(uint totalFee);\n event ValueTransferFailed(address indexed to, uint indexed quantity);\n event SetDstPrice(uint16 chainId, uint128 dstPriceRatio, uint128 dstGasPriceInWei);\n event SetDstConfig(\n uint16 chainId,\n uint16 outboundProofType,\n uint128 dstNativeAmtCap,\n uint64 baseGas,\n uint64 gasPerByte\n );\n\n // new pauseable relayer\n bool public paused;\n\n // map of legacyChainid => v2 chainId. allows lookup thru to RelayerV2 contract (which is updated frequently)\n mapping(uint16 => uint16) public legacyToV2ChainId; // legacy ChainId => v2 chainId\n\n // Upgrade\n ILayerZeroPriceFeed public priceFeed;\n // all encoded param bytes except for proof for validateTransactionProofV1\n uint128 public multiplierBps;\n uint16 public validateProofBytes;\n uint16 public fpBytes;\n uint16 public mptOverhead; // average overhead for mpt\n\n // owner is always approved\n modifier onlyApproved() {\n if (owner() != msg.sender) {\n require(isApproved(msg.sender), \"Relayer: not approved\");\n }\n _;\n }\n\n function initialize(address _ulnRadar, address _relayerV2, address _priceFeed) public proxied initializer {\n __Ownable_init();\n uln = ILayerZeroUltraLightNodeV2(_ulnRadar);\n setApprovedAddress(address(this), true);\n\n relayerV2 = ILayerZeroRelayerV2PriceData(_relayerV2);\n\n legacyToV2ChainId[1] = 101; // ethereum\n legacyToV2ChainId[2] = 102; // bsc\n legacyToV2ChainId[12] = 112; // fantom\n\n priceFeed = ILayerZeroPriceFeed(_priceFeed);\n validateProofBytes = 164;\n fpBytes = 160;\n mptOverhead = 500;\n }\n\n function onUpgrade(address _priceFeed) public proxied {\n multiplierBps = 12000;\n priceFeed = ILayerZeroPriceFeed(_priceFeed);\n validateProofBytes = 164;\n fpBytes = 160;\n mptOverhead = 500;\n }\n\n function getV2ChainId(uint16 _legacyChainId) public view returns (uint16) {\n require(legacyToV2ChainId[_legacyChainId] != 0, \"getLegacyChainId(): lookup not found\");\n return legacyToV2ChainId[_legacyChainId];\n }\n\n //----------------------------------------------------------------------------------\n // onlyApproved\n\n function setDstPrice(uint16 _chainId, uint128 _dstPriceRatio, uint128 _dstGasPriceInWei) external onlyApproved {\n // dstPriceLookup[_chainId] = DstPrice(_dstPriceRatio, _dstGasPriceInWei);\n // emit SetDstPrice(_chainId, _dstPriceRatio, _dstGasPriceInWei);\n }\n\n function setPriceFeed(address _priceFeed) external onlyApproved {\n priceFeed = ILayerZeroPriceFeed(_priceFeed);\n }\n\n function setPriceMultiplierBps(uint128 _multiplierBps) external onlyApproved {\n multiplierBps = _multiplierBps;\n }\n\n function setDstConfig(\n uint16 _chainId,\n uint16 _outboundProofType,\n uint128 _dstNativeAmtCap,\n uint64 _baseGas,\n uint64 _gasPerByte\n ) external onlyApproved {\n // dstConfigLookup[_chainId][_outboundProofType] = DstConfig(_dstNativeAmtCap, _baseGas, _gasPerByte);\n // emit SetDstConfig(_chainId, _outboundProofType, _dstNativeAmtCap, _baseGas, _gasPerByte);\n }\n\n function dstPriceLookup(\n uint16 _legacyChainId\n ) public view override returns (ILayerZeroRelayerV2PriceData.DstPrice memory) {\n return relayerV2.dstPriceLookup(getV2ChainId(_legacyChainId));\n }\n\n function dstConfigLookup(\n uint16 _legacyChainId,\n uint16 _outboundProofType\n ) public view override returns (ILayerZeroRelayerV2PriceData.DstConfig memory) {\n return relayerV2.dstConfigLookup(getV2ChainId(_legacyChainId), _outboundProofType);\n }\n\n function setStargateAddress(address _stargateAddress) external onlyApproved {\n stargateBridgeAddress = _stargateAddress;\n }\n\n //----------------------------------------------------------------------------------\n // onlyOwner\n\n function setApprovedAddress(address _relayerAddress, bool _approve) public onlyOwner {\n approvedAddresses[_relayerAddress] = _approve;\n emit ApproveAddress(_relayerAddress, _approve);\n }\n\n function setPause(bool _paused) public onlyOwner {\n paused = _paused;\n }\n\n // txType 1\n // bytes [2 32 ]\n // fields [txType extraGas]\n // txType 2\n // bytes [2 32 32 bytes[] ]\n // fields [txType extraGas dstNativeAmt dstNativeAddress]\n // User App Address is not used in this version\n function _getPrices(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n address,\n uint _payloadSize,\n bytes memory _adapterParameters\n ) internal view returns (uint) {\n require(!paused, \"Admin: paused\");\n // decoding the _adapterParameters - reverts if type 2 and there is no dstNativeAddress\n require(\n _adapterParameters.length == 34 || _adapterParameters.length > 66,\n \"Relayer: wrong _adapterParameters size\"\n );\n uint16 txType;\n uint extraGas;\n assembly {\n txType := mload(add(_adapterParameters, 2))\n extraGas := mload(add(_adapterParameters, 34))\n }\n require(extraGas > 0, \"Relayer: gas too low\");\n require(txType == 1 || txType == 2, \"Relayer: unsupported txType\");\n\n DstConfig memory dstConfig = dstConfigLookup(_dstChainId, _outboundProofType);\n\n uint dstNativeAmt = 0;\n if (txType == 2) {\n assembly {\n dstNativeAmt := mload(add(_adapterParameters, 66))\n }\n require(dstConfig.dstNativeAmtCap >= dstNativeAmt, \"Relayer: dstNativeAmt too large\");\n }\n\n // validateTransactionProof bytes = fixedBytes + proofBytes\n // V2 has an extra 32 bytes for payable address\n uint totalFixedBytes = txType == 2 ? uint(validateProofBytes).add(32) : validateProofBytes;\n uint proofBytes = _outboundProofType == 2 ? fpBytes : _payloadSize.add(mptOverhead);\n uint totalCallDataBytes = totalFixedBytes.add(proofBytes);\n\n uint16 dstChainId = _dstChainId; // stack too deep\n (uint fee, uint128 priceRatio) = priceFeed.estimateFeeByChain(\n getV2ChainId(dstChainId),\n totalCallDataBytes,\n dstConfig.baseGas.add(extraGas)\n );\n uint airdropAmount = dstNativeAmt.mul(priceRatio).div(10 ** 10);\n return fee.add(airdropAmount).mul(multiplierBps).div(10000);\n }\n\n function getFee(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n address _userApplication,\n uint _payloadSize,\n bytes calldata _adapterParams\n ) external view override returns (uint) {\n require(_payloadSize <= 10000, \"Relayer: _payloadSize tooooo big\");\n return _getPrices(_dstChainId, _outboundProofType, _userApplication, _payloadSize, _adapterParams);\n }\n\n function isApproved(address _relayerAddress) public view returns (bool) {\n return approvedAddresses[_relayerAddress];\n }\n\n function assignJob(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n address _userApplication,\n uint _payloadSize,\n bytes calldata _adapterParams\n ) external override returns (uint) {\n require(msg.sender == address(uln), \"Relayer: invalid uln\");\n require(_payloadSize <= 10000, \"Relayer: _payloadSize tooooo big\");\n uint fee = _getPrices(_dstChainId, _outboundProofType, _userApplication, _payloadSize, _adapterParams);\n emit AssignJob(fee);\n return fee;\n }\n\n function withdrawFee(address payable _to, uint _amount) external override onlyApproved {\n uint totalFee = uln.accruedNativeFee(address(this));\n require(_amount <= totalFee, \"Relayer: not enough fee for withdrawal\");\n uln.withdrawNative(_to, _amount);\n }\n\n function validateTransactionProofV2(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _blockHash,\n bytes32 _data,\n bytes calldata _transactionProof,\n address payable _to\n ) external payable onlyApproved nonReentrant {\n (bool sent, ) = _to.call{value: msg.value}(\"\");\n //require(sent, \"Relayer: failed to send ether\");\n if (!sent) {\n emit ValueTransferFailed(_to, msg.value);\n }\n uln.validateTransactionProof(_srcChainId, _dstAddress, _gasLimit, _blockHash, _data, _transactionProof);\n }\n\n function validateTransactionProofV1(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _blockHash,\n bytes32 _data,\n bytes calldata _transactionProof\n ) external onlyApproved nonReentrant {\n uln.validateTransactionProof(_srcChainId, _dstAddress, _gasLimit, _blockHash, _data, _transactionProof);\n }\n}\n"
|
|
256
|
+
},
|
|
257
|
+
"contracts/Treasury.sol": {
|
|
258
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\n\nimport \"./interfaces/ILayerZeroTreasury.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"./interfaces/ILayerZeroUltraLightNodeV1.sol\";\n\ncontract Treasury is ILayerZeroTreasury, Ownable {\n using SafeMath for uint;\n\n uint public nativeBP;\n uint public zroFee;\n bool public feeEnabled;\n bool public zroEnabled;\n\n ILayerZeroUltraLightNodeV1 public immutable uln;\n\n event NativeBP(uint bp);\n event ZroFee(uint zroFee);\n event FeeEnabled(bool feeEnabled);\n event ZroEnabled(bool zroEnabled);\n\n constructor(address _uln) {\n uln = ILayerZeroUltraLightNodeV1(_uln);\n }\n\n function getFees(bool payInZro, uint relayerFee, uint oracleFee) external view override returns (uint) {\n if (feeEnabled) {\n if (payInZro) {\n require(zroEnabled, \"LayerZero: ZRO is not enabled\");\n return zroFee;\n } else {\n return relayerFee.add(oracleFee).mul(nativeBP).div(10000);\n }\n }\n return 0;\n }\n\n function setFeeEnabled(bool _feeEnabled) external onlyOwner {\n feeEnabled = _feeEnabled;\n emit FeeEnabled(_feeEnabled);\n }\n\n function setZroEnabled(bool _zroEnabled) external onlyOwner {\n zroEnabled = _zroEnabled;\n emit ZroEnabled(_zroEnabled);\n }\n\n function setNativeBP(uint _nativeBP) external onlyOwner {\n nativeBP = _nativeBP;\n emit NativeBP(_nativeBP);\n }\n\n function setZroFee(uint _zroFee) external onlyOwner {\n zroFee = _zroFee;\n emit ZroFee(_zroFee);\n }\n\n // uint8 public constant WITHDRAW_TYPE_TREASURY_PROTOCOL_FEES = 0;\n function withdrawZROFromULN(address _to, uint _amount) external onlyOwner {\n uln.withdrawZRO(_to, _amount);\n }\n\n // uint8 public constant WITHDRAW_TYPE_TREASURY_PROTOCOL_FEES = 0;\n function withdrawNativeFromULN(address payable _to, uint _amount) external onlyOwner {\n uln.withdrawNative(0, address(0x0), _to, _amount);\n }\n}\n"
|
|
259
|
+
},
|
|
260
|
+
"contracts/TreasuryV2.sol": {
|
|
261
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"./interfaces/ILayerZeroTreasury.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./interfaces/ILayerZeroUltraLightNodeV2.sol\";\n\ncontract TreasuryV2 is ILayerZeroTreasury, Ownable {\n uint public nativeBP;\n uint public zroFee;\n bool public feeEnabled;\n bool public zroEnabled;\n\n ILayerZeroUltraLightNodeV2 public uln;\n\n event NativeBP(uint bp);\n event ZroFee(uint zroFee);\n event FeeEnabled(bool feeEnabled);\n event ZroEnabled(bool zroEnabled);\n\n constructor(address _ulnv2) {\n uln = ILayerZeroUltraLightNodeV2(_ulnv2);\n }\n\n function getFees(bool payInZro, uint relayerFee, uint oracleFee) external view override returns (uint) {\n if (feeEnabled) {\n if (payInZro) {\n require(zroEnabled, \"LayerZero: ZRO is not enabled\");\n return zroFee;\n } else {\n return ((relayerFee + oracleFee) * nativeBP) / 10000;\n }\n }\n return 0;\n }\n\n function setFeeEnabled(bool _feeEnabled) external onlyOwner {\n feeEnabled = _feeEnabled;\n emit FeeEnabled(_feeEnabled);\n }\n\n function setZroEnabled(bool _zroEnabled) external onlyOwner {\n zroEnabled = _zroEnabled;\n emit ZroEnabled(_zroEnabled);\n }\n\n function setNativeBP(uint _nativeBP) external onlyOwner {\n nativeBP = _nativeBP;\n emit NativeBP(_nativeBP);\n }\n\n function setZroFee(uint _zroFee) external onlyOwner {\n zroFee = _zroFee;\n emit ZroFee(_zroFee);\n }\n\n function withdrawZROFromULN(address _to, uint _amount) external onlyOwner {\n uln.withdrawZRO(_to, _amount);\n }\n\n function withdrawNativeFromULN(address payable _to, uint _amount) external onlyOwner {\n uln.withdrawNative(_to, _amount);\n }\n}\n"
|
|
262
|
+
},
|
|
263
|
+
"contracts/TreasuryV2Radar.sol": {
|
|
264
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\n\nimport \"./interfaces/ILayerZeroTreasury.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"./interfaces/ILayerZeroUltraLightNodeV2.sol\";\n\ncontract TreasuryV2Radar is ILayerZeroTreasury, Ownable {\n using SafeMath for uint;\n\n uint public nativeBP;\n uint public zroFee;\n bool public feeEnabled;\n bool public zroEnabled;\n\n ILayerZeroUltraLightNodeV2 public uln;\n\n event NativeBP(uint bp);\n event ZroFee(uint zroFee);\n event FeeEnabled(bool feeEnabled);\n event ZroEnabled(bool zroEnabled);\n\n constructor(address _ulnv2) {\n uln = ILayerZeroUltraLightNodeV2(_ulnv2);\n }\n\n function getFees(bool payInZro, uint relayerFee, uint oracleFee) external view override returns (uint) {\n if (feeEnabled) {\n if (payInZro) {\n require(zroEnabled, \"LayerZero: ZRO is not enabled\");\n return zroFee;\n } else {\n return relayerFee.add(oracleFee).mul(nativeBP).div(10000);\n }\n }\n return 0;\n }\n\n function setFeeEnabled(bool _feeEnabled) external onlyOwner {\n feeEnabled = _feeEnabled;\n emit FeeEnabled(_feeEnabled);\n }\n\n function setZroEnabled(bool _zroEnabled) external onlyOwner {\n zroEnabled = _zroEnabled;\n emit ZroEnabled(_zroEnabled);\n }\n\n function setNativeBP(uint _nativeBP) external onlyOwner {\n nativeBP = _nativeBP;\n emit NativeBP(_nativeBP);\n }\n\n function setZroFee(uint _zroFee) external onlyOwner {\n zroFee = _zroFee;\n emit ZroFee(_zroFee);\n }\n\n function withdrawZROFromULN(address _to, uint _amount) external onlyOwner {\n uln.withdrawZRO(_to, _amount);\n }\n\n function withdrawNativeFromULN(address payable _to, uint _amount) external onlyOwner {\n uln.withdrawNative(_to, _amount);\n }\n}\n"
|
|
265
|
+
},
|
|
266
|
+
"contracts/UltraLightNode.sol": {
|
|
267
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./interfaces/ILayerZeroValidationLibrary.sol\";\nimport \"./interfaces/ILayerZeroMessagingLibrary.sol\";\nimport \"./interfaces/ILayerZeroReceiver.sol\";\nimport \"./interfaces/ILayerZeroRelayer.sol\";\nimport \"./interfaces/ILayerZeroTreasury.sol\";\nimport \"./interfaces/ILayerZeroOracle.sol\";\nimport \"./interfaces/ILayerZeroUltraLightNodeV1.sol\";\nimport \"./interfaces/ILayerZeroEndpoint.sol\";\n\ncontract UltraLightNode is ILayerZeroMessagingLibrary, ILayerZeroUltraLightNodeV1, ReentrancyGuard, Ownable {\n using SafeERC20 for IERC20;\n using SafeMath for uint;\n\n struct BlockData {\n uint confirmations;\n bytes32 data;\n }\n\n // Application config\n uint public constant CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION = 1;\n uint public constant CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS = 2;\n uint public constant CONFIG_TYPE_RELAYER = 3;\n uint public constant CONFIG_TYPE_OUTBOUND_PROOF_TYPE = 4;\n uint public constant CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS = 5;\n uint public constant CONFIG_TYPE_ORACLE = 6;\n\n struct ApplicationConfiguration {\n uint16 inboundProofLibraryVersion;\n uint64 inboundBlockConfirmations;\n address relayer;\n uint16 outboundProofType;\n uint64 outboundBlockConfirmations;\n address oracle;\n }\n\n // Token and Contracts\n IERC20 public layerZeroToken;\n ILayerZeroTreasury public treasuryContract;\n\n // Fee management\n uint public constant BP_DENOMINATOR = 10000;\n // treasury and relayer share the protocol fee, either in native token or ZRO\n uint8 public constant WITHDRAW_TYPE_TREASURY_PROTOCOL_FEES = 0;\n uint8 public constant WITHDRAW_TYPE_ORACLE_QUOTED_FEES = 1; // quoted fee refers to the fee in block relaying\n uint8 public constant WITHDRAW_TYPE_RELAYER_QUOTED_FEES = 2; //quoted fee refers the fee in msg relaying\n\n mapping(address => uint) public oracleQuotedFees;\n mapping(address => uint) public relayerQuotedFees;\n uint public treasuryNativeFees;\n uint public treasuryZROFees;\n\n // User Application\n mapping(address => mapping(uint16 => ApplicationConfiguration)) public appConfig; // app address => chainId => config\n mapping(uint16 => ApplicationConfiguration) public defaultAppConfig; // default UA settings if no version specified\n mapping(uint16 => mapping(uint16 => bytes)) public defaultAdapterParams;\n\n // Validation\n mapping(uint16 => mapping(uint16 => address)) public inboundProofLibrary; // chainId => library Id => inboundProofLibrary contract\n mapping(uint16 => uint16) public maxInboundProofLibrary; // chainId => inboundProofLibrary\n mapping(uint16 => mapping(uint16 => bool)) public supportedOutboundProof; // chainId => outboundProofType => enabled\n mapping(uint16 => uint) public chainAddressSizeMap;\n mapping(address => mapping(uint16 => mapping(bytes32 => BlockData))) public hashLookup;\n mapping(uint16 => bytes32) public ulnLookup; // remote ulns\n\n ILayerZeroEndpoint public immutable endpoint;\n\n // Events\n event AppConfigUpdated(address userApplication, uint configType, bytes newConfig);\n event AddInboundProofLibraryForChain(uint16 chainId, address lib);\n event EnableSupportedOutboundProof(uint16 chainId, uint16 proofType);\n event HashReceived(uint16 srcChainId, address oracle, uint confirmations, bytes32 blockhash);\n event Packet(uint16 chainId, bytes payload);\n event RelayerParams(uint16 chainId, uint64 nonce, uint16 outboundProofType, bytes adapterParams);\n event SetChainAddressSize(uint16 chainId, uint size);\n event SetDefaultConfigForChainId(\n uint16 chainId,\n uint16 inboundProofLib,\n uint64 inboundBlockConfirm,\n address relayer,\n uint16 outboundProofType,\n uint16 outboundBlockConfirm,\n address oracle\n );\n event SetDefaultAdapterParamsForChainId(uint16 chainId, uint16 proofType, bytes adapterParams);\n event SetLayerZeroToken(address tokenAddress);\n event SetRelayerFeeContract(address relayerFeeContract);\n event SetRemoteUln(uint16 chainId, bytes32 uln);\n event SetTreasury(address treasuryAddress);\n event WithdrawZRO(address _msgSender, address _to, uint _amount);\n event WithdrawNative(uint8 _type, address _owner, address _msgSender, address _to, uint _amount);\n\n constructor(address _endpoint) {\n require(_endpoint != address(0x0), \"LayerZero: endpoint cannot be zero address\");\n endpoint = ILayerZeroEndpoint(_endpoint);\n }\n\n // only the endpoint can call SEND() and setConfig()\n modifier onlyEndpoint() {\n require(address(endpoint) == msg.sender, \"LayerZero: only endpoint\");\n _;\n }\n\n //----------------------------------------------------------------------------------\n // PROTOCOL\n\n // This function completes delivery of a LayerZero message.\n //\n // In order to deliver the message, this function:\n // (a) takes the _transactionProof submitted by UA's relayer, and\n // (b) retrieve UA's validation library\n // (c) takes the _blockData submitted by the UA's oracle given the their configuration (and blockConfirmations),\n // (d) decodes using UA's validation library using (a) and (c)\n // then, this functions asserts that\n // (e) the payload originated from the known Ultra Light Node from source chain, and\n // (f) the _dstAddress the specified destination contract\n function validateTransactionProof(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _lookupHash,\n bytes calldata _transactionProof\n ) external override {\n // retrieve UA's configuration using the _dstAddress from arguments.\n ApplicationConfiguration memory uaConfig = getAppConfig(_srcChainId, _dstAddress);\n\n // (a) assert that the caller == UA's relayer\n require(uaConfig.relayer == msg.sender, \"LayerZero: invalid relayer\");\n\n LayerZeroPacket.Packet memory _packet;\n {\n // (b) retrieve UA's validation library\n address inboundProofLib = inboundProofLibrary[_srcChainId][uaConfig.inboundProofLibraryVersion];\n\n // (c) assert that the data submitted by UA's oracle have no fewer confirmations than UA's configuration\n BlockData storage blockData = hashLookup[uaConfig.oracle][_srcChainId][_lookupHash];\n require(\n blockData.confirmations >= uaConfig.inboundBlockConfirmations,\n \"LayerZero: not enough block confirmations\"\n );\n\n // (d) decode\n uint remoteAddressSize = chainAddressSizeMap[_srcChainId];\n _packet = ILayerZeroValidationLibrary(inboundProofLib).validateProof(\n blockData.data,\n _transactionProof,\n remoteAddressSize\n );\n }\n\n // (e) assert that the packet was emitted by the source ultra light node\n require(ulnLookup[_srcChainId] == _packet.ulnAddress, \"LayerZero: _packet.ulnAddress is invalid\");\n\n // (f) assert that the _packet._dstAddress == the _dstAddress specified by the UAs message\n require(_packet.dstAddress == _dstAddress, \"LayerZero: invalid dst address\");\n\n // publish the payload and _gasLimit to the endpoint for calling lzReceive at _dstAddress\n endpoint.receivePayload(\n _packet.srcChainId,\n _packet.srcAddress,\n _packet.dstAddress,\n _packet.nonce,\n _gasLimit,\n _packet.payload\n );\n }\n\n // Called (by the Endpoint) with the information required to send a LayerZero message for a User Application.\n // This function:\n // (a) pays the protocol (native token or ZRO), oracle (native token) and relayer (native token) for their roles in sending the message.\n // (b) generates the message payload and emits events of the message and adapterParams\n // (c) notifies the oracle\n function send(\n address _ua,\n uint64 _nonce,\n uint16 _chainId,\n bytes calldata _destination,\n bytes calldata _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable override onlyEndpoint {\n ApplicationConfiguration memory uaConfig = getAppConfig(_chainId, _ua);\n address ua = _ua;\n uint64 nonce = _nonce;\n uint16 chainId = _chainId;\n require(ulnLookup[chainId] != bytes32(0), \"LayerZero: chainId does not exist\");\n\n uint totalNativeFee;\n {\n uint oracleFee;\n // (a - 1), pay the oracle\n {\n oracleFee = ILayerZeroOracle(uaConfig.oracle).getPrice(chainId, uaConfig.outboundProofType);\n oracleQuotedFees[uaConfig.oracle] = oracleQuotedFees[uaConfig.oracle].add(oracleFee);\n }\n\n // (a - 2), pay the relayer\n {\n uint payloadSize = _payload.length;\n ILayerZeroRelayer relayer = ILayerZeroRelayer(uaConfig.relayer);\n if (_adapterParams.length == 0) {\n bytes memory defaultAdaptorParam = defaultAdapterParams[chainId][uaConfig.outboundProofType];\n totalNativeFee = relayer.getPrice(\n chainId,\n uaConfig.outboundProofType,\n ua,\n payloadSize,\n defaultAdaptorParam\n );\n relayer.notifyRelayer(chainId, uaConfig.outboundProofType, defaultAdaptorParam);\n } else {\n totalNativeFee = relayer.getPrice(\n chainId,\n uaConfig.outboundProofType,\n ua,\n payloadSize,\n _adapterParams\n );\n relayer.notifyRelayer(chainId, uaConfig.outboundProofType, _adapterParams);\n }\n relayerQuotedFees[uaConfig.relayer] = relayerQuotedFees[uaConfig.relayer].add(totalNativeFee); // totalNativeFee == relayerFee here\n\n // emit the param events\n emit RelayerParams(chainId, nonce, uaConfig.outboundProofType, _adapterParams);\n }\n\n // (a - 3), pay the protocol\n {\n // if no ZRO token or not specifying a payment address, pay in native token\n bool payInNative = _zroPaymentAddress == address(0x0) || address(layerZeroToken) == address(0x0);\n uint protocolFee = treasuryContract.getFees(!payInNative, totalNativeFee, oracleFee); // totalNativeFee == relayerFee here\n\n if (protocolFee > 0) {\n if (payInNative) {\n treasuryNativeFees = treasuryNativeFees.add(protocolFee);\n totalNativeFee = totalNativeFee.add(protocolFee);\n } else {\n // zro payment address must equal the _ua or the tx.origin otherwise the transaction reverts\n require(\n _zroPaymentAddress == ua || _zroPaymentAddress == tx.origin,\n \"LayerZero: must be paid by sender or origin\"\n );\n\n // transfer the LayerZero token to this contract from the payee\n layerZeroToken.safeTransferFrom(_zroPaymentAddress, address(this), protocolFee);\n\n treasuryZROFees = treasuryZROFees.add(protocolFee);\n }\n }\n }\n\n totalNativeFee = totalNativeFee.add(oracleFee);\n }\n\n // (b) emit payload and the adapterParams if any\n {\n bytes memory encodedPayload = abi.encodePacked(nonce, ua, _destination, _payload);\n emit Packet(chainId, encodedPayload);\n // (c) notify the oracle\n ILayerZeroOracle(uaConfig.oracle).notifyOracle(\n chainId,\n uaConfig.outboundProofType,\n uaConfig.outboundBlockConfirmations\n );\n }\n\n require(totalNativeFee <= msg.value, \"LayerZero: not enough native for fees\");\n // refund if they send too much\n uint amount = msg.value.sub(totalNativeFee);\n if (amount > 0) {\n (bool success, ) = _refundAddress.call{value: amount}(\"\");\n require(success, \"LayerZero: failed to refund\");\n }\n }\n\n // Can be called by any address to update a block header\n // can only upload new block data or the same block data with more confirmations\n function updateHash(uint16 _srcChainId, bytes32 _lookupHash, uint _confirmations, bytes32 _data) external override {\n // this function may revert with a default message if the oracle address is not an ILayerZeroOracle\n BlockData storage bd = hashLookup[msg.sender][_srcChainId][_lookupHash];\n // if it has a record, requires a larger confirmation.\n require(\n bd.confirmations < _confirmations,\n \"LayerZero: oracle data can only update if it has more confirmations\"\n );\n\n // set the new information into storage\n bd.confirmations = _confirmations;\n bd.data = _data;\n\n emit HashReceived(_srcChainId, msg.sender, _confirmations, _lookupHash);\n }\n\n //----------------------------------------------------------------------------------\n // Other Library Interfaces\n\n // default to DEFAULT setting if ZERO value\n function getAppConfig(\n uint16 _chainId,\n address userApplicationAddress\n ) public view returns (ApplicationConfiguration memory) {\n ApplicationConfiguration memory config = appConfig[userApplicationAddress][_chainId];\n ApplicationConfiguration storage defaultConfig = defaultAppConfig[_chainId];\n\n if (config.inboundProofLibraryVersion == 0) {\n config.inboundProofLibraryVersion = defaultConfig.inboundProofLibraryVersion;\n }\n\n if (config.inboundBlockConfirmations == 0) {\n config.inboundBlockConfirmations = defaultConfig.inboundBlockConfirmations;\n }\n\n if (config.relayer == address(0x0)) {\n config.relayer = defaultConfig.relayer;\n }\n\n if (config.outboundProofType == 0) {\n config.outboundProofType = defaultConfig.outboundProofType;\n }\n\n if (config.outboundBlockConfirmations == 0) {\n config.outboundBlockConfirmations = defaultConfig.outboundBlockConfirmations;\n }\n\n if (config.oracle == address(0x0)) {\n config.oracle = defaultConfig.oracle;\n }\n\n return config;\n }\n\n function setConfig(\n uint16 chainId,\n address _ua,\n uint _configType,\n bytes calldata _config\n ) external override onlyEndpoint {\n ApplicationConfiguration storage uaConfig = appConfig[_ua][chainId];\n if (_configType == CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION) {\n uint16 inboundProofLibraryVersion = abi.decode(_config, (uint16));\n require(\n inboundProofLibraryVersion <= maxInboundProofLibrary[chainId],\n \"LayerZero: invalid inbound proof library version\"\n );\n uaConfig.inboundProofLibraryVersion = inboundProofLibraryVersion;\n } else if (_configType == CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS) {\n uint64 blockConfirmations = abi.decode(_config, (uint64));\n uaConfig.inboundBlockConfirmations = blockConfirmations;\n } else if (_configType == CONFIG_TYPE_RELAYER) {\n address relayer = abi.decode(_config, (address));\n uaConfig.relayer = relayer;\n } else if (_configType == CONFIG_TYPE_OUTBOUND_PROOF_TYPE) {\n uint16 outboundProofType = abi.decode(_config, (uint16));\n require(\n supportedOutboundProof[chainId][outboundProofType] || outboundProofType == 0,\n \"LayerZero: invalid outbound proof type\"\n );\n uaConfig.outboundProofType = outboundProofType;\n } else if (_configType == CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS) {\n uint64 blockConfirmations = abi.decode(_config, (uint64));\n uaConfig.outboundBlockConfirmations = blockConfirmations;\n } else if (_configType == CONFIG_TYPE_ORACLE) {\n address oracle = abi.decode(_config, (address));\n uaConfig.oracle = oracle;\n } else {\n revert(\"LayerZero: Invalid config type\");\n }\n\n emit AppConfigUpdated(_ua, _configType, _config);\n }\n\n function getConfig(\n uint16 _chainId,\n address userApplicationAddress,\n uint _configType\n ) external view override returns (bytes memory) {\n ApplicationConfiguration storage uaConfig = appConfig[userApplicationAddress][_chainId];\n\n if (_configType == CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION) {\n if (uaConfig.inboundProofLibraryVersion == 0) {\n return abi.encode(defaultAppConfig[_chainId].inboundProofLibraryVersion);\n }\n return abi.encode(uaConfig.inboundProofLibraryVersion);\n } else if (_configType == CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS) {\n if (uaConfig.inboundBlockConfirmations == 0) {\n return abi.encode(defaultAppConfig[_chainId].inboundBlockConfirmations);\n }\n return abi.encode(uaConfig.inboundBlockConfirmations);\n } else if (_configType == CONFIG_TYPE_RELAYER) {\n if (uaConfig.relayer == address(0x0)) {\n return abi.encode(defaultAppConfig[_chainId].relayer);\n }\n return abi.encode(uaConfig.relayer);\n } else if (_configType == CONFIG_TYPE_OUTBOUND_PROOF_TYPE) {\n if (uaConfig.outboundProofType == 0) {\n return abi.encode(defaultAppConfig[_chainId].outboundProofType);\n }\n return abi.encode(uaConfig.outboundProofType);\n } else if (_configType == CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS) {\n if (uaConfig.outboundBlockConfirmations == 0) {\n return abi.encode(defaultAppConfig[_chainId].outboundBlockConfirmations);\n }\n return abi.encode(uaConfig.outboundBlockConfirmations);\n } else if (_configType == CONFIG_TYPE_ORACLE) {\n if (uaConfig.oracle == address(0x0)) {\n return abi.encode(defaultAppConfig[_chainId].oracle);\n }\n return abi.encode(uaConfig.oracle);\n } else {\n revert(\"LayerZero: Invalid config type\");\n }\n }\n\n // returns the native fee the UA pays to cover fees\n function estimateFees(\n uint16 _chainId,\n address _ua,\n bytes calldata _payload,\n bool _payInZRO,\n bytes calldata _adapterParams\n ) external view override returns (uint nativeFee, uint zroFee) {\n uint16 chainId = _chainId;\n address ua = _ua;\n uint payloadSize = _payload.length;\n bytes memory adapterParam = _adapterParams;\n\n ApplicationConfiguration memory uaConfig = getAppConfig(chainId, ua);\n\n // Relayer Fee\n uint relayerFee;\n {\n if (adapterParam.length == 0) {\n bytes memory defaultAdaptorParam = defaultAdapterParams[chainId][uaConfig.outboundProofType];\n relayerFee = ILayerZeroRelayer(uaConfig.relayer).getPrice(\n chainId,\n uaConfig.outboundProofType,\n ua,\n payloadSize,\n defaultAdaptorParam\n );\n } else {\n relayerFee = ILayerZeroRelayer(uaConfig.relayer).getPrice(\n chainId,\n uaConfig.outboundProofType,\n ua,\n payloadSize,\n adapterParam\n );\n }\n }\n\n // Oracle Fee\n uint oracleFee = ILayerZeroOracle(uaConfig.oracle).getPrice(chainId, uaConfig.outboundProofType);\n\n // LayerZero Fee\n {\n uint protocolFee = treasuryContract.getFees(_payInZRO, relayerFee, oracleFee);\n _payInZRO ? zroFee = protocolFee : nativeFee = protocolFee;\n }\n\n // return the sum of fees\n nativeFee = nativeFee.add(relayerFee).add(oracleFee);\n }\n\n //---------------------------------------------------------------------------\n // Claim Fees\n\n // universal withdraw ZRO token function\n function withdrawZRO(address _to, uint _amount) external override nonReentrant {\n require(msg.sender == address(treasuryContract), \"LayerZero: only treasury\");\n treasuryZROFees = treasuryZROFees.sub(_amount);\n layerZeroToken.safeTransfer(_to, _amount);\n emit WithdrawZRO(msg.sender, _to, _amount);\n }\n\n // universal withdraw native token function.\n // the source contract should perform all the authentication control\n // safemath overflow if the amount is not enough\n function withdrawNative(\n uint8 _type,\n address _owner,\n address payable _to,\n uint _amount\n ) external override nonReentrant {\n if (_type == WITHDRAW_TYPE_TREASURY_PROTOCOL_FEES) {\n require(msg.sender == address(treasuryContract), \"LayerZero:only treasury\");\n treasuryNativeFees = treasuryNativeFees.sub(_amount);\n } else if (_type == WITHDRAW_TYPE_ORACLE_QUOTED_FEES) {\n oracleQuotedFees[msg.sender] = oracleQuotedFees[msg.sender].sub(_amount);\n } else if (_type == WITHDRAW_TYPE_RELAYER_QUOTED_FEES) {\n relayerQuotedFees[msg.sender] = relayerQuotedFees[msg.sender].sub(_amount);\n } else {\n revert(\"LayerZero: unsupported withdraw type\");\n }\n\n (bool success, ) = _to.call{value: _amount}(\"\");\n require(success, \"LayerZero: withdraw failed\");\n emit WithdrawNative(_type, _owner, msg.sender, _to, _amount);\n }\n\n //---------------------------------------------------------------------------\n // Owner calls, configuration only.\n function setLayerZeroToken(address _layerZeroToken) external onlyOwner {\n require(_layerZeroToken != address(0x0), \"LayerZero: _layerZeroToken cannot be zero address\");\n layerZeroToken = IERC20(_layerZeroToken);\n emit SetLayerZeroToken(_layerZeroToken);\n }\n\n function setTreasury(address _treasury) external onlyOwner {\n require(_treasury != address(0x0), \"LayerZero: treasury cannot be zero address\");\n treasuryContract = ILayerZeroTreasury(_treasury);\n emit SetTreasury(_treasury);\n }\n\n function addInboundProofLibraryForChain(uint16 _chainId, address _library) external onlyOwner {\n require(_library != address(0x0), \"LayerZero: library cannot be zero address\");\n require(maxInboundProofLibrary[_chainId] < 65535, \"LayerZero: can not add new library\");\n maxInboundProofLibrary[_chainId]++;\n inboundProofLibrary[_chainId][maxInboundProofLibrary[_chainId]] = _library;\n emit AddInboundProofLibraryForChain(_chainId, _library);\n }\n\n function enableSupportedOutboundProof(uint16 _chainId, uint16 _proofType) external onlyOwner {\n supportedOutboundProof[_chainId][_proofType] = true;\n emit EnableSupportedOutboundProof(_chainId, _proofType);\n }\n\n function setDefaultConfigForChainId(\n uint16 _chainId,\n uint16 _inboundProofLibraryVersion,\n uint64 _inboundBlockConfirmations,\n address _relayer,\n uint16 _outboundProofType,\n uint16 _outboundBlockConfirmations,\n address _oracle\n ) external onlyOwner {\n require(\n _inboundProofLibraryVersion <= maxInboundProofLibrary[_chainId] && _inboundProofLibraryVersion > 0,\n \"LayerZero: invalid inbound proof library version\"\n );\n require(_inboundBlockConfirmations > 0, \"LayerZero: invalid inbound block confirmation\");\n require(_relayer != address(0x0), \"LayerZero: invalid relayer address\");\n require(supportedOutboundProof[_chainId][_outboundProofType], \"LayerZero: invalid outbound proof type\");\n require(_outboundBlockConfirmations > 0, \"LayerZero: invalid outbound block confirmation\");\n require(_oracle != address(0x0), \"LayerZero: invalid oracle address\");\n defaultAppConfig[_chainId] = ApplicationConfiguration(\n _inboundProofLibraryVersion,\n _inboundBlockConfirmations,\n _relayer,\n _outboundProofType,\n _outboundBlockConfirmations,\n _oracle\n );\n emit SetDefaultConfigForChainId(\n _chainId,\n _inboundProofLibraryVersion,\n _inboundBlockConfirmations,\n _relayer,\n _outboundProofType,\n _outboundBlockConfirmations,\n _oracle\n );\n }\n\n function setDefaultAdapterParamsForChainId(\n uint16 _chainId,\n uint16 _proofType,\n bytes calldata _adapterParams\n ) external onlyOwner {\n defaultAdapterParams[_chainId][_proofType] = _adapterParams;\n emit SetDefaultAdapterParamsForChainId(_chainId, _proofType, _adapterParams);\n }\n\n function setRemoteUln(uint16 _remoteChainId, bytes32 _remoteUln) external onlyOwner {\n require(ulnLookup[_remoteChainId] == bytes32(0), \"LayerZero: remote uln already set\");\n ulnLookup[_remoteChainId] = _remoteUln;\n emit SetRemoteUln(_remoteChainId, _remoteUln);\n }\n\n function setChainAddressSize(uint16 _chainId, uint _size) external onlyOwner {\n require(chainAddressSizeMap[_chainId] == 0, \"LayerZero: remote chain address size already set\");\n chainAddressSizeMap[_chainId] = _size;\n emit SetChainAddressSize(_chainId, _size);\n }\n\n //----------------------------------------------------------------------------------\n // view functions\n function getBlockHeaderData(\n address _oracle,\n uint16 _remoteChainId,\n bytes32 _lookupHash\n ) external view returns (BlockData memory blockData) {\n return hashLookup[_oracle][_remoteChainId][_lookupHash];\n }\n\n function oracleQuotedAmount(address _oracle) external view override returns (uint) {\n return oracleQuotedFees[_oracle];\n }\n\n function relayerQuotedAmount(address _relayer) external view override returns (uint) {\n return relayerQuotedFees[_relayer];\n }\n}\n"
|
|
268
|
+
},
|
|
269
|
+
"contracts/UltraLightNodeV2.sol": {
|
|
270
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"./interfaces/ILayerZeroValidationLibrary.sol\";\nimport \"./interfaces/ILayerZeroReceiver.sol\";\nimport \"./interfaces/ILayerZeroTreasury.sol\";\nimport \"./interfaces/ILayerZeroEndpoint.sol\";\n// v2\nimport \"./interfaces/ILayerZeroMessagingLibraryV2.sol\";\nimport \"./interfaces/ILayerZeroOracleV2.sol\";\nimport \"./interfaces/ILayerZeroUltraLightNodeV2.sol\";\nimport \"./interfaces/ILayerZeroRelayerV2.sol\";\nimport \"./NonceContract.sol\";\n\ncontract UltraLightNodeV2 is ILayerZeroMessagingLibraryV2, ILayerZeroUltraLightNodeV2, ReentrancyGuard, Ownable {\n using SafeERC20 for IERC20;\n\n // Application config\n uint public constant CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION = 1;\n uint public constant CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS = 2;\n uint public constant CONFIG_TYPE_RELAYER = 3;\n uint public constant CONFIG_TYPE_OUTBOUND_PROOF_TYPE = 4;\n uint public constant CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS = 5;\n uint public constant CONFIG_TYPE_ORACLE = 6;\n\n // Token and Contracts\n IERC20 public layerZeroToken;\n ILayerZeroTreasury public treasuryContract;\n\n mapping(address => uint) public nativeFees;\n uint public treasuryZROFees;\n\n // User Application\n mapping(address => mapping(uint16 => ApplicationConfiguration)) public appConfig; // app address => chainId => config\n mapping(uint16 => ApplicationConfiguration) public defaultAppConfig; // default UA settings if no version specified\n mapping(uint16 => mapping(uint16 => bytes)) public defaultAdapterParams;\n\n // Validation\n mapping(uint16 => mapping(uint16 => address)) public inboundProofLibrary; // chainId => library Id => inboundProofLibrary contract\n mapping(uint16 => uint16) public maxInboundProofLibrary; // chainId => inboundProofLibrary\n mapping(uint16 => mapping(uint16 => bool)) public supportedOutboundProof; // chainId => outboundProofType => enabled\n mapping(uint16 => uint) public chainAddressSizeMap;\n mapping(address => mapping(uint16 => mapping(bytes32 => mapping(bytes32 => uint)))) public hashLookup; //[oracle][srcChainId][blockhash][datahash] -> confirmation\n mapping(uint16 => bytes32) public ulnLookup; // remote ulns\n\n ILayerZeroEndpoint public immutable endpoint;\n uint16 public immutable localChainId;\n NonceContract public immutable nonceContract;\n\n constructor(address _endpoint, address _nonceContract, uint16 _localChainId) {\n require(_endpoint != address(0x0), \"LayerZero: endpoint cannot be zero address\");\n require(_nonceContract != address(0x0), \"LayerZero: nonceContract cannot be zero address\");\n ILayerZeroEndpoint lzEndpoint = ILayerZeroEndpoint(_endpoint);\n localChainId = _localChainId;\n endpoint = lzEndpoint;\n nonceContract = NonceContract(_nonceContract);\n }\n\n // only the endpoint can call SEND() and setConfig()\n modifier onlyEndpoint() {\n require(address(endpoint) == msg.sender, \"LayerZero: only endpoint\");\n _;\n }\n\n //----------------------------------------------------------------------------------\n // PROTOCOL\n function validateTransactionProof(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _lookupHash,\n bytes32 _blockData,\n bytes calldata _transactionProof\n ) external override {\n // retrieve UA's configuration using the _dstAddress from arguments.\n ApplicationConfiguration memory uaConfig = _getAppConfig(_srcChainId, _dstAddress);\n\n // assert that the caller == UA's relayer\n require(uaConfig.relayer == msg.sender, \"LayerZero: invalid relayer\");\n\n LayerZeroPacket.Packet memory _packet;\n uint remoteAddressSize = chainAddressSizeMap[_srcChainId];\n require(remoteAddressSize != 0, \"LayerZero: incorrect remote address size\");\n {\n // assert that the data submitted by UA's oracle have no fewer confirmations than UA's configuration\n uint storedConfirmations = hashLookup[uaConfig.oracle][_srcChainId][_lookupHash][_blockData];\n require(\n storedConfirmations > 0 && storedConfirmations >= uaConfig.inboundBlockConfirmations,\n \"LayerZero: not enough block confirmations\"\n );\n\n // decode\n address inboundProofLib = inboundProofLibrary[_srcChainId][uaConfig.inboundProofLibraryVersion];\n _packet = ILayerZeroValidationLibrary(inboundProofLib).validateProof(\n _blockData,\n _transactionProof,\n remoteAddressSize\n );\n }\n\n // packet content assertion\n require(\n ulnLookup[_srcChainId] == _packet.ulnAddress && _packet.ulnAddress != bytes32(0),\n \"LayerZero: invalid _packet.ulnAddress\"\n );\n require(_packet.srcChainId == _srcChainId, \"LayerZero: invalid srcChain Id\");\n // failsafe because the remoteAddress size being passed into validateProof trims the address this should not hit\n require(_packet.srcAddress.length == remoteAddressSize, \"LayerZero: invalid srcAddress size\");\n require(_packet.dstChainId == localChainId, \"LayerZero: invalid dstChain Id\");\n require(_packet.dstAddress == _dstAddress, \"LayerZero: invalid dstAddress\");\n\n // if the dst is not a contract, then emit and return early. This will break inbound nonces, but this particular\n // path is already broken and wont ever be able to deliver anyways\n if (!_isContract(_dstAddress)) {\n emit InvalidDst(\n _packet.srcChainId,\n _packet.srcAddress,\n _packet.dstAddress,\n _packet.nonce,\n keccak256(_packet.payload)\n );\n return;\n }\n\n bytes memory pathData = abi.encodePacked(_packet.srcAddress, _packet.dstAddress);\n emit PacketReceived(\n _packet.srcChainId,\n _packet.srcAddress,\n _packet.dstAddress,\n _packet.nonce,\n keccak256(_packet.payload)\n );\n endpoint.receivePayload(_srcChainId, pathData, _dstAddress, _packet.nonce, _gasLimit, _packet.payload);\n }\n\n function send(\n address _ua,\n uint64,\n uint16 _dstChainId,\n bytes calldata _path,\n bytes calldata _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable override onlyEndpoint {\n address ua = _ua;\n uint16 dstChainId = _dstChainId;\n require(ulnLookup[dstChainId] != bytes32(0), \"LayerZero: dstChainId does not exist\");\n\n bytes memory dstAddress;\n uint64 nonce;\n // code block for solving 'Stack Too Deep'\n {\n uint chainAddressSize = chainAddressSizeMap[dstChainId];\n // path = remoteAddress + localAddress\n require(\n chainAddressSize != 0 && _path.length == 20 + chainAddressSize,\n \"LayerZero: incorrect remote address size\"\n );\n address srcInPath;\n bytes memory path = _path; // copy to memory\n assembly {\n srcInPath := mload(add(add(path, 20), chainAddressSize)) // chainAddressSize + 20\n }\n require(ua == srcInPath, \"LayerZero: wrong path data\");\n dstAddress = _path[0:chainAddressSize];\n nonce = nonceContract.increment(dstChainId, ua, path);\n }\n\n bytes memory payload = _payload;\n ApplicationConfiguration memory uaConfig = _getAppConfig(dstChainId, ua);\n\n // compute all the fees\n uint relayerFee = _handleRelayer(dstChainId, uaConfig, ua, payload.length, _adapterParams);\n uint oracleFee = _handleOracle(dstChainId, uaConfig, ua);\n uint nativeProtocolFee = _handleProtocolFee(relayerFee, oracleFee, ua, _zroPaymentAddress);\n\n // total native fee, does not include ZRO protocol fee\n uint totalNativeFee = relayerFee + oracleFee + nativeProtocolFee;\n\n // assert the user has attached enough native token for this address\n require(totalNativeFee <= msg.value, \"LayerZero: not enough native for fees\");\n // refund if they send too much\n uint amount = msg.value - totalNativeFee;\n if (amount > 0) {\n (bool success, ) = _refundAddress.call{value: amount}(\"\");\n require(success, \"LayerZero: failed to refund\");\n }\n\n // emit the data packet\n bytes memory encodedPayload = abi.encodePacked(nonce, localChainId, ua, dstChainId, dstAddress, payload);\n emit Packet(encodedPayload);\n }\n\n function _handleRelayer(\n uint16 _dstChainId,\n ApplicationConfiguration memory _uaConfig,\n address _ua,\n uint _payloadSize,\n bytes memory _adapterParams\n ) internal returns (uint relayerFee) {\n if (_adapterParams.length == 0) {\n _adapterParams = defaultAdapterParams[_dstChainId][_uaConfig.outboundProofType];\n }\n address relayerAddress = _uaConfig.relayer;\n ILayerZeroRelayerV2 relayer = ILayerZeroRelayerV2(relayerAddress);\n relayerFee = relayer.assignJob(_dstChainId, _uaConfig.outboundProofType, _ua, _payloadSize, _adapterParams);\n\n _creditNativeFee(relayerAddress, relayerFee);\n\n // emit the param events\n emit RelayerParams(_adapterParams, _uaConfig.outboundProofType);\n }\n\n function _handleOracle(\n uint16 _dstChainId,\n ApplicationConfiguration memory _uaConfig,\n address _ua\n ) internal returns (uint oracleFee) {\n address oracleAddress = _uaConfig.oracle;\n oracleFee = ILayerZeroOracleV2(oracleAddress).assignJob(\n _dstChainId,\n _uaConfig.outboundProofType,\n _uaConfig.outboundBlockConfirmations,\n _ua\n );\n\n _creditNativeFee(oracleAddress, oracleFee);\n }\n\n function _handleProtocolFee(\n uint _relayerFee,\n uint _oracleFee,\n address _ua,\n address _zroPaymentAddress\n ) internal returns (uint protocolNativeFee) {\n // if no ZRO token or not specifying a payment address, pay in native token\n bool payInNative = _zroPaymentAddress == address(0x0) || address(layerZeroToken) == address(0x0);\n uint protocolFee = treasuryContract.getFees(!payInNative, _relayerFee, _oracleFee);\n\n if (protocolFee > 0) {\n if (payInNative) {\n address treasuryAddress = address(treasuryContract);\n _creditNativeFee(treasuryAddress, protocolFee);\n protocolNativeFee = protocolFee;\n } else {\n // zro payment address must equal the ua or the tx.origin otherwise the transaction reverts\n require(\n _zroPaymentAddress == _ua || _zroPaymentAddress == tx.origin,\n \"LayerZero: must be paid by sender or origin\"\n );\n\n // transfer the LayerZero token to this contract from the payee\n layerZeroToken.safeTransferFrom(_zroPaymentAddress, address(this), protocolFee);\n\n treasuryZROFees += protocolFee;\n }\n }\n }\n\n function _creditNativeFee(address _receiver, uint _amount) internal {\n nativeFees[_receiver] += _amount;\n }\n\n // Can be called by any address to update a block header\n // can only upload new block data or the same block data with more confirmations\n function updateHash(\n uint16 _srcChainId,\n bytes32 _lookupHash,\n uint _confirmations,\n bytes32 _blockData\n ) external override {\n uint storedConfirmations = hashLookup[msg.sender][_srcChainId][_lookupHash][_blockData];\n\n // if it has a record, requires a larger confirmation.\n require(\n storedConfirmations < _confirmations,\n \"LayerZero: oracle data can only update if it has more confirmations\"\n );\n\n // set the new information into storage\n hashLookup[msg.sender][_srcChainId][_lookupHash][_blockData] = _confirmations;\n\n emit HashReceived(_srcChainId, msg.sender, _lookupHash, _blockData, _confirmations);\n }\n\n //----------------------------------------------------------------------------------\n // Other Library Interfaces\n\n // default to DEFAULT setting if ZERO value\n function getAppConfig(\n uint16 _remoteChainId,\n address _ua\n ) external view override returns (ApplicationConfiguration memory) {\n return _getAppConfig(_remoteChainId, _ua);\n }\n\n function _getAppConfig(uint16 _remoteChainId, address _ua) internal view returns (ApplicationConfiguration memory) {\n ApplicationConfiguration memory config = appConfig[_ua][_remoteChainId];\n ApplicationConfiguration storage defaultConfig = defaultAppConfig[_remoteChainId];\n\n if (config.inboundProofLibraryVersion == 0) {\n config.inboundProofLibraryVersion = defaultConfig.inboundProofLibraryVersion;\n }\n\n if (config.inboundBlockConfirmations == 0) {\n config.inboundBlockConfirmations = defaultConfig.inboundBlockConfirmations;\n }\n\n if (config.relayer == address(0x0)) {\n config.relayer = defaultConfig.relayer;\n }\n\n if (config.outboundProofType == 0) {\n config.outboundProofType = defaultConfig.outboundProofType;\n }\n\n if (config.outboundBlockConfirmations == 0) {\n config.outboundBlockConfirmations = defaultConfig.outboundBlockConfirmations;\n }\n\n if (config.oracle == address(0x0)) {\n config.oracle = defaultConfig.oracle;\n }\n\n return config;\n }\n\n function setConfig(\n uint16 _remoteChainId,\n address _ua,\n uint _configType,\n bytes calldata _config\n ) external override onlyEndpoint {\n ApplicationConfiguration storage uaConfig = appConfig[_ua][_remoteChainId];\n if (_configType == CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION) {\n uint16 inboundProofLibraryVersion = abi.decode(_config, (uint16));\n require(\n inboundProofLibraryVersion <= maxInboundProofLibrary[_remoteChainId],\n \"LayerZero: invalid inbound proof library version\"\n );\n uaConfig.inboundProofLibraryVersion = inboundProofLibraryVersion;\n } else if (_configType == CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS) {\n uint64 blockConfirmations = abi.decode(_config, (uint64));\n uaConfig.inboundBlockConfirmations = blockConfirmations;\n } else if (_configType == CONFIG_TYPE_RELAYER) {\n address relayer = abi.decode(_config, (address));\n uaConfig.relayer = relayer;\n } else if (_configType == CONFIG_TYPE_OUTBOUND_PROOF_TYPE) {\n uint16 outboundProofType = abi.decode(_config, (uint16));\n require(\n supportedOutboundProof[_remoteChainId][outboundProofType] || outboundProofType == 0,\n \"LayerZero: invalid outbound proof type\"\n );\n uaConfig.outboundProofType = outboundProofType;\n } else if (_configType == CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS) {\n uint64 blockConfirmations = abi.decode(_config, (uint64));\n uaConfig.outboundBlockConfirmations = blockConfirmations;\n } else if (_configType == CONFIG_TYPE_ORACLE) {\n address oracle = abi.decode(_config, (address));\n uaConfig.oracle = oracle;\n } else {\n revert(\"LayerZero: Invalid config type\");\n }\n\n emit AppConfigUpdated(_ua, _configType, _config);\n }\n\n function getConfig(\n uint16 _remoteChainId,\n address _ua,\n uint _configType\n ) external view override returns (bytes memory) {\n ApplicationConfiguration storage uaConfig = appConfig[_ua][_remoteChainId];\n\n if (_configType == CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION) {\n if (uaConfig.inboundProofLibraryVersion == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].inboundProofLibraryVersion);\n }\n return abi.encode(uaConfig.inboundProofLibraryVersion);\n } else if (_configType == CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS) {\n if (uaConfig.inboundBlockConfirmations == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].inboundBlockConfirmations);\n }\n return abi.encode(uaConfig.inboundBlockConfirmations);\n } else if (_configType == CONFIG_TYPE_RELAYER) {\n if (uaConfig.relayer == address(0x0)) {\n return abi.encode(defaultAppConfig[_remoteChainId].relayer);\n }\n return abi.encode(uaConfig.relayer);\n } else if (_configType == CONFIG_TYPE_OUTBOUND_PROOF_TYPE) {\n if (uaConfig.outboundProofType == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].outboundProofType);\n }\n return abi.encode(uaConfig.outboundProofType);\n } else if (_configType == CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS) {\n if (uaConfig.outboundBlockConfirmations == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].outboundBlockConfirmations);\n }\n return abi.encode(uaConfig.outboundBlockConfirmations);\n } else if (_configType == CONFIG_TYPE_ORACLE) {\n if (uaConfig.oracle == address(0x0)) {\n return abi.encode(defaultAppConfig[_remoteChainId].oracle);\n }\n return abi.encode(uaConfig.oracle);\n } else {\n revert(\"LayerZero: Invalid config type\");\n }\n }\n\n // returns the native fee the UA pays to cover fees\n function estimateFees(\n uint16 _dstChainId,\n address _ua,\n bytes calldata _payload,\n bool _payInZRO,\n bytes calldata _adapterParams\n ) external view override returns (uint nativeFee, uint zroFee) {\n ApplicationConfiguration memory uaConfig = _getAppConfig(_dstChainId, _ua);\n\n // Relayer Fee\n bytes memory adapterParams;\n if (_adapterParams.length > 0) {\n adapterParams = _adapterParams;\n } else {\n adapterParams = defaultAdapterParams[_dstChainId][uaConfig.outboundProofType];\n }\n uint relayerFee = ILayerZeroRelayerV2(uaConfig.relayer).getFee(\n _dstChainId,\n uaConfig.outboundProofType,\n _ua,\n _payload.length,\n adapterParams\n );\n\n // Oracle Fee\n address ua = _ua; // stack too deep\n uint oracleFee = ILayerZeroOracleV2(uaConfig.oracle).getFee(\n _dstChainId,\n uaConfig.outboundProofType,\n uaConfig.outboundBlockConfirmations,\n ua\n );\n\n // LayerZero Fee\n uint protocolFee = treasuryContract.getFees(_payInZRO, relayerFee, oracleFee);\n _payInZRO ? zroFee = protocolFee : nativeFee = protocolFee;\n\n // return the sum of fees\n nativeFee += relayerFee + oracleFee;\n }\n\n //---------------------------------------------------------------------------\n // Claim Fees\n\n // universal withdraw ZRO token function\n function withdrawZRO(address _to, uint _amount) external override nonReentrant {\n require(msg.sender == address(treasuryContract), \"LayerZero: only treasury\");\n treasuryZROFees -= _amount;\n layerZeroToken.safeTransfer(_to, _amount);\n emit WithdrawZRO(msg.sender, _to, _amount);\n }\n\n // universal withdraw native token function.\n // the source contract should perform all the authentication control\n function withdrawNative(address payable _to, uint _amount) external override nonReentrant {\n require(_to != address(0x0), \"LayerZero: _to cannot be zero address\");\n nativeFees[msg.sender] -= _amount;\n\n (bool success, ) = _to.call{value: _amount}(\"\");\n require(success, \"LayerZero: withdraw failed\");\n emit WithdrawNative(msg.sender, _to, _amount);\n }\n\n //---------------------------------------------------------------------------\n // Owner calls, configuration only.\n function setLayerZeroToken(address _layerZeroToken) external onlyOwner {\n require(_layerZeroToken != address(0x0), \"LayerZero: _layerZeroToken cannot be zero address\");\n layerZeroToken = IERC20(_layerZeroToken);\n emit SetLayerZeroToken(_layerZeroToken);\n }\n\n function setTreasury(address _treasury) external onlyOwner {\n require(_treasury != address(0x0), \"LayerZero: treasury cannot be zero address\");\n treasuryContract = ILayerZeroTreasury(_treasury);\n emit SetTreasury(_treasury);\n }\n\n function addInboundProofLibraryForChain(uint16 _chainId, address _library) external onlyOwner {\n require(_library != address(0x0), \"LayerZero: library cannot be zero address\");\n uint16 libId = maxInboundProofLibrary[_chainId];\n require(libId < 65535, \"LayerZero: can not add new library\");\n maxInboundProofLibrary[_chainId] = ++libId;\n inboundProofLibrary[_chainId][libId] = _library;\n emit AddInboundProofLibraryForChain(_chainId, _library);\n }\n\n function enableSupportedOutboundProof(uint16 _chainId, uint16 _proofType) external onlyOwner {\n supportedOutboundProof[_chainId][_proofType] = true;\n emit EnableSupportedOutboundProof(_chainId, _proofType);\n }\n\n function setDefaultConfigForChainId(\n uint16 _chainId,\n uint16 _inboundProofLibraryVersion,\n uint64 _inboundBlockConfirmations,\n address _relayer,\n uint16 _outboundProofType,\n uint64 _outboundBlockConfirmations,\n address _oracle\n ) external onlyOwner {\n require(\n _inboundProofLibraryVersion <= maxInboundProofLibrary[_chainId] && _inboundProofLibraryVersion > 0,\n \"LayerZero: invalid inbound proof library version\"\n );\n require(_inboundBlockConfirmations > 0, \"LayerZero: invalid inbound block confirmation\");\n require(_relayer != address(0x0), \"LayerZero: invalid relayer address\");\n require(supportedOutboundProof[_chainId][_outboundProofType], \"LayerZero: invalid outbound proof type\");\n require(_outboundBlockConfirmations > 0, \"LayerZero: invalid outbound block confirmation\");\n require(_oracle != address(0x0), \"LayerZero: invalid oracle address\");\n defaultAppConfig[_chainId] = ApplicationConfiguration(\n _inboundProofLibraryVersion,\n _inboundBlockConfirmations,\n _relayer,\n _outboundProofType,\n _outboundBlockConfirmations,\n _oracle\n );\n emit SetDefaultConfigForChainId(\n _chainId,\n _inboundProofLibraryVersion,\n _inboundBlockConfirmations,\n _relayer,\n _outboundProofType,\n _outboundBlockConfirmations,\n _oracle\n );\n }\n\n function setDefaultAdapterParamsForChainId(\n uint16 _chainId,\n uint16 _proofType,\n bytes calldata _adapterParams\n ) external onlyOwner {\n defaultAdapterParams[_chainId][_proofType] = _adapterParams;\n emit SetDefaultAdapterParamsForChainId(_chainId, _proofType, _adapterParams);\n }\n\n function setRemoteUln(uint16 _remoteChainId, bytes32 _remoteUln) external onlyOwner {\n require(ulnLookup[_remoteChainId] == bytes32(0), \"LayerZero: remote uln already set\");\n ulnLookup[_remoteChainId] = _remoteUln;\n emit SetRemoteUln(_remoteChainId, _remoteUln);\n }\n\n function setChainAddressSize(uint16 _chainId, uint _size) external onlyOwner {\n require(chainAddressSizeMap[_chainId] == 0, \"LayerZero: remote chain address size already set\");\n chainAddressSizeMap[_chainId] = _size;\n emit SetChainAddressSize(_chainId, _size);\n }\n\n //----------------------------------------------------------------------------------\n // view functions\n\n function accruedNativeFee(address _address) external view override returns (uint) {\n return nativeFees[_address];\n }\n\n function getOutboundNonce(uint16 _chainId, bytes calldata _path) external view override returns (uint64) {\n return nonceContract.outboundNonce(_chainId, _path);\n }\n\n function _isContract(address addr) internal view returns (bool) {\n uint size;\n assembly {\n size := extcodesize(addr)\n }\n return size != 0;\n }\n}\n"
|
|
271
|
+
},
|
|
272
|
+
"contracts/UltraLightNodeV2AltToken.sol": {
|
|
273
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./interfaces/ILayerZeroValidationLibrary.sol\";\nimport \"./interfaces/ILayerZeroReceiver.sol\";\nimport \"./interfaces/ILayerZeroTreasury.sol\";\nimport \"./interfaces/ILayerZeroEndpoint.sol\";\n// v2\nimport \"./interfaces/ILayerZeroMessagingLibraryV2.sol\";\nimport \"./interfaces/ILayerZeroOracleV2.sol\";\nimport \"./interfaces/ILayerZeroUltraLightNodeV2.sol\";\nimport \"./interfaces/ILayerZeroRelayerV2.sol\";\nimport \"./FeeHandler.sol\";\nimport \"./NonceContract.sol\";\n\ncontract UltraLightNodeV2AltToken is\n ILayerZeroMessagingLibraryV2,\n ILayerZeroUltraLightNodeV2,\n ReentrancyGuard,\n Ownable\n{\n using SafeERC20 for IERC20;\n using SafeMath for uint;\n\n // Application config\n uint public constant CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION = 1;\n uint public constant CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS = 2;\n uint public constant CONFIG_TYPE_RELAYER = 3;\n uint public constant CONFIG_TYPE_OUTBOUND_PROOF_TYPE = 4;\n uint public constant CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS = 5;\n uint public constant CONFIG_TYPE_ORACLE = 6;\n\n // Token and Contracts\n IERC20 public layerZeroToken;\n ILayerZeroTreasury public treasuryContract;\n\n mapping(address => uint) public nativeFees;\n uint public treasuryZROFees;\n\n // User Application\n mapping(address => mapping(uint16 => ApplicationConfiguration)) public appConfig; // app address => chainId => config\n mapping(uint16 => ApplicationConfiguration) public defaultAppConfig; // default UA settings if no version specified\n mapping(uint16 => mapping(uint16 => bytes)) public defaultAdapterParams;\n\n // Validation\n mapping(uint16 => mapping(uint16 => address)) public inboundProofLibrary; // chainId => library Id => inboundProofLibrary contract\n mapping(uint16 => uint16) public maxInboundProofLibrary; // chainId => inboundProofLibrary\n mapping(uint16 => mapping(uint16 => bool)) public supportedOutboundProof; // chainId => outboundProofType => enabled\n mapping(uint16 => uint) public chainAddressSizeMap;\n mapping(address => mapping(uint16 => mapping(bytes32 => mapping(bytes32 => uint)))) public hashLookup; //[oracle][srcChainId][blockhash][datahash] -> confirmation\n mapping(uint16 => bytes32) public ulnLookup; // remote ulns\n\n ILayerZeroEndpoint public immutable endpoint;\n uint16 public immutable localChainId;\n NonceContract public immutable nonceContract;\n FeeHandler public immutable feeHandler;\n\n constructor(address _endpoint, address _nonceContract, uint16 _localChainId, address _feeHandler) {\n require(_endpoint != address(0x0), \"LayerZero: endpoint cannot be zero address\");\n require(_nonceContract != address(0x0), \"LayerZero: nonceContract cannot be zero address\");\n ILayerZeroEndpoint lzEndpoint = ILayerZeroEndpoint(_endpoint);\n localChainId = _localChainId;\n endpoint = lzEndpoint;\n nonceContract = NonceContract(_nonceContract);\n feeHandler = FeeHandler(_feeHandler);\n }\n\n // only the endpoint can call SEND() and setConfig()\n modifier onlyEndpoint() {\n require(address(endpoint) == msg.sender, \"LayerZero: only endpoint\");\n _;\n }\n\n //----------------------------------------------------------------------------------\n // PROTOCOL\n function validateTransactionProof(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _lookupHash,\n bytes32 _blockData,\n bytes calldata _transactionProof\n ) external override {\n // retrieve UA's configuration using the _dstAddress from arguments.\n ApplicationConfiguration memory uaConfig = _getAppConfig(_srcChainId, _dstAddress);\n\n // assert that the caller == UA's relayer\n require(uaConfig.relayer == msg.sender, \"LayerZero: invalid relayer\");\n\n LayerZeroPacket.Packet memory _packet;\n uint remoteAddressSize = chainAddressSizeMap[_srcChainId];\n require(remoteAddressSize != 0, \"LayerZero: incorrect remote address size\");\n {\n // assert that the data submitted by UA's oracle have no fewer confirmations than UA's configuration\n uint storedConfirmations = hashLookup[uaConfig.oracle][_srcChainId][_lookupHash][_blockData];\n require(\n storedConfirmations > 0 && storedConfirmations >= uaConfig.inboundBlockConfirmations,\n \"LayerZero: not enough block confirmations\"\n );\n\n // decode\n address inboundProofLib = inboundProofLibrary[_srcChainId][uaConfig.inboundProofLibraryVersion];\n _packet = ILayerZeroValidationLibrary(inboundProofLib).validateProof(\n _blockData,\n _transactionProof,\n remoteAddressSize\n );\n }\n\n // packet content assertion\n require(\n ulnLookup[_srcChainId] == _packet.ulnAddress && _packet.ulnAddress != bytes32(0),\n \"LayerZero: invalid _packet.ulnAddress\"\n );\n require(_packet.srcChainId == _srcChainId, \"LayerZero: invalid srcChain Id\");\n // failsafe because the remoteAddress size being passed into validateProof trims the address this should not hit\n require(_packet.srcAddress.length == remoteAddressSize, \"LayerZero: invalid srcAddress size\");\n require(_packet.dstChainId == localChainId, \"LayerZero: invalid dstChain Id\");\n require(_packet.dstAddress == _dstAddress, \"LayerZero: invalid dstAddress\");\n\n // if the dst is not a contract, then emit and return early. This will break inbound nonces, but this particular\n // path is already broken and wont ever be able to deliver anyways\n if (!_isContract(_dstAddress)) {\n emit InvalidDst(\n _packet.srcChainId,\n _packet.srcAddress,\n _packet.dstAddress,\n _packet.nonce,\n keccak256(_packet.payload)\n );\n return;\n }\n\n bytes memory pathData = abi.encodePacked(_packet.srcAddress, _packet.dstAddress);\n emit PacketReceived(\n _packet.srcChainId,\n _packet.srcAddress,\n _packet.dstAddress,\n _packet.nonce,\n keccak256(_packet.payload)\n );\n endpoint.receivePayload(_srcChainId, pathData, _dstAddress, _packet.nonce, _gasLimit, _packet.payload);\n }\n\n function send(\n address _ua,\n uint64,\n uint16 _dstChainId,\n bytes calldata _path,\n bytes calldata _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable override onlyEndpoint {\n address ua = _ua;\n uint16 dstChainId = _dstChainId;\n require(ulnLookup[dstChainId] != bytes32(0), \"LayerZero: dstChainId does not exist\");\n\n bytes memory dstAddress;\n uint64 nonce;\n // code block for solving 'Stack Too Deep'\n {\n uint chainAddressSize = chainAddressSizeMap[dstChainId];\n // path = remoteAddress + localAddress\n require(\n chainAddressSize != 0 && _path.length == 20 + chainAddressSize,\n \"LayerZero: incorrect remote address size\"\n );\n address srcInPath;\n bytes memory path = _path; // copy to memory\n assembly {\n srcInPath := mload(add(add(path, 20), chainAddressSize)) // chainAddressSize + 20\n }\n require(ua == srcInPath, \"LayerZero: wrong path data\");\n dstAddress = _path[0:chainAddressSize];\n nonce = nonceContract.increment(dstChainId, ua, path);\n }\n\n bytes memory payload = _payload;\n ApplicationConfiguration memory uaConfig = _getAppConfig(dstChainId, ua);\n\n // compute all the fees\n uint[] memory fees = new uint[](3);\n fees[0] = _handleRelayer(dstChainId, uaConfig, ua, payload.length, _adapterParams);\n fees[1] = _handleOracle(dstChainId, uaConfig, ua);\n fees[2] = _handleProtocolFee(fees[0], fees[1], ua, _zroPaymentAddress);\n\n address[] memory receivers = new address[](3);\n receivers[0] = uaConfig.relayer;\n receivers[1] = uaConfig.oracle;\n receivers[2] = address(treasuryContract);\n\n feeHandler.creditFee(receivers, fees, _refundAddress);\n\n // emit the data packet\n bytes memory encodedPayload = abi.encodePacked(nonce, localChainId, ua, dstChainId, dstAddress, payload);\n emit Packet(encodedPayload);\n }\n\n function _handleRelayer(\n uint16 _dstChainId,\n ApplicationConfiguration memory _uaConfig,\n address _ua,\n uint _payloadSize,\n bytes memory _adapterParams\n ) internal returns (uint relayerFee) {\n if (_adapterParams.length == 0) {\n _adapterParams = defaultAdapterParams[_dstChainId][_uaConfig.outboundProofType];\n }\n address relayerAddress = _uaConfig.relayer;\n ILayerZeroRelayerV2 relayer = ILayerZeroRelayerV2(relayerAddress);\n relayerFee = relayer.assignJob(_dstChainId, _uaConfig.outboundProofType, _ua, _payloadSize, _adapterParams);\n\n // emit the param events\n emit RelayerParams(_adapterParams, _uaConfig.outboundProofType);\n }\n\n function _handleOracle(\n uint16 _dstChainId,\n ApplicationConfiguration memory _uaConfig,\n address _ua\n ) internal returns (uint oracleFee) {\n address oracleAddress = _uaConfig.oracle;\n oracleFee = ILayerZeroOracleV2(oracleAddress).assignJob(\n _dstChainId,\n _uaConfig.outboundProofType,\n _uaConfig.outboundBlockConfirmations,\n _ua\n );\n }\n\n function _handleProtocolFee(\n uint _relayerFee,\n uint _oracleFee,\n address _ua,\n address _zroPaymentAddress\n ) internal returns (uint protocolNativeFee) {\n // if no ZRO token or not specifying a payment address, pay in native token\n bool payInNative = _zroPaymentAddress == address(0x0) || address(layerZeroToken) == address(0x0);\n uint protocolFee = treasuryContract.getFees(!payInNative, _relayerFee, _oracleFee);\n\n if (protocolFee > 0) {\n if (payInNative) {\n address treasuryAddress = address(treasuryContract);\n protocolNativeFee = protocolFee;\n } else {\n // zro payment address must equal the ua or the tx.origin otherwise the transaction reverts\n require(\n _zroPaymentAddress == _ua || _zroPaymentAddress == tx.origin,\n \"LayerZero: must be paid by sender or origin\"\n );\n\n // transfer the LayerZero token to this contract from the payee\n layerZeroToken.safeTransferFrom(_zroPaymentAddress, address(this), protocolFee);\n\n treasuryZROFees = treasuryZROFees.add(protocolFee);\n }\n }\n }\n\n // Can be called by any address to update a block header\n // can only upload new block data or the same block data with more confirmations\n function updateHash(\n uint16 _srcChainId,\n bytes32 _lookupHash,\n uint _confirmations,\n bytes32 _blockData\n ) external override {\n uint storedConfirmations = hashLookup[msg.sender][_srcChainId][_lookupHash][_blockData];\n\n // if it has a record, requires a larger confirmation.\n require(\n storedConfirmations < _confirmations,\n \"LayerZero: oracle data can only update if it has more confirmations\"\n );\n\n // set the new information into storage\n hashLookup[msg.sender][_srcChainId][_lookupHash][_blockData] = _confirmations;\n\n emit HashReceived(_srcChainId, msg.sender, _lookupHash, _blockData, _confirmations);\n }\n\n //----------------------------------------------------------------------------------\n // Other Library Interfaces\n\n // default to DEFAULT setting if ZERO value\n function getAppConfig(\n uint16 _remoteChainId,\n address _ua\n ) external view override returns (ApplicationConfiguration memory) {\n return _getAppConfig(_remoteChainId, _ua);\n }\n\n function _getAppConfig(uint16 _remoteChainId, address _ua) internal view returns (ApplicationConfiguration memory) {\n ApplicationConfiguration memory config = appConfig[_ua][_remoteChainId];\n ApplicationConfiguration storage defaultConfig = defaultAppConfig[_remoteChainId];\n\n if (config.inboundProofLibraryVersion == 0) {\n config.inboundProofLibraryVersion = defaultConfig.inboundProofLibraryVersion;\n }\n\n if (config.inboundBlockConfirmations == 0) {\n config.inboundBlockConfirmations = defaultConfig.inboundBlockConfirmations;\n }\n\n if (config.relayer == address(0x0)) {\n config.relayer = defaultConfig.relayer;\n }\n\n if (config.outboundProofType == 0) {\n config.outboundProofType = defaultConfig.outboundProofType;\n }\n\n if (config.outboundBlockConfirmations == 0) {\n config.outboundBlockConfirmations = defaultConfig.outboundBlockConfirmations;\n }\n\n if (config.oracle == address(0x0)) {\n config.oracle = defaultConfig.oracle;\n }\n\n return config;\n }\n\n function setConfig(\n uint16 _remoteChainId,\n address _ua,\n uint _configType,\n bytes calldata _config\n ) external override onlyEndpoint {\n ApplicationConfiguration storage uaConfig = appConfig[_ua][_remoteChainId];\n if (_configType == CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION) {\n uint16 inboundProofLibraryVersion = abi.decode(_config, (uint16));\n require(\n inboundProofLibraryVersion <= maxInboundProofLibrary[_remoteChainId],\n \"LayerZero: invalid inbound proof library version\"\n );\n uaConfig.inboundProofLibraryVersion = inboundProofLibraryVersion;\n } else if (_configType == CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS) {\n uint64 blockConfirmations = abi.decode(_config, (uint64));\n uaConfig.inboundBlockConfirmations = blockConfirmations;\n } else if (_configType == CONFIG_TYPE_RELAYER) {\n address relayer = abi.decode(_config, (address));\n uaConfig.relayer = relayer;\n } else if (_configType == CONFIG_TYPE_OUTBOUND_PROOF_TYPE) {\n uint16 outboundProofType = abi.decode(_config, (uint16));\n require(\n supportedOutboundProof[_remoteChainId][outboundProofType] || outboundProofType == 0,\n \"LayerZero: invalid outbound proof type\"\n );\n uaConfig.outboundProofType = outboundProofType;\n } else if (_configType == CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS) {\n uint64 blockConfirmations = abi.decode(_config, (uint64));\n uaConfig.outboundBlockConfirmations = blockConfirmations;\n } else if (_configType == CONFIG_TYPE_ORACLE) {\n address oracle = abi.decode(_config, (address));\n uaConfig.oracle = oracle;\n } else {\n revert(\"LayerZero: Invalid config type\");\n }\n\n emit AppConfigUpdated(_ua, _configType, _config);\n }\n\n function getConfig(\n uint16 _remoteChainId,\n address _ua,\n uint _configType\n ) external view override returns (bytes memory) {\n ApplicationConfiguration storage uaConfig = appConfig[_ua][_remoteChainId];\n\n if (_configType == CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION) {\n if (uaConfig.inboundProofLibraryVersion == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].inboundProofLibraryVersion);\n }\n return abi.encode(uaConfig.inboundProofLibraryVersion);\n } else if (_configType == CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS) {\n if (uaConfig.inboundBlockConfirmations == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].inboundBlockConfirmations);\n }\n return abi.encode(uaConfig.inboundBlockConfirmations);\n } else if (_configType == CONFIG_TYPE_RELAYER) {\n if (uaConfig.relayer == address(0x0)) {\n return abi.encode(defaultAppConfig[_remoteChainId].relayer);\n }\n return abi.encode(uaConfig.relayer);\n } else if (_configType == CONFIG_TYPE_OUTBOUND_PROOF_TYPE) {\n if (uaConfig.outboundProofType == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].outboundProofType);\n }\n return abi.encode(uaConfig.outboundProofType);\n } else if (_configType == CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS) {\n if (uaConfig.outboundBlockConfirmations == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].outboundBlockConfirmations);\n }\n return abi.encode(uaConfig.outboundBlockConfirmations);\n } else if (_configType == CONFIG_TYPE_ORACLE) {\n if (uaConfig.oracle == address(0x0)) {\n return abi.encode(defaultAppConfig[_remoteChainId].oracle);\n }\n return abi.encode(uaConfig.oracle);\n } else {\n revert(\"LayerZero: Invalid config type\");\n }\n }\n\n // returns the native fee the UA pays to cover fees\n function estimateFees(\n uint16 _dstChainId,\n address _ua,\n bytes calldata _payload,\n bool _payInZRO,\n bytes calldata _adapterParams\n ) external view override returns (uint nativeFee, uint zroFee) {\n ApplicationConfiguration memory uaConfig = _getAppConfig(_dstChainId, _ua);\n\n // Relayer Fee\n bytes memory adapterParams;\n if (_adapterParams.length > 0) {\n adapterParams = _adapterParams;\n } else {\n adapterParams = defaultAdapterParams[_dstChainId][uaConfig.outboundProofType];\n }\n uint relayerFee = ILayerZeroRelayerV2(uaConfig.relayer).getFee(\n _dstChainId,\n uaConfig.outboundProofType,\n _ua,\n _payload.length,\n adapterParams\n );\n\n // Oracle Fee\n address ua = _ua; // stack too deep\n uint oracleFee = ILayerZeroOracleV2(uaConfig.oracle).getFee(\n _dstChainId,\n uaConfig.outboundProofType,\n uaConfig.outboundBlockConfirmations,\n ua\n );\n\n // LayerZero Fee\n uint protocolFee = treasuryContract.getFees(_payInZRO, relayerFee, oracleFee);\n _payInZRO ? zroFee = protocolFee : nativeFee = protocolFee;\n\n // return the sum of fees\n nativeFee = nativeFee.add(relayerFee).add(oracleFee);\n }\n\n //---------------------------------------------------------------------------\n // Claim Fees\n\n // universal withdraw ZRO token function\n function withdrawZRO(address _to, uint _amount) external override nonReentrant {\n require(msg.sender == address(treasuryContract), \"LayerZero: only treasury\");\n treasuryZROFees = treasuryZROFees.sub(_amount);\n layerZeroToken.safeTransfer(_to, _amount);\n emit WithdrawZRO(msg.sender, _to, _amount);\n }\n\n // universal withdraw native token function.\n // the source contract should perform all the authentication control\n function withdrawNative(address payable _to, uint _amount) external override nonReentrant {\n require(_to != address(0x0), \"LayerZero: _to cannot be zero address\");\n nativeFees[msg.sender] = nativeFees[msg.sender].sub(_amount);\n\n (bool success, ) = _to.call{value: _amount}(\"\");\n require(success, \"LayerZero: withdraw failed\");\n emit WithdrawNative(msg.sender, _to, _amount);\n }\n\n //---------------------------------------------------------------------------\n // Owner calls, configuration only.\n function setLayerZeroToken(address _layerZeroToken) external onlyOwner {\n require(_layerZeroToken != address(0x0), \"LayerZero: _layerZeroToken cannot be zero address\");\n layerZeroToken = IERC20(_layerZeroToken);\n emit SetLayerZeroToken(_layerZeroToken);\n }\n\n function setTreasury(address _treasury) external onlyOwner {\n require(_treasury != address(0x0), \"LayerZero: treasury cannot be zero address\");\n treasuryContract = ILayerZeroTreasury(_treasury);\n emit SetTreasury(_treasury);\n }\n\n function addInboundProofLibraryForChain(uint16 _chainId, address _library) external onlyOwner {\n require(_library != address(0x0), \"LayerZero: library cannot be zero address\");\n uint16 libId = maxInboundProofLibrary[_chainId];\n require(libId < 65535, \"LayerZero: can not add new library\");\n maxInboundProofLibrary[_chainId] = ++libId;\n inboundProofLibrary[_chainId][libId] = _library;\n emit AddInboundProofLibraryForChain(_chainId, _library);\n }\n\n function enableSupportedOutboundProof(uint16 _chainId, uint16 _proofType) external onlyOwner {\n supportedOutboundProof[_chainId][_proofType] = true;\n emit EnableSupportedOutboundProof(_chainId, _proofType);\n }\n\n function setDefaultConfigForChainId(\n uint16 _chainId,\n uint16 _inboundProofLibraryVersion,\n uint64 _inboundBlockConfirmations,\n address _relayer,\n uint16 _outboundProofType,\n uint64 _outboundBlockConfirmations,\n address _oracle\n ) external onlyOwner {\n require(\n _inboundProofLibraryVersion <= maxInboundProofLibrary[_chainId] && _inboundProofLibraryVersion > 0,\n \"LayerZero: invalid inbound proof library version\"\n );\n require(_inboundBlockConfirmations > 0, \"LayerZero: invalid inbound block confirmation\");\n require(_relayer != address(0x0), \"LayerZero: invalid relayer address\");\n require(supportedOutboundProof[_chainId][_outboundProofType], \"LayerZero: invalid outbound proof type\");\n require(_outboundBlockConfirmations > 0, \"LayerZero: invalid outbound block confirmation\");\n require(_oracle != address(0x0), \"LayerZero: invalid oracle address\");\n defaultAppConfig[_chainId] = ApplicationConfiguration(\n _inboundProofLibraryVersion,\n _inboundBlockConfirmations,\n _relayer,\n _outboundProofType,\n _outboundBlockConfirmations,\n _oracle\n );\n emit SetDefaultConfigForChainId(\n _chainId,\n _inboundProofLibraryVersion,\n _inboundBlockConfirmations,\n _relayer,\n _outboundProofType,\n _outboundBlockConfirmations,\n _oracle\n );\n }\n\n function setDefaultAdapterParamsForChainId(\n uint16 _chainId,\n uint16 _proofType,\n bytes calldata _adapterParams\n ) external onlyOwner {\n defaultAdapterParams[_chainId][_proofType] = _adapterParams;\n emit SetDefaultAdapterParamsForChainId(_chainId, _proofType, _adapterParams);\n }\n\n function setRemoteUln(uint16 _remoteChainId, bytes32 _remoteUln) external onlyOwner {\n require(ulnLookup[_remoteChainId] == bytes32(0), \"LayerZero: remote uln already set\");\n ulnLookup[_remoteChainId] = _remoteUln;\n emit SetRemoteUln(_remoteChainId, _remoteUln);\n }\n\n function setChainAddressSize(uint16 _chainId, uint _size) external onlyOwner {\n require(chainAddressSizeMap[_chainId] == 0, \"LayerZero: remote chain address size already set\");\n chainAddressSizeMap[_chainId] = _size;\n emit SetChainAddressSize(_chainId, _size);\n }\n\n //----------------------------------------------------------------------------------\n // view functions\n\n function accruedNativeFee(address _address) external view override returns (uint) {\n return nativeFees[_address];\n }\n\n function getOutboundNonce(uint16 _chainId, bytes calldata _path) external view override returns (uint64) {\n return nonceContract.outboundNonce(_chainId, _path);\n }\n\n function _isContract(address addr) internal view returns (bool) {\n uint size;\n assembly {\n size := extcodesize(addr)\n }\n return size != 0;\n }\n}\n"
|
|
274
|
+
},
|
|
275
|
+
"contracts/UltraLightNodeV2Radar.sol": {
|
|
276
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.7.6;\npragma abicoder v2;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./interfaces/ILayerZeroValidationLibrary.sol\";\nimport \"./interfaces/ILayerZeroReceiver.sol\";\nimport \"./interfaces/ILayerZeroTreasury.sol\";\nimport \"./interfaces/ILayerZeroEndpoint.sol\";\n// v2\nimport \"./interfaces/ILayerZeroMessagingLibraryV2.sol\";\nimport \"./interfaces/ILayerZeroOracleV2.sol\";\nimport \"./interfaces/ILayerZeroUltraLightNodeV2.sol\";\nimport \"./interfaces/ILayerZeroRelayerV2.sol\";\nimport \"./NonceContractRadar.sol\";\n\ncontract UltraLightNodeV2Radar is ILayerZeroMessagingLibraryV2, ILayerZeroUltraLightNodeV2, ReentrancyGuard, Ownable {\n using SafeERC20 for IERC20;\n using SafeMath for uint;\n\n // Application config\n uint public constant CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION = 1;\n uint public constant CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS = 2;\n uint public constant CONFIG_TYPE_RELAYER = 3;\n uint public constant CONFIG_TYPE_OUTBOUND_PROOF_TYPE = 4;\n uint public constant CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS = 5;\n uint public constant CONFIG_TYPE_ORACLE = 6;\n\n // Token and Contracts\n IERC20 public layerZeroToken;\n ILayerZeroTreasury public treasuryContract;\n\n mapping(address => uint) public nativeFees;\n uint public treasuryZROFees;\n\n // User Application\n mapping(address => mapping(uint16 => ApplicationConfiguration)) public appConfig; // app address => chainId => config\n mapping(uint16 => ApplicationConfiguration) public defaultAppConfig; // default UA settings if no version specified\n mapping(uint16 => mapping(uint16 => bytes)) public defaultAdapterParams;\n\n // Validation\n mapping(uint16 => mapping(uint16 => address)) public inboundProofLibrary; // chainId => library Id => inboundProofLibrary contract\n mapping(uint16 => uint16) public maxInboundProofLibrary; // chainId => inboundProofLibrary\n mapping(uint16 => mapping(uint16 => bool)) public supportedOutboundProof; // chainId => outboundProofType => enabled\n mapping(uint16 => uint) public chainAddressSizeMap;\n mapping(address => mapping(uint16 => mapping(bytes32 => mapping(bytes32 => uint)))) public hashLookup; //[oracle][srcChainId][blockhash][datahash] -> confirmation\n mapping(uint16 => bytes32) public ulnLookup; // remote ulns\n\n ILayerZeroEndpoint public immutable endpoint;\n uint16 public immutable localChainId;\n NonceContractRadar public immutable nonceContract;\n\n constructor(address _endpoint, address _nonceContract, uint16 _localChainId, address _dappRadar) {\n require(_endpoint != address(0x0), \"LayerZero: endpoint cannot be zero address\");\n require(_nonceContract != address(0x0), \"LayerZero: nonceContract cannot be zero address\");\n ILayerZeroEndpoint lzEndpoint = ILayerZeroEndpoint(_endpoint);\n localChainId = _localChainId;\n endpoint = lzEndpoint;\n nonceContract = NonceContractRadar(_nonceContract);\n\n // dappRadar\n dappRadar = _dappRadar;\n }\n\n // only the endpoint can call SEND() and setConfig()\n modifier onlyEndpoint() {\n require(address(endpoint) == msg.sender, \"LayerZero: only endpoint\");\n _;\n }\n\n // Manual for DappRadar handling. This contract is dappRadar-only (send/receive)\n // 1. Layerzero deploys UltraLightNodeV2Radar and NonceContractRadar using old chain ID with the local dappRadar address in constructor\n // 2. Dapp Radar sets the messaging library to UltraLightNodeV2Radar\n // 3. Dapp Radar sets the trustedRemote to the full path\n // 4. Layerzero initializes the outboundNonce (1 call) and inboundNonce (batch call)\n // 5. Test message flows\n //\n // 6. after an agree-upon period of time, decommission this contract (one-way trip).\n\n //\n // DappRadar constructs\n //\n address public immutable dappRadar;\n bool public decommissioned;\n mapping(uint16 => bool) public outboundNonceSet;\n mapping(address => uint64) public inboundNonceCap;\n\n // only dappRadar\n function initRadarOutboundNonce(uint16 _dstChainId, address _dstRadarAddress) external onlyOwner {\n // can only inherit the outbound nonce from previous path once\n // assuming dappRadar has only 1 remote peer at a destination chain.\n require(!outboundNonceSet[_dstChainId], \"LayerZero: dappRadar nonce already set\");\n uint64 inheritedNonce = endpoint.getOutboundNonce(_dstChainId, dappRadar);\n outboundNonceSet[_dstChainId] = true;\n\n // can only set the path owned by the dappRadar\n // dappRadar is only deployed on EVM chains so the address is 20 bytes for all\n bytes memory radarPath = abi.encodePacked(_dstRadarAddress, dappRadar); //// remote + local\n\n // insert into the nonce contract\n nonceContract.initRadarOutboundNonce(_dstChainId, radarPath, inheritedNonce);\n }\n\n // generate a message from the new dappRadar-owned path with now payload\n // dappRadar needs to first change the trustedRemote\n // messages will fail locally in the nonBlockingLzApp from the nonce checking\n // can only increment the nonce till we hit the legacy nonce\n function incrementRadarInboundNonce(\n uint16 _srcChainId,\n address _srcRadarAddress,\n uint _gasLimitPerCall,\n uint _steps\n ) external onlyOwner {\n // initialize the inboundNonceCap, only once\n if (inboundNonceCap[_srcRadarAddress] == 0) {\n // check if the _srcRadarAddress is a legacy address by checking the nonce\n uint64 inheritNonce = endpoint.getInboundNonce(_srcChainId, abi.encodePacked(_srcRadarAddress));\n require(inheritNonce > 0, \"LayerZero: not legacy radar address\");\n\n inboundNonceCap[_srcRadarAddress] = inheritNonce;\n }\n\n // can only set the path owned by the dappRadar\n // dappRadar is only deployed on EVM chains so the address is 20 bytes for all\n bytes memory radarPath = abi.encodePacked(_srcRadarAddress, dappRadar); // remote + local\n uint64 radarPathNonce = endpoint.getInboundNonce(_srcChainId, radarPath);\n uint64 nonceCap = inboundNonceCap[_srcRadarAddress];\n\n for (uint i = 0; i < _steps; i++) {\n // ensure that the nonce of the new path is not already at the cap\n radarPathNonce++;\n if (radarPathNonce > nonceCap) {\n break;\n }\n // receive the message with null Payload\n endpoint.receivePayload(_srcChainId, radarPath, dappRadar, radarPathNonce, _gasLimitPerCall, bytes(\"\"));\n }\n }\n\n // this contract will only serve for a period of time\n function decommission() external onlyOwner {\n decommissioned = true;\n }\n\n //----------------------------------------------------------------------------------\n // PROTOCOL\n function validateTransactionProof(\n uint16 _srcChainId,\n address _dstAddress,\n uint _gasLimit,\n bytes32 _lookupHash,\n bytes32 _blockData,\n bytes calldata _transactionProof\n ) external override {\n require(_dstAddress == dappRadar, \"LayerZero: only dappRadar\");\n require(!decommissioned, \"LayerZero: decommissioned\");\n\n // retrieve UA's configuration using the _dstAddress from arguments.\n ApplicationConfiguration memory uaConfig = _getAppConfig(_srcChainId, _dstAddress);\n\n // assert that the caller == UA's relayer\n require(uaConfig.relayer == msg.sender, \"LayerZero: invalid relayer\");\n\n LayerZeroPacket.Packet memory _packet;\n uint remoteAddressSize = chainAddressSizeMap[_srcChainId];\n require(remoteAddressSize != 0, \"LayerZero: incorrect remote address size\");\n {\n // assert that the data submitted by UA's oracle have no fewer confirmations than UA's configuration\n uint storedConfirmations = hashLookup[uaConfig.oracle][_srcChainId][_lookupHash][_blockData];\n require(\n storedConfirmations > 0 && storedConfirmations >= uaConfig.inboundBlockConfirmations,\n \"LayerZero: not enough block confirmations\"\n );\n\n // decode\n address inboundProofLib = inboundProofLibrary[_srcChainId][uaConfig.inboundProofLibraryVersion];\n _packet = ILayerZeroValidationLibrary(inboundProofLib).validateProof(\n _blockData,\n _transactionProof,\n remoteAddressSize\n );\n }\n\n // packet content assertion\n require(\n ulnLookup[_srcChainId] == _packet.ulnAddress && _packet.ulnAddress != bytes32(0),\n \"LayerZero: invalid _packet.ulnAddress\"\n );\n require(_packet.srcChainId == _srcChainId, \"LayerZero: invalid srcChain Id\");\n // failsafe because the remoteAddress size being passed into validateProof trims the address this should not hit\n require(_packet.srcAddress.length == remoteAddressSize, \"LayerZero: invalid srcAddress size\");\n require(_packet.dstChainId == localChainId, \"LayerZero: invalid dstChain Id\");\n require(_packet.dstAddress == _dstAddress, \"LayerZero: invalid dstAddress\");\n\n // if the dst is not a contract, then emit and return early. This will break inbound nonces, but this particular\n // path is already broken and wont ever be able to deliver anyways\n if (!_isContract(_dstAddress)) {\n emit InvalidDst(\n _packet.srcChainId,\n _packet.srcAddress,\n _packet.dstAddress,\n _packet.nonce,\n keccak256(_packet.payload)\n );\n return;\n }\n\n bytes memory pathData = abi.encodePacked(_packet.srcAddress, _packet.dstAddress);\n emit PacketReceived(\n _packet.srcChainId,\n _packet.srcAddress,\n _packet.dstAddress,\n _packet.nonce,\n keccak256(_packet.payload)\n );\n endpoint.receivePayload(_srcChainId, pathData, _dstAddress, _packet.nonce, _gasLimit, _packet.payload);\n }\n\n function send(\n address _ua,\n uint64,\n uint16 _dstChainId,\n bytes calldata _path,\n bytes calldata _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable override onlyEndpoint {\n require(_ua == dappRadar, \"LayerZero: only dappRadar\");\n require(!decommissioned, \"LayerZero: decommissioned\");\n\n address ua = _ua;\n uint16 dstChainId = _dstChainId;\n require(ulnLookup[dstChainId] != bytes32(0), \"LayerZero: dstChainId does not exist\");\n\n bytes memory dstAddress;\n uint64 nonce;\n // code block for solving 'Stack Too Deep'\n {\n uint chainAddressSize = chainAddressSizeMap[dstChainId];\n // path = remoteAddress + localAddress\n require(\n chainAddressSize != 0 && _path.length == 20 + chainAddressSize,\n \"LayerZero: incorrect remote address size\"\n );\n address srcInPath;\n bytes memory path = _path; // copy to memory\n assembly {\n srcInPath := mload(add(add(path, 20), chainAddressSize)) // chainAddressSize + 20\n }\n require(ua == srcInPath, \"LayerZero: wrong path data\");\n dstAddress = _path[0:chainAddressSize];\n nonce = nonceContract.increment(dstChainId, ua, path);\n }\n\n bytes memory payload = _payload;\n ApplicationConfiguration memory uaConfig = _getAppConfig(dstChainId, ua);\n\n // compute all the fees\n uint relayerFee = _handleRelayer(dstChainId, uaConfig, ua, payload.length, _adapterParams);\n uint oracleFee = _handleOracle(dstChainId, uaConfig, ua);\n uint nativeProtocolFee = _handleProtocolFee(relayerFee, oracleFee, ua, _zroPaymentAddress);\n\n // total native fee, does not include ZRO protocol fee\n uint totalNativeFee = relayerFee.add(oracleFee).add(nativeProtocolFee);\n\n // assert the user has attached enough native token for this address\n require(totalNativeFee <= msg.value, \"LayerZero: not enough native for fees\");\n // refund if they send too much\n uint amount = msg.value.sub(totalNativeFee);\n if (amount > 0) {\n (bool success, ) = _refundAddress.call{value: amount}(\"\");\n require(success, \"LayerZero: failed to refund\");\n }\n\n // emit the data packet\n bytes memory encodedPayload = abi.encodePacked(nonce, localChainId, ua, dstChainId, dstAddress, payload);\n emit Packet(encodedPayload);\n }\n\n function _handleRelayer(\n uint16 _dstChainId,\n ApplicationConfiguration memory _uaConfig,\n address _ua,\n uint _payloadSize,\n bytes memory _adapterParams\n ) internal returns (uint relayerFee) {\n if (_adapterParams.length == 0) {\n _adapterParams = defaultAdapterParams[_dstChainId][_uaConfig.outboundProofType];\n }\n address relayerAddress = _uaConfig.relayer;\n ILayerZeroRelayerV2 relayer = ILayerZeroRelayerV2(relayerAddress);\n relayerFee = relayer.assignJob(_dstChainId, _uaConfig.outboundProofType, _ua, _payloadSize, _adapterParams);\n\n _creditNativeFee(relayerAddress, relayerFee);\n\n // emit the param events\n emit RelayerParams(_adapterParams, _uaConfig.outboundProofType);\n }\n\n function _handleOracle(\n uint16 _dstChainId,\n ApplicationConfiguration memory _uaConfig,\n address _ua\n ) internal returns (uint oracleFee) {\n address oracleAddress = _uaConfig.oracle;\n oracleFee = ILayerZeroOracleV2(oracleAddress).assignJob(\n _dstChainId,\n _uaConfig.outboundProofType,\n _uaConfig.outboundBlockConfirmations,\n _ua\n );\n\n _creditNativeFee(oracleAddress, oracleFee);\n }\n\n function _handleProtocolFee(\n uint _relayerFee,\n uint _oracleFee,\n address _ua,\n address _zroPaymentAddress\n ) internal returns (uint protocolNativeFee) {\n // if no ZRO token or not specifying a payment address, pay in native token\n bool payInNative = _zroPaymentAddress == address(0x0) || address(layerZeroToken) == address(0x0);\n uint protocolFee = treasuryContract.getFees(!payInNative, _relayerFee, _oracleFee);\n\n if (protocolFee > 0) {\n if (payInNative) {\n address treasuryAddress = address(treasuryContract);\n _creditNativeFee(treasuryAddress, protocolFee);\n protocolNativeFee = protocolFee;\n } else {\n // zro payment address must equal the ua or the tx.origin otherwise the transaction reverts\n require(\n _zroPaymentAddress == _ua || _zroPaymentAddress == tx.origin,\n \"LayerZero: must be paid by sender or origin\"\n );\n\n // transfer the LayerZero token to this contract from the payee\n layerZeroToken.safeTransferFrom(_zroPaymentAddress, address(this), protocolFee);\n\n treasuryZROFees = treasuryZROFees.add(protocolFee);\n }\n }\n }\n\n function _creditNativeFee(address _receiver, uint _amount) internal {\n nativeFees[_receiver] = nativeFees[_receiver].add(_amount);\n }\n\n // Can be called by any address to update a block header\n // can only upload new block data or the same block data with more confirmations\n function updateHash(\n uint16 _srcChainId,\n bytes32 _lookupHash,\n uint _confirmations,\n bytes32 _blockData\n ) external override {\n uint storedConfirmations = hashLookup[msg.sender][_srcChainId][_lookupHash][_blockData];\n\n // if it has a record, requires a larger confirmation.\n require(\n storedConfirmations < _confirmations,\n \"LayerZero: oracle data can only update if it has more confirmations\"\n );\n\n // set the new information into storage\n hashLookup[msg.sender][_srcChainId][_lookupHash][_blockData] = _confirmations;\n\n emit HashReceived(_srcChainId, msg.sender, _lookupHash, _blockData, _confirmations);\n }\n\n //----------------------------------------------------------------------------------\n // Other Library Interfaces\n\n // default to DEFAULT setting if ZERO value\n function getAppConfig(\n uint16 _remoteChainId,\n address _ua\n ) external view override returns (ApplicationConfiguration memory) {\n return _getAppConfig(_remoteChainId, _ua);\n }\n\n function _getAppConfig(uint16 _remoteChainId, address _ua) internal view returns (ApplicationConfiguration memory) {\n ApplicationConfiguration memory config = appConfig[_ua][_remoteChainId];\n ApplicationConfiguration storage defaultConfig = defaultAppConfig[_remoteChainId];\n\n if (config.inboundProofLibraryVersion == 0) {\n config.inboundProofLibraryVersion = defaultConfig.inboundProofLibraryVersion;\n }\n\n if (config.inboundBlockConfirmations == 0) {\n config.inboundBlockConfirmations = defaultConfig.inboundBlockConfirmations;\n }\n\n if (config.relayer == address(0x0)) {\n config.relayer = defaultConfig.relayer;\n }\n\n if (config.outboundProofType == 0) {\n config.outboundProofType = defaultConfig.outboundProofType;\n }\n\n if (config.outboundBlockConfirmations == 0) {\n config.outboundBlockConfirmations = defaultConfig.outboundBlockConfirmations;\n }\n\n if (config.oracle == address(0x0)) {\n config.oracle = defaultConfig.oracle;\n }\n\n return config;\n }\n\n function setConfig(\n uint16 _remoteChainId,\n address _ua,\n uint _configType,\n bytes calldata _config\n ) external override onlyEndpoint {\n ApplicationConfiguration storage uaConfig = appConfig[_ua][_remoteChainId];\n if (_configType == CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION) {\n uint16 inboundProofLibraryVersion = abi.decode(_config, (uint16));\n require(\n inboundProofLibraryVersion <= maxInboundProofLibrary[_remoteChainId],\n \"LayerZero: invalid inbound proof library version\"\n );\n uaConfig.inboundProofLibraryVersion = inboundProofLibraryVersion;\n } else if (_configType == CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS) {\n uint64 blockConfirmations = abi.decode(_config, (uint64));\n uaConfig.inboundBlockConfirmations = blockConfirmations;\n } else if (_configType == CONFIG_TYPE_RELAYER) {\n address relayer = abi.decode(_config, (address));\n uaConfig.relayer = relayer;\n } else if (_configType == CONFIG_TYPE_OUTBOUND_PROOF_TYPE) {\n uint16 outboundProofType = abi.decode(_config, (uint16));\n require(\n supportedOutboundProof[_remoteChainId][outboundProofType] || outboundProofType == 0,\n \"LayerZero: invalid outbound proof type\"\n );\n uaConfig.outboundProofType = outboundProofType;\n } else if (_configType == CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS) {\n uint64 blockConfirmations = abi.decode(_config, (uint64));\n uaConfig.outboundBlockConfirmations = blockConfirmations;\n } else if (_configType == CONFIG_TYPE_ORACLE) {\n address oracle = abi.decode(_config, (address));\n uaConfig.oracle = oracle;\n } else {\n revert(\"LayerZero: Invalid config type\");\n }\n\n emit AppConfigUpdated(_ua, _configType, _config);\n }\n\n function getConfig(\n uint16 _remoteChainId,\n address _ua,\n uint _configType\n ) external view override returns (bytes memory) {\n ApplicationConfiguration storage uaConfig = appConfig[_ua][_remoteChainId];\n\n if (_configType == CONFIG_TYPE_INBOUND_PROOF_LIBRARY_VERSION) {\n if (uaConfig.inboundProofLibraryVersion == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].inboundProofLibraryVersion);\n }\n return abi.encode(uaConfig.inboundProofLibraryVersion);\n } else if (_configType == CONFIG_TYPE_INBOUND_BLOCK_CONFIRMATIONS) {\n if (uaConfig.inboundBlockConfirmations == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].inboundBlockConfirmations);\n }\n return abi.encode(uaConfig.inboundBlockConfirmations);\n } else if (_configType == CONFIG_TYPE_RELAYER) {\n if (uaConfig.relayer == address(0x0)) {\n return abi.encode(defaultAppConfig[_remoteChainId].relayer);\n }\n return abi.encode(uaConfig.relayer);\n } else if (_configType == CONFIG_TYPE_OUTBOUND_PROOF_TYPE) {\n if (uaConfig.outboundProofType == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].outboundProofType);\n }\n return abi.encode(uaConfig.outboundProofType);\n } else if (_configType == CONFIG_TYPE_OUTBOUND_BLOCK_CONFIRMATIONS) {\n if (uaConfig.outboundBlockConfirmations == 0) {\n return abi.encode(defaultAppConfig[_remoteChainId].outboundBlockConfirmations);\n }\n return abi.encode(uaConfig.outboundBlockConfirmations);\n } else if (_configType == CONFIG_TYPE_ORACLE) {\n if (uaConfig.oracle == address(0x0)) {\n return abi.encode(defaultAppConfig[_remoteChainId].oracle);\n }\n return abi.encode(uaConfig.oracle);\n } else {\n revert(\"LayerZero: Invalid config type\");\n }\n }\n\n // returns the native fee the UA pays to cover fees\n function estimateFees(\n uint16 _dstChainId,\n address _ua,\n bytes calldata _payload,\n bool _payInZRO,\n bytes calldata _adapterParams\n ) external view override returns (uint nativeFee, uint zroFee) {\n ApplicationConfiguration memory uaConfig = _getAppConfig(_dstChainId, _ua);\n\n // Relayer Fee\n bytes memory adapterParams;\n if (_adapterParams.length > 0) {\n adapterParams = _adapterParams;\n } else {\n adapterParams = defaultAdapterParams[_dstChainId][uaConfig.outboundProofType];\n }\n uint relayerFee = ILayerZeroRelayerV2(uaConfig.relayer).getFee(\n _dstChainId,\n uaConfig.outboundProofType,\n _ua,\n _payload.length,\n adapterParams\n );\n\n // Oracle Fee\n address ua = _ua; // stack too deep\n uint oracleFee = ILayerZeroOracleV2(uaConfig.oracle).getFee(\n _dstChainId,\n uaConfig.outboundProofType,\n uaConfig.outboundBlockConfirmations,\n ua\n );\n\n // LayerZero Fee\n uint protocolFee = treasuryContract.getFees(_payInZRO, relayerFee, oracleFee);\n _payInZRO ? zroFee = protocolFee : nativeFee = protocolFee;\n\n // return the sum of fees\n nativeFee = nativeFee.add(relayerFee).add(oracleFee);\n }\n\n //---------------------------------------------------------------------------\n // Claim Fees\n\n // universal withdraw ZRO token function\n function withdrawZRO(address _to, uint _amount) external override nonReentrant {\n require(msg.sender == address(treasuryContract), \"LayerZero: only treasury\");\n treasuryZROFees = treasuryZROFees.sub(_amount);\n layerZeroToken.safeTransfer(_to, _amount);\n emit WithdrawZRO(msg.sender, _to, _amount);\n }\n\n // universal withdraw native token function.\n // the source contract should perform all the authentication control\n function withdrawNative(address payable _to, uint _amount) external override nonReentrant {\n require(_to != address(0x0), \"LayerZero: _to cannot be zero address\");\n nativeFees[msg.sender] = nativeFees[msg.sender].sub(_amount);\n\n (bool success, ) = _to.call{value: _amount}(\"\");\n require(success, \"LayerZero: withdraw failed\");\n emit WithdrawNative(msg.sender, _to, _amount);\n }\n\n //---------------------------------------------------------------------------\n // Owner calls, configuration only.\n function setLayerZeroToken(address _layerZeroToken) external onlyOwner {\n require(_layerZeroToken != address(0x0), \"LayerZero: _layerZeroToken cannot be zero address\");\n layerZeroToken = IERC20(_layerZeroToken);\n emit SetLayerZeroToken(_layerZeroToken);\n }\n\n function setTreasury(address _treasury) external onlyOwner {\n require(_treasury != address(0x0), \"LayerZero: treasury cannot be zero address\");\n treasuryContract = ILayerZeroTreasury(_treasury);\n emit SetTreasury(_treasury);\n }\n\n function addInboundProofLibraryForChain(uint16 _chainId, address _library) external onlyOwner {\n require(_library != address(0x0), \"LayerZero: library cannot be zero address\");\n uint16 libId = maxInboundProofLibrary[_chainId];\n require(libId < 65535, \"LayerZero: can not add new library\");\n maxInboundProofLibrary[_chainId] = ++libId;\n inboundProofLibrary[_chainId][libId] = _library;\n emit AddInboundProofLibraryForChain(_chainId, _library);\n }\n\n function enableSupportedOutboundProof(uint16 _chainId, uint16 _proofType) external onlyOwner {\n supportedOutboundProof[_chainId][_proofType] = true;\n emit EnableSupportedOutboundProof(_chainId, _proofType);\n }\n\n function setDefaultConfigForChainId(\n uint16 _chainId,\n uint16 _inboundProofLibraryVersion,\n uint64 _inboundBlockConfirmations,\n address _relayer,\n uint16 _outboundProofType,\n uint64 _outboundBlockConfirmations,\n address _oracle\n ) external onlyOwner {\n require(\n _inboundProofLibraryVersion <= maxInboundProofLibrary[_chainId] && _inboundProofLibraryVersion > 0,\n \"LayerZero: invalid inbound proof library version\"\n );\n require(_inboundBlockConfirmations > 0, \"LayerZero: invalid inbound block confirmation\");\n require(_relayer != address(0x0), \"LayerZero: invalid relayer address\");\n require(supportedOutboundProof[_chainId][_outboundProofType], \"LayerZero: invalid outbound proof type\");\n require(_outboundBlockConfirmations > 0, \"LayerZero: invalid outbound block confirmation\");\n require(_oracle != address(0x0), \"LayerZero: invalid oracle address\");\n defaultAppConfig[_chainId] = ApplicationConfiguration(\n _inboundProofLibraryVersion,\n _inboundBlockConfirmations,\n _relayer,\n _outboundProofType,\n _outboundBlockConfirmations,\n _oracle\n );\n emit SetDefaultConfigForChainId(\n _chainId,\n _inboundProofLibraryVersion,\n _inboundBlockConfirmations,\n _relayer,\n _outboundProofType,\n _outboundBlockConfirmations,\n _oracle\n );\n }\n\n function setDefaultAdapterParamsForChainId(\n uint16 _chainId,\n uint16 _proofType,\n bytes calldata _adapterParams\n ) external onlyOwner {\n defaultAdapterParams[_chainId][_proofType] = _adapterParams;\n emit SetDefaultAdapterParamsForChainId(_chainId, _proofType, _adapterParams);\n }\n\n function setRemoteUln(uint16 _remoteChainId, bytes32 _remoteUln) external onlyOwner {\n require(ulnLookup[_remoteChainId] == bytes32(0), \"LayerZero: remote uln already set\");\n ulnLookup[_remoteChainId] = _remoteUln;\n emit SetRemoteUln(_remoteChainId, _remoteUln);\n }\n\n function setChainAddressSize(uint16 _chainId, uint _size) external onlyOwner {\n require(chainAddressSizeMap[_chainId] == 0, \"LayerZero: remote chain address size already set\");\n chainAddressSizeMap[_chainId] = _size;\n emit SetChainAddressSize(_chainId, _size);\n }\n\n //----------------------------------------------------------------------------------\n // view functions\n\n function accruedNativeFee(address _address) external view override returns (uint) {\n return nativeFees[_address];\n }\n\n function getOutboundNonce(uint16 _chainId, bytes calldata _path) external view override returns (uint64) {\n return nonceContract.outboundNonce(_chainId, _path);\n }\n\n function _isContract(address addr) internal view returns (bool) {\n uint size;\n assembly {\n size := extcodesize(addr)\n }\n return size != 0;\n }\n}\n"
|
|
277
|
+
},
|
|
278
|
+
"hardhat-deploy/solc_0.7/proxy/Proxied.sol": {
|
|
279
|
+
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.7.0;\n\nabstract contract Proxied {\n /// @notice to be used by initialisation / postUpgrade function so that only the proxy's admin can execute them\n /// It also allows these functions to be called inside a contructor\n /// even if the contract is meant to be used without proxy\n modifier proxied() {\n address proxyAdminAddress = _proxyAdmin();\n // With hardhat-deploy proxies\n // the proxyAdminAddress is zero only for the implementation contract\n // if the implementation contract want to be used as a standalone/immutable contract\n // it simply has to execute the `proxied` function\n // This ensure the proxyAdminAddress is never zero post deployment\n // And allow you to keep the same code for both proxied contract and immutable contract\n if (proxyAdminAddress == address(0)) {\n // ensure can not be called twice when used outside of proxy : no admin\n // solhint-disable-next-line security/no-inline-assembly\n assembly {\n sstore(\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103,\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n )\n }\n } else {\n require(msg.sender == proxyAdminAddress);\n }\n _;\n }\n\n modifier onlyProxyAdmin() {\n require(msg.sender == _proxyAdmin(), \"NOT_AUTHORIZED\");\n _;\n }\n\n function _proxyAdmin() internal view returns (address ownerAddress) {\n // solhint-disable-next-line security/no-inline-assembly\n assembly {\n ownerAddress := sload(0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103)\n }\n }\n}\n"
|
|
280
|
+
},
|
|
281
|
+
"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
|
|
282
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n"
|
|
283
|
+
},
|
|
284
|
+
"@openzeppelin/contracts/interfaces/draft-IERC1822.sol": {
|
|
285
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n"
|
|
286
|
+
},
|
|
287
|
+
"@openzeppelin/contracts/interfaces/IERC1967.sol": {
|
|
288
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967 {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n"
|
|
289
|
+
},
|
|
290
|
+
"@openzeppelin/contracts/proxy/beacon/IBeacon.sol": {
|
|
291
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n"
|
|
292
|
+
},
|
|
293
|
+
"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": {
|
|
294
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializing the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n"
|
|
295
|
+
},
|
|
296
|
+
"@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": {
|
|
297
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/IERC1967.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967Upgrade is IERC1967 {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n"
|
|
298
|
+
},
|
|
299
|
+
"@openzeppelin/contracts/security/ReentrancyGuard.sol": {
|
|
300
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n}\n"
|
|
301
|
+
},
|
|
302
|
+
"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
|
|
303
|
+
"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"
|
|
304
|
+
},
|
|
305
|
+
"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
|
|
306
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
|
|
307
|
+
},
|
|
308
|
+
"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
|
|
309
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n }\n}\n"
|
|
310
|
+
},
|
|
311
|
+
"@openzeppelin/contracts/utils/StorageSlot.sol": {
|
|
312
|
+
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n"
|
|
313
|
+
},
|
|
314
|
+
"contracts/mocks/Endpoint_0818.sol": {
|
|
315
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\nimport \"../interfaces/ILayerZeroReceiver.sol\";\nimport \"../interfaces/ILayerZeroEndpoint.sol\";\nimport \"../interfaces/ILayerZeroMessagingLibrary.sol\";\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract Endpoint_0818 is Ownable, ILayerZeroEndpoint {\n uint16 public immutable chainId;\n\n // installed libraries and reserved versions\n uint16 public constant BLOCK_VERSION = 65535;\n uint16 public constant DEFAULT_VERSION = 0;\n uint16 public latestVersion;\n mapping(uint16 => ILayerZeroMessagingLibrary) public libraryLookup; // version -> ILayerZeroEndpointLibrary\n\n // default send/receive libraries\n uint16 public defaultSendVersion;\n uint16 public defaultReceiveVersion;\n ILayerZeroMessagingLibrary public defaultSendLibrary;\n address public defaultReceiveLibraryAddress;\n\n struct LibraryConfig {\n uint16 sendVersion;\n uint16 receiveVersion;\n address receiveLibraryAddress;\n ILayerZeroMessagingLibrary sendLibrary;\n }\n\n struct StoredPayload {\n uint64 payloadLength;\n address dstAddress;\n bytes32 payloadHash;\n }\n\n // user app config = [uaAddress]\n mapping(address => LibraryConfig) public uaConfigLookup;\n // inboundNonce = [srcChainId][srcAddress].\n mapping(uint16 => mapping(bytes => uint64)) public inboundNonce;\n // outboundNonce = [dstChainId][srcAddress].\n mapping(uint16 => mapping(address => uint64)) public outboundNonce;\n // storedPayload = [srcChainId][srcAddress]\n mapping(uint16 => mapping(bytes => StoredPayload)) public storedPayload;\n\n // library versioning events\n event NewLibraryVersionAdded(uint16 version);\n event DefaultSendVersionSet(uint16 version);\n event DefaultReceiveVersionSet(uint16 version);\n event UaSendVersionSet(address ua, uint16 version);\n event UaReceiveVersionSet(address ua, uint16 version);\n event UaForceResumeReceive(uint16 chainId, bytes srcAddress);\n // payload events\n event PayloadCleared(uint16 srcChainId, bytes srcAddress, uint64 nonce, address dstAddress);\n event PayloadStored(\n uint16 srcChainId,\n bytes srcAddress,\n address dstAddress,\n uint64 nonce,\n bytes payload,\n bytes reason\n );\n\n constructor(uint16 _chainId) {\n chainId = _chainId;\n }\n\n //---------------------------------------------------------------------------\n // send and receive nonreentrant lock\n uint8 internal constant _NOT_ENTERED = 1;\n uint8 internal constant _ENTERED = 2;\n uint8 internal _send_entered_state = 1;\n uint8 internal _receive_entered_state = 1;\n\n modifier sendNonReentrant() {\n require(_send_entered_state == _NOT_ENTERED, \"LayerZero: no send reentrancy\");\n _send_entered_state = _ENTERED;\n _;\n _send_entered_state = _NOT_ENTERED;\n }\n modifier receiveNonReentrant() {\n require(_receive_entered_state == _NOT_ENTERED, \"LayerZero: no receive reentrancy\");\n _receive_entered_state = _ENTERED;\n _;\n _receive_entered_state = _NOT_ENTERED;\n }\n\n // BLOCK_VERSION is also a valid version\n modifier validVersion(uint16 _version) {\n require(_version <= latestVersion || _version == BLOCK_VERSION, \"LayerZero: invalid messaging library version\");\n _;\n }\n\n //---------------------------------------------------------------------------\n // User Application Calls - Endpoint Interface\n\n function send(\n uint16 _dstChainId,\n bytes calldata _destination,\n bytes calldata _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable override sendNonReentrant {\n LibraryConfig storage uaConfig = uaConfigLookup[msg.sender];\n uint64 nonce = ++outboundNonce[_dstChainId][msg.sender];\n _getSendLibrary(uaConfig).send{value: msg.value}(\n msg.sender,\n nonce,\n _dstChainId,\n _destination,\n _payload,\n _refundAddress,\n _zroPaymentAddress,\n _adapterParams\n );\n }\n\n //---------------------------------------------------------------------------\n // authenticated Library (msg.sender) Calls to pass through Endpoint to UA (dstAddress)\n function receivePayload(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n address _dstAddress,\n uint64 _nonce,\n uint _gasLimit,\n bytes calldata _payload\n ) external override receiveNonReentrant {\n // assert and increment the nonce. no message shuffling\n require(_nonce == ++inboundNonce[_srcChainId][_srcAddress], \"LayerZero: wrong nonce\");\n\n LibraryConfig storage uaConfig = uaConfigLookup[_dstAddress];\n\n // authentication to prevent cross-version message validation\n // protects against a malicious library from passing arbitrary data\n if (uaConfig.receiveVersion == DEFAULT_VERSION) {\n require(defaultReceiveLibraryAddress == msg.sender, \"LayerZero: invalid default library\");\n } else {\n require(uaConfig.receiveLibraryAddress == msg.sender, \"LayerZero: invalid library\");\n }\n\n // block if any message blocking\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n require(sp.payloadHash == bytes32(0), \"LayerZero: in message blocking\");\n\n try ILayerZeroReceiver(_dstAddress).lzReceive{gas: _gasLimit}(_srcChainId, _srcAddress, _nonce, _payload) {\n // success, do nothing, end of the message delivery\n } catch (bytes memory reason) {\n // revert nonce if any uncaught errors/exceptions if the ua chooses the blocking mode\n storedPayload[_srcChainId][_srcAddress] = StoredPayload(\n uint64(_payload.length),\n _dstAddress,\n keccak256(_payload)\n );\n emit PayloadStored(_srcChainId, _srcAddress, _dstAddress, _nonce, _payload, reason);\n }\n }\n\n function retryPayload(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n bytes calldata _payload\n ) external override receiveNonReentrant {\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n require(sp.payloadHash != bytes32(0), \"LayerZero: no stored payload\");\n require(\n _payload.length == sp.payloadLength && keccak256(_payload) == sp.payloadHash,\n \"LayerZero: invalid payload\"\n );\n\n address dstAddress = sp.dstAddress;\n // empty the storedPayload\n sp.payloadLength = 0;\n sp.dstAddress = address(0);\n sp.payloadHash = bytes32(0);\n\n uint64 nonce = inboundNonce[_srcChainId][_srcAddress];\n\n ILayerZeroReceiver(dstAddress).lzReceive(_srcChainId, _srcAddress, nonce, _payload);\n emit PayloadCleared(_srcChainId, _srcAddress, nonce, dstAddress);\n }\n\n //---------------------------------------------------------------------------\n // Owner Calls, only new library version upgrade (3 steps)\n\n // note libraryLookup[0] = 0x0, no library implementation\n // LIBRARY UPGRADE step 1: set _newLayerZeroLibraryAddress be the new version\n function newVersion(address _newLayerZeroLibraryAddress) external onlyOwner {\n require(_newLayerZeroLibraryAddress != address(0x0), \"LayerZero: new version cannot be zero address\");\n require(latestVersion < 65535, \"LayerZero: can not add new messaging library\");\n latestVersion++;\n libraryLookup[latestVersion] = ILayerZeroMessagingLibrary(_newLayerZeroLibraryAddress);\n emit NewLibraryVersionAdded(latestVersion);\n }\n\n // LIBRARY UPGRADE step 2: stop sending messages from the old version\n function setDefaultSendVersion(\n uint16 _newDefaultSendVersion\n ) external onlyOwner validVersion(_newDefaultSendVersion) {\n require(_newDefaultSendVersion != DEFAULT_VERSION, \"LayerZero: default send version must > 0\");\n defaultSendVersion = _newDefaultSendVersion;\n defaultSendLibrary = libraryLookup[defaultSendVersion];\n emit DefaultSendVersionSet(_newDefaultSendVersion);\n }\n\n // LIBRARY UPGRADE step 3: stop receiving messages from the old version\n function setDefaultReceiveVersion(\n uint16 _newDefaultReceiveVersion\n ) external onlyOwner validVersion(_newDefaultReceiveVersion) {\n require(_newDefaultReceiveVersion != DEFAULT_VERSION, \"LayerZero: default receive version must > 0\");\n defaultReceiveVersion = _newDefaultReceiveVersion;\n defaultReceiveLibraryAddress = address(libraryLookup[defaultReceiveVersion]);\n emit DefaultReceiveVersionSet(_newDefaultReceiveVersion);\n }\n\n //---------------------------------------------------------------------------\n // User Application Calls - UA set/get Interface\n\n function setConfig(\n uint16 _version,\n uint16 _chainId,\n uint _configType,\n bytes calldata _config\n ) external override validVersion(_version) {\n if (_version == DEFAULT_VERSION) {\n require(\n defaultSendVersion == defaultReceiveVersion,\n \"LayerZero: can not set Config during DEFAULT migration\"\n );\n _version = defaultSendVersion;\n }\n require(_version != BLOCK_VERSION, \"LayerZero: can not set config for BLOCK_VERSION\");\n libraryLookup[_version].setConfig(_chainId, msg.sender, _configType, _config);\n }\n\n // Migration step 1: set the send version\n // Define what library the UA points too\n function setSendVersion(uint16 _newVersion) external override validVersion(_newVersion) {\n // write into config\n LibraryConfig storage uaConfig = uaConfigLookup[msg.sender];\n uaConfig.sendVersion = _newVersion;\n // the libraryLookup[BLOCK_VERSION || DEFAULT_VERSION] = 0x0\n uaConfig.sendLibrary = libraryLookup[_newVersion];\n emit UaSendVersionSet(msg.sender, _newVersion);\n }\n\n // Migration step 2: set the receive version\n // after all messages sent from the old version are received\n // the UA can now safely switch to the new receive version\n // it is the UA's responsibility make sure all messages from the old version are processed\n function setReceiveVersion(uint16 _newVersion) external override validVersion(_newVersion) {\n // write into config\n LibraryConfig storage uaConfig = uaConfigLookup[msg.sender];\n uaConfig.receiveVersion = _newVersion;\n // the libraryLookup[BLOCK_VERSION || DEFAULT_VERSION] = 0x0\n uaConfig.receiveLibraryAddress = address(libraryLookup[_newVersion]);\n emit UaReceiveVersionSet(msg.sender, _newVersion);\n }\n\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override {\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n // revert if no messages are cached. safeguard malicious UA behaviour\n require(sp.payloadHash != bytes32(0), \"LayerZero: no stored payload\");\n require(sp.dstAddress == msg.sender, \"LayerZero: invalid caller\");\n\n // empty the storedPayload\n sp.payloadLength = 0;\n sp.dstAddress = address(0);\n sp.payloadHash = bytes32(0);\n\n // emit the event with the new nonce\n emit UaForceResumeReceive(_srcChainId, _srcAddress);\n }\n\n //---------------------------------------------------------------------------\n // view helper function\n\n function estimateFees(\n uint16 _dstChainId,\n address _userApplication,\n bytes calldata _payload,\n bool _payInZRO,\n bytes calldata _adapterParams\n ) external view override returns (uint nativeFee, uint zroFee) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n ILayerZeroMessagingLibrary lib = uaConfig.sendVersion == DEFAULT_VERSION\n ? defaultSendLibrary\n : uaConfig.sendLibrary;\n return lib.estimateFees(_dstChainId, _userApplication, _payload, _payInZRO, _adapterParams);\n }\n\n function _getSendLibrary(LibraryConfig storage uaConfig) internal view returns (ILayerZeroMessagingLibrary) {\n if (uaConfig.sendVersion == DEFAULT_VERSION) {\n // check if the in send-blocking upgrade\n require(defaultSendVersion != BLOCK_VERSION, \"LayerZero: default in BLOCK_VERSION\");\n return defaultSendLibrary;\n } else {\n // check if the in send-blocking upgrade\n require(uaConfig.sendVersion != BLOCK_VERSION, \"LayerZero: in BLOCK_VERSION\");\n return uaConfig.sendLibrary;\n }\n }\n\n function getSendLibraryAddress(\n address _userApplication\n ) external view override returns (address sendLibraryAddress) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n uint16 sendVersion = uaConfig.sendVersion;\n require(sendVersion != BLOCK_VERSION, \"LayerZero: send version is BLOCK_VERSION\");\n if (sendVersion == DEFAULT_VERSION) {\n require(defaultSendVersion != BLOCK_VERSION, \"LayerZero: send version (default) is BLOCK_VERSION\");\n sendLibraryAddress = address(defaultSendLibrary);\n } else {\n sendLibraryAddress = address(uaConfig.sendLibrary);\n }\n }\n\n function getReceiveLibraryAddress(\n address _userApplication\n ) external view override returns (address receiveLibraryAddress) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n uint16 receiveVersion = uaConfig.receiveVersion;\n require(receiveVersion != BLOCK_VERSION, \"LayerZero: receive version is BLOCK_VERSION\");\n if (receiveVersion == DEFAULT_VERSION) {\n require(defaultReceiveVersion != BLOCK_VERSION, \"LayerZero: receive version (default) is BLOCK_VERSION\");\n receiveLibraryAddress = defaultReceiveLibraryAddress;\n } else {\n receiveLibraryAddress = uaConfig.receiveLibraryAddress;\n }\n }\n\n function isSendingPayload() external view override returns (bool) {\n return _send_entered_state == _ENTERED;\n }\n\n function isReceivingPayload() external view override returns (bool) {\n return _receive_entered_state == _ENTERED;\n }\n\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view override returns (uint64) {\n return inboundNonce[_srcChainId][_srcAddress];\n }\n\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view override returns (uint64) {\n return outboundNonce[_dstChainId][_srcAddress];\n }\n\n function getChainId() external view override returns (uint16) {\n return chainId;\n }\n\n function getSendVersion(address _userApplication) external view override returns (uint16) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n return uaConfig.sendVersion == DEFAULT_VERSION ? defaultSendVersion : uaConfig.sendVersion;\n }\n\n function getReceiveVersion(address _userApplication) external view override returns (uint16) {\n LibraryConfig storage uaConfig = uaConfigLookup[_userApplication];\n return uaConfig.receiveVersion == DEFAULT_VERSION ? defaultReceiveVersion : uaConfig.receiveVersion;\n }\n\n function getConfig(\n uint16 _version,\n uint16 _chainId,\n address _userApplication,\n uint _configType\n ) external view override validVersion(_version) returns (bytes memory) {\n if (_version == DEFAULT_VERSION) {\n require(defaultSendVersion == defaultReceiveVersion, \"LayerZero: no DEFAULT config while migration\");\n _version = defaultSendVersion;\n }\n require(_version != BLOCK_VERSION, \"LayerZero: can not get config for BLOCK_VERSION\");\n return libraryLookup[_version].getConfig(_chainId, _userApplication, _configType);\n }\n\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view override returns (bool) {\n StoredPayload storage sp = storedPayload[_srcChainId][_srcAddress];\n return sp.payloadHash != bytes32(0);\n }\n}\n"
|
|
316
|
+
},
|
|
317
|
+
"contracts/oracle/OracleV2.sol": {
|
|
318
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"hardhat-deploy/solc_0.8/proxy/Proxied.sol\";\n\nimport \"../interfaces/ILayerZeroOracleV2.sol\";\nimport \"../interfaces/ILayerZeroUltraLightNodeV2.sol\";\nimport \"../interfaces/ILayerZeroPriceFeed.sol\";\n\ncontract OracleV2 is ILayerZeroOracleV2, ReentrancyGuard, OwnableUpgradeable, Proxied {\n using SafeERC20 for IERC20;\n\n ILayerZeroUltraLightNodeV2 public uln;\n uint16 public threshold;\n uint16 public committeeSize;\n\n struct DstPrice {\n uint128 dstPriceRatio; // 10^10\n uint128 dstGasPriceInWei;\n }\n\n struct ProposedBlock {\n uint16 approvalCount;\n bool submitted;\n mapping(address => bool) approvedBy;\n }\n\n mapping(address => bool) public admins; // sets pricing\n mapping(address => bool) public validators; // submit and validates lookup hash and confirmations\n mapping(address => bool) public whitelist; // to call notify oracle\n\n mapping(uint16 => DstPrice) public dstPriceLookupOld;\n // [_chainId][_outboundProofType]\n mapping(uint16 => mapping(uint16 => uint64)) public dstGasLookup;\n\n //proposalLookup[_srcChainId][_lookupHash][_confirmations][_data];\n mapping(uint16 => mapping(bytes32 => mapping(uint => mapping(bytes32 => ProposedBlock)))) public proposalLookup; //chainId => lookupHash => confirmations\n\n event AdminUpdated(address _addr, bool _active);\n event ValidatorUpdated(address _addr, bool _active);\n event WhitelistUpdated(address _addr, bool _active);\n event ThresholdUpdated(uint16 _threshold);\n event ValidatedBlock(\n address indexed validator,\n uint16 srcChainId,\n bytes32 lookupHash,\n uint confirmations,\n bytes32 data\n );\n event AssignJob(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n uint _outboundBlockConfirmations,\n address _userApplication,\n uint _fee\n );\n event SetDstPrice(uint16 _chainId, uint128 _dstPriceRatio, uint128 _dstGasPriceInWei);\n event SetDstGas(uint16 _chainId, uint16 _outboundProofType, uint64 _gas);\n\n // Update for Price Feed\n ILayerZeroPriceFeed public priceFeed;\n // multiplier\n uint128 public multiplierBps;\n\n // PriceFeedContract Upgrade\n uint16 public validateBlockBytes; // funcSigHash + params -> 4 + (32 * 4)\n\n // MultiSigOracle Upgrade\n event UpdateAdmin(address _addr, bool _active);\n event SetUln(address _addr, bool _active);\n event Execute(address _target, bytes32 _callDataHash, bool _success, bytes _data);\n event UpdatePriceFeed(address _priceFeed);\n event UpdatePriceMultiplierBps(uint128 _multiplierBps);\n mapping(address => bool) public ulns; // to call assignJob\n mapping(bytes32 => bool) public usedHashes;\n uint16 public executeFixedBytes; // encoded: funcSigHash + params -> 4 + (32 * 2)\n uint16 public signatureRawBytes; // not encoded\n // callData(updateHash) = 132 (4 + 32 * 4), padded to 32 = 160 and encoded as bytes with an 64 byte overhead = 224\n uint16 public updateHashBytes;\n bool public useMso;\n\n // MultiSig\n mapping(address => bool) public signers;\n uint64 public signerSize;\n uint64 public quorum;\n\n event UpdateSigner(address _signer, bool _active);\n event UpdateQuorum(uint64 _quorum);\n\n // AccessControl\n mapping(address => bool) public allowlist;\n mapping(address => bool) public denylist;\n uint64 public allowlistSize;\n\n event UpdateAllowlist(address _addr, bool _active);\n event UpdateDenylist(address _addr, bool _active);\n\n // ============================ Constructor ====================================\n\n function initialize(address _uln, address _priceFeed) public proxied initializer {\n __Ownable_init();\n uln = ILayerZeroUltraLightNodeV2(_uln);\n multiplierBps = 12000;\n priceFeed = ILayerZeroPriceFeed(_priceFeed);\n validateBlockBytes = 132;\n\n // should not ever deploy a new one\n revert(\"Oracle: upgrade only\");\n }\n\n function onUpgrade(\n address _uln,\n address _priceFeed,\n address[] memory _signers,\n uint64 _quorum,\n address[] memory _admins\n ) public proxied {\n multiplierBps = 12000;\n priceFeed = ILayerZeroPriceFeed(_priceFeed);\n validateBlockBytes = 132;\n\n // MultiSigOracle upgrade\n // Constructor of MultiSig\n require(_signers.length >= _quorum && _quorum > 0, \"MultiSig: signers too few \");\n // MultSigOracle fixed bytes for quoting\n executeFixedBytes = 68;\n signatureRawBytes = 65;\n updateHashBytes = 224;\n\n address lastSigner = address(0);\n for (uint i = 0; i < _signers.length; i++) {\n address signer = _signers[i];\n require(signer > lastSigner, \"MultiSig: signers not sorted\"); // to ensure no duplicates\n signers[signer] = true;\n lastSigner = signer;\n }\n signerSize = uint64(_signers.length);\n quorum = _quorum;\n\n // Constructor of MultiSigOracle\n ulns[_uln] = true;\n for (uint i = 0; i < _admins.length; i++) {\n admins[_admins[i]] = true;\n }\n\n useMso = true;\n }\n\n // ============================ Modifier ====================================\n\n // owner is always approved\n modifier onlyAdmin() {\n if (owner() != msg.sender) {\n require(admins[msg.sender], \"Oracle: not admin \");\n }\n _;\n }\n\n modifier onlyValidator() {\n require(validators[msg.sender], \"Oracle: not validator\");\n _;\n }\n\n // uln is always approved\n modifier onlyWhitelist() {\n if (address(uln) != msg.sender) {\n require(whitelist[msg.sender], \"Oracle: not in whitelist\");\n }\n _;\n }\n\n modifier onlySelf() {\n require(address(this) == msg.sender, \"MultiSigOracle: caller must be self\");\n _;\n }\n\n // ============================ onlyWhitelist =====================================\n\n function assignJob(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n uint64 _outboundBlockConfirmation,\n address _userApplication\n ) external override returns (uint fee) {\n if (useMso) {\n require(ulns[msg.sender], \"MultiSigOracle: caller must be uln\");\n fee = _getFee(_dstChainId, _outboundProofType, _outboundBlockConfirmation, _userApplication);\n emit AssignJob(_dstChainId, _outboundProofType, _outboundBlockConfirmation, _userApplication, fee);\n } else {\n if (address(uln) != msg.sender) {\n require(whitelist[msg.sender], \"Oracle: not in whitelist\");\n }\n fee = _getFee(_dstChainId, _outboundProofType, _outboundBlockConfirmation, _userApplication);\n emit AssignJob(_dstChainId, _outboundProofType, _outboundBlockConfirmation, _userApplication, fee);\n }\n fee;\n }\n\n // ============================ onlySelf =====================================\n\n function setSigner(address _signer, bool _active) external onlySelf {\n _revertIfOracle();\n _setSigner(_signer, _active);\n }\n\n function setQuorum(uint64 _quorum) external onlySelf {\n _revertIfOracle();\n _setQuorum(_quorum);\n }\n\n function setAllowlist(address _userApplication, bool _allowed) external onlySelf {\n _revertIfOracle();\n _setAllowlist(_userApplication, _allowed);\n }\n\n function setDenylist(address _userApplication, bool _denied) external onlySelf {\n _revertIfOracle();\n _setDenylist(_userApplication, _denied);\n }\n\n function setUln(address _uln, bool _active) external onlySelf {\n _revertIfOracle();\n require(ulns[_uln] != _active, \"MultiSigOracle: uln already in that state\");\n ulns[_uln] = _active;\n emit SetUln(_uln, _active);\n }\n\n // ============================ OnlyOwner =====================================\n\n function setValidator(address _addr, bool _active) external onlyOwner {\n _revertIfMso();\n require(validators[_addr] != _active, \"Oracle: validator already in that state\");\n validators[_addr] = _active;\n if (_active) {\n committeeSize++;\n } else {\n committeeSize--;\n }\n require(committeeSize >= threshold, \"Oracle: committee size < threshold\");\n emit ValidatorUpdated(_addr, _active);\n }\n\n function setWhitelist(address _addr, bool _active) external onlyOwner {\n _revertIfMso();\n whitelist[_addr] = _active;\n emit WhitelistUpdated(_addr, _active);\n }\n\n function setThreshold(uint16 _threshold) external onlyOwner {\n _revertIfMso();\n require(_threshold <= committeeSize, \"Oracle: threshold > committee size\");\n threshold = _threshold;\n emit ThresholdUpdated(_threshold);\n }\n\n // ============================ External =======================================\n\n function isApproved(address _address) public view returns (bool) {\n _revertIfMso();\n return _address == address(this);\n }\n\n // ============================ OnlyAdmin =====================================\n\n // signer can call this function to:\n // 1. submit a block data to ULN\n // 2. change configuration of this oracle\n // 3. withdraw fee from ULN\n function execute(\n address _target,\n bytes calldata _callData,\n uint _expiration,\n bytes calldata _signatures\n ) external onlyAdmin {\n _revertIfOracle();\n require(ulns[_target] || _target == address(this), \"MultiSigOracle: target must be uln or self\");\n require(_expiration > block.timestamp, \"MultiSigOracle: call data expired\");\n\n // generate and validate hash\n bytes32 hash = hashCallData(_target, _callData, _expiration);\n require(!usedHashes[hash], \"MultiSigOracle: call data already executed\");\n usedHashes[hash] = true; // prevent reentry and replay attack\n\n // check signatures\n verifySignatures(hash, _signatures);\n\n // execute call data\n (bool success, bytes memory rtnData) = _target.call(_callData);\n emit Execute(_target, hash, success, rtnData);\n }\n\n function setDstPrice(uint16 _dstChainId, uint128 _dstPriceRatio, uint128 _dstGasPriceInWei) external onlyAdmin {\n // Old no longer used. Should set price in PriceFeed contract.\n }\n\n function setPriceFeed(address _priceFeed) external onlyAdmin {\n priceFeed = ILayerZeroPriceFeed(_priceFeed);\n emit UpdatePriceFeed(_priceFeed);\n }\n\n function setPriceMultiplierBps(uint128 _multiplierBps) external onlyAdmin {\n multiplierBps = _multiplierBps;\n emit UpdatePriceMultiplierBps(_multiplierBps);\n }\n\n function setDstGas(uint16 _dstChainId, uint16 _proofType, uint64 _gas) external onlyAdmin {\n dstGasLookup[_dstChainId][_proofType] = _gas;\n emit SetDstGas(_dstChainId, _proofType, _gas);\n }\n\n function withdrawFee(address payable _to, uint _amount) external override onlyAdmin {\n _revertIfMso();\n uln.withdrawNative(_to, _amount);\n }\n\n function withdrawToken(address _token, address _to, uint _amount) external onlyAdmin {\n IERC20(_token).safeTransfer(_to, _amount);\n }\n\n function withdrawFeeFromUlnV2Like(address _uln, address payable _to, uint _amount) external onlyAdmin {\n _revertIfOracle();\n require(ulns[_uln], \"MultiSigOracle: _uln is not allowed\");\n ILayerZeroUltraLightNodeV2(_uln).withdrawNative(_to, _amount);\n }\n\n function setUseMso(bool _useMso) external onlyAdmin {\n useMso = _useMso;\n }\n\n function setAdmin(address _admin, bool _active) external onlyAdmin {\n if (useMso) {\n require(admins[_admin] != _active, \"MultiSigOracle: admin already in that state\");\n admins[_admin] = _active;\n emit UpdateAdmin(_admin, _active);\n } else {\n admins[_admin] = _active;\n emit AdminUpdated(_admin, _active);\n }\n }\n\n // ============================ OnlyValidator =====================================\n\n function validateBlock(\n uint16 _srcChainId,\n bytes32 _lookupHash,\n uint _confirmations,\n bytes32 _data\n ) external onlyValidator {\n _revertIfMso();\n ProposedBlock storage pb = proposalLookup[_srcChainId][_lookupHash][_confirmations][_data];\n require(!pb.submitted, \"Oracle: already submitted\");\n require(!pb.approvedBy[msg.sender], \"Oracle: already approved block\");\n uint16 approvalCount = pb.approvalCount;\n if (approvalCount + 1 == threshold) {\n // just submit it, not need to store locally to save gas\n uln.updateHash(_srcChainId, _lookupHash, _confirmations, _data);\n // only write this field to save gas. no need to write dta and approvalCount\n pb.submitted = true;\n } else {\n // update records\n pb.approvedBy[msg.sender] = true;\n pb.approvalCount = approvalCount + 1;\n }\n emit ValidatedBlock(msg.sender, _srcChainId, _lookupHash, _confirmations, _data);\n }\n\n // ============================ View Functions =======================================\n\n function getFee(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n uint64 _outboundBlockConfirmation,\n address _userApplication\n ) external view override returns (uint) {\n return _getFee(_dstChainId, _outboundProofType, _outboundBlockConfirmation, _userApplication);\n }\n\n function hashCallData(address _target, bytes calldata _callData, uint _expiration) public pure returns (bytes32) {\n return keccak256(abi.encodePacked(_target, _expiration, _callData));\n }\n\n // ============================ Internal =======================================\n\n function _revertIfMso() internal view {\n if (useMso) {\n revert(\"MultiSigOracle: deprecated\");\n }\n }\n\n function _revertIfOracle() internal view {\n if (!useMso) {\n revert(\"Oracle: not implemented\");\n }\n }\n\n function _getFee(\n uint16 _dstChainId,\n uint16 _outboundProofType,\n uint64,\n address _userApplication\n ) internal view returns (uint) {\n if (useMso) {\n require(checkPermission(_userApplication), \"MultiSigOracle: _userApplication is not allowed\");\n\n uint dstGas = dstGasLookup[_dstChainId][_outboundProofType];\n\n uint totalSignatureBytes = uint(quorum) * signatureRawBytes;\n uint totalSignatureBytesPadded = totalSignatureBytes;\n if (totalSignatureBytes % 32 != 0) {\n totalSignatureBytesPadded = totalSignatureBytes - (totalSignatureBytes % 32) + 32;\n }\n // getFee should charge on execute(updateHash)\n // totalSignatureBytesPadded also has 64 overhead for bytes\n uint callDataSize = uint(executeFixedBytes) + updateHashBytes + totalSignatureBytesPadded + 64;\n uint16 dstChainId = _dstChainId; // stack too deep\n (uint fee, ) = priceFeed.estimateFeeByChain(dstChainId, callDataSize, dstGas);\n return (fee * multiplierBps) / 10000;\n } else {\n uint64 dstGas = dstGasLookup[_dstChainId][_outboundProofType];\n\n // callDataSize = 4 + 32 * 4 (all params are fixed bytes32)\n (uint fee, ) = priceFeed.estimateFeeByChain(_dstChainId, validateBlockBytes, dstGas);\n return (fee * threshold * multiplierBps) / 10000;\n }\n }\n\n // submit to uln\n function isBlockHashUpdated(\n uint16 _srcChainId,\n bytes32 _lookupHash,\n uint _confirmations,\n bytes32 _data\n ) external view returns (bool) {\n _revertIfMso();\n ProposedBlock storage pb = proposalLookup[_srcChainId][_lookupHash][_confirmations][_data];\n return pb.submitted;\n }\n\n function isBlockValidated(\n uint16 _srcChainId,\n bytes32 _lookupHash,\n uint _confirmations,\n bytes32 _data,\n address _addr\n ) external view returns (bool) {\n _revertIfMso();\n ProposedBlock storage pb = proposalLookup[_srcChainId][_lookupHash][_confirmations][_data];\n // if the pb has been submitted, consider it validated anyway. because a submission will fail.\n if (pb.submitted) return true;\n return pb.approvedBy[_addr];\n }\n\n function committeeStatus() external view returns (uint16, uint16) {\n _revertIfMso();\n return (committeeSize, threshold);\n }\n\n // view function to convert pricefeed price to current price (for backwards compatibility)\n function dstPriceLookup(uint16 _dstChainId) public view returns (DstPrice memory) {\n ILayerZeroPriceFeed.Price memory price = priceFeed.getPrice(_dstChainId);\n return DstPrice(price.priceRatio, price.gasPriceInUnit);\n }\n\n // ============================ MultiSig Functions =======================================\n\n function _setSigner(address _signer, bool _active) internal {\n require(signers[_signer] != _active, \"MultiSig: signer already in that state\");\n signers[_signer] = _active;\n signerSize = _active ? signerSize + 1 : signerSize - 1;\n require(signerSize >= quorum, \"MultiSig: committee size < threshold\");\n emit UpdateSigner(_signer, _active);\n }\n\n function _setQuorum(uint64 _quorum) internal {\n require(_quorum <= signerSize && _quorum > 0, \"MultiSig: invalid quorum\");\n quorum = _quorum;\n emit UpdateQuorum(_quorum);\n }\n\n function verifySignatures(bytes32 _hash, bytes calldata _signatures) public view {\n require(_signatures.length >= uint(quorum) * 65, \"MultiSig: signatures too short\");\n\n bytes32 messageDigest = _getEthSignedMessageHash(_hash);\n\n address lastSigner = address(0); // There cannot be a signer with address 0.\n for (uint i = 0; i < quorum; i++) {\n (uint8 v, bytes32 r, bytes32 s) = _splitSignature(_signatures, i);\n address currentSigner = ecrecover(messageDigest, v, r, s);\n\n require(currentSigner > lastSigner, \"MultiSig: signatures must be in ascending order\"); // prevent duplicate signatures\n require(signers[currentSigner], \"MultiSig: signature is not from a signer\");\n lastSigner = currentSigner;\n }\n }\n\n /// divides bytes signature into `uint8 v, bytes32 r, bytes32 s`.\n function _splitSignature(\n bytes memory _signatures,\n uint256 _pos\n ) internal pure returns (uint8 v, bytes32 r, bytes32 s) {\n // The signature format is a compact form of:\n // {bytes32 r}{bytes32 s}{uint8 v}\n // Compact means, uint8 is not padded to 32 bytes.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let signaturePos := mul(0x41, _pos)\n r := mload(add(_signatures, add(signaturePos, 0x20)))\n s := mload(add(_signatures, add(signaturePos, 0x40)))\n // Here we are loading the last 32 bytes, including 31 bytes\n // of 's'. There is no 'mload8' to do this.\n //\n // 'byte' is not working due to the Solidity parser, so lets\n // use the second best option, 'and'\n v := and(mload(add(_signatures, add(signaturePos, 0x41))), 0xff)\n }\n }\n\n function _getEthSignedMessageHash(bytes32 _messageHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", _messageHash));\n }\n\n // ============================ AccessControl Functions =======================================\n function _setAllowlist(address _addr, bool _allowed) internal {\n require(allowlist[_addr] != _allowed, \"AccessControl: address already in that state\");\n allowlist[_addr] = _allowed;\n allowlistSize = _allowed ? allowlistSize + 1 : allowlistSize - 1;\n emit UpdateAllowlist(_addr, _allowed);\n }\n\n function _setDenylist(address _addr, bool _denied) internal {\n require(denylist[_addr] != _denied, \"AccessControl: address already in that state\");\n denylist[_addr] = _denied;\n emit UpdateDenylist(_addr, _denied);\n }\n\n /// 1) If one address is in the deny list, it is denied\n /// 2) If the allow list is empty and not in the deny list, it is allowed\n /// 3) If one address is in the allow list and not in the deny list, it is allowed\n /// 4) If the allow list is not empty and the address is not in the allow list, it is denied\n function checkPermission(address _address) public view returns (bool) {\n if (denylist[_address]) {\n return false;\n } else if (allowlist[_address]) {\n return true;\n } else if (allowlistSize > 0) {\n return false;\n } else {\n return true;\n }\n }\n}\n"
|
|
319
|
+
},
|
|
320
|
+
"contracts/proxy/ProxyAdmin.sol": {
|
|
321
|
+
"content": "// SPDX-License-Identifier: BUSL-1.1\n\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./TransparentUpgradeableProxy.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n constructor(address initialOwner) {\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n TransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n"
|
|
322
|
+
},
|
|
323
|
+
"hardhat-deploy/solc_0.8/proxy/Proxied.sol": {
|
|
324
|
+
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nabstract contract Proxied {\n /// @notice to be used by initialisation / postUpgrade function so that only the proxy's admin can execute them\n /// It also allows these functions to be called inside a contructor\n /// even if the contract is meant to be used without proxy\n modifier proxied() {\n address proxyAdminAddress = _proxyAdmin();\n // With hardhat-deploy proxies\n // the proxyAdminAddress is zero only for the implementation contract\n // if the implementation contract want to be used as a standalone/immutable contract\n // it simply has to execute the `proxied` function\n // This ensure the proxyAdminAddress is never zero post deployment\n // And allow you to keep the same code for both proxied contract and immutable contract\n if (proxyAdminAddress == address(0)) {\n // ensure can not be called twice when used outside of proxy : no admin\n // solhint-disable-next-line security/no-inline-assembly\n assembly {\n sstore(\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103,\n 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n )\n }\n } else {\n require(msg.sender == proxyAdminAddress);\n }\n _;\n }\n\n modifier onlyProxyAdmin() {\n require(msg.sender == _proxyAdmin(), \"NOT_AUTHORIZED\");\n _;\n }\n\n function _proxyAdmin() internal view returns (address ownerAddress) {\n // solhint-disable-next-line security/no-inline-assembly\n assembly {\n ownerAddress := sload(0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103)\n }\n }\n}\n"
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
"language": "Solidity"
|
|
328
|
+
}
|
|
329
|
+
}
|