LZEndpointMock.sol 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // SPDX-License-Identifier: BUSL-1.1
  2. pragma solidity 0.7.6;
  3. pragma abicoder v2;
  4. import "@layerzerolabs/contracts/contracts/interfaces/ILayerZeroReceiver.sol";
  5. import "@layerzerolabs/contracts/contracts/interfaces/ILayerZeroEndpoint.sol";
  6. import "@layerzerolabs/contracts/contracts/interfaces/ILayerZeroUserApplicationConfig.sol";
  7. /*
  8. mocking multi endpoint connection.
  9. - send() will short circuit to lzReceive() directly
  10. - no reentrancy guard. the real LayerZero endpoint on main net has a send and receive guard, respectively.
  11. if we run a ping-pong-like application, the recursive call might use all gas limit in the block.
  12. - not using any messaging library, hence all messaging library func, e.g. estimateFees, version, will not work
  13. */
  14. contract LZEndpointMock is ILayerZeroEndpoint {
  15. mapping(address => address) public lzEndpointLookup;
  16. uint16 public mockChainId;
  17. address payable public mockOracle;
  18. address payable public mockRelayer;
  19. uint256 public mockBlockConfirmations;
  20. uint16 public mockLibraryVersion;
  21. uint256 public mockStaticNativeFee;
  22. uint16 public mockLayerZeroVersion;
  23. uint16 public mockReceiveVersion;
  24. uint16 public mockSendVersion;
  25. // inboundNonce = [srcChainId][srcAddress].
  26. mapping(uint16 => mapping(bytes => uint64)) public inboundNonce;
  27. // outboundNonce = [dstChainId][srcAddress].
  28. mapping(uint16 => mapping(address => uint64)) public outboundNonce;
  29. event SetConfig(uint16 version, uint16 chainId, uint256 configType, bytes config);
  30. event ForceResumeReceive(uint16 srcChainId, bytes srcAddress);
  31. constructor(uint16 _chainId) {
  32. mockStaticNativeFee = 42;
  33. mockLayerZeroVersion = 1;
  34. mockChainId = _chainId;
  35. }
  36. function getChainId() external view override returns (uint16) {
  37. return mockChainId;
  38. }
  39. function setDestLzEndpoint(address destAddr, address lzEndpointAddr) external {
  40. lzEndpointLookup[destAddr] = lzEndpointAddr;
  41. }
  42. function send(
  43. uint16 _chainId,
  44. bytes calldata _destination,
  45. bytes calldata _payload,
  46. address payable, /*_refundAddress*/
  47. address, /*_zroPaymentAddress*/
  48. bytes memory dstGas
  49. ) external payable override {
  50. address destAddr = packedBytesToAddr(_destination);
  51. address lzEndpoint = lzEndpointLookup[destAddr];
  52. require(lzEndpoint != address(0), "LayerZeroMock: destination LayerZero Endpoint not found");
  53. uint64 nonce;
  54. {
  55. nonce = ++outboundNonce[_chainId][msg.sender];
  56. }
  57. // Mock the relayer paying the dstNativeAddr the amount of extra native token
  58. {
  59. uint256 dstNative;
  60. address dstNativeAddr;
  61. assembly {
  62. dstNative := mload(add(dstGas, 66))
  63. dstNativeAddr := mload(add(dstGas, 86))
  64. }
  65. if (dstNativeAddr == 0x90F79bf6EB2c4f870365E785982E1f101E93b906) {
  66. require(dstNative == 453, "Gas incorrect");
  67. require(1 != 1, "NativeGasParams check");
  68. }
  69. // Doesnt actually transfer the native amount to the other side
  70. }
  71. bytes memory bytesSourceUserApplicationAddr = addrToPackedBytes(address(msg.sender)); // cast this address to bytes
  72. inboundNonce[_chainId][abi.encodePacked(msg.sender)] = nonce;
  73. LZEndpointMock(lzEndpoint).receiveAndForward(destAddr, mockChainId, bytesSourceUserApplicationAddr, nonce, _payload);
  74. }
  75. function receiveAndForward(
  76. address _destAddr,
  77. uint16 _srcChainId,
  78. bytes memory _srcAddress,
  79. uint64 _nonce,
  80. bytes memory _payload
  81. ) external {
  82. ILayerZeroReceiver(_destAddr).lzReceive(_srcChainId, _srcAddress, _nonce, _payload); // invoke lzReceive
  83. }
  84. // override from ILayerZeroEndpoint
  85. function estimateFees(
  86. uint16,
  87. address,
  88. bytes calldata,
  89. bool,
  90. bytes calldata
  91. ) external view override returns (uint256, uint256) {
  92. return (mockStaticNativeFee, 0); // just a mock
  93. }
  94. // give 20 bytes, return the decoded address
  95. function packedBytesToAddr(bytes calldata _b) public pure returns (address) {
  96. address addr;
  97. assembly {
  98. let ptr := mload(0x40)
  99. calldatacopy(ptr, sub(_b.offset, 2), add(_b.length, 2))
  100. addr := mload(sub(ptr, 10))
  101. }
  102. return addr;
  103. }
  104. // given an address, return the 20 bytes
  105. function addrToPackedBytes(address _a) public pure returns (bytes memory) {
  106. bytes memory data = abi.encodePacked(_a);
  107. return data;
  108. }
  109. function setConfig(
  110. uint16 _version,
  111. uint16 _chainId,
  112. uint256 _configType,
  113. bytes memory _config
  114. ) external override {
  115. emit SetConfig(_version, _chainId, _configType, _config);
  116. }
  117. function getConfig(
  118. uint16, /*_version*/
  119. uint16, /*_chainId*/
  120. address, /*_ua*/
  121. uint256 /*_configType*/
  122. ) external pure override returns (bytes memory) {
  123. return "";
  124. }
  125. function receivePayload(
  126. uint16 _srcChainId,
  127. bytes calldata _srcAddress,
  128. address _dstAddress,
  129. uint64 _nonce,
  130. uint256 _gasLimit,
  131. bytes calldata _payload
  132. ) external override {}
  133. function setSendVersion(uint16 _version) external override {
  134. mockSendVersion = _version;
  135. }
  136. function setReceiveVersion(uint16 _version) external override {
  137. mockReceiveVersion = _version;
  138. }
  139. function getSendVersion(
  140. address /*_userApplication*/
  141. ) external pure override returns (uint16) {
  142. return 1;
  143. }
  144. function getReceiveVersion(
  145. address /*_userApplication*/
  146. ) external pure override returns (uint16) {
  147. return 1;
  148. }
  149. function getInboundNonce(uint16 _chainID, bytes calldata _srcAddress) external view override returns (uint64) {
  150. return inboundNonce[_chainID][_srcAddress];
  151. }
  152. function getOutboundNonce(uint16 _chainID, address _srcAddress) external view override returns (uint64) {
  153. return outboundNonce[_chainID][_srcAddress];
  154. }
  155. function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override {
  156. emit ForceResumeReceive(_srcChainId, _srcAddress);
  157. }
  158. function retryPayload(
  159. uint16 _srcChainId,
  160. bytes calldata _srcAddress,
  161. bytes calldata _payload
  162. ) external pure override {}
  163. function hasStoredPayload(uint16 /*_srcChainId*/, bytes calldata /*_srcAddress*/) external pure override returns (bool) {
  164. return true;
  165. }
  166. function isSendingPayload() external pure override returns (bool) {
  167. return false;
  168. }
  169. function isReceivingPayload() external pure override returns (bool) {
  170. return false;
  171. }
  172. function getSendLibraryAddress(address /*_userApplication*/) external view override returns (address) {
  173. return address(this);
  174. }
  175. function getReceiveLibraryAddress(address /*_userApplication*/) external view override returns (address) {
  176. return address(this);
  177. }
  178. }