Prechádzať zdrojové kódy

test: accountant e2e contract queries

Kevin Peters 2 rokov pred
rodič
commit
8dcd3f615f

+ 524 - 0
wormchain/contracts/tools/__tests__/test_accountant.ts

@@ -0,0 +1,524 @@
+import "dotenv/config";
+import { describe, expect, jest, test } from "@jest/globals";
+import {
+  approveEth,
+  attestFromEth,
+  CHAIN_ID_BSC,
+  CHAIN_ID_ETH,
+  ChainId,
+  CONTRACTS,
+  createWrappedOnEth,
+  getEmitterAddressEth,
+  getForeignAssetEth,
+  getSignedVAAWithRetry,
+  hexToUint8Array,
+  parseSequenceFromLogEth,
+  parseTokenTransferVaa,
+  redeemOnEth,
+  serialiseVAA,
+  sign,
+  TokenBridgeTransfer,
+  transferFromEth,
+  tryNativeToHexString,
+  tryNativeToUint8Array,
+  uint8ArrayToHex,
+  VAA,
+} from "@certusone/wormhole-sdk";
+import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
+import { ethers } from "ethers";
+import * as devnetConsts from "../devnet-consts.json";
+import { parseUnits } from "ethers/lib/utils";
+import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";
+
+jest.setTimeout(60000);
+
+if (process.env.INIT_SIGNERS_KEYS_CSV === "undefined") {
+  let msg = `.env is missing. run "make contracts-tools-deps" to fetch.`;
+  console.error(msg);
+  throw msg;
+}
+
+/*
+ * Goals:
+ *   1. Ensure a token can be sent from its origin chain
+ *   2. Ensure a token can be sent back from a foreign chain
+ *   3. Ensure spoofed tokens for more than the outstanding amount rejects successfully
+ *   4. Validate the guardian metrics for each of these cases
+ *   5. Bonus: Validate the on chain contract state via queries
+ */
+
+const ci = !!process.env.CI;
+
+const GUARDIAN_HOST = ci ? "guardian" : "localhost";
+const GUARDIAN_RPCS = [`http://${GUARDIAN_HOST}:7071`];
+const GUARDIAN_METRICS = `http://${GUARDIAN_HOST}:6060/metrics`;
+const ETH_NODE_URL = ci ? "ws://eth-devnet:8545" : "ws://localhost:8545";
+const BSC_NODE_URL = ci ? "ws://eth-devnet2:8545" : "ws://localhost:8546";
+const ETH_PRIVATE_KEY9 =
+  "0xb0057716d5917badaf911b193b12b910811c1497b5bada8d7711f758981c3773";
+const ETH_GA_TEST_TOKEN =
+  devnetConsts.chains[CHAIN_ID_ETH].addresses.testGA.address;
+const DECIMALS = devnetConsts.chains[CHAIN_ID_ETH].addresses.testGA.decimals;
+const VAA_SIGNERS = process.env.INIT_SIGNERS_KEYS_CSV.split(",");
+const GOVERNANCE_CHAIN = Number(devnetConsts.global.governanceChainId);
+const GOVERNANCE_EMITTER = devnetConsts.global.governanceEmitterAddress;
+const TENDERMINT_URL = ci ? "http://wormchain:26657" : "http://localhost:26659";
+const GA_ADDRESS =
+  "wormhole14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9srrg465";
+
+function sleep(ms) {
+  return new Promise((resolve) => setTimeout(resolve, ms));
+}
+
+let ethProvider: ethers.providers.WebSocketProvider;
+let ethSigner: ethers.Wallet;
+let bscProvider: ethers.providers.WebSocketProvider;
+let bscSigner: ethers.Wallet;
+let cosmWasmClient: CosmWasmClient;
+
+beforeAll(async () => {
+  // create a signer for Eth
+  ethProvider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
+  ethSigner = new ethers.Wallet(ETH_PRIVATE_KEY9, ethProvider);
+  // create a signer for BSC
+  bscProvider = new ethers.providers.WebSocketProvider(BSC_NODE_URL);
+  bscSigner = new ethers.Wallet(ETH_PRIVATE_KEY9, bscProvider);
+  cosmWasmClient = await CosmWasmClient.connect(TENDERMINT_URL);
+});
+
+afterAll(async () => {
+  await ethProvider.destroy();
+  await bscProvider.destroy();
+  cosmWasmClient.disconnect();
+});
+
+// Guardian metrics are prometheus data
+const fetchGlobalAccountantMetrics = async (): Promise<{
+  global_accountant_connection_errors_total: number;
+  global_accountant_error_events_received: number;
+  global_accountant_events_received: number;
+  global_accountant_submit_failures: number;
+  global_accountant_total_balance_errors: number;
+  global_accountant_total_digest_mismatches: number;
+  global_accountant_transfer_vaas_outstanding: number;
+  global_accountant_transfer_vaas_submitted: number;
+  global_accountant_transfer_vaas_submitted_and_approved: number;
+}> =>
+  (await (await fetch(GUARDIAN_METRICS)).text())
+    .split("\n")
+    .filter((m) => m.startsWith("global_accountant"))
+    .reduce((p, m) => {
+      const [k, v] = m.split(" ");
+      p[k] = Number(v);
+      return p;
+    }, {} as any);
+
+const fetchGlobalAccountantBalance = async (
+  tokenAddress: string,
+  chainId: ChainId,
+  tokenChain: ChainId
+): Promise<BigInt> => {
+  try {
+    return BigInt(
+      await cosmWasmClient.queryContractSmart(GA_ADDRESS, {
+        balance: {
+          token_address: tokenAddress,
+          chain_id: chainId,
+          token_chain: tokenChain,
+        },
+      })
+    );
+  } catch (e) {
+    if (e.message?.includes("accountant::state::account::Balance not found")) {
+      // account not created yet
+      return BigInt(0);
+    }
+    throw e;
+  }
+};
+
+const fetchGlobalAccountantTransferStatus = async (
+  emitterChain: ChainId,
+  emitterAddress: string,
+  sequence: string
+): Promise<any> => {
+  return await cosmWasmClient.queryContractSmart(GA_ADDRESS, {
+    transfer_status: {
+      emitter_chain: emitterChain,
+      emitter_address: emitterAddress,
+      sequence: Number(sequence),
+    },
+  });
+};
+
+describe("Global Accountant Tests", () => {
+  test("Metrics and Contract Queries", async () => {
+    let attestedAddress = "";
+    //
+    // STEP 0 - attest the token
+    //
+    {
+      attestedAddress = await getForeignAssetEth(
+        CONTRACTS.DEVNET.bsc.token_bridge,
+        bscProvider,
+        CHAIN_ID_ETH,
+        tryNativeToUint8Array(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH)
+      );
+      if (attestedAddress && attestedAddress !== ethers.constants.AddressZero) {
+        console.log("already attested");
+      } else {
+        console.log("attesting...");
+        // attest the test token
+        const receipt = await attestFromEth(
+          CONTRACTS.DEVNET.ethereum.token_bridge,
+          ethSigner,
+          ETH_GA_TEST_TOKEN
+        );
+        // get the sequence from the logs (needed to fetch the vaa)
+        const sequence = parseSequenceFromLogEth(
+          receipt,
+          CONTRACTS.DEVNET.ethereum.core
+        );
+        const emitterAddress = getEmitterAddressEth(
+          CONTRACTS.DEVNET.ethereum.token_bridge
+        );
+        console.log(`fetching vaa ${sequence}...`);
+        // poll until the guardian(s) witness and sign the vaa
+        const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
+          GUARDIAN_RPCS,
+          CHAIN_ID_ETH,
+          emitterAddress,
+          sequence,
+          {
+            transport: NodeHttpTransport(),
+          }
+        );
+        console.log("creating...");
+        await createWrappedOnEth(
+          CONTRACTS.DEVNET.bsc.token_bridge,
+          bscSigner,
+          signedVAA
+        );
+        attestedAddress = await getForeignAssetEth(
+          CONTRACTS.DEVNET.bsc.token_bridge,
+          bscProvider,
+          CHAIN_ID_ETH,
+          tryNativeToUint8Array(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH)
+        );
+      }
+    }
+
+    //
+    // STEP 1 - send the token out
+    //
+    {
+      const beforeMetrics = await fetchGlobalAccountantMetrics();
+      const beforeEthBalance = await fetchGlobalAccountantBalance(
+        tryNativeToHexString(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH),
+        CHAIN_ID_ETH,
+        CHAIN_ID_ETH
+      );
+      const beforeBscBalance = await fetchGlobalAccountantBalance(
+        tryNativeToHexString(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH),
+        CHAIN_ID_BSC,
+        CHAIN_ID_ETH
+      );
+      const amount = parseUnits("1", DECIMALS);
+      // approve the bridge to spend tokens
+      console.log("approving...");
+      await approveEth(
+        CONTRACTS.DEVNET.ethereum.token_bridge,
+        ETH_GA_TEST_TOKEN,
+        ethSigner,
+        amount
+      );
+      // transfer tokens out
+      console.log("transferring...");
+      const receipt = await transferFromEth(
+        CONTRACTS.DEVNET.ethereum.token_bridge,
+        ethSigner,
+        ETH_GA_TEST_TOKEN,
+        amount,
+        CHAIN_ID_BSC,
+        tryNativeToUint8Array(await bscSigner.getAddress(), CHAIN_ID_BSC)
+      );
+      // get the sequence from the logs (needed to fetch the vaa)
+      const sequence = parseSequenceFromLogEth(
+        receipt,
+        CONTRACTS.DEVNET.ethereum.core
+      );
+      const emitterAddress = getEmitterAddressEth(
+        CONTRACTS.DEVNET.ethereum.token_bridge
+      );
+      console.log(`fetching vaa ${sequence}...`);
+      // poll until the guardian(s) witness and sign the vaa
+      const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
+        GUARDIAN_RPCS,
+        CHAIN_ID_ETH,
+        emitterAddress,
+        sequence,
+        {
+          transport: NodeHttpTransport(),
+        }
+      );
+      console.log("redeeming...");
+      await redeemOnEth(
+        CONTRACTS.DEVNET.bsc.token_bridge,
+        bscSigner,
+        signedVAA
+      );
+      const afterMetrics = await fetchGlobalAccountantMetrics();
+      console.log(
+        "approved b/a:",
+        beforeMetrics.global_accountant_transfer_vaas_submitted_and_approved,
+        afterMetrics.global_accountant_transfer_vaas_submitted_and_approved
+      );
+      if (
+        afterMetrics.global_accountant_events_received <=
+          beforeMetrics.global_accountant_events_received ||
+        afterMetrics.global_accountant_transfer_vaas_submitted <=
+          beforeMetrics.global_accountant_transfer_vaas_submitted ||
+        afterMetrics.global_accountant_transfer_vaas_submitted_and_approved <=
+          beforeMetrics.global_accountant_transfer_vaas_submitted_and_approved
+      ) {
+        throw new Error("Expected metrics change did not occur");
+      }
+      const parsedVAA = parseTokenTransferVaa(signedVAA);
+      const transferStatus = await fetchGlobalAccountantTransferStatus(
+        CHAIN_ID_ETH,
+        emitterAddress,
+        sequence
+      );
+      expect(transferStatus).toMatchObject({
+        committed: {
+          data: {
+            amount: parsedVAA.amount.toString(),
+            token_chain: CHAIN_ID_ETH,
+            token_address: tryNativeToHexString(
+              ETH_GA_TEST_TOKEN,
+              CHAIN_ID_ETH
+            ),
+            recipient_chain: CHAIN_ID_BSC,
+          },
+        },
+      });
+      const afterEthBalance = await fetchGlobalAccountantBalance(
+        tryNativeToHexString(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH),
+        CHAIN_ID_ETH,
+        CHAIN_ID_ETH
+      );
+      expect(afterEthBalance).toBeGreaterThan(beforeEthBalance.valueOf());
+      const afterBscBalance = await fetchGlobalAccountantBalance(
+        tryNativeToHexString(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH),
+        CHAIN_ID_BSC,
+        CHAIN_ID_ETH
+      );
+      expect(afterBscBalance).toBeGreaterThan(beforeBscBalance.valueOf());
+    }
+
+    //
+    // STEP 2 - send the token back
+    //
+    {
+      const beforeMetrics = await fetchGlobalAccountantMetrics();
+      const beforeEthBalance = await fetchGlobalAccountantBalance(
+        tryNativeToHexString(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH),
+        CHAIN_ID_ETH,
+        CHAIN_ID_ETH
+      );
+      const beforeBscBalance = await fetchGlobalAccountantBalance(
+        tryNativeToHexString(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH),
+        CHAIN_ID_BSC,
+        CHAIN_ID_ETH
+      );
+      const amount = parseUnits("1", DECIMALS);
+      // approve the bridge to spend tokens
+      console.log("approving...");
+      await approveEth(
+        CONTRACTS.DEVNET.bsc.token_bridge,
+        attestedAddress,
+        bscSigner,
+        amount
+      );
+      // transfer tokens out
+      console.log("transferring...");
+      const receipt = await transferFromEth(
+        CONTRACTS.DEVNET.bsc.token_bridge,
+        bscSigner,
+        attestedAddress,
+        amount,
+        CHAIN_ID_ETH,
+        tryNativeToUint8Array(await ethSigner.getAddress(), CHAIN_ID_ETH)
+      );
+      // get the sequence from the logs (needed to fetch the vaa)
+      const sequence = parseSequenceFromLogEth(
+        receipt,
+        CONTRACTS.DEVNET.bsc.core
+      );
+      const emitterAddress = getEmitterAddressEth(
+        CONTRACTS.DEVNET.bsc.token_bridge
+      );
+      console.log(`fetching vaa ${sequence}...`);
+      // poll until the guardian(s) witness and sign the vaa
+      const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
+        GUARDIAN_RPCS,
+        CHAIN_ID_BSC,
+        emitterAddress,
+        sequence,
+        {
+          transport: NodeHttpTransport(),
+        }
+      );
+      console.log("redeeming...");
+      await redeemOnEth(
+        CONTRACTS.DEVNET.ethereum.token_bridge,
+        ethSigner,
+        signedVAA
+      );
+      const afterMetrics = await fetchGlobalAccountantMetrics();
+      console.log(
+        "approved b/a:",
+        beforeMetrics.global_accountant_transfer_vaas_submitted_and_approved,
+        afterMetrics.global_accountant_transfer_vaas_submitted_and_approved
+      );
+      if (
+        afterMetrics.global_accountant_events_received <=
+          beforeMetrics.global_accountant_events_received ||
+        afterMetrics.global_accountant_transfer_vaas_submitted <=
+          beforeMetrics.global_accountant_transfer_vaas_submitted ||
+        afterMetrics.global_accountant_transfer_vaas_submitted_and_approved <=
+          beforeMetrics.global_accountant_transfer_vaas_submitted_and_approved
+      ) {
+        throw new Error("Expected metrics change did not occur");
+      }
+      const parsedVAA = parseTokenTransferVaa(signedVAA);
+      const transferStatus = await fetchGlobalAccountantTransferStatus(
+        CHAIN_ID_BSC,
+        emitterAddress,
+        sequence
+      );
+      expect(transferStatus).toMatchObject({
+        committed: {
+          data: {
+            amount: parsedVAA.amount.toString(),
+            token_chain: CHAIN_ID_ETH,
+            token_address: tryNativeToHexString(
+              ETH_GA_TEST_TOKEN,
+              CHAIN_ID_ETH
+            ),
+            recipient_chain: CHAIN_ID_ETH,
+          },
+        },
+      });
+      const afterEthBalance = await fetchGlobalAccountantBalance(
+        tryNativeToHexString(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH),
+        CHAIN_ID_ETH,
+        CHAIN_ID_ETH
+      );
+      expect(afterEthBalance).toBeLessThan(beforeEthBalance.valueOf());
+      const afterBscBalance = await fetchGlobalAccountantBalance(
+        tryNativeToHexString(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH),
+        CHAIN_ID_BSC,
+        CHAIN_ID_ETH
+      );
+      expect(afterBscBalance).toBeLessThan(beforeBscBalance.valueOf());
+    }
+
+    //
+    // STEP 3a - redeem spoofed tokens
+    //
+    {
+      console.log("redeeming spoofed tokens");
+      let vaa: VAA<TokenBridgeTransfer> = {
+        version: 1,
+        guardianSetIndex: 0,
+        signatures: [],
+        timestamp: 0,
+        nonce: 0,
+        emitterChain: CHAIN_ID_ETH,
+        emitterAddress: getEmitterAddressEth(
+          CONTRACTS.DEVNET.ethereum.token_bridge
+        ),
+        sequence: BigInt(979999116 + Math.floor(Math.random() * 100000000)),
+        consistencyLevel: 0,
+        payload: {
+          module: "TokenBridge",
+          type: "Transfer",
+          tokenChain: CHAIN_ID_ETH,
+          tokenAddress: uint8ArrayToHex(
+            tryNativeToUint8Array(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH)
+          ),
+          amount: parseUnits("9000", DECIMALS).toBigInt(),
+          toAddress: uint8ArrayToHex(
+            tryNativeToUint8Array(await bscSigner.getAddress(), CHAIN_ID_BSC)
+          ),
+          chain: CHAIN_ID_BSC,
+          fee: BigInt(0),
+        },
+      };
+      vaa.signatures = sign(VAA_SIGNERS, vaa);
+      await redeemOnEth(
+        CONTRACTS.DEVNET.bsc.token_bridge,
+        bscSigner,
+        hexToUint8Array(serialiseVAA(vaa))
+      );
+    }
+
+    //
+    // STEP 3b - send the spoofed tokens back
+    //
+    {
+      const beforeMetrics = await fetchGlobalAccountantMetrics();
+      const amount = parseUnits("9000", DECIMALS);
+      // approve the bridge to spend tokens
+      console.log("approving...");
+      await approveEth(
+        CONTRACTS.DEVNET.bsc.token_bridge,
+        attestedAddress,
+        bscSigner,
+        amount
+      );
+      // transfer tokens out
+      console.log("transferring...");
+      const receipt = await transferFromEth(
+        CONTRACTS.DEVNET.bsc.token_bridge,
+        bscSigner,
+        attestedAddress,
+        amount,
+        CHAIN_ID_ETH,
+        tryNativeToUint8Array(await ethSigner.getAddress(), CHAIN_ID_ETH)
+      );
+      const sequence = parseSequenceFromLogEth(
+        receipt,
+        CONTRACTS.DEVNET.bsc.core
+      );
+      console.log("waiting 30s to fetch metrics...");
+      await sleep(30 * 1000); // give the guardian a few seconds to pick up the transfers and attempt to submit them
+      const afterMetrics = await fetchGlobalAccountantMetrics();
+      console.log(
+        "balance errors b/a:",
+        beforeMetrics.global_accountant_total_balance_errors,
+        afterMetrics.global_accountant_total_balance_errors
+      );
+      if (
+        afterMetrics.global_accountant_error_events_received <=
+          beforeMetrics.global_accountant_error_events_received ||
+        afterMetrics.global_accountant_transfer_vaas_submitted <=
+          beforeMetrics.global_accountant_transfer_vaas_submitted ||
+        afterMetrics.global_accountant_total_balance_errors <=
+          beforeMetrics.global_accountant_total_balance_errors
+      ) {
+        throw new Error("Expected metrics change did not occur");
+      }
+      // the transfer should fail, because there's an insufficient source balance
+      await expect(
+        fetchGlobalAccountantTransferStatus(
+          CHAIN_ID_BSC,
+          getEmitterAddressEth(CONTRACTS.DEVNET.bsc.core),
+          sequence
+        )
+      ).rejects.toThrow();
+    }
+    console.log("success!");
+  });
+});

+ 5 - 0
wormchain/contracts/tools/jest.config.js

@@ -0,0 +1,5 @@
+/** @type {import('ts-jest').JestConfigWithTsJest} */
+module.exports = {
+  preset: 'ts-jest',
+  testEnvironment: 'node',
+};

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1579 - 1661
wormchain/contracts/tools/package-lock.json


+ 4 - 1
wormchain/contracts/tools/package.json

@@ -5,7 +5,7 @@
   "main": "deploy_wormchain.ts",
   "scripts": {
     "deploy-wormchain": "ts-node deploy_wormchain.ts",
-    "test-accountant": "ts-node test_accountant.ts",
+    "test-accountant": "jest test_accountant.ts --verbose",
     "test-wormchain": "ts-node test_wormchain.ts",
     "deploy-and-test": "npm run deploy-wormchain && npm run test-wormchain"
   },
@@ -26,6 +26,9 @@
   },
   "devDependencies": {
     "@types/elliptic": "6.4.14",
+    "@types/jest": "29.4.0",
+    "jest": "29.4.1",
+    "ts-jest": "29.0.5",
     "ts-node": "10.9.1",
     "typescript": "4.9.4"
   }

+ 0 - 371
wormchain/contracts/tools/test_accountant.ts

@@ -1,371 +0,0 @@
-import "dotenv/config";
-import {
-  approveEth,
-  attestFromEth,
-  CHAIN_ID_BSC,
-  CHAIN_ID_ETH,
-  CONTRACTS,
-  createWrappedOnEth,
-  getEmitterAddressEth,
-  getForeignAssetEth,
-  getSignedVAAWithRetry,
-  hexToUint8Array,
-  parseSequenceFromLogEth,
-  redeemOnEth,
-  serialiseVAA,
-  sign,
-  TokenBridgeTransfer,
-  transferFromEth,
-  tryNativeToUint8Array,
-  uint8ArrayToHex,
-  VAA,
-} from "@certusone/wormhole-sdk";
-import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport";
-import { ethers } from "ethers";
-import * as devnetConsts from "./devnet-consts.json";
-import { parseUnits } from "ethers/lib/utils";
-
-if (process.env.INIT_SIGNERS_KEYS_CSV === "undefined") {
-  let msg = `.env is missing. run "make contracts-tools-deps" to fetch.`;
-  console.error(msg);
-  throw msg;
-}
-
-// TODO: consider using jest
-
-/*
- * Goals:
- *   1. Ensure a token can be sent from its origin chain
- *   2. Ensure a token can be sent back from a foreign chain
- *   3. Ensure spoofed tokens for more than the outstanding amount rejects successfully
- *   4. Validate the guardian metrics for each of these cases
- *   5. Bonus: Validate the on chain contract state via queries
- */
-
-const ci = !!process.env.CI;
-
-const GUARDIAN_HOST = ci ? "guardian" : "localhost";
-const GUARDIAN_RPCS = [`http://${GUARDIAN_HOST}:7071`];
-const GUARDIAN_METRICS = `http://${GUARDIAN_HOST}:6060/metrics`;
-const ETH_NODE_URL = ci ? "ws://eth-devnet:8545" : "ws://localhost:8545";
-const BSC_NODE_URL = ci ? "ws://eth-devnet2:8545" : "ws://localhost:8546";
-const ETH_PRIVATE_KEY9 =
-  "0xb0057716d5917badaf911b193b12b910811c1497b5bada8d7711f758981c3773";
-const ETH_GA_TEST_TOKEN =
-  devnetConsts.chains[CHAIN_ID_ETH].addresses.testGA.address;
-const DECIMALS = devnetConsts.chains[CHAIN_ID_ETH].addresses.testGA.decimals;
-const VAA_SIGNERS = process.env.INIT_SIGNERS_KEYS_CSV.split(",");
-const GOVERNANCE_CHAIN = Number(devnetConsts.global.governanceChainId);
-const GOVERNANCE_EMITTER = devnetConsts.global.governanceEmitterAddress;
-
-function sleep(ms) {
-  return new Promise((resolve) => setTimeout(resolve, ms));
-}
-
-// Guardian metrics are prometheus data
-const fetchGlobalAccountantMetrics = async (): Promise<{
-  global_accountant_connection_errors_total: number;
-  global_accountant_error_events_received: number;
-  global_accountant_events_received: number;
-  global_accountant_submit_failures: number;
-  global_accountant_total_balance_errors: number;
-  global_accountant_total_digest_mismatches: number;
-  global_accountant_transfer_vaas_outstanding: number;
-  global_accountant_transfer_vaas_submitted: number;
-  global_accountant_transfer_vaas_submitted_and_approved: number;
-}> =>
-  (await (await fetch(GUARDIAN_METRICS)).text())
-    .split("\n")
-    .filter((m) => m.startsWith("global_accountant"))
-    .reduce((p, m) => {
-      const [k, v] = m.split(" ");
-      p[k] = Number(v);
-      return p;
-    }, {} as any);
-
-(async () => {
-  //
-  // PREAMBLE
-  //
-
-  // create a signer for Eth
-  const ethProvider = new ethers.providers.WebSocketProvider(ETH_NODE_URL);
-  const ethSigner = new ethers.Wallet(ETH_PRIVATE_KEY9, ethProvider);
-  // create a signer for BSC
-  const bscProvider = new ethers.providers.WebSocketProvider(BSC_NODE_URL);
-  const bscSigner = new ethers.Wallet(ETH_PRIVATE_KEY9, bscProvider);
-
-  let attestedAddress = "";
-
-  //
-  // STEP 0 - attest the token
-  //
-  {
-    attestedAddress = await getForeignAssetEth(
-      CONTRACTS.DEVNET.bsc.token_bridge,
-      bscProvider,
-      CHAIN_ID_ETH,
-      tryNativeToUint8Array(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH)
-    );
-    if (attestedAddress && attestedAddress !== ethers.constants.AddressZero) {
-      console.log("already attested");
-    } else {
-      console.log("attesting...");
-      // attest the test token
-      const receipt = await attestFromEth(
-        CONTRACTS.DEVNET.ethereum.token_bridge,
-        ethSigner,
-        ETH_GA_TEST_TOKEN
-      );
-      // get the sequence from the logs (needed to fetch the vaa)
-      const sequence = parseSequenceFromLogEth(
-        receipt,
-        CONTRACTS.DEVNET.ethereum.core
-      );
-      const emitterAddress = getEmitterAddressEth(
-        CONTRACTS.DEVNET.ethereum.token_bridge
-      );
-      console.log(`fetching vaa ${sequence}...`);
-      // poll until the guardian(s) witness and sign the vaa
-      const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
-        GUARDIAN_RPCS,
-        CHAIN_ID_ETH,
-        emitterAddress,
-        sequence,
-        {
-          transport: NodeHttpTransport(),
-        }
-      );
-      console.log("creating...");
-      await createWrappedOnEth(
-        CONTRACTS.DEVNET.bsc.token_bridge,
-        bscSigner,
-        signedVAA
-      );
-      attestedAddress = await getForeignAssetEth(
-        CONTRACTS.DEVNET.bsc.token_bridge,
-        bscProvider,
-        CHAIN_ID_ETH,
-        tryNativeToUint8Array(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH)
-      );
-    }
-  }
-
-  //
-  // STEP 1 - send the token out
-  //
-  {
-    const beforeMetrics = await fetchGlobalAccountantMetrics();
-    const amount = parseUnits("1", DECIMALS);
-    // approve the bridge to spend tokens
-    console.log("approving...");
-    await approveEth(
-      CONTRACTS.DEVNET.ethereum.token_bridge,
-      ETH_GA_TEST_TOKEN,
-      ethSigner,
-      amount
-    );
-    // transfer tokens out
-    console.log("transferring...");
-    const receipt = await transferFromEth(
-      CONTRACTS.DEVNET.ethereum.token_bridge,
-      ethSigner,
-      ETH_GA_TEST_TOKEN,
-      amount,
-      CHAIN_ID_BSC,
-      tryNativeToUint8Array(await bscSigner.getAddress(), CHAIN_ID_BSC)
-    );
-    // get the sequence from the logs (needed to fetch the vaa)
-    const sequence = parseSequenceFromLogEth(
-      receipt,
-      CONTRACTS.DEVNET.ethereum.core
-    );
-    const emitterAddress = getEmitterAddressEth(
-      CONTRACTS.DEVNET.ethereum.token_bridge
-    );
-    console.log(`fetching vaa ${sequence}...`);
-    // poll until the guardian(s) witness and sign the vaa
-    const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
-      GUARDIAN_RPCS,
-      CHAIN_ID_ETH,
-      emitterAddress,
-      sequence,
-      {
-        transport: NodeHttpTransport(),
-      }
-    );
-    console.log("redeeming...");
-    await redeemOnEth(CONTRACTS.DEVNET.bsc.token_bridge, bscSigner, signedVAA);
-    const afterMetrics = await fetchGlobalAccountantMetrics();
-    console.log(
-      "approved b/a:",
-      beforeMetrics.global_accountant_transfer_vaas_submitted_and_approved,
-      afterMetrics.global_accountant_transfer_vaas_submitted_and_approved
-    );
-    if (
-      afterMetrics.global_accountant_events_received <=
-        beforeMetrics.global_accountant_events_received ||
-      afterMetrics.global_accountant_transfer_vaas_submitted <=
-        beforeMetrics.global_accountant_transfer_vaas_submitted ||
-      afterMetrics.global_accountant_transfer_vaas_submitted_and_approved <=
-        beforeMetrics.global_accountant_transfer_vaas_submitted_and_approved
-    ) {
-      throw new Error("Expected metrics change did not occur");
-    }
-  }
-
-  //
-  // STEP 2 - send the token back
-  //
-  {
-    const beforeMetrics = await fetchGlobalAccountantMetrics();
-    const amount = parseUnits("1", DECIMALS);
-    // approve the bridge to spend tokens
-    console.log("approving...");
-    await approveEth(
-      CONTRACTS.DEVNET.bsc.token_bridge,
-      attestedAddress,
-      bscSigner,
-      amount
-    );
-    // transfer tokens out
-    console.log("transferring...");
-    const receipt = await transferFromEth(
-      CONTRACTS.DEVNET.bsc.token_bridge,
-      bscSigner,
-      attestedAddress,
-      amount,
-      CHAIN_ID_ETH,
-      tryNativeToUint8Array(await ethSigner.getAddress(), CHAIN_ID_ETH)
-    );
-    // get the sequence from the logs (needed to fetch the vaa)
-    const sequence = parseSequenceFromLogEth(
-      receipt,
-      CONTRACTS.DEVNET.bsc.core
-    );
-    const emitterAddress = getEmitterAddressEth(
-      CONTRACTS.DEVNET.bsc.token_bridge
-    );
-    console.log(`fetching vaa ${sequence}...`);
-    // poll until the guardian(s) witness and sign the vaa
-    const { vaaBytes: signedVAA } = await getSignedVAAWithRetry(
-      GUARDIAN_RPCS,
-      CHAIN_ID_BSC,
-      emitterAddress,
-      sequence,
-      {
-        transport: NodeHttpTransport(),
-      }
-    );
-    console.log("redeeming...");
-    await redeemOnEth(
-      CONTRACTS.DEVNET.ethereum.token_bridge,
-      ethSigner,
-      signedVAA
-    );
-    const afterMetrics = await fetchGlobalAccountantMetrics();
-    console.log(
-      "approved b/a:",
-      beforeMetrics.global_accountant_transfer_vaas_submitted_and_approved,
-      afterMetrics.global_accountant_transfer_vaas_submitted_and_approved
-    );
-    if (
-      afterMetrics.global_accountant_events_received <=
-        beforeMetrics.global_accountant_events_received ||
-      afterMetrics.global_accountant_transfer_vaas_submitted <=
-        beforeMetrics.global_accountant_transfer_vaas_submitted ||
-      afterMetrics.global_accountant_transfer_vaas_submitted_and_approved <=
-        beforeMetrics.global_accountant_transfer_vaas_submitted_and_approved
-    ) {
-      throw new Error("Expected metrics change did not occur");
-    }
-  }
-
-  //
-  // STEP 3a - redeem spoofed tokens
-  //
-  {
-    console.log("redeeming spoofed tokens");
-    let vaa: VAA<TokenBridgeTransfer> = {
-      version: 1,
-      guardianSetIndex: 0,
-      signatures: [],
-      timestamp: 0,
-      nonce: 0,
-      emitterChain: CHAIN_ID_ETH,
-      emitterAddress: getEmitterAddressEth(
-        CONTRACTS.DEVNET.ethereum.token_bridge
-      ),
-      sequence: BigInt(979999116 + Math.floor(Math.random() * 100000000)),
-      consistencyLevel: 0,
-      payload: {
-        module: "TokenBridge",
-        type: "Transfer",
-        tokenChain: CHAIN_ID_ETH,
-        tokenAddress: uint8ArrayToHex(
-          tryNativeToUint8Array(ETH_GA_TEST_TOKEN, CHAIN_ID_ETH)
-        ),
-        amount: parseUnits("9000", DECIMALS).toBigInt(),
-        toAddress: uint8ArrayToHex(
-          tryNativeToUint8Array(await bscSigner.getAddress(), CHAIN_ID_BSC)
-        ),
-        chain: CHAIN_ID_BSC,
-        fee: BigInt(0),
-      },
-    };
-    vaa.signatures = sign(VAA_SIGNERS, vaa);
-    await redeemOnEth(
-      CONTRACTS.DEVNET.bsc.token_bridge,
-      bscSigner,
-      hexToUint8Array(serialiseVAA(vaa))
-    );
-  }
-
-  //
-  // STEP 3b - send the spoofed tokens back
-  //
-  {
-    const beforeMetrics = await fetchGlobalAccountantMetrics();
-    const amount = parseUnits("9000", DECIMALS);
-    // approve the bridge to spend tokens
-    console.log("approving...");
-    await approveEth(
-      CONTRACTS.DEVNET.bsc.token_bridge,
-      attestedAddress,
-      bscSigner,
-      amount
-    );
-    // transfer tokens out
-    console.log("transferring...");
-    const receipt = await transferFromEth(
-      CONTRACTS.DEVNET.bsc.token_bridge,
-      bscSigner,
-      attestedAddress,
-      amount,
-      CHAIN_ID_ETH,
-      tryNativeToUint8Array(await ethSigner.getAddress(), CHAIN_ID_ETH)
-    );
-    console.log("waiting 30s to fetch metrics...");
-    await sleep(30 * 1000); // give the guardian a few seconds to pick up the transfers and attempt to submit them
-    const afterMetrics = await fetchGlobalAccountantMetrics();
-    console.log(
-      "balance errors b/a:",
-      beforeMetrics.global_accountant_total_balance_errors,
-      afterMetrics.global_accountant_total_balance_errors
-    );
-    if (
-      afterMetrics.global_accountant_error_events_received <=
-        beforeMetrics.global_accountant_error_events_received ||
-      afterMetrics.global_accountant_transfer_vaas_submitted <=
-        beforeMetrics.global_accountant_transfer_vaas_submitted ||
-      afterMetrics.global_accountant_total_balance_errors <=
-        beforeMetrics.global_accountant_total_balance_errors
-    ) {
-      throw new Error("Expected metrics change did not occur");
-    }
-  }
-
-  ethProvider.destroy();
-  bscProvider.destroy();
-  console.log("success!");
-})();

+ 4 - 3
wormchain/contracts/tools/tsconfig.json

@@ -1,5 +1,6 @@
 {
-    "compilerOptions": {
-        "resolveJsonModule": true
-    }
+  "compilerOptions": {
+    "resolveJsonModule": true,
+    "esModuleInterop": true
+  }
 }

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov