test.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // This test is intended to be run on devnet without an active eth miner
  2. // see https://github.com/trufflesuite/ganache-cli-archive#custom-methods
  3. const {
  4. NodeHttpTransport,
  5. } = require("@improbable-eng/grpc-web-node-http-transport");
  6. const { ethers } = require("ethers");
  7. const { parseUnits } = require("ethers/lib/utils");
  8. const {
  9. approveEth,
  10. transferFromEth,
  11. CHAIN_ID_BSC,
  12. CHAIN_ID_ETH,
  13. hexToUint8Array,
  14. nativeToHexString,
  15. parseSequenceFromLogEth,
  16. getEmitterAddressEth,
  17. getSignedVAA,
  18. } = require("@certusone/wormhole-sdk");
  19. const { default: axios } = require("axios");
  20. const ETH_NODE_URL = "ws://localhost:8545";
  21. const ETH_PRIVATE_KEY =
  22. "0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d";
  23. const ETH_CORE_BRIDGE_ADDRESS = "0xC89Ce4735882C9F0f0FE26686c53074E09B0D550";
  24. const ETH_TOKEN_BRIDGE_ADDRESS = "0x0290FB167208Af455bB137780163b7B7a9a10C16";
  25. const TEST_ERC20 = "0x2D8BE6BF0baA74e0A907016679CaE9190e80dD0A";
  26. const WORMHOLE_RPC_HOST = "http://localhost:7071";
  27. (async () => {
  28. // create a signer for Eth
  29. const provider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
  30. const signer = new ethers.Wallet(ETH_PRIVATE_KEY, provider);
  31. console.log(`Height ${await provider.getBlockNumber()}`);
  32. // TEST 1 - send with 20 blocks conf
  33. const amount = parseUnits("1", 18);
  34. // approve the bridge to spend tokens
  35. await approveEth(ETH_TOKEN_BRIDGE_ADDRESS, TEST_ERC20, signer, amount);
  36. // transfer tokens
  37. const receipt = await transferFromEth(
  38. ETH_TOKEN_BRIDGE_ADDRESS,
  39. signer,
  40. TEST_ERC20,
  41. amount,
  42. CHAIN_ID_BSC,
  43. hexToUint8Array(
  44. nativeToHexString(await signer.getAddress(), CHAIN_ID_ETH) || ""
  45. )
  46. );
  47. // get the sequence from the logs (needed to fetch the vaa)
  48. const sequence = parseSequenceFromLogEth(receipt, ETH_CORE_BRIDGE_ADDRESS);
  49. const emitterAddress = getEmitterAddressEth(ETH_TOKEN_BRIDGE_ADDRESS);
  50. console.log(`FIRST TX, SEQ ${sequence}`);
  51. for (let i = 1; i <= 20; i++) {
  52. console.log(`Attempt ${i}`);
  53. await axios.post("http://localhost:8545", {
  54. id: 1337,
  55. jsonrpc: "2.0",
  56. method: "evm_mine",
  57. params: [Date.now()],
  58. });
  59. console.log(`Height ${await provider.getBlockNumber()}`);
  60. try {
  61. const { vaaBytes: signedVAA } = await getSignedVAA(
  62. WORMHOLE_RPC_HOST,
  63. CHAIN_ID_ETH,
  64. emitterAddress,
  65. sequence,
  66. {
  67. transport: NodeHttpTransport(),
  68. }
  69. );
  70. console.log(!!signedVAA);
  71. } catch (e) {
  72. console.error(e.message);
  73. }
  74. }
  75. // TEST 2 - send with 1 conf, rollback before tx, 30 confs
  76. const {
  77. data: { result: snapshotId },
  78. } = await axios.post("http://localhost:8545", {
  79. id: 1337,
  80. jsonrpc: "2.0",
  81. method: "evm_snapshot",
  82. params: [],
  83. });
  84. console.log(`SNAPSHOT ${snapshotId}`);
  85. console.log(`Height ${await provider.getBlockNumber()}`);
  86. const amount2 = parseUnits("2", 18);
  87. // approve the bridge to spend tokens
  88. await approveEth(ETH_TOKEN_BRIDGE_ADDRESS, TEST_ERC20, signer, amount2);
  89. // transfer tokens
  90. const receipt2 = await transferFromEth(
  91. ETH_TOKEN_BRIDGE_ADDRESS,
  92. signer,
  93. TEST_ERC20,
  94. amount2,
  95. CHAIN_ID_BSC,
  96. hexToUint8Array(
  97. nativeToHexString(await signer.getAddress(), CHAIN_ID_ETH) || ""
  98. )
  99. );
  100. // get the sequence from the logs (needed to fetch the vaa)
  101. const sequence2 = parseSequenceFromLogEth(receipt2, ETH_CORE_BRIDGE_ADDRESS);
  102. console.log(`SECOND TX, SEQ ${sequence2}`);
  103. console.log(`Attempt 1`);
  104. await axios.post("http://localhost:8545", {
  105. id: 1337,
  106. jsonrpc: "2.0",
  107. method: "evm_mine",
  108. params: [Date.now()],
  109. });
  110. console.log(`Height ${await provider.getBlockNumber()}`);
  111. try {
  112. const { vaaBytes: signedVAA } = await getSignedVAA(
  113. WORMHOLE_RPC_HOST,
  114. CHAIN_ID_ETH,
  115. emitterAddress,
  116. sequence2,
  117. {
  118. transport: NodeHttpTransport(),
  119. }
  120. );
  121. console.log(!!signedVAA);
  122. } catch (e) {
  123. console.error(e.message);
  124. }
  125. console.log(`Rollback 1`);
  126. await axios.post("http://localhost:8545", {
  127. id: 1337,
  128. jsonrpc: "2.0",
  129. method: "evm_revert",
  130. params: [snapshotId],
  131. });
  132. console.log(`Height ${await provider.getBlockNumber()}`);
  133. try {
  134. const { vaaBytes: signedVAA } = await getSignedVAA(
  135. WORMHOLE_RPC_HOST,
  136. CHAIN_ID_ETH,
  137. emitterAddress,
  138. sequence2,
  139. {
  140. transport: NodeHttpTransport(),
  141. }
  142. );
  143. console.log(!!signedVAA);
  144. } catch (e) {
  145. console.error(e.message);
  146. }
  147. for (let i = 1; i <= 30; i++) {
  148. console.log(`Attempt ${i}`);
  149. await axios.post("http://localhost:8545", {
  150. id: 1337,
  151. jsonrpc: "2.0",
  152. method: "evm_mine",
  153. params: [Date.now()],
  154. });
  155. console.log(`Height ${await provider.getBlockNumber()}`);
  156. try {
  157. const { vaaBytes: signedVAA } = await getSignedVAA(
  158. WORMHOLE_RPC_HOST,
  159. CHAIN_ID_ETH,
  160. emitterAddress,
  161. sequence2,
  162. {
  163. transport: NodeHttpTransport(),
  164. }
  165. );
  166. console.log(!!signedVAA);
  167. } catch (e) {
  168. console.error(e.message);
  169. }
  170. }
  171. // TEST 3 - repeat test 1 and verify test 2 is still not found
  172. const amount3 = parseUnits("3", 18);
  173. // approve the bridge to spend tokens
  174. await approveEth(ETH_TOKEN_BRIDGE_ADDRESS, TEST_ERC20, signer, amount3);
  175. // transfer tokens
  176. const receipt3 = await transferFromEth(
  177. ETH_TOKEN_BRIDGE_ADDRESS,
  178. signer,
  179. TEST_ERC20,
  180. amount3,
  181. CHAIN_ID_BSC,
  182. hexToUint8Array(
  183. nativeToHexString(await signer.getAddress(), CHAIN_ID_ETH) || ""
  184. )
  185. );
  186. // get the sequence from the logs (needed to fetch the vaa)
  187. const sequence3 = parseSequenceFromLogEth(receipt3, ETH_CORE_BRIDGE_ADDRESS);
  188. console.log(`FIRST TX, SEQ ${sequence3}`);
  189. for (let i = 1; i <= 20; i++) {
  190. console.log(`Attempt ${i}`);
  191. await axios.post("http://localhost:8545", {
  192. id: 1337,
  193. jsonrpc: "2.0",
  194. method: "evm_mine",
  195. params: [Date.now()],
  196. });
  197. console.log(`Height ${await provider.getBlockNumber()}`);
  198. try {
  199. const { vaaBytes: signedVAA } = await getSignedVAA(
  200. WORMHOLE_RPC_HOST,
  201. CHAIN_ID_ETH,
  202. emitterAddress,
  203. sequence3,
  204. {
  205. transport: NodeHttpTransport(),
  206. }
  207. );
  208. console.log(!!signedVAA);
  209. } catch (e) {
  210. console.error(e.message);
  211. }
  212. }
  213. console.log("Checking SEQ from test 2");
  214. try {
  215. const { vaaBytes: signedVAA } = await getSignedVAA(
  216. WORMHOLE_RPC_HOST,
  217. CHAIN_ID_ETH,
  218. emitterAddress,
  219. sequence2,
  220. {
  221. transport: NodeHttpTransport(),
  222. }
  223. );
  224. console.log(!!signedVAA);
  225. } catch (e) {
  226. console.error(e.message);
  227. }
  228. provider.destroy();
  229. })();