LZEndpointMock.sol 6.8 KB

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