From 73202fb2e8110e391a73e4a5b7160f80b51da101 Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Tue, 25 Jun 2024 09:34:53 -0400 Subject: [PATCH 1/5] rename existing tx prep functions to not overlap with protocol definition --- evm/ts/src/TokenRouter/evm.ts | 12 ++++----- evm/ts/src/TokenRouter/index.ts | 13 +++++---- evm/ts/src/protocol/index.ts | 1 + evm/ts/src/protocol/tokenRouter.ts | 42 +++++++++++++++++++++++++++++ evm/ts/tests/03__marketOrder.ts | 4 +-- evm/ts/tests/04__fastMarketOrder.ts | 16 +++++------ 6 files changed, 65 insertions(+), 23 deletions(-) create mode 100644 evm/ts/src/protocol/index.ts create mode 100644 evm/ts/src/protocol/tokenRouter.ts diff --git a/evm/ts/src/TokenRouter/evm.ts b/evm/ts/src/TokenRouter/evm.ts index c4948071..c12d89fa 100644 --- a/evm/ts/src/TokenRouter/evm.ts +++ b/evm/ts/src/TokenRouter/evm.ts @@ -35,7 +35,7 @@ export class EvmTokenRouter implements TokenRouter { return this.contract.address; } - placeMarketOrder( + placeMarketOrderTx( amountIn: bigint, targetChain: number, redeemer: Buffer | Uint8Array, @@ -62,7 +62,7 @@ export class EvmTokenRouter implements TokenRouter { } } - placeFastMarketOrder( + placeFastMarketOrderTx( amountIn: bigint, targetChain: number, redeemer: Buffer | Uint8Array, @@ -97,19 +97,19 @@ export class EvmTokenRouter implements TokenRouter { } } - redeemFill(response: OrderResponse) { + redeemFillTx(response: OrderResponse) { return this.contract.redeemFill(response); } - addRouterEndpoint(chain: number, endpoint: Endpoint, domain: number) { + addRouterEndpointTx(chain: number, endpoint: Endpoint, domain: number) { return this.contract.addRouterEndpoint(chain, endpoint, domain); } - updateFastTransferParameters(newParams: FastTransferParameters) { + updateFastTransferParametersTx(newParams: FastTransferParameters) { return this.contract.updateFastTransferParameters(newParams); } - enableFastTransfer(enable: boolean) { + enableFastTransferTx(enable: boolean) { return this.contract.enableFastTransfers(enable); } diff --git a/evm/ts/src/TokenRouter/index.ts b/evm/ts/src/TokenRouter/index.ts index 112795d4..a45b8e82 100644 --- a/evm/ts/src/TokenRouter/index.ts +++ b/evm/ts/src/TokenRouter/index.ts @@ -23,7 +23,7 @@ export type Endpoint = { export abstract class TokenRouter { abstract get address(): string; - abstract placeMarketOrder( + abstract placeMarketOrderTx( amountIn: bigint, targetChain: number, redeemer: Buffer | Uint8Array, @@ -32,7 +32,7 @@ export abstract class TokenRouter; - abstract placeFastMarketOrder( + abstract placeFastMarketOrderTx( amountIn: bigint, targetChain: number, redeemer: Buffer | Uint8Array, @@ -43,21 +43,20 @@ export abstract class TokenRouter; - abstract redeemFill(response: OrderResponse): Promise; + abstract redeemFillTx(response: OrderResponse): Promise; - abstract addRouterEndpoint( + abstract addRouterEndpointTx( chain: number, endpoint: Endpoint, domain: number, ): Promise; - abstract updateFastTransferParameters( + abstract updateFastTransferParametersTx( newParams: FastTransferParameters, ): Promise; - abstract enableFastTransfer(enable: boolean): Promise; + abstract enableFastTransferTx(enable: boolean): Promise; abstract getInitialAuctionFee(): Promise; - abstract getTransactionResults(txHash: string): Promise; } diff --git a/evm/ts/src/protocol/index.ts b/evm/ts/src/protocol/index.ts new file mode 100644 index 00000000..d3eb3fad --- /dev/null +++ b/evm/ts/src/protocol/index.ts @@ -0,0 +1 @@ +export * from "./tokenRouter"; diff --git a/evm/ts/src/protocol/tokenRouter.ts b/evm/ts/src/protocol/tokenRouter.ts new file mode 100644 index 00000000..01628e64 --- /dev/null +++ b/evm/ts/src/protocol/tokenRouter.ts @@ -0,0 +1,42 @@ +import { TokenRouter } from "@wormhole-foundation/example-liquidity-layer-definitions"; +import { Chain, Network } from "@wormhole-foundation/sdk-base"; +import { + AccountAddress, + UnsignedTransaction, + VAA, + CircleBridge, + Contracts, +} from "@wormhole-foundation/sdk-definitions"; +import { EvmTokenRouter as _EvmTokenRouter } from "../TokenRouter"; +import { ethers } from "ethers"; + +export class EvmTokenRouter + extends _EvmTokenRouter + implements TokenRouter +{ + constructor( + readonly network: N, + readonly chain: C, + readonly provider: ethers.providers.Provider, + readonly contracts: Contracts & TokenRouter.Addresses, + ) { + super(provider, contracts.tokenRouter, contracts.cctp.tokenMessenger); + } + + async *placeMarketOrder( + sender: AccountAddress, + order: TokenRouter.OrderRequest | TokenRouter.PreparedOrder, + ): AsyncGenerator, any, unknown> { + throw new Error("Method not implemented."); + } + async *redeemFill( + sender: AccountAddress, + vaa: + | VAA<"FastTransfer:CctpDeposit"> + | VAA<"FastTransfer:FastMarketOrder"> + | VAA<"FastTransfer:FastFill">, + cctp: CircleBridge.Attestation, + ): AsyncGenerator, any, unknown> { + throw new Error("Method not implemented."); + } +} diff --git a/evm/ts/tests/03__marketOrder.ts b/evm/ts/tests/03__marketOrder.ts index c3388d0c..60b16ce3 100644 --- a/evm/ts/tests/03__marketOrder.ts +++ b/evm/ts/tests/03__marketOrder.ts @@ -110,7 +110,7 @@ describe("Market Order Business Logic -- CCTP to CCTP", () => { const targetChain = toChainId(toChainName); const minAmountOut = BigInt(0); const receipt = await fromTokenRouter - .placeMarketOrder( + .placeMarketOrderTx( amountIn, targetChain, Buffer.from(tryNativeToUint8Array(toWallet.address, toChainName)), @@ -159,7 +159,7 @@ describe("Market Order Business Logic -- CCTP to CCTP", () => { const balanceBefore = await usdc.balanceOf(toWallet.address); const receipt = await toTokenRouter - .redeemFill(orderResponse) + .redeemFillTx(orderResponse) .then((tx) => mineWait(toProvider, tx)) .catch((err) => { console.log(err); diff --git a/evm/ts/tests/04__fastMarketOrder.ts b/evm/ts/tests/04__fastMarketOrder.ts index ef742150..9cc2f90c 100644 --- a/evm/ts/tests/04__fastMarketOrder.ts +++ b/evm/ts/tests/04__fastMarketOrder.ts @@ -159,7 +159,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const minAmountOut = BigInt(0); const deadline = 0; const receipt = await fromTokenRouter - .placeFastMarketOrder( + .placeFastMarketOrderTx( amountIn, targetChain, Buffer.from(tryNativeToUint8Array(toWallet.address, toChainName)), @@ -443,7 +443,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const balanceBefore = await usdc.balanceOf(toWallet.address); const receipt = await toTokenRouter - .redeemFill(orderResponse) + .redeemFillTx(orderResponse) .then((tx) => mineWait(toProvider, tx)) .catch((err) => { console.log(err); @@ -540,7 +540,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const minAmountOut = BigInt(0); const deadline = 0; const receipt = await fromTokenRouter - .placeFastMarketOrder( + .placeFastMarketOrderTx( amountIn, targetChain, Buffer.from(tryNativeToUint8Array(toWallet.address, toChainName)), @@ -840,7 +840,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const balanceBefore = await usdc.balanceOf(toWallet.address); const receipt = await toTokenRouter - .redeemFill(orderResponse) + .redeemFillTx(orderResponse) .then((tx) => mineWait(toProvider, tx)) .catch((err) => { console.log(err); @@ -939,7 +939,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const minAmountOut = BigInt(0); const deadline = 0; const receipt = await fromTokenRouter - .placeFastMarketOrder( + .placeFastMarketOrderTx( amountIn, targetChain, Buffer.from(tryNativeToUint8Array(toWallet.address, toChainName)), @@ -1089,7 +1089,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const balanceBefore = await usdc.balanceOf(toWallet.address); const receipt = await toTokenRouter - .redeemFill(orderResponse) + .redeemFillTx(orderResponse) .then((tx) => mineWait(toProvider, tx)) .catch((err) => { console.log(err); @@ -1153,7 +1153,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const deadline = (await engineProvider.getBlock(currentBlock)).timestamp; const receipt = await fromTokenRouter - .placeFastMarketOrder( + .placeFastMarketOrderTx( amountIn, targetChain, Buffer.from(tryNativeToUint8Array(toWallet.address, toChainName)), @@ -1339,7 +1339,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const balanceBefore = await usdc.balanceOf(toWallet.address); const receipt = await toTokenRouter - .redeemFill(orderResponse) + .redeemFillTx(orderResponse) .then((tx) => mineWait(toProvider, tx)) .catch((err) => { console.log(err); From 530598ab6ec3cddb59c853a4f53d5e265623b190 Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Tue, 25 Jun 2024 09:52:29 -0400 Subject: [PATCH 2/5] tmp before migrating ethers version --- evm/ts/src/protocol/tokenRouter.ts | 59 +++++++++++++++++++++++++----- universal/ts/src/protocol.ts | 2 +- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/evm/ts/src/protocol/tokenRouter.ts b/evm/ts/src/protocol/tokenRouter.ts index 01628e64..a14870ac 100644 --- a/evm/ts/src/protocol/tokenRouter.ts +++ b/evm/ts/src/protocol/tokenRouter.ts @@ -1,19 +1,25 @@ import { TokenRouter } from "@wormhole-foundation/example-liquidity-layer-definitions"; -import { Chain, Network } from "@wormhole-foundation/sdk-base"; +import { Network, nativeChainIds, toChainId } from "@wormhole-foundation/sdk-base"; import { - AccountAddress, - UnsignedTransaction, - VAA, CircleBridge, Contracts, + UnsignedTransaction, + VAA, } from "@wormhole-foundation/sdk-definitions"; -import { EvmTokenRouter as _EvmTokenRouter } from "../TokenRouter"; +import { + AnyEvmAddress, + EvmAddress, + EvmChains, + EvmUnsignedTransaction, +} from "@wormhole-foundation/sdk-evm"; import { ethers } from "ethers"; +import { EvmTokenRouter as _EvmTokenRouter } from "../TokenRouter"; -export class EvmTokenRouter +export class EvmTokenRouter extends _EvmTokenRouter implements TokenRouter { + private _chainId: number; constructor( readonly network: N, readonly chain: C, @@ -21,16 +27,32 @@ export class EvmTokenRouter readonly contracts: Contracts & TokenRouter.Addresses, ) { super(provider, contracts.tokenRouter, contracts.cctp.tokenMessenger); + this._chainId = 0; //nativeChainIds.networkChainToNativeChainId(network, chain); } async *placeMarketOrder( - sender: AccountAddress, - order: TokenRouter.OrderRequest | TokenRouter.PreparedOrder, + sender: AnyEvmAddress, + order: TokenRouter.OrderRequest, ): AsyncGenerator, any, unknown> { - throw new Error("Method not implemented."); + const msg = order.redeemerMessage ? order.redeemerMessage : new Uint8Array(); + + const refundAddress = order.refundAddress + ? new EvmAddress(order.refundAddress).unwrap() + : undefined; + + const tx = await this.placeMarketOrderTx( + order.amountIn, + toChainId(order.targetChain), + order.redeemer.toUint8Array(), + msg, + order.minAmountOut, + refundAddress, + ); + + yield this.createUnsignedTx(tx, "TokenRouter.placeMarketOrder"); } async *redeemFill( - sender: AccountAddress, + sender: AnyEvmAddress, vaa: | VAA<"FastTransfer:CctpDeposit"> | VAA<"FastTransfer:FastMarketOrder"> @@ -39,4 +61,21 @@ export class EvmTokenRouter ): AsyncGenerator, any, unknown> { throw new Error("Method not implemented."); } + + private createUnsignedTx( + txReq: ethers.ContractTransaction, + description: string, + parallelizable: boolean = false, + ): EvmUnsignedTransaction { + txReq.chainId = this._chainId; + + return new EvmUnsignedTransaction( + // txReq, + {}, + this.network, + this.chain, + description, + parallelizable, + ); + } } diff --git a/universal/ts/src/protocol.ts b/universal/ts/src/protocol.ts index 502e7efe..794407b1 100644 --- a/universal/ts/src/protocol.ts +++ b/universal/ts/src/protocol.ts @@ -150,7 +150,7 @@ export namespace TokenRouter { export type PreparedOrder = AccountAddress; } -export interface TokenRouter { +export interface TokenRouter { placeMarketOrder( sender: AccountAddress, order: TokenRouter.OrderRequest | TokenRouter.PreparedOrder, From e7c57b9dcf82191434928ab966af2ba9a0141f38 Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Tue, 25 Jun 2024 16:33:03 -0400 Subject: [PATCH 3/5] convert to ethers v6 --- evm/package.json | 6 +- evm/ts/src/MatchingEngine/evm.ts | 70 ++-- evm/ts/src/MatchingEngine/index.ts | 34 +- evm/ts/src/TokenRouter/evm.ts | 58 ++-- evm/ts/src/TokenRouter/index.ts | 3 +- evm/ts/src/error.ts | 25 +- evm/ts/src/protocol/tokenRouter.ts | 4 +- evm/ts/src/testing/mock/circleAttester.ts | 13 +- evm/ts/src/testing/mock/index.ts | 8 +- evm/ts/src/testing/mock/wormhole.ts | 16 +- evm/ts/src/testing/utils.ts | 47 +-- evm/ts/src/utils.ts | 25 +- evm/ts/tests/00__environment.ts | 103 +++--- evm/ts/tests/01__registration.ts | 6 +- evm/ts/tests/02__configuration.ts | 12 +- evm/ts/tests/03__marketOrder.ts | 20 +- evm/ts/tests/04__fastMarketOrder.ts | 388 +++++++++++++--------- evm/ts/tests/run_integration_test.sh | 54 +-- package-lock.json | 104 +++++- 19 files changed, 577 insertions(+), 419 deletions(-) diff --git a/evm/package.json b/evm/package.json index e2462784..09e469c0 100644 --- a/evm/package.json +++ b/evm/package.json @@ -14,7 +14,7 @@ "build:esm": "tsc -p tsconfig.esm.json", "build:cjs": "tsc -p tsconfig.cjs.json", "build": "npm run build:esm && npm run build:cjs", - "generate": "typechain --target=ethers-v5 --out-dir=ts/src/types out/[!build-info]*/*.json", + "generate": "typechain --target=ethers-v6 --out-dir=ts/src/types out/[!build-info]*/*.json", "clean": "rm -rf dist && rm -rf node_modules && rm -f ./*.tsbuildinfo" }, "exports": { @@ -34,11 +34,11 @@ "@wormhole-foundation/sdk-definitions": "^0.7.0-beta.6", "@wormhole-foundation/sdk-evm": "^0.7.0-beta.6", "@wormhole-foundation/example-liquidity-layer-definitions": "0.0.1", - "ethers": "^5.7.2" + "ethers": "^6.5.1" }, "devDependencies": { "envfile": "^7.1.0", - "@typechain/ethers-v5": "^10.2.0", + "@typechain/ethers-v6":"0.5.1", "@types/chai": "^4.3.4", "@types/mocha": "^10.0.1", "@types/node": "^18.14.5", diff --git a/evm/ts/src/MatchingEngine/evm.ts b/evm/ts/src/MatchingEngine/evm.ts index f97b213c..6034c080 100644 --- a/evm/ts/src/MatchingEngine/evm.ts +++ b/evm/ts/src/MatchingEngine/evm.ts @@ -1,4 +1,4 @@ -import { ChainId } from "@wormhole-foundation/sdk-base"; +import { ChainId, asChainId } from "@wormhole-foundation/sdk-base"; import { ethers } from "ethers"; import { RouterEndpoint, LiveAuctionData, MatchingEngine, RedeemParameters } from "."; import { LiquidityLayerTransactionResult } from ".."; @@ -23,32 +23,24 @@ export class EvmMatchingEngine implements MatchingEngine { - return this.contract.signer.getAddress(); - } - - get provider(): ethers.providers.Provider { - return this.contract.provider; - } - - connect(connection: ethers.Signer | ethers.providers.Provider): EvmMatchingEngine { - return new EvmMatchingEngine(connection, this.address, this.circle.address); + connect(connection: ethers.Provider): EvmMatchingEngine { + return new EvmMatchingEngine(connection, this.address, this.circleBridge); } async addRouterEndpoint( @@ -56,41 +48,41 @@ export class EvmMatchingEngine implements MatchingEngine { - return this.contract.addRouterEndpoint(chain, endpoint, domain); + return this.contract.addRouterEndpoint.populateTransaction(chain, endpoint, domain); } async placeInitialBid( fastTransferVaa: Buffer | Uint8Array, feeBid: bigint | ethers.BigNumberish, ): Promise { - return this.contract.placeInitialBid(fastTransferVaa, feeBid); + return this.contract.placeInitialBid.populateTransaction(fastTransferVaa, feeBid); } async improveBid( auctionId: Buffer | Uint8Array, feeBid: bigint | ethers.BigNumberish, ): Promise { - return this.contract.improveBid(auctionId, feeBid); + return this.contract.improveBid.populateTransaction(auctionId, feeBid); } async executeFastOrder( fastTransferVaa: Buffer | Uint8Array, ): Promise { - return this.contract.executeFastOrder(fastTransferVaa); + return this.contract.executeFastOrder.populateTransaction(fastTransferVaa); } async executeSlowOrderAndRedeem( fastTransferVaa: Buffer | Uint8Array, params: RedeemParameters, ): Promise { - return this.contract.executeSlowOrderAndRedeem(fastTransferVaa, params); + return this.contract.executeSlowOrderAndRedeem.populateTransaction(fastTransferVaa, params); } async calculateDynamicPenalty( auctionId?: Buffer | Uint8Array, amount?: bigint | ethers.BigNumberish, blocksElapsed?: bigint | ethers.BigNumberish, - ): Promise<[ethers.BigNumberish, ethers.BigNumberish]> { + ): Promise<[bigint, bigint]> { if (auctionId !== undefined) { return this.contract["calculateDynamicPenalty(bytes32)"](auctionId); } else if (amount !== undefined && blocksElapsed !== undefined) { @@ -104,27 +96,27 @@ export class EvmMatchingEngine implements MatchingEngine { + async auctionStatus(auctionId: Buffer | Uint8Array) { return this.contract.liveAuctionInfo(auctionId).then((res) => res.status); } - async getAuctionGracePeriod(): Promise { + async getAuctionGracePeriod() { return this.contract.getAuctionGracePeriod(); } - async getAuctionDuration(): Promise { + async getAuctionDuration() { return this.contract.getAuctionDuration(); } - async getPenaltyBlocks(): Promise { + async getPenaltyBlocks() { return this.contract.getAuctionPenaltyBlocks(); } - async getInitialPenaltyBps(): Promise { + async getInitialPenaltyBps() { return this.contract.getInitialPenaltyBps(); } - async getUserPenaltyRewardBps(): Promise { + async getUserPenaltyRewardBps() { return this.contract.getUserPenaltyRewardBps(); } @@ -136,14 +128,16 @@ export class EvmMatchingEngine implements MatchingEngine LiquidityLayerTransactionResult.fromEthersTransactionReceipt( chainId, this.address, - coreBridge.address, - txReceipt, + coreAddress, + txReceipt!, circleTransmitterAddress, ), ); @@ -151,20 +145,16 @@ export class EvmMatchingEngine implements MatchingEngine IWormhole__factory.connect(addr, provider)); const circleTransmitterAddress = await this.circle.localMessageTransmitter(); // If this isn't a recognized ChainId, we have problems. - const chainId = await coreBridge.chainId(); + const chainId = asChainId(Number(await coreBridge.chainId())); - this.cache = { - chainId: chainId as ChainId, - coreBridge, - circleTransmitterAddress, - }; + this.cache = { chainId, coreBridge, circleTransmitterAddress }; } return this.cache; diff --git a/evm/ts/src/MatchingEngine/index.ts b/evm/ts/src/MatchingEngine/index.ts index cd389007..208036c8 100644 --- a/evm/ts/src/MatchingEngine/index.ts +++ b/evm/ts/src/MatchingEngine/index.ts @@ -10,13 +10,13 @@ export type RedeemParameters = { }; export type LiveAuctionData = { - status: number; - startBlock: bigint | ethers.BigNumberish; + status: bigint; + startBlock: bigint; highestBidder: string; initialBidder: string; - amount: bigint | ethers.BigNumberish; - securityDeposit: bigint | ethers.BigNumberish; - bidPrice: bigint | ethers.BigNumberish; + amount: bigint; + securityDeposit: bigint; + bidPrice: bigint; }; export type RouterEndpoint = { @@ -30,47 +30,47 @@ export abstract class MatchingEngine; abstract liveAuctionInfo(auctionId: Buffer | Uint8Array): Promise; - abstract auctionStatus(auctionId: Buffer | Uint8Array): Promise; + abstract auctionStatus(auctionId: Buffer | Uint8Array): Promise; abstract placeInitialBid( fastTransferVaa: Buffer | Uint8Array, - feeBid: bigint + feeBid: bigint, ): Promise; abstract improveBid( auctionId: Buffer | Uint8Array, - feeBid: bigint + feeBid: bigint, ): Promise; abstract executeFastOrder( - fastTransferVaa: Buffer | Uint8Array + fastTransferVaa: Buffer | Uint8Array, ): Promise; abstract executeSlowOrderAndRedeem( fastTransferVaa: Buffer | Uint8Array, - params: RedeemParameters + params: RedeemParameters, ): Promise; abstract calculateDynamicPenalty( auctionId?: Buffer | Uint8Array, amount?: bigint, - blocksElapsed?: bigint + blocksElapsed?: bigint, ): Promise<[ethers.BigNumberish, ethers.BigNumberish]>; - abstract getAuctionGracePeriod(): Promise; + abstract getAuctionGracePeriod(): Promise; - abstract getAuctionDuration(): Promise; + abstract getAuctionDuration(): Promise; - abstract getPenaltyBlocks(): Promise; + abstract getPenaltyBlocks(): Promise; - abstract getInitialPenaltyBps(): Promise; + abstract getInitialPenaltyBps(): Promise; - abstract getInitialPenaltyBps(): Promise; + abstract getInitialPenaltyBps(): Promise; abstract wormhole(): Promise; diff --git a/evm/ts/src/TokenRouter/evm.ts b/evm/ts/src/TokenRouter/evm.ts index c12d89fa..863ebc97 100644 --- a/evm/ts/src/TokenRouter/evm.ts +++ b/evm/ts/src/TokenRouter/evm.ts @@ -1,4 +1,4 @@ -import { ChainId } from "@wormhole-foundation/sdk-base"; +import { ChainId, asChainId } from "@wormhole-foundation/sdk-base"; import { ethers } from "ethers"; import { Endpoint, OrderResponse, TokenRouter, FastTransferParameters } from "."; import { LiquidityLayerTransactionResult } from ".."; @@ -23,16 +23,16 @@ export class EvmTokenRouter implements TokenRouter { }; constructor( - connection: ethers.Signer | ethers.providers.Provider, - contractAddress: string, - circleBridge: string, + private connection: ethers.Signer | ethers.Provider, + readonly contractAddress: string, + readonly circleBridge: string, ) { this.contract = ITokenRouter__factory.connect(contractAddress, connection); this.circle = ITokenMessenger__factory.connect(circleBridge, connection); } get address(): string { - return this.contract.address; + return this.contractAddress; } placeMarketOrderTx( @@ -44,7 +44,9 @@ export class EvmTokenRouter implements TokenRouter { refundAddress?: string, ) { if (minAmountOut !== undefined && refundAddress !== undefined) { - return this.contract["placeMarketOrder(uint64,uint64,uint16,bytes32,bytes,address)"]( + return this.contract[ + "placeMarketOrder(uint64,uint64,uint16,bytes32,bytes,address)" + ].populateTransaction( amountIn, minAmountOut, targetChain, @@ -53,12 +55,9 @@ export class EvmTokenRouter implements TokenRouter { refundAddress, ); } else { - return this.contract["placeMarketOrder(uint64,uint16,bytes32,bytes)"]( - amountIn, - targetChain, - redeemer, - redeemerMessage, - ); + return this.contract[ + "placeMarketOrder(uint64,uint16,bytes32,bytes)" + ].populateTransaction(amountIn, targetChain, redeemer, redeemerMessage); } } @@ -75,7 +74,7 @@ export class EvmTokenRouter implements TokenRouter { if (minAmountOut !== undefined && refundAddress !== undefined) { return this.contract[ "placeFastMarketOrder(uint64,uint64,uint16,bytes32,bytes,address,uint64,uint32)" - ]( + ].populateTransaction( amountIn, minAmountOut, targetChain, @@ -86,7 +85,9 @@ export class EvmTokenRouter implements TokenRouter { deadline, ); } else { - return this.contract["placeFastMarketOrder(uint64,uint16,bytes32,bytes,uint64,uint32)"]( + return this.contract[ + "placeFastMarketOrder(uint64,uint16,bytes32,bytes,uint64,uint32)" + ].populateTransaction( amountIn, targetChain, redeemer, @@ -98,26 +99,26 @@ export class EvmTokenRouter implements TokenRouter { } redeemFillTx(response: OrderResponse) { - return this.contract.redeemFill(response); + return this.contract.redeemFill.populateTransaction(response); } addRouterEndpointTx(chain: number, endpoint: Endpoint, domain: number) { - return this.contract.addRouterEndpoint(chain, endpoint, domain); + return this.contract.addRouterEndpoint.populateTransaction(chain, endpoint, domain); } updateFastTransferParametersTx(newParams: FastTransferParameters) { - return this.contract.updateFastTransferParameters(newParams); + return this.contract.updateFastTransferParameters.populateTransaction(newParams); } enableFastTransferTx(enable: boolean) { - return this.contract.enableFastTransfers(enable); + return this.contract.enableFastTransfers.populateTransaction(enable); } async getRouter(chain: number): Promise { return this.contract.getRouter(chain); } - async getInitialAuctionFee(): Promise { + async getInitialAuctionFee() { return this.contract.getInitialAuctionFee(); } @@ -125,14 +126,15 @@ export class EvmTokenRouter implements TokenRouter { // Check cached contracts. const { chainId, coreBridge, circleTransmitterAddress } = await this._cacheIfNeeded(); - return this.contract.provider - .getTransactionReceipt(txHash) + const coreAddress = await coreBridge.getAddress(); + return this.connection + .provider!.getTransactionReceipt(txHash) .then((txReceipt) => LiquidityLayerTransactionResult.fromEthersTransactionReceipt( chainId, this.address, - coreBridge.address, - txReceipt, + coreAddress, + txReceipt!, circleTransmitterAddress, ), ); @@ -140,20 +142,16 @@ export class EvmTokenRouter implements TokenRouter { private async _cacheIfNeeded() { if (this.cache === undefined) { - const provider = this.contract.provider; + const provider = this.connection.provider!; const coreBridge = await this.contract .wormhole() .then((addr) => IWormhole__factory.connect(addr, provider)); const circleTransmitterAddress = await this.circle.localMessageTransmitter(); // If this isn't a recognized ChainId, we have problems. - const chainId = await coreBridge.chainId(); + const chainId = asChainId(Number(await coreBridge.chainId())); - this.cache = { - chainId: chainId as ChainId, - coreBridge, - circleTransmitterAddress, - }; + this.cache = { chainId, coreBridge, circleTransmitterAddress }; } return this.cache; diff --git a/evm/ts/src/TokenRouter/index.ts b/evm/ts/src/TokenRouter/index.ts index a45b8e82..0bd4acb0 100644 --- a/evm/ts/src/TokenRouter/index.ts +++ b/evm/ts/src/TokenRouter/index.ts @@ -1,5 +1,4 @@ import { LiquidityLayerTransactionResult, PreparedInstruction } from ".."; -import { ethers } from "ethers"; export * from "./evm"; export type FastTransferParameters = { @@ -57,6 +56,6 @@ export abstract class TokenRouter; - abstract getInitialAuctionFee(): Promise; + abstract getInitialAuctionFee(): Promise; abstract getTransactionResults(txHash: string): Promise; } diff --git a/evm/ts/src/error.ts b/evm/ts/src/error.ts index 53d61c71..1faef59d 100644 --- a/evm/ts/src/error.ts +++ b/evm/ts/src/error.ts @@ -1,4 +1,6 @@ -import { ethers } from "ethers"; +import { encoding } from "@wormhole-foundation/sdk-base"; +import { keccak256 } from "@wormhole-foundation/sdk-definitions"; +import { isError } from "ethers"; export type DecodedErr = { selector: string; @@ -6,22 +8,11 @@ export type DecodedErr = { }; export function errorDecoder(ethersError: any): DecodedErr { - if ( - !("code" in ethersError) || - !("error" in ethersError) || - !("error" in ethersError.error) || - !("error" in ethersError.error.error) || - !("code" in ethersError.error.error.error) || - !("data" in ethersError.error.error.error) - ) { - throw new Error("not contract error"); - } + if (!isError(ethersError, "CALL_EXCEPTION")) throw new Error("not a CALL_EXCEPTION error"); - const { data } = ethersError.error.error.error as { - data: string; - }; + const { data } = ethersError; - if (data.length < 10 || data.substring(0, 2) != "0x") { + if (!data || data.length < 10 || data.substring(0, 2) != "0x") { throw new Error("data not custom error"); } @@ -51,5 +42,7 @@ export function errorDecoder(ethersError: any): DecodedErr { } function computeSelector(methodSignature: string): string { - return ethers.utils.keccak256(Buffer.from(methodSignature)).substring(0, 10); + return encoding.hex + .encode(keccak256(encoding.bytes.encode(methodSignature)), true) + .substring(0, 10); } diff --git a/evm/ts/src/protocol/tokenRouter.ts b/evm/ts/src/protocol/tokenRouter.ts index a14870ac..e49b64e3 100644 --- a/evm/ts/src/protocol/tokenRouter.ts +++ b/evm/ts/src/protocol/tokenRouter.ts @@ -23,7 +23,7 @@ export class EvmTokenRouter constructor( readonly network: N, readonly chain: C, - readonly provider: ethers.providers.Provider, + readonly provider: ethers.Provider, readonly contracts: Contracts & TokenRouter.Addresses, ) { super(provider, contracts.tokenRouter, contracts.cctp.tokenMessenger); @@ -67,7 +67,7 @@ export class EvmTokenRouter description: string, parallelizable: boolean = false, ): EvmUnsignedTransaction { - txReq.chainId = this._chainId; + //txReq.chainId = this._chainId; return new EvmUnsignedTransaction( // txReq, diff --git a/evm/ts/src/testing/mock/circleAttester.ts b/evm/ts/src/testing/mock/circleAttester.ts index 8d927659..2d76d55a 100644 --- a/evm/ts/src/testing/mock/circleAttester.ts +++ b/evm/ts/src/testing/mock/circleAttester.ts @@ -1,5 +1,6 @@ import { ethers } from "ethers"; import { GUARDIAN_PRIVATE_KEY } from "../consts"; +import { keccak256 } from "@wormhole-foundation/sdk-definitions"; export type Attestation = { circleBridgeMessage: Buffer; @@ -7,20 +8,20 @@ export type Attestation = { }; export class CircleAttester { - attester: ethers.utils.SigningKey; + attester: ethers.SigningKey; constructor() { - this.attester = new ethers.utils.SigningKey("0x" + GUARDIAN_PRIVATE_KEY); + this.attester = new ethers.SigningKey("0x" + GUARDIAN_PRIVATE_KEY); } createAttestation(message: Buffer | Uint8Array) { - const signature = this.attester.signDigest(ethers.utils.keccak256(message)); + const signature = this.attester.sign(keccak256(message)); const attestation = Buffer.alloc(65); - attestation.set(ethers.utils.arrayify(signature.r), 0); - attestation.set(ethers.utils.arrayify(signature.s), 32); + attestation.set(ethers.getBytes(signature.r), 0); + attestation.set(ethers.getBytes(signature.s), 32); - const recoveryId = signature.recoveryParam; + const recoveryId = signature.v; attestation.writeUInt8(recoveryId < 27 ? recoveryId + 27 : recoveryId, 64); return attestation; diff --git a/evm/ts/src/testing/mock/index.ts b/evm/ts/src/testing/mock/index.ts index 38362f54..6b49166e 100644 --- a/evm/ts/src/testing/mock/index.ts +++ b/evm/ts/src/testing/mock/index.ts @@ -6,14 +6,14 @@ export * from "./wormhole"; export abstract class EvmObserver { abstract observeEvm( - provider: ethers.providers.Provider, + provider: ethers.Provider, chain: Chain, - txReceipt: ethers.ContractReceipt, + txReceipt: ethers.TransactionReceipt, ): Promise; abstract observeManyEvm( - provider: ethers.providers.Provider, + provider: ethers.Provider, chain: Chain, - txReceipt: ethers.ContractReceipt, + txReceipt: ethers.TransactionReceipt, ): Promise; } diff --git a/evm/ts/src/testing/mock/wormhole.ts b/evm/ts/src/testing/mock/wormhole.ts index 131978d8..fdd86828 100644 --- a/evm/ts/src/testing/mock/wormhole.ts +++ b/evm/ts/src/testing/mock/wormhole.ts @@ -16,10 +16,10 @@ export class GuardianNetwork implements EvmObserver { } async body( - message: ethers.utils.Result, - provider: ethers.providers.Provider, + message: ethers.Result, + provider: ethers.Provider, chain: Chain, - txReceipt: ethers.ContractReceipt, + txReceipt: ethers.TransactionReceipt, ) { const { sender: emitterAddress, sequence, nonce, payload, consistencyLevel } = message; @@ -34,16 +34,16 @@ export class GuardianNetwork implements EvmObserver { nonce, Buffer.from(payload.substring(2), "hex"), consistencyLevel, - block.timestamp, + block!.timestamp, ); return published; } async observeEvm( - provider: ethers.providers.Provider, + provider: ethers.Provider, chain: Chain, - txReceipt: ethers.ContractReceipt, + txReceipt: ethers.TransactionReceipt, ) { const coreBridgeAddress = contracts.coreBridge.get("Mainnet", chain)!; const message = parseEvmEvent( @@ -57,9 +57,9 @@ export class GuardianNetwork implements EvmObserver { } async observeManyEvm( - provider: ethers.providers.Provider, + provider: ethers.Provider, chain: Chain, - txReceipt: ethers.ContractReceipt, + txReceipt: ethers.TransactionReceipt, ) { const coreBridgeAddress = contracts.coreBridge.get("Mainnet", chain)!; const messages = parseEvmEvents( diff --git a/evm/ts/src/testing/utils.ts b/evm/ts/src/testing/utils.ts index 4210eb50..6104385b 100644 --- a/evm/ts/src/testing/utils.ts +++ b/evm/ts/src/testing/utils.ts @@ -7,16 +7,16 @@ import { Chain } from "@wormhole-foundation/sdk-base"; import { toUniversal } from "@wormhole-foundation/sdk-definitions"; export interface ScoreKeeper { - player: ethers.Wallet; - bid: ethers.BigNumber; - balance: ethers.BigNumber; + player: ethers.NonceManager; + bid: bigint; + balance: bigint; } -export async function mine(provider: ethers.providers.StaticJsonRpcProvider) { +export async function mine(provider: ethers.JsonRpcProvider) { await provider.send("evm_mine", []); } -export async function mineMany(provider: ethers.providers.StaticJsonRpcProvider, count: number) { +export async function mineMany(provider: ethers.JsonRpcProvider, count: number) { for (let i = 0; i < count; i++) { await mine(provider); } @@ -29,35 +29,32 @@ export function tryNativeToUint8Array(address: string, chain: Chain) { export async function mineToGracePeriod( auctionId: Uint8Array, engine: EvmMatchingEngine, - provider: ethers.providers.StaticJsonRpcProvider, + provider: ethers.JsonRpcProvider, ) { - const startBlock = await engine.liveAuctionInfo(auctionId).then((info) => info.startBlock); + const { startBlock } = await engine.liveAuctionInfo(auctionId); const gracePeriod = await engine.getAuctionGracePeriod(); - const currentBlock = await provider.getBlockNumber(); + const currentBlock = BigInt(await provider.getBlockNumber()); // Will mine blocks until there is one block left in the grace period. - const blocksToMine = gracePeriod - (currentBlock - Number(startBlock)) - 1; - await mineMany(provider, blocksToMine); + const blocksToMine = gracePeriod - (currentBlock - startBlock) - 2n; + await mineMany(provider, Number(blocksToMine)); } export async function mineToPenaltyPeriod( auctionId: Uint8Array, engine: EvmMatchingEngine, - provider: ethers.providers.StaticJsonRpcProvider, + provider: ethers.JsonRpcProvider, penaltyBlocks: number, ) { const startBlock = await engine.liveAuctionInfo(auctionId).then((info) => info.startBlock); const gracePeriod = await engine.getAuctionGracePeriod(); - const currentBlock = await provider.getBlockNumber(); + const currentBlock = BigInt(await provider.getBlockNumber()); - const blocksToMine = gracePeriod - (currentBlock - Number(startBlock)) + penaltyBlocks; - await mineMany(provider, blocksToMine); + const blocksToMine = gracePeriod - (currentBlock - startBlock) + BigInt(penaltyBlocks); + await mineMany(provider, Number(blocksToMine)); } -export async function mineWait( - provider: ethers.providers.StaticJsonRpcProvider, - tx: ethers.ContractTransaction, -) { +export async function mineWait(provider: ethers.JsonRpcProvider, tx: ethers.TransactionResponse) { await mine(provider); return tx.wait(); } @@ -68,14 +65,15 @@ export async function mintNativeUsdc( amount: ethers.BigNumberish, mineBlock: boolean = true, ) { - if (!("detectNetwork" in usdc.provider)) { + if (!usdc.runner) { throw new Error("provider must be a StaticJsonRpcProvider"); } - const provider = usdc.provider as ethers.providers.StaticJsonRpcProvider; + const provider = usdc.runner.provider as ethers.JsonRpcProvider; + const address = await usdc.getAddress(); const tx = await IUSDC__factory.connect( - usdc.address, + address, new ethers.Wallet(WALLET_PRIVATE_KEYS[9], provider), ).mint(recipient, amount); @@ -85,8 +83,11 @@ export async function mintNativeUsdc( } export async function burnAllUsdc(usdc: IERC20) { + const signer = usdc.runner! as ethers.Signer; + const address = signer.getAddress(); + await usdc - .balanceOf(usdc.signer.getAddress()) + .balanceOf(address) .then((balance) => usdc.transfer("0x6969696969696969696969696969696969696969", balance)) - .then((tx) => mineWait(usdc.provider as ethers.providers.StaticJsonRpcProvider, tx)); + .then((tx) => mineWait(usdc.runner?.provider as ethers.JsonRpcProvider, tx)); } diff --git a/evm/ts/src/utils.ts b/evm/ts/src/utils.ts index 6a2ff120..71a28dbc 100644 --- a/evm/ts/src/utils.ts +++ b/evm/ts/src/utils.ts @@ -4,16 +4,16 @@ import { ethers } from "ethers"; import { CoreBridgeLiquidityLayerMessage, MessageDecoder } from "./messages"; export function parseEvmEvents( - txReceipt: ethers.ContractReceipt, + txReceipt: ethers.TransactionReceipt, contractAddress: string, eventInterface: string, ) { - let wormholeLogs: ethers.utils.Result[] = []; + let wormholeLogs: ethers.Result[] = []; for (const txLog of txReceipt.logs) { if (txLog.address === contractAddress) { try { - const iface = new ethers.utils.Interface([`event ${eventInterface}`]); - const event = iface.parseLog(txLog).args; + const iface = new ethers.Interface([`event ${eventInterface}`]); + const event = iface.parseLog(txLog)!.args; wormholeLogs.push(event); } catch (e: any) { if (e.reason === "no matching event") { @@ -30,15 +30,15 @@ export function parseEvmEvents( } export function parseEvmEvent( - txReceipt: ethers.ContractReceipt, + txReceipt: ethers.TransactionReceipt, contractAddress: string, eventInterface: string, ) { for (const txLog of txReceipt.logs) { if (txLog.address === contractAddress) { try { - const iface = new ethers.utils.Interface([`event ${eventInterface}`]); - return iface.parseLog(txLog).args; + const iface = new ethers.Interface([`event ${eventInterface}`]); + return iface.parseLog(txLog)!.args; } catch (e: any) { if (e.reason === "no matching event") { continue; @@ -50,8 +50,9 @@ export function parseEvmEvent( throw new Error("contract address not found"); } -export function bufferfy(value: number | ethers.utils.BytesLike | ethers.utils.Hexable): Buffer { - return Buffer.from(ethers.utils.arrayify(value)); +export function bufferfy(value: number | ethers.BytesLike): Buffer { + if (typeof value === "number") value = ethers.toQuantity(value); + return Buffer.from(ethers.getBytes(value)); } export type LiquidityLayerObservation = { @@ -81,7 +82,7 @@ export class LiquidityLayerTransactionResult { chainId: ChainId, contractAddress: string, coreBridgeAddress: string, - txReceipt: ethers.ContractReceipt, + txReceipt: ethers.TransactionReceipt, circleTransmitterAddress: string, ) { const chain = toChain(chainId); @@ -110,8 +111,8 @@ export class LiquidityLayerTransactionResult { const encodedMessage = bufferfy(payloadByteslike); // Make sure the address is checksummed. - evmEmitterAddress = ethers.utils.getAddress(evmEmitterAddress); - contractAddress = ethers.utils.getAddress(contractAddress); + evmEmitterAddress = ethers.getAddress(evmEmitterAddress); + contractAddress = ethers.getAddress(contractAddress); if (evmEmitterAddress !== contractAddress) { throw new Error("Unrecognized emitter address."); diff --git a/evm/ts/tests/00__environment.ts b/evm/ts/tests/00__environment.ts index fbd7058d..09091b19 100644 --- a/evm/ts/tests/00__environment.ts +++ b/evm/ts/tests/00__environment.ts @@ -20,6 +20,8 @@ import { WORMHOLE_MESSAGE_FEE, mineWait, } from "../src/testing"; +import { encoding } from "@wormhole-foundation/sdk-base"; +import { EvmAddress } from "@wormhole-foundation/sdk-evm"; describe("Environment", () => { const chainNames: ValidNetwork[] = ["Avalanche", "Ethereum", "Base"]; @@ -40,61 +42,64 @@ describe("Environment", () => { const localhost = LOCALHOSTS[chainName] as string; describe(`Forked Network: ${chainName}`, () => { - const provider = new ethers.providers.StaticJsonRpcProvider(localhost); + const provider = new ethers.JsonRpcProvider(localhost); const wallets = WALLET_PRIVATE_KEYS.map((key) => new ethers.Wallet(key, provider)); - const owner = new ethers.Wallet(OWNER_PRIVATE_KEY, provider); + const owner = new ethers.NonceManager(new ethers.Wallet(OWNER_PRIVATE_KEY, provider)); it("Wallets", async () => { - const balances = await Promise.all(wallets.map((wallet) => wallet.getBalance())); + const balances = await Promise.all( + wallets.map((wallet) => wallet.provider?.getBalance(wallet.address)), + ); for (const balance of balances) { - expect(balance.toString()).equals("10000000000000000000000"); + expect(balance!.toString()).equals("10000000000000000000000"); } }); it("Modify Core Bridge", async () => { const coreBridge = IWormhole__factory.connect(wormholeAddress, provider); - const actualChainId = await coreBridge.chainId(); + const actualChainId = Number(await coreBridge.chainId()); expect(actualChainId).to.equal(chainId); // fetch current coreBridge protocol fee - const messageFee = await coreBridge.messageFee(); - expect(messageFee.eq(WORMHOLE_MESSAGE_FEE)).to.be.true; + const messageFee = Number(await coreBridge.messageFee()); + expect(messageFee).to.equal(WORMHOLE_MESSAGE_FEE); // override guardian set { // check guardian set index - const guardianSetIndex = await coreBridge.getCurrentGuardianSetIndex(); + const guardianSetIndex = Number(await coreBridge.getCurrentGuardianSetIndex()); expect(guardianSetIndex).to.equal(WORMHOLE_GUARDIAN_SET_INDEX); // override guardian set - const abiCoder = ethers.utils.defaultAbiCoder; + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); // get slot for Guardian Set at the current index - const guardianSetSlot = ethers.utils.keccak256( + const guardianSetSlot = ethers.keccak256( abiCoder.encode(["uint32", "uint256"], [guardianSetIndex, 2]), ); + const coreAddress = await coreBridge.getAddress(); // Overwrite all but first guardian set to zero address. This isn't // necessary, but just in case we inadvertently access these slots // for any reason. const numGuardians = await provider - .getStorageAt(coreBridge.address, guardianSetSlot) - .then((value) => ethers.BigNumber.from(value).toBigInt()); + .getStorage(coreAddress, guardianSetSlot) + .then((value) => BigInt(value)); + for (let i = 1; i < numGuardians; ++i) { await provider.send("anvil_setStorageAt", [ - coreBridge.address, + coreAddress, abiCoder.encode( ["uint256"], [ - ethers.BigNumber.from( - ethers.utils.keccak256(guardianSetSlot), - ).add(i), + encoding.bignum.decode(ethers.keccak256(guardianSetSlot)) + + BigInt(i), ], ), - ethers.utils.hexZeroPad("0x0", 32), + encoding.hex.encode(encoding.bignum.toBytes(0n, 32), true), ]); } @@ -102,23 +107,21 @@ describe("Environment", () => { // in the function argument. const devnetGuardian = new ethers.Wallet(GUARDIAN_PRIVATE_KEY).address; await provider.send("anvil_setStorageAt", [ - coreBridge.address, + coreAddress, abiCoder.encode( ["uint256"], [ - ethers.BigNumber.from(ethers.utils.keccak256(guardianSetSlot)).add( - 0, // just explicit w/ index 0 - ), + encoding.bignum.decode(ethers.keccak256(guardianSetSlot)) + 0n, // just explicit w/ index 0 ], ), - ethers.utils.hexZeroPad(devnetGuardian, 32), + new EvmAddress(devnetGuardian).toUniversalAddress().toString(), ]); // change the length to 1 guardian await provider.send("anvil_setStorageAt", [ - coreBridge.address, + coreAddress, guardianSetSlot, - ethers.utils.hexZeroPad("0x1", 32), + encoding.hex.encode(encoding.bignum.toBytes(1n, 32), true), ]); // Confirm guardian set override @@ -147,23 +150,21 @@ describe("Environment", () => { await provider.send("anvil_impersonateAccount", [attesterManager]); await provider.send("anvil_setBalance", [ attesterManager, - ethers.BigNumber.from("1000000000000000000")._hex, + encoding.hex.encode(encoding.bignum.toBytes(1000000000000000000n), true), ]); + const attesterSigner = await provider.getSigner(attesterManager); // instantiate message transmitter const messageTransmitter = await circleBridge .localMessageTransmitter() .then((address) => - IMessageTransmitter__factory.connect( - address, - provider.getSigner(attesterManager), - ), + IMessageTransmitter__factory.connect(address, attesterSigner), ); // const existingAttester = await messageTransmitter.getEnabledAttester(0); // update the number of required attestations to one await messageTransmitter - .setSignatureThreshold(ethers.BigNumber.from("1")) + .setSignatureThreshold(1n) .then((tx) => mineWait(provider, tx)); // enable devnet guardian as attester @@ -182,14 +183,13 @@ describe("Environment", () => { .localMessageTransmitter() .then((address) => IMessageTransmitter__factory.connect(address, provider)) .then((messageTransmitter) => - messageTransmitter.getEnabledAttester( - numAttesters.sub(ethers.BigNumber.from("1")), - ), + messageTransmitter.getEnabledAttester(numAttesters - 1n), ); expect(myAttester.address).to.equal(attester); }); it("Mint CCTP USDC", async () => { + const ownerAddress = await owner.getAddress(); // fetch master minter address const masterMinter = await IUSDC__factory.connect( usdcAddress, @@ -200,18 +200,18 @@ describe("Environment", () => { await provider.send("anvil_impersonateAccount", [masterMinter]); await provider.send("anvil_setBalance", [ masterMinter, - ethers.BigNumber.from("1000000000000000000")._hex, + encoding.hex.encode(encoding.bignum.encode(1000000000000000000n), true), ]); // configure my wallet as minter { const usdc = IUSDC__factory.connect( usdcAddress, - provider.getSigner(masterMinter), + await provider.getSigner(masterMinter), ); await usdc - .configureMinter(owner.address, ethers.constants.MaxUint256) + .configureMinter(ownerAddress, ethers.MaxUint256) .then((tx) => mineWait(provider, tx)); } @@ -221,17 +221,24 @@ describe("Environment", () => { // mint USDC and confirm with a balance check { const usdc = IUSDC__factory.connect(usdcAddress, owner); - const amount = ethers.utils.parseUnits("69420", 6); + const amount = ethers.parseUnits("69420", 6); - const balanceBefore = await usdc.balanceOf(owner.address); + const balanceBefore = await usdc.balanceOf(ownerAddress); - await usdc.mint(owner.address, amount).then((tx) => mineWait(provider, tx)); + await usdc.mint(ownerAddress, amount).then((tx) => mineWait(provider, tx)); - const balanceAfter = await usdc.balanceOf(owner.address); - expect(balanceAfter.sub(balanceBefore).eq(amount)).is.true; + const balanceAfter = await usdc.balanceOf(ownerAddress); + expect(balanceAfter - balanceBefore).to.eq(amount); - await usdc - .transfer("0x0000000000000000000000000000000000000001", balanceAfter) + await usdc.transfer + .populateTransaction( + "0x0000000000000000000000000000000000000001", + balanceAfter, + ) + .then(async (txreq) => { + txreq.nonce = await owner.getNonce(); + return await owner.signer.sendTransaction(txreq); + }) .then((tx) => mineWait(provider, tx)); } }); @@ -243,7 +250,9 @@ describe("Environment", () => { const scripts = `${__dirname}/../../sh`; const cmd = `bash ${scripts}/deploy_matching_engine.sh ` + - `-n localnet -c ${chainName} -u ${localhost} -k ${owner.privateKey} ` + + `-n localnet -c ${chainName} -u ${localhost} -k ${ + (owner.signer as ethers.Wallet).privateKey + } ` + `> /dev/null 2>&1`; const out = execSync(cmd, { encoding: "utf8" }); @@ -256,7 +265,7 @@ describe("Environment", () => { const scripts = `${__dirname}/../../sh`; const cmd = `bash ${scripts}/upgrade_matching_engine.sh ` + - `-n localnet -c ${chainName} -u ${localhost} -k ${owner.privateKey}` + + `-n localnet -c ${chainName} -u ${localhost} -k ${OWNER_PRIVATE_KEY}` + `> /dev/null 2>&1`; const out = execSync(cmd, { encoding: "utf8" }); await provider.send("evm_setAutomine", [false]); @@ -269,7 +278,7 @@ describe("Environment", () => { const scripts = `${__dirname}/../../sh`; const cmd = `bash ${scripts}/deploy_token_router.sh ` + - `-n localnet -c ${chainName} -u ${localhost} -k ${owner.privateKey} ` + + `-n localnet -c ${chainName} -u ${localhost} -k ${OWNER_PRIVATE_KEY} ` + `> /dev/null 2>&1`; const out = execSync(cmd, { encoding: "utf8" }); @@ -282,7 +291,7 @@ describe("Environment", () => { const scripts = `${__dirname}/../../sh`; const cmd = `bash ${scripts}/upgrade_token_router.sh ` + - `-n localnet -c ${chainName} -u ${localhost} -k ${owner.privateKey}` + + `-n localnet -c ${chainName} -u ${localhost} -k ${OWNER_PRIVATE_KEY}` + `> /dev/null 2>&1`; const out = execSync(cmd, { encoding: "utf8" }); await provider.send("evm_setAutomine", [false]); diff --git a/evm/ts/tests/01__registration.ts b/evm/ts/tests/01__registration.ts index 6c3c01f3..17ea3549 100644 --- a/evm/ts/tests/01__registration.ts +++ b/evm/ts/tests/01__registration.ts @@ -22,9 +22,7 @@ describe("Registration", () => { describe(`Register Token Routers on ${MATCHING_ENGINE_NAME} Matching Engine`, () => { const env = parseLiquidityLayerEnvFile(`${envPath}/${MATCHING_ENGINE_NAME}.env`); - const provider = new ethers.providers.StaticJsonRpcProvider( - LOCALHOSTS[MATCHING_ENGINE_NAME], - ); + const provider = new ethers.JsonRpcProvider(LOCALHOSTS[MATCHING_ENGINE_NAME]); const assistant = new ethers.Wallet(OWNER_ASSISTANT_PRIVATE_KEY, provider); const matchingEngineAddress = toUniversal("Avalanche", env.matchingEngineAddress).toNative( @@ -65,7 +63,7 @@ describe("Registration", () => { for (const chainName of CHAIN_PATHWAYS) { describe(`Register Token Routers on ${chainName}`, () => { const env = parseLiquidityLayerEnvFile(`${envPath}/${chainName}.env`); - const provider = new ethers.providers.StaticJsonRpcProvider(LOCALHOSTS[chainName]); + const provider = new ethers.JsonRpcProvider(LOCALHOSTS[chainName]); const assistant = new ethers.Wallet(OWNER_ASSISTANT_PRIVATE_KEY, provider); const router = ITokenRouter__factory.connect(env.tokenRouterAddress, assistant); diff --git a/evm/ts/tests/02__configuration.ts b/evm/ts/tests/02__configuration.ts index 7788c72f..e6190c61 100644 --- a/evm/ts/tests/02__configuration.ts +++ b/evm/ts/tests/02__configuration.ts @@ -21,7 +21,7 @@ describe("Configuration", () => { describe("Token Router Configuration", () => { for (const chainName of CHAIN_PATHWAYS) { const env = parseLiquidityLayerEnvFile(`${envPath}/${chainName}.env`); - const provider = new ethers.providers.StaticJsonRpcProvider(LOCALHOSTS[chainName]); + const provider = new ethers.JsonRpcProvider(LOCALHOSTS[chainName]); const assistant = new ethers.Wallet(OWNER_ASSISTANT_PRIVATE_KEY, provider); const router = ITokenRouter__factory.connect(env.tokenRouterAddress, assistant); @@ -45,7 +45,7 @@ describe("Configuration", () => { it(`Set Infinite Approval For ${chainName}`, async () => { await router - .setCctpAllowance(ethers.constants.MaxUint256) + .setCctpAllowance(ethers.MaxUint256) .then((tx) => mineWait(provider, tx)); }); } @@ -54,9 +54,7 @@ describe("Configuration", () => { describe("Matching Engine Configuration", () => { it("Set Infinite Approval For Matching Engine", async () => { const env = parseLiquidityLayerEnvFile(`${envPath}/${MATCHING_ENGINE_NAME}.env`); - const provider = new ethers.providers.StaticJsonRpcProvider( - LOCALHOSTS[MATCHING_ENGINE_NAME], - ); + const provider = new ethers.JsonRpcProvider(LOCALHOSTS[MATCHING_ENGINE_NAME]); const assistant = new ethers.Wallet(OWNER_ASSISTANT_PRIVATE_KEY, provider); const matchingEngineAddress = toUniversal( @@ -68,9 +66,7 @@ describe("Configuration", () => { assistant, ); - await engine - .setCctpAllowance(ethers.constants.MaxUint256) - .then((tx) => mineWait(provider, tx)); + await engine.setCctpAllowance(ethers.MaxUint256).then((tx) => mineWait(provider, tx)); }); }); }); diff --git a/evm/ts/tests/03__marketOrder.ts b/evm/ts/tests/03__marketOrder.ts index 60b16ce3..cccfdb45 100644 --- a/evm/ts/tests/03__marketOrder.ts +++ b/evm/ts/tests/03__marketOrder.ts @@ -26,7 +26,7 @@ const CHAIN_PATHWAYS: ValidNetwork[][] = [ ["Base", "Avalanche"], ]; -const TEST_AMOUNT = ethers.utils.parseUnits("1000", 6); +const TEST_AMOUNT = ethers.parseUnits("1000", 6); describe("Market Order Business Logic -- CCTP to CCTP", () => { const envPath = `${__dirname}/../../env/localnet`; @@ -39,9 +39,7 @@ describe("Market Order Business Logic -- CCTP to CCTP", () => { describe(`${fromChainName} <> ${toChainName}`, () => { // From setup. - const fromProvider = new ethers.providers.StaticJsonRpcProvider( - LOCALHOSTS[fromChainName], - ); + const fromProvider = new ethers.JsonRpcProvider(LOCALHOSTS[fromChainName]); const fromWallet = new ethers.Wallet(WALLET_PRIVATE_KEYS[0], fromProvider); const fromEnv = parseLiquidityLayerEnvFile(`${envPath}/${fromChainName}.env`); @@ -58,7 +56,7 @@ describe("Market Order Business Logic -- CCTP to CCTP", () => { })(); // To setup. - const toProvider = new ethers.providers.StaticJsonRpcProvider(LOCALHOSTS[toChainName]); + const toProvider = new ethers.JsonRpcProvider(LOCALHOSTS[toChainName]); const toWallet = new ethers.Wallet(WALLET_PRIVATE_KEYS[1], toProvider); const toEnv = parseLiquidityLayerEnvFile(`${envPath}/${toChainName}.env`); @@ -118,14 +116,19 @@ describe("Market Order Business Logic -- CCTP to CCTP", () => { minAmountOut, fromWallet.address, ) + .then(async (txReq) => { + txReq.nonce = await fromWallet.getNonce(); + return await fromWallet.sendTransaction(txReq); + }) .then((tx) => mineWait(fromProvider, tx)) .catch((err) => { console.log(err); console.log(errorDecoder(err)); throw err; }); + const transactionResult = await fromTokenRouter.getTransactionResults( - receipt.transactionHash, + receipt!.hash, ); expect(transactionResult.wormhole.emitterAddress).to.eql( @@ -137,7 +140,7 @@ describe("Market Order Business Logic -- CCTP to CCTP", () => { const fillVaa = await guardianNetwork.observeEvm( fromProvider, fromChainName, - receipt, + receipt!, ); const circleBridgeMessage = transactionResult.circleMessage!; @@ -160,6 +163,7 @@ describe("Market Order Business Logic -- CCTP to CCTP", () => { const receipt = await toTokenRouter .redeemFillTx(orderResponse) + .then((txReq) => toWallet.sendTransaction(txReq)) .then((tx) => mineWait(toProvider, tx)) .catch((err) => { console.log(err); @@ -169,7 +173,7 @@ describe("Market Order Business Logic -- CCTP to CCTP", () => { const balanceAfter = await usdc.balanceOf(toWallet.address); - expect(balanceAfter.sub(balanceBefore).toString()).to.eql( + expect((balanceAfter - balanceBefore).toString()).to.eql( localVariables.get("amountIn").toString(), ); expect(localVariables.delete("amountIn")).is.true; diff --git a/evm/ts/tests/04__fastMarketOrder.ts b/evm/ts/tests/04__fastMarketOrder.ts index 9cc2f90c..549d0fc9 100644 --- a/evm/ts/tests/04__fastMarketOrder.ts +++ b/evm/ts/tests/04__fastMarketOrder.ts @@ -29,7 +29,12 @@ import { } from "../src/testing"; import { toChainId } from "@wormhole-foundation/sdk-base"; -import { deserialize, keccak256, toUniversal } from "@wormhole-foundation/sdk-definitions"; +import { + deserialize, + keccak256, + serializePayload, + toUniversal, +} from "@wormhole-foundation/sdk-definitions"; import "@wormhole-foundation/sdk-evm"; // Cannot send a fast market order from the matching engine chain. @@ -40,8 +45,11 @@ const CHAIN_PATHWAYS: ValidNetwork[][] = [ ["Ethereum", "Avalanche"], ]; -const TEST_AMOUNT = ethers.utils.parseUnits("1000", 6); -const FEE_AMOUNT = BigInt(ethers.utils.parseUnits("10", 6).toString()); +const TEST_AMOUNT = ethers.parseUnits("1000", 6); +const FEE_AMOUNT = BigInt(ethers.parseUnits("10", 6).toString()); + +const sleep = async (seconds: number) => + await new Promise((resolve) => setTimeout(resolve, seconds * 1000)); describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Mocha.Suite) { const envPath = `${__dirname}/../../env/localnet`; @@ -50,15 +58,13 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const circleAttester = new CircleAttester(); // Matching Engine configuration. - const engineProvider = new ethers.providers.StaticJsonRpcProvider( - LOCALHOSTS[MATCHING_ENGINE_NAME], - ); + const engineProvider = new ethers.JsonRpcProvider(LOCALHOSTS[MATCHING_ENGINE_NAME]); const engineWallet = new ethers.Wallet(WALLET_PRIVATE_KEYS[2], engineProvider); const engineEnv = parseLiquidityLayerEnvFile(`${envPath}/${MATCHING_ENGINE_NAME}.env`); const engine = (() => { if (engineEnv.chainType === ChainType.Evm) { return new EvmMatchingEngine( - engineWallet, + engineProvider, toUniversal("Avalanche", engineEnv.matchingEngineAddress) .toNative("Avalanche") .toString(), @@ -70,20 +76,28 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc })(); // Auction participants. - const initialBidder = new ethers.Wallet(WALLET_PRIVATE_KEYS[3], engineProvider); - const bidderTwo = new ethers.Wallet(WALLET_PRIVATE_KEYS[4], engineProvider); - const bidderThree = new ethers.Wallet(WALLET_PRIVATE_KEYS[5], engineProvider); - const highestBidder = new ethers.Wallet(WALLET_PRIVATE_KEYS[6], engineProvider); - const liquidator = new ethers.Wallet(WALLET_PRIVATE_KEYS[7], engineProvider); + const initialBidder = new ethers.NonceManager( + new ethers.Wallet(WALLET_PRIVATE_KEYS[3], engineProvider), + ); + const bidderTwo = new ethers.NonceManager( + new ethers.Wallet(WALLET_PRIVATE_KEYS[4], engineProvider), + ); + const bidderThree = new ethers.NonceManager( + new ethers.Wallet(WALLET_PRIVATE_KEYS[5], engineProvider), + ); + const highestBidder = new ethers.NonceManager( + new ethers.Wallet(WALLET_PRIVATE_KEYS[6], engineProvider), + ); + const liquidator = new ethers.NonceManager( + new ethers.Wallet(WALLET_PRIVATE_KEYS[7], engineProvider), + ); for (const [fromChainName, toChainName] of CHAIN_PATHWAYS) { const localVariables = new Map(); describe(`${fromChainName} <> ${toChainName}`, () => { // From setup. - const fromProvider = new ethers.providers.StaticJsonRpcProvider( - LOCALHOSTS[fromChainName], - ); + const fromProvider = new ethers.JsonRpcProvider(LOCALHOSTS[fromChainName]); const fromWallet = new ethers.Wallet(WALLET_PRIVATE_KEYS[0], fromProvider); const fromEnv = parseLiquidityLayerEnvFile(`${envPath}/${fromChainName}.env`); @@ -100,7 +114,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc })(); // To setup. - const toProvider = new ethers.providers.StaticJsonRpcProvider(LOCALHOSTS[toChainName]); + const toProvider = new ethers.JsonRpcProvider(LOCALHOSTS[toChainName]); const toWallet = new ethers.Wallet(WALLET_PRIVATE_KEYS[1], toProvider); const toEnv = parseLiquidityLayerEnvFile(`${envPath}/${toChainName}.env`); @@ -169,14 +183,16 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc minAmountOut, fromWallet.address, ) + .then((txReq) => fromWallet.sendTransaction(txReq)) .then((tx) => mineWait(fromProvider, tx)) .catch((err) => { console.log(err); console.log(errorDecoder(err)); throw err; }); + const transactionResult = await fromTokenRouter.getTransactionResults( - receipt.transactionHash, + receipt!.hash, ); expect(transactionResult.wormhole.emitterAddress).to.eql( tryNativeToUint8Array(fromEnv.tokenRouterAddress, fromChainName), @@ -190,7 +206,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const signedVaas = await guardianNetwork.observeManyEvm( fromProvider, fromChainName, - receipt, + receipt!, ); expect(signedVaas.length).to.eql(2); @@ -226,15 +242,25 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const initialDeposit = fastOrder.amountIn + fastOrder.maxFee; // Prepare usdc for the auction. - const usdc = IERC20__factory.connect(engineEnv.tokenAddress, initialBidder); - await mintNativeUsdc(usdc, initialBidder.address, initialDeposit); - await usdc.approve(engine.address, initialDeposit); + const usdc = IERC20__factory.connect( + engineEnv.tokenAddress, + initialBidder.provider!, + ); + const initialBidderAddress = await initialBidder.getAddress(); + await mintNativeUsdc(usdc, initialBidderAddress, initialDeposit); + await usdc.approve + .populateTransaction(engine.address, initialDeposit) + .then((txReq) => initialBidder.sendTransaction(txReq)) + .then((tx) => mineWait(engineProvider, tx)); - const balanceBefore = await usdc.balanceOf(initialBidder.address); + const balanceBefore = await usdc.balanceOf(initialBidderAddress); const receipt = await engine - .connect(initialBidder) + .connect(initialBidder.provider!) .placeInitialBid(fastVaa, fastOrder.maxFee) + .then(async (txReq) => { + return await initialBidder.sendTransaction(txReq); + }) .then((tx) => mineWait(engineProvider, tx)) .catch((err) => { console.log(err); @@ -242,8 +268,8 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc throw err; }); - const balanceAfter = await usdc.balanceOf(initialBidder.address); - expect(balanceBefore.sub(balanceAfter).toString()).to.eql( + const balanceAfter = await usdc.balanceOf(initialBidderAddress); + expect((balanceBefore - balanceAfter).toString()).to.eql( initialDeposit.toString(), ); @@ -252,12 +278,12 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc localVariables.get("auctionId"), ); - expect(auctionData.status).to.eql(1); + expect(auctionData.status).to.eql(1n); expect(auctionData.startBlock.toString()).to.eql( - receipt.blockNumber.toString(), + receipt!.blockNumber.toString(), ); - expect(auctionData.highestBidder).to.eql(initialBidder.address); - expect(auctionData.initialBidder).to.eql(initialBidder.address); + expect(auctionData.highestBidder).to.eql(initialBidderAddress); + expect(auctionData.initialBidder).to.eql(initialBidderAddress); expect(auctionData.amount.toString()).to.eql(fastOrder.amountIn.toString()); expect(auctionData.securityDeposit.toString()).to.eql( fastOrder.maxFee.toString(), @@ -269,43 +295,54 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const auctionId = localVariables.get("auctionId") as Uint8Array; const auctionInfoBefore = await engine.liveAuctionInfo(auctionId); - const startingBid = ethers.BigNumber.from(auctionInfoBefore.bidPrice); - const initialDeposit = ethers.BigNumber.from(auctionInfoBefore.amount).add( - ethers.BigNumber.from(auctionInfoBefore.securityDeposit), - ); - expect(startingBid.gt(0) && initialDeposit.gt(0)).is.true; + const startingBid = auctionInfoBefore.bidPrice; + const initialDeposit = + auctionInfoBefore.amount + auctionInfoBefore.securityDeposit; + + expect(startingBid > 0n && initialDeposit > 0n).is.true; // Create array of test bids. This structure should not change, otherwise // the following tests will fail. const bids: ScoreKeeper[] = [ { player: bidderTwo, - bid: startingBid.sub(1), - balance: ethers.BigNumber.from(0), + bid: startingBid - 1n, + balance: 0n, }, { player: bidderThree, - bid: startingBid.div(2), - balance: ethers.BigNumber.from(0), + bid: startingBid / 2n, + balance: 0n, }, { player: highestBidder, - bid: startingBid.div(3), - balance: ethers.BigNumber.from(0), + bid: startingBid / 3n, + balance: 0n, }, ]; // Loop through and make multiple bids in the same block. for (let i = 0; i < bids.length; i++) { const player = bids[i].player; + const playerAddress = await player.getAddress(); + const usdc = IERC20__factory.connect(engineEnv.tokenAddress, player); - await mintNativeUsdc(usdc, player.address, initialDeposit, false); + await mintNativeUsdc(usdc, playerAddress, initialDeposit, false); await usdc.approve(engine.address, initialDeposit); - bids[i].balance = await usdc.balanceOf(player.address); + // sleep because otherwise nonce collisions (??) + await sleep(1); + + bids[i].balance = await usdc.balanceOf(playerAddress); // Improve the bid. - await engine.connect(player).improveBid(auctionId, bids[i].bid); + await engine + .connect(player.provider!) + .improveBid(auctionId, bids[i].bid) + .then(async (txReq) => { + txReq.nonce = await player.getNonce("pending"); + return await player.sendTransaction(txReq); + }); } // Mine the block. @@ -315,14 +352,15 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // should've been refunded. for (let i = 0; i < bids.length; i++) { const player = bids[i].player; + const playerAddress = await player.getAddress(); const usdc = IERC20__factory.connect(engineEnv.tokenAddress, player); - const balanceAfter = await usdc.balanceOf(player.address); + const balanceAfter = await usdc.balanceOf(playerAddress); if (i == 2) { - expect(balanceAfter.sub(bids[i].balance).toString()).to.eql("0"); + expect((balanceAfter - bids[i].balance).toString()).to.eql("0"); } else { expect(balanceAfter.toString()).to.eql( - bids[i].balance.add(initialDeposit).toString(), + (bids[i].balance + initialDeposit).toString(), ); } } @@ -330,11 +368,11 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Validate state changes. const auctionInfoAfter = await engine.liveAuctionInfo(auctionId); - expect(auctionInfoAfter.status).to.eql(1); + expect(auctionInfoAfter.status).to.eql(1n); expect(auctionInfoAfter.startBlock.toString()).to.eql( auctionInfoBefore.startBlock.toString(), ); - expect(auctionInfoAfter.highestBidder).to.eql(highestBidder.address); + expect(auctionInfoAfter.highestBidder).to.eql(await highestBidder.getAddress()); expect(auctionInfoAfter.initialBidder).to.eql(auctionInfoBefore.initialBidder); expect(auctionInfoAfter.amount.toString()).to.eql( auctionInfoBefore.amount.toString(), @@ -353,13 +391,14 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Fetch the initial bidder so we can do a balance check. const auctionInfo = await engine.liveAuctionInfo(auctionId); - const usdc = IERC20__factory.connect(engineEnv.tokenAddress, highestBidder); - const balanceBefore = await usdc.balanceOf(highestBidder.address); + const usdc = IERC20__factory.connect(engineEnv.tokenAddress, engineProvider); + const balanceBefore = await usdc.balanceOf(await highestBidder.getAddress()); const initialBidderBefore = await usdc.balanceOf(auctionInfo.initialBidder); const receipt = await engine - .connect(highestBidder) + .connect(engineProvider) .executeFastOrder(localVariables.get("fastVaa")) + .then((txReq) => highestBidder.sendTransaction(txReq)) .then((tx) => mineWait(engineProvider, tx)) .catch((err) => { console.log(err); @@ -367,9 +406,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc throw err; }); - const transactionResult = await engine.getTransactionResults( - receipt.transactionHash, - ); + const transactionResult = await engine.getTransactionResults(receipt!.hash); if (toChainName == MATCHING_ENGINE_NAME) { expect(transactionResult.wormhole.emitterAddress).to.eql( @@ -388,28 +425,26 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc expect(transactionResult.fastMessage).is.undefined; // Validate state and balance changes. - const balanceAfter = await usdc.balanceOf(highestBidder.address); + const balanceAfter = await usdc.balanceOf(await highestBidder.getAddress()); const initialBidderAfter = await usdc.balanceOf(auctionInfo.initialBidder); const initAuctionFee = await fromTokenRouter.getInitialAuctionFee(); - expect(balanceAfter.sub(balanceBefore).toString()).to.eql( - ethers.BigNumber.from(auctionInfo.bidPrice) - .add(ethers.BigNumber.from(auctionInfo.securityDeposit)) - .toString(), + expect((balanceAfter - balanceBefore).toString()).to.eql( + (auctionInfo.bidPrice + auctionInfo.securityDeposit).toString(), ); - expect(initialBidderAfter.sub(initialBidderBefore).eq(initAuctionFee)).is.true; + expect(initialBidderAfter - initialBidderBefore).to.eql(initAuctionFee); // Auction status should be complete (2). const auctionStatus = await engine .liveAuctionInfo(auctionId) .then((info) => info.status); - expect(auctionStatus).to.eql(2); + expect(auctionStatus).to.eql(2n); // Fetch and store the vaa for redeeming the fill. const signedVaa = await guardianNetwork.observeEvm( engineProvider, MATCHING_ENGINE_NAME, - receipt, + receipt!, ); let orderResponse: OrderResponse; @@ -444,6 +479,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const receipt = await toTokenRouter .redeemFillTx(orderResponse) + .then((txReq) => toWallet.sendTransaction(txReq)) .then((tx) => mineWait(toProvider, tx)) .catch((err) => { console.log(err); @@ -452,17 +488,12 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc }); // Validate balance changes. - const [bidPrice, amount] = await engine - .liveAuctionInfo(auctionId) - .then((info) => [ - ethers.BigNumber.from(info.bidPrice), - ethers.BigNumber.from(info.amount), - ]); + const { bidPrice, amount } = await engine.liveAuctionInfo(auctionId); const initAuctionFee = await fromTokenRouter.getInitialAuctionFee(); const balanceAfter = await usdc.balanceOf(toWallet.address); - expect(balanceAfter.sub(balanceBefore).toString()).to.eql( - amount.sub(bidPrice).sub(initAuctionFee).toString(), + expect((balanceAfter - balanceBefore).toString()).to.eql( + (amount - bidPrice - initAuctionFee).toString(), ); }); @@ -476,13 +507,14 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Fetch balance of player four since they were the highest bidder. const usdc = IERC20__factory.connect(engineEnv.tokenAddress, engineProvider); - const balanceBefore = await usdc.balanceOf(highestBidder.address); + const balanceBefore = await usdc.balanceOf(await highestBidder.getAddress()); const expectedAmount = await engine .liveAuctionInfo(auctionId) .then((info) => info.amount); const receipt = await engine .executeSlowOrderAndRedeem(fastVaa, params) + .then((txReq) => engineWallet.sendTransaction(txReq)) .then((tx) => mineWait(engineProvider, tx)) .catch((err) => { console.log(err); @@ -490,8 +522,8 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc throw err; }); - const balanceAfter = await usdc.balanceOf(highestBidder.address); - expect(balanceAfter.sub(balanceBefore).toString()).to.eql( + const balanceAfter = await usdc.balanceOf(await highestBidder.getAddress()); + expect((balanceAfter - balanceBefore).toString()).to.eql( expectedAmount.toString(), ); }); @@ -525,8 +557,12 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc if (fromEnv.chainType == ChainType.Evm) { const usdc = IERC20__factory.connect(fromEnv.tokenAddress, fromWallet); const amount = await usdc.balanceOf(fromWallet.address); - await usdc - .approve(fromTokenRouter.address, amount) + await usdc.approve + .populateTransaction(fromTokenRouter.address, amount) + .then(async (txReq) => { + txReq.nonce = await fromWallet.getNonce("pending"); + return fromWallet.sendTransaction(txReq); + }) .then((tx) => mineWait(fromProvider, tx)); return BigInt(amount.toString()); @@ -550,6 +586,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc minAmountOut, fromWallet.address, ) + .then((txReq) => fromWallet.sendTransaction(txReq)) .then((tx) => mineWait(fromProvider, tx)) .catch((err) => { console.log(err); @@ -557,7 +594,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc throw err; }); const transactionResult = await fromTokenRouter.getTransactionResults( - receipt.transactionHash, + receipt!.hash, ); expect(transactionResult.wormhole.emitterAddress).to.eql( tryNativeToUint8Array(fromEnv.tokenRouterAddress, fromChainName), @@ -571,7 +608,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const signedVaas = await guardianNetwork.observeManyEvm( fromProvider, fromChainName, - receipt, + receipt!, ); expect(signedVaas.length).to.eql(2); @@ -606,16 +643,21 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Security deposit amount of the initial bid. const initialDeposit = fastOrder.amountIn + fastOrder.maxFee; + const initialBidderAddress = await initialBidder.getAddress(); // Prepare usdc for the auction. const usdc = IERC20__factory.connect(engineEnv.tokenAddress, initialBidder); - await mintNativeUsdc(usdc, initialBidder.address, initialDeposit); + await mintNativeUsdc(usdc, initialBidderAddress, initialDeposit); await usdc.approve(engine.address, initialDeposit); - const balanceBefore = await usdc.balanceOf(initialBidder.address); + const balanceBefore = await usdc.balanceOf(initialBidderAddress); const receipt = await engine - .connect(initialBidder) + .connect(initialBidder.provider!) .placeInitialBid(fastVaa, fastOrder.maxFee) + .then(async (txReq) => { + txReq.nonce = await initialBidder.getNonce("pending"); + return initialBidder.sendTransaction(txReq); + }) .then((tx) => mineWait(engineProvider, tx)) .catch((err) => { console.log(err); @@ -623,8 +665,8 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc throw err; }); - const balanceAfter = await usdc.balanceOf(initialBidder.address); - expect(balanceBefore.sub(balanceAfter).toString()).to.eql( + const balanceAfter = await usdc.balanceOf(initialBidderAddress); + expect((balanceBefore - balanceAfter).toString()).to.eql( initialDeposit.toString(), ); @@ -633,12 +675,12 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc localVariables.get("auctionId"), ); - expect(auctionData.status).to.eql(1); + expect(auctionData.status).to.eql(1n); expect(auctionData.startBlock.toString()).to.eql( - receipt.blockNumber.toString(), + receipt!.blockNumber.toString(), ); - expect(auctionData.highestBidder).to.eql(initialBidder.address); - expect(auctionData.initialBidder).to.eql(initialBidder.address); + expect(auctionData.highestBidder).to.eql(initialBidderAddress); + expect(auctionData.initialBidder).to.eql(initialBidderAddress); expect(auctionData.amount.toString()).to.eql(fastOrder.amountIn.toString()); expect(auctionData.securityDeposit.toString()).to.eql( fastOrder.maxFee.toString(), @@ -650,45 +692,52 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const auctionId = localVariables.get("auctionId") as Uint8Array; const auctionInfoBefore = await engine.liveAuctionInfo(auctionId); - const startingBid = ethers.BigNumber.from(auctionInfoBefore.bidPrice); - const initialDeposit = ethers.BigNumber.from(auctionInfoBefore.amount).add( - ethers.BigNumber.from(auctionInfoBefore.securityDeposit), - ); - expect(startingBid.gt(0) && initialDeposit.gt(0)).is.true; + const startingBid = auctionInfoBefore.bidPrice; + const initialDeposit = + auctionInfoBefore.amount + auctionInfoBefore.securityDeposit; + expect(startingBid > 0n && initialDeposit > 0n).is.true; // Create array of test bids. This structure should not change, otherwise // the following tests will fail. const bids: ScoreKeeper[] = [ { player: bidderTwo, - bid: startingBid.sub(1), - balance: ethers.BigNumber.from(0), + bid: startingBid - 1n, + balance: 0n, }, { player: bidderThree, - bid: startingBid.div(2), - balance: ethers.BigNumber.from(0), + bid: startingBid / 2n, + balance: 0n, }, { player: highestBidder, - bid: startingBid.div(3), - balance: ethers.BigNumber.from(0), + bid: startingBid / 3n, + balance: 0n, }, ]; // Loop through and make multiple bids in the same block. for (let i = 0; i < bids.length; i++) { const player = bids[i].player; + const playerAddress = await player.getAddress(); const usdc = IERC20__factory.connect(engineEnv.tokenAddress, player); - await mintNativeUsdc(usdc, player.address, initialDeposit, false); + await mintNativeUsdc(usdc, playerAddress, initialDeposit, false); await usdc.approve(engine.address, initialDeposit); - bids[i].balance = await usdc.balanceOf(player.address); + await sleep(1); + + bids[i].balance = await usdc.balanceOf(playerAddress); // Improve the bid. - await engine.connect(player).improveBid(auctionId, bids[i].bid); + await engine + .connect(player.provider!) + .improveBid(auctionId, bids[i].bid) + .then(async (txReq) => { + txReq.nonce = await player.getNonce("pending"); + return await player.sendTransaction(txReq); + }); } - // Mine the block. await mine(engineProvider); @@ -697,13 +746,13 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc for (let i = 0; i < bids.length; i++) { const player = bids[i].player; const usdc = IERC20__factory.connect(engineEnv.tokenAddress, player); - const balanceAfter = await usdc.balanceOf(player.address); + const balanceAfter = await usdc.balanceOf(await player.getAddress()); if (i == 2) { - expect(balanceAfter.sub(bids[i].balance).toString()).to.eql("0"); + expect((balanceAfter - bids[i].balance).toString()).to.eql("0"); } else { expect(balanceAfter.toString()).to.eql( - bids[i].balance.add(initialDeposit).toString(), + (bids[i].balance + initialDeposit).toString(), ); } } @@ -711,11 +760,11 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Validate state changes. const auctionInfoAfter = await engine.liveAuctionInfo(auctionId); - expect(auctionInfoAfter.status).to.eql(1); + expect(auctionInfoAfter.status).to.eql(1n); expect(auctionInfoAfter.startBlock.toString()).to.eql( auctionInfoBefore.startBlock.toString(), ); - expect(auctionInfoAfter.highestBidder).to.eql(highestBidder.address); + expect(auctionInfoAfter.highestBidder).to.eql(await highestBidder.getAddress()); expect(auctionInfoAfter.initialBidder).to.eql(auctionInfoBefore.initialBidder); expect(auctionInfoAfter.amount.toString()).to.eql( auctionInfoBefore.amount.toString(), @@ -733,20 +782,28 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc await engine .getPenaltyBlocks() .then((blocks) => - mineToPenaltyPeriod(auctionId, engine, engineProvider, blocks / 2), + mineToPenaltyPeriod( + auctionId, + engine, + engineProvider, + Number(blocks / 2n), + ), ); // Fetch the initial bidder so we can do a balance check. const auctionInfo = await engine.liveAuctionInfo(auctionId); const usdc = IERC20__factory.connect(engineEnv.tokenAddress, highestBidder); - const balanceBefore = await usdc.balanceOf(highestBidder.address); - const balanceLiquidatorBefore = await usdc.balanceOf(liquidator.address); + const balanceBefore = await usdc.balanceOf(await highestBidder.getAddress()); + const balanceLiquidatorBefore = await usdc.balanceOf( + await liquidator.getAddress(), + ); const initialBidderBefore = await usdc.balanceOf(auctionInfo.initialBidder); const receipt = await engine - .connect(liquidator) + .connect(liquidator.provider!) .executeFastOrder(localVariables.get("fastVaa")) + .then((txReq) => liquidator.sendTransaction(txReq)) .then((tx) => mineWait(engineProvider, tx)) .catch((err) => { console.log(err); @@ -756,9 +813,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const [penalty, reward] = await engine.calculateDynamicPenalty(auctionId); - const transactionResult = await engine.getTransactionResults( - receipt.transactionHash, - ); + const transactionResult = await engine.getTransactionResults(receipt!.hash); if (toChainName == MATCHING_ENGINE_NAME) { expect(transactionResult.wormhole.emitterAddress).to.eql( @@ -777,33 +832,36 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc expect(transactionResult.fastMessage).is.undefined; // Validate state and balance changes. - const balanceAfter = await usdc.balanceOf(highestBidder.address); + const balanceAfter = await usdc.balanceOf(await highestBidder.getAddress()); const initialBidderAfter = await usdc.balanceOf(auctionInfo.initialBidder); - const balanceLiquidatorAfter = await usdc.balanceOf(liquidator.address); + const balanceLiquidatorAfter = await usdc.balanceOf( + await liquidator.getAddress(), + ); const initAuctionFee = await fromTokenRouter.getInitialAuctionFee(); - expect(balanceAfter.sub(balanceBefore).toString()).to.eql( - ethers.BigNumber.from(auctionInfo.bidPrice) - .add(ethers.BigNumber.from(auctionInfo.securityDeposit)) - .sub(ethers.BigNumber.from(penalty).add(ethers.BigNumber.from(reward))) - .toString(), + expect((balanceAfter - balanceBefore).toString()).to.eql( + ( + auctionInfo.bidPrice + + auctionInfo.securityDeposit - + (penalty + reward) + ).toString(), ); - expect(balanceLiquidatorAfter.sub(balanceLiquidatorBefore).toString()).to.eql( + expect((balanceLiquidatorAfter - balanceLiquidatorBefore).toString()).to.eql( penalty.toString(), ); - expect(initialBidderAfter.sub(initialBidderBefore).eq(initAuctionFee)).is.true; + expect(initialBidderAfter - initialBidderBefore).eq(initAuctionFee); // Auction status should be complete (2). const auctionStatus = await engine .liveAuctionInfo(auctionId) .then((info) => info.status); - expect(auctionStatus).to.eql(2); + expect(auctionStatus).to.eql(2n); // Fetch and store the vaa for redeeming the fill. const signedVaa = await guardianNetwork.observeEvm( engineProvider, MATCHING_ENGINE_NAME, - receipt, + receipt!, ); let orderResponse: OrderResponse; @@ -841,6 +899,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const receipt = await toTokenRouter .redeemFillTx(orderResponse) + .then((txReq) => toWallet.sendTransaction(txReq)) .then((tx) => mineWait(toProvider, tx)) .catch((err) => { console.log(err); @@ -851,17 +910,14 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Validate balance changes. const [bidPrice, amount] = await engine .liveAuctionInfo(auctionId) - .then((info) => [ - ethers.BigNumber.from(info.bidPrice), - ethers.BigNumber.from(info.amount), - ]); + .then((info) => [info.bidPrice, info.amount]); const initAuctionFee = await fromTokenRouter.getInitialAuctionFee(); const balanceAfter = await usdc.balanceOf(toWallet.address); // Add the reward, since the fast auction wasn't executed during // the grace period. - expect(balanceAfter.sub(balanceBefore).toString()).to.eql( - amount.sub(bidPrice).sub(initAuctionFee).add(reward).toString(), + expect((balanceAfter - balanceBefore).toString()).to.eql( + (amount - bidPrice - initAuctionFee + reward).toString(), ); }); @@ -875,13 +931,14 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Fetch balance of player four since they were the highest bidder. const usdc = IERC20__factory.connect(engineEnv.tokenAddress, engineProvider); - const balanceBefore = await usdc.balanceOf(highestBidder.address); + const balanceBefore = await usdc.balanceOf(await highestBidder.getAddress()); const expectedAmount = await engine .liveAuctionInfo(auctionId) .then((info) => info.amount); const receipt = await engine .executeSlowOrderAndRedeem(fastVaa, params) + .then((txReq) => engineWallet.sendTransaction(txReq)) .then((tx) => mineWait(engineProvider, tx)) .catch((err) => { console.log(err); @@ -889,8 +946,8 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc throw err; }); - const balanceAfter = await usdc.balanceOf(highestBidder.address); - expect(balanceAfter.sub(balanceBefore).toString()).to.eql( + const balanceAfter = await usdc.balanceOf(await highestBidder.getAddress()); + expect((balanceAfter - balanceBefore).toString()).to.eql( expectedAmount.toString(), ); }); @@ -949,6 +1006,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc minAmountOut, fromWallet.address, ) + .then((txReq) => fromWallet.sendTransaction(txReq)) .then((tx) => mineWait(fromProvider, tx)) .catch((err) => { console.log(err); @@ -956,7 +1014,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc throw err; }); const transactionResult = await fromTokenRouter.getTransactionResults( - receipt.transactionHash, + receipt!.hash, ); expect(transactionResult.wormhole.emitterAddress).to.eql( tryNativeToUint8Array(fromEnv.tokenRouterAddress, fromChainName), @@ -970,7 +1028,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const signedVaas = await guardianNetwork.observeManyEvm( fromProvider, fromChainName, - receipt, + receipt!, ); expect(signedVaas.length).to.eql(2); @@ -1007,8 +1065,9 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const feeRecipientBefore = await usdc.balanceOf(engineEnv.feeRecipient!); const receipt = await engine - .connect(initialBidder) + .connect(initialBidder.provider!) .executeSlowOrderAndRedeem(fastVaa, params) + .then((txReq) => initialBidder.sendTransaction(txReq)) .then((tx) => mineWait(engineProvider, tx)) .catch((err) => { console.log(err); @@ -1018,13 +1077,11 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Balance check. const feeRecipientAfter = await usdc.balanceOf(engineEnv.feeRecipient!); - expect(feeRecipientAfter.sub(feeRecipientBefore).toString()).to.eql( + expect((feeRecipientAfter - feeRecipientBefore).toString()).to.eql( baseFee.toString(), ); - const transactionResult = await engine.getTransactionResults( - receipt.transactionHash, - ); + const transactionResult = await engine.getTransactionResults(receipt!.hash); if (toChainName == MATCHING_ENGINE_NAME) { expect(transactionResult.wormhole.emitterAddress).to.eql( @@ -1046,7 +1103,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const signedVaa = await guardianNetwork.observeEvm( engineProvider, MATCHING_ENGINE_NAME, - receipt, + receipt!, ); let orderResponse: OrderResponse; @@ -1073,7 +1130,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const auctionStatus = await engine .liveAuctionInfo(auctionId) .then((info) => info.status); - expect(auctionStatus).to.eql(2); + expect(auctionStatus).to.eql(2n); localVariables.set("fastOrderResponse", orderResponse); localVariables.set("baseFee", baseFee); @@ -1081,7 +1138,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc it(`To Network -- Redeem Fill`, async () => { const orderResponse = localVariables.get("fastOrderResponse") as OrderResponse; - const baseFee = localVariables.get("baseFee") as string; + const baseFee = localVariables.get("baseFee") as bigint; expect(localVariables.delete("fastOrderResponse")).is.true; expect(localVariables.delete("baseFee")).is.true; @@ -1090,6 +1147,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const receipt = await toTokenRouter .redeemFillTx(orderResponse) + .then((txReq) => toWallet.sendTransaction(txReq)) .then((tx) => mineWait(toProvider, tx)) .catch((err) => { console.log(err); @@ -1100,8 +1158,8 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Validate balance changes. const balanceAfter = await usdc.balanceOf(toWallet.address); - expect(balanceAfter.sub(balanceBefore).toString()).to.eql( - TEST_AMOUNT.sub(baseFee).toString(), + expect((balanceAfter - balanceBefore).toString()).to.eql( + (TEST_AMOUNT - baseFee).toString(), ); }); }); @@ -1150,7 +1208,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Set the deadline to the current block timestamp. const currentBlock = await engineProvider.getBlockNumber(); - const deadline = (await engineProvider.getBlock(currentBlock)).timestamp; + const deadline = (await engineProvider.getBlock(currentBlock))!.timestamp; const receipt = await fromTokenRouter .placeFastMarketOrderTx( @@ -1163,6 +1221,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc minAmountOut, fromWallet.address, ) + .then((txReq) => fromWallet.sendTransaction(txReq)) .then((tx) => mineWait(fromProvider, tx)) .catch((err) => { console.log(err); @@ -1170,7 +1229,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc throw err; }); const transactionResult = await fromTokenRouter.getTransactionResults( - receipt.transactionHash, + receipt!.hash, ); expect(transactionResult.wormhole.emitterAddress).to.eql( tryNativeToUint8Array(fromEnv.tokenRouterAddress, fromChainName), @@ -1184,7 +1243,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const signedVaas = await guardianNetwork.observeManyEvm( fromProvider, fromChainName, - receipt, + receipt!, ); expect(signedVaas.length).to.eql(2); @@ -1221,13 +1280,17 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Prepare usdc for the auction. const usdc = IERC20__factory.connect(engineEnv.tokenAddress, initialBidder); - await mintNativeUsdc(usdc, initialBidder.address, initialDeposit); + await mintNativeUsdc(usdc, await initialBidder.getAddress(), initialDeposit); await usdc.approve(engine.address, initialDeposit); let failedGracefully = false; const receipt = await engine - .connect(initialBidder) + .connect(initialBidder.provider!) .placeInitialBid(fastVaa, fastOrder.maxFee) + .then(async (txReq) => { + txReq.nonce = await initialBidder.getNonce("pending"); + return initialBidder.sendTransaction(txReq); + }) .then((tx) => mineWait(engineProvider, tx)) .catch((err) => { const error = errorDecoder(err); @@ -1256,9 +1319,15 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const usdc = IERC20__factory.connect(engineEnv.tokenAddress, engineProvider); const feeRecipientBefore = await usdc.balanceOf(engineEnv.feeRecipient!); + await sleep(1); + const receipt = await engine - .connect(initialBidder) + .connect(initialBidder.provider!) .executeSlowOrderAndRedeem(fastVaa, params) + .then(async (txReq) => { + //txReq.nonce = await initialBidder.getNonce("pending"); + return initialBidder.sendTransaction(txReq); + }) .then((tx) => mineWait(engineProvider, tx)) .catch((err) => { console.log(err); @@ -1268,13 +1337,11 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Balance check. const feeRecipientAfter = await usdc.balanceOf(engineEnv.feeRecipient!); - expect(feeRecipientAfter.sub(feeRecipientBefore).toString()).to.eql( + expect((feeRecipientAfter - feeRecipientBefore).toString()).to.eql( baseFee.toString(), ); - const transactionResult = await engine.getTransactionResults( - receipt.transactionHash, - ); + const transactionResult = await engine.getTransactionResults(receipt!.hash); if (toChainName == MATCHING_ENGINE_NAME) { expect(transactionResult.wormhole.emitterAddress).to.eql( @@ -1296,7 +1363,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const signedVaa = await guardianNetwork.observeEvm( engineProvider, MATCHING_ENGINE_NAME, - receipt, + receipt!, ); let orderResponse: OrderResponse; @@ -1323,7 +1390,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const auctionStatus = await engine .liveAuctionInfo(auctionId) .then((info) => info.status); - expect(auctionStatus).to.eql(2); + expect(auctionStatus).to.eql(2n); localVariables.set("fastOrderResponse", orderResponse); localVariables.set("baseFee", baseFee); @@ -1331,7 +1398,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc it(`To Network -- Redeem Fill`, async () => { const orderResponse = localVariables.get("fastOrderResponse") as OrderResponse; - const baseFee = localVariables.get("baseFee") as string; + const baseFee = localVariables.get("baseFee") as bigint; expect(localVariables.delete("fastOrderResponse")).is.true; expect(localVariables.delete("baseFee")).is.true; @@ -1340,6 +1407,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const receipt = await toTokenRouter .redeemFillTx(orderResponse) + .then((txReq) => toWallet.sendTransaction(txReq)) .then((tx) => mineWait(toProvider, tx)) .catch((err) => { console.log(err); @@ -1350,8 +1418,8 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Validate balance changes. const balanceAfter = await usdc.balanceOf(toWallet.address); - expect(balanceAfter.sub(balanceBefore).toString()).to.eql( - TEST_AMOUNT.sub(baseFee).toString(), + expect((balanceAfter - balanceBefore).toString()).to.eql( + (TEST_AMOUNT - baseFee).toString(), ); }); }); diff --git a/evm/ts/tests/run_integration_test.sh b/evm/ts/tests/run_integration_test.sh index 279bef82..dc14c9ec 100644 --- a/evm/ts/tests/run_integration_test.sh +++ b/evm/ts/tests/run_integration_test.sh @@ -1,11 +1,5 @@ #/bin/bash -pgrep anvil > /dev/null -if [ $? -eq 0 ]; then - echo "anvil already running" - exit 1; -fi - ROOT=$(dirname $0) . $ROOT/.env @@ -13,26 +7,34 @@ ROOT=$(dirname $0) LOGS=$ROOT/.anvil mkdir -p $LOGS -# Avalanche (ME and CCTP). -anvil --port 8547 \ - -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ - --no-mining \ - --fork-url $AVALANCHE_RPC > $LOGS/avalanche.log & - -# Ethereum (CCTP). -anvil --port 8548 \ - -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ - --no-mining \ - --fork-url $ETHEREUM_RPC > $LOGS/ethereum.log & - -# Base (CCTP). -anvil --port 8549 \ - -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ - --no-mining \ - --fork-url $BASE_RPC > $LOGS/base.log & +pgrep anvil > /dev/null +if [ $? -eq 0 ]; then + echo "anvil already running, run 'pkill anvil' if you want to stop it to reset state" +else + echo "starting anvil" + + # Avalanche (ME and CCTP). + anvil --port 8547 \ + -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ + --no-mining \ + --fork-url $AVALANCHE_RPC > $LOGS/avalanche.log & + + # Ethereum (CCTP). + anvil --port 8548 \ + -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ + --no-mining \ + --fork-url $ETHEREUM_RPC > $LOGS/ethereum.log & + + # Base (CCTP). + anvil --port 8549 \ + -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ + --no-mining \ + --fork-url $BASE_RPC > $LOGS/base.log & + + # Chill. + sleep 2 +fi -# Chill. -sleep 2 # Double-check number of anvil instances. if [ "$( pgrep anvil | wc -l )" -ne 3 ]; then @@ -45,5 +47,5 @@ fi set -e npx ts-mocha -t 1000000 -p $ROOT/tsconfig.json --bail $ROOT/[0-9]*.ts -# # Nuke. +# Nuke. pkill anvil \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2eaf2423..4753bc0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,17 +27,16 @@ "@wormhole-foundation/sdk-base": "^0.7.0-beta.6", "@wormhole-foundation/sdk-definitions": "^0.7.0-beta.6", "@wormhole-foundation/sdk-evm": "^0.7.0-beta.6", - "ethers": "^5.7.2" + "ethers": "^6.5.1" }, "devDependencies": { - "@typechain/ethers-v5": "^10.2.0", + "@typechain/ethers-v6": "0.5.1", "@types/chai": "^4.3.4", "@types/mocha": "^10.0.1", "@types/node": "^18.14.5", "chai": "^4.3.7", "dotenv": "^16.3.1", "envfile": "^7.1.0", - "ethers": "^5.7.2", "mocha": "^10.0.0", "prettier": "^2.8.7", "prettier-plugin-solidity": "^1.1.3", @@ -45,6 +44,53 @@ "typechain": "^8.1.1" } }, + "evm/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "evm/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "evm/node_modules/@typechain/ethers-v6": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz", + "integrity": "sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15", + "ts-essentials": "^7.0.1" + }, + "peerDependencies": { + "ethers": "6.x", + "typechain": "^8.3.2", + "typescript": ">=4.7.0" + } + }, + "evm/node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + }, + "evm/node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, "evm/node_modules/envfile": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/envfile/-/envfile-7.1.0.tgz", @@ -60,6 +106,58 @@ "url": "https://bevry.me/fund" } }, + "evm/node_modules/ethers": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.1.tgz", + "integrity": "sha512-hdJ2HOxg/xx97Lm9HdCWk949BfYqYWpyw4//78SiwOLgASyfrNszfMUNB2joKjvGUdwhHfaiMMFFwacVVoLR9A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "evm/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "evm/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/@adraffy/ens-normalize": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", From 113b88410373c88a0aee9698151e5730a9b8e77b Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Wed, 26 Jun 2024 08:51:34 -0400 Subject: [PATCH 4/5] fix signer for correct nonce --- evm/ts/src/error.ts | 2 +- evm/ts/src/testing/utils.ts | 5 +-- evm/ts/tests/04__fastMarketOrder.ts | 46 +++++++++++--------------- evm/ts/tests/run_integration_test.sh | 48 +++++++++++++++------------- 4 files changed, 48 insertions(+), 53 deletions(-) diff --git a/evm/ts/src/error.ts b/evm/ts/src/error.ts index 1faef59d..e8fe1edd 100644 --- a/evm/ts/src/error.ts +++ b/evm/ts/src/error.ts @@ -13,7 +13,7 @@ export function errorDecoder(ethersError: any): DecodedErr { const { data } = ethersError; if (!data || data.length < 10 || data.substring(0, 2) != "0x") { - throw new Error("data not custom error"); + throw ethersError; } const selector = data.substring(0, 10); diff --git a/evm/ts/src/testing/utils.ts b/evm/ts/src/testing/utils.ts index 6104385b..01749ce5 100644 --- a/evm/ts/src/testing/utils.ts +++ b/evm/ts/src/testing/utils.ts @@ -56,7 +56,8 @@ export async function mineToPenaltyPeriod( export async function mineWait(provider: ethers.JsonRpcProvider, tx: ethers.TransactionResponse) { await mine(provider); - return tx.wait(); + // 1 is default confirms, 5000ms timeout to prevent hanging forever. + return await tx.wait(1, 5000); } export async function mintNativeUsdc( @@ -66,7 +67,7 @@ export async function mintNativeUsdc( mineBlock: boolean = true, ) { if (!usdc.runner) { - throw new Error("provider must be a StaticJsonRpcProvider"); + throw new Error("provider must be a JsonRpcProvider"); } const provider = usdc.runner.provider as ethers.JsonRpcProvider; diff --git a/evm/ts/tests/04__fastMarketOrder.ts b/evm/ts/tests/04__fastMarketOrder.ts index 549d0fc9..cb489214 100644 --- a/evm/ts/tests/04__fastMarketOrder.ts +++ b/evm/ts/tests/04__fastMarketOrder.ts @@ -1,16 +1,14 @@ import { expect } from "chai"; import { ethers } from "ethers"; import { - EvmTokenRouter, EvmMatchingEngine, - errorDecoder, - OrderResponse, + EvmTokenRouter, MessageDecoder, + OrderResponse, + errorDecoder, } from "../src"; -import { IERC20__factory } from "../src/types"; import { ChainType, - parseLiquidityLayerEnvFile, CircleAttester, GuardianNetwork, LOCALHOSTS, @@ -20,21 +18,18 @@ import { ValidNetwork, WALLET_PRIVATE_KEYS, burnAllUsdc, - mineWait, mine, - mintNativeUsdc, mineToGracePeriod, mineToPenaltyPeriod, + mineWait, + mintNativeUsdc, + parseLiquidityLayerEnvFile, tryNativeToUint8Array, } from "../src/testing"; +import { IERC20__factory } from "../src/types"; import { toChainId } from "@wormhole-foundation/sdk-base"; -import { - deserialize, - keccak256, - serializePayload, - toUniversal, -} from "@wormhole-foundation/sdk-definitions"; +import { deserialize, keccak256, toUniversal } from "@wormhole-foundation/sdk-definitions"; import "@wormhole-foundation/sdk-evm"; // Cannot send a fast market order from the matching engine chain. @@ -330,7 +325,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc await mintNativeUsdc(usdc, playerAddress, initialDeposit, false); await usdc.approve(engine.address, initialDeposit); - // sleep because otherwise nonce collisions (??) + // give it time to hit the mempool await sleep(1); bids[i].balance = await usdc.balanceOf(playerAddress); @@ -725,6 +720,7 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc await mintNativeUsdc(usdc, playerAddress, initialDeposit, false); await usdc.approve(engine.address, initialDeposit); + // give it time to hit the mempool await sleep(1); bids[i].balance = await usdc.balanceOf(playerAddress); @@ -1163,7 +1159,6 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc ); }); }); - describe(`No Auction - Deadline Exceeded`, () => { before(`From Network -- Mint USDC`, async () => { if (fromEnv.chainId == MATCHING_ENGINE_CHAIN) { @@ -1281,22 +1276,24 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc // Prepare usdc for the auction. const usdc = IERC20__factory.connect(engineEnv.tokenAddress, initialBidder); await mintNativeUsdc(usdc, await initialBidder.getAddress(), initialDeposit); - await usdc.approve(engine.address, initialDeposit); + await usdc + .approve(engine.address, initialDeposit) + .then((tx) => mineWait(engineProvider, tx)); let failedGracefully = false; const receipt = await engine .connect(initialBidder.provider!) .placeInitialBid(fastVaa, fastOrder.maxFee) - .then(async (txReq) => { - txReq.nonce = await initialBidder.getNonce("pending"); - return initialBidder.sendTransaction(txReq); - }) - .then((tx) => mineWait(engineProvider, tx)) + .then(async (txReq) => await initialBidder.sendTransaction(txReq)) .catch((err) => { const error = errorDecoder(err); if (error.selector == "ErrDeadlineExceeded") { failedGracefully = true; } + + // We got a failed transaction so we need to + // reset the NonceManagers local tracker + initialBidder.reset(); }); expect(failedGracefully).is.true; @@ -1319,15 +1316,10 @@ describe("Fast Market Order Business Logic -- CCTP to CCTP", function (this: Moc const usdc = IERC20__factory.connect(engineEnv.tokenAddress, engineProvider); const feeRecipientBefore = await usdc.balanceOf(engineEnv.feeRecipient!); - await sleep(1); - const receipt = await engine .connect(initialBidder.provider!) .executeSlowOrderAndRedeem(fastVaa, params) - .then(async (txReq) => { - //txReq.nonce = await initialBidder.getNonce("pending"); - return initialBidder.sendTransaction(txReq); - }) + .then((txReq) => initialBidder.sendTransaction(txReq)) .then((tx) => mineWait(engineProvider, tx)) .catch((err) => { console.log(err); diff --git a/evm/ts/tests/run_integration_test.sh b/evm/ts/tests/run_integration_test.sh index dc14c9ec..95cbdb30 100644 --- a/evm/ts/tests/run_integration_test.sh +++ b/evm/ts/tests/run_integration_test.sh @@ -8,33 +8,35 @@ LOGS=$ROOT/.anvil mkdir -p $LOGS pgrep anvil > /dev/null + if [ $? -eq 0 ]; then echo "anvil already running, run 'pkill anvil' if you want to stop it to reset state" -else - echo "starting anvil" - - # Avalanche (ME and CCTP). - anvil --port 8547 \ - -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ - --no-mining \ - --fork-url $AVALANCHE_RPC > $LOGS/avalanche.log & - - # Ethereum (CCTP). - anvil --port 8548 \ - -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ - --no-mining \ - --fork-url $ETHEREUM_RPC > $LOGS/ethereum.log & - - # Base (CCTP). - anvil --port 8549 \ - -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ - --no-mining \ - --fork-url $BASE_RPC > $LOGS/base.log & - - # Chill. - sleep 2 + exit 1 fi +echo "starting anvil" + +# Avalanche (ME and CCTP). +anvil --port 8547 \ + -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ + --no-mining \ + --fork-url $AVALANCHE_RPC > $LOGS/avalanche.log & + +# Ethereum (CCTP). +anvil --port 8548 \ + -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ + --no-mining \ + --fork-url $ETHEREUM_RPC > $LOGS/ethereum.log & + +# Base (CCTP). +anvil --port 8549 \ + -m "myth like bonus scare over problem client lizard pioneer submit female collect" \ + --no-mining \ + --fork-url $BASE_RPC > $LOGS/base.log & + +# Chill. +sleep 2 + # Double-check number of anvil instances. if [ "$( pgrep anvil | wc -l )" -ne 3 ]; then From 308ce549b69f192eda6fe75a0b71308edf797e9a Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Wed, 26 Jun 2024 09:09:37 -0400 Subject: [PATCH 5/5] update ethers in other workspaces --- package-lock.json | 1006 ++++++--------------------------- solana/package.json | 2 +- solana/ts/src/testing/mock.ts | 12 +- universal/ts/package.json | 3 +- 4 files changed, 187 insertions(+), 836 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4753bc0b..dca55b43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -240,716 +240,6 @@ "kuler": "^2.0.0" } }, - "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", - "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", - "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", - "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/rlp": "^5.7.0" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", - "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0" - } - }, - "node_modules/@ethersproject/basex": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", - "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", - "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", - "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0" - } - }, - "node_modules/@ethersproject/contracts": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", - "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", - "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/hdnode": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", - "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/json-wallets": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", - "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", - "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "js-sha3": "0.8.0" - } - }, - "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ] - }, - "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", - "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/pbkdf2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", - "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/sha2": "^5.7.0" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", - "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/providers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", - "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0", - "bech32": "1.1.4", - "ws": "7.4.6" - } - }, - "node_modules/@ethersproject/providers/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@ethersproject/random": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", - "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", - "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/sha2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", - "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", - "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "bn.js": "^5.2.1", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/signing-key/node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/@ethersproject/signing-key/node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/@ethersproject/solidity": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", - "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", - "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", - "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0" - } - }, - "node_modules/@ethersproject/units": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", - "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/wallet": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", - "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/json-wallets": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", - "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/wordlists": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", - "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, "node_modules/@grpc/grpc-js": { "version": "1.10.8", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.8.tgz", @@ -1283,23 +573,6 @@ "integrity": "sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==", "dev": true }, - "node_modules/@typechain/ethers-v5": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-10.2.1.tgz", - "integrity": "sha512-n3tQmCZjRE6IU4h6lqUGiQ1j866n5MTCBJreNEHHVWXa2u9GJTaeYyU1/k+1qLutkyw+sS6VAN+AbeiTqsxd/A==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15", - "ts-essentials": "^7.0.1" - }, - "peerDependencies": { - "@ethersproject/abi": "^5.0.0", - "@ethersproject/providers": "^5.0.0", - "ethers": "^5.1.3", - "typechain": "^8.1.1", - "typescript": ">=4.3.0" - } - }, "node_modules/@types/bn.js": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", @@ -1574,11 +847,6 @@ "node": ">=16" } }, - "node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" - }, "node_modules/agentkeepalive": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", @@ -1761,11 +1029,6 @@ } ] }, - "node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, "node_modules/bigint-buffer": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", @@ -1843,11 +1106,6 @@ "node": ">=8" } }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -2366,53 +1624,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -2611,15 +1822,6 @@ "node": ">=8" } }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2629,16 +1831,6 @@ "he": "bin/he" } }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -2814,7 +2006,8 @@ "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", @@ -3016,16 +2209,6 @@ "node": ">= 0.6" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3495,11 +2678,6 @@ "node": ">=10" } }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" - }, "node_modules/semver": { "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", @@ -4207,7 +3385,7 @@ "anchor-0.29.0": "npm:@coral-xyz/anchor@^0.29.0", "bn.js": "^5.2.1", "dotenv": "^16.4.1", - "ethers": "^5.7.2", + "ethers": "^6.5.1", "sha3": "^2.1.4", "winston": "^3.13.0", "yargs": "^17.7.2" @@ -4265,6 +3443,28 @@ "@solana/web3.js": "^1.68.0" } }, + "solana/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "solana/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "solana/node_modules/@solana/spl-token": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.4.6.tgz", @@ -4283,6 +3483,68 @@ "@solana/web3.js": "^1.91.6" } }, + "solana/node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + }, + "solana/node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, + "solana/node_modules/ethers": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.1.tgz", + "integrity": "sha512-hdJ2HOxg/xx97Lm9HdCWk949BfYqYWpyw4//78SiwOLgASyfrNszfMUNB2joKjvGUdwhHfaiMMFFwacVVoLR9A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "solana/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "solana/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "solver": { "name": "@wormhole-foundation/example-liquidity-layer-solver", "version": "0.0.1", @@ -4323,20 +3585,110 @@ "@wormhole-foundation/sdk-definitions": "^0.7.0-beta.6" }, "devDependencies": { - "@typechain/ethers-v5": "^10.2.0", "@types/chai": "^4.3.4", "@types/mocha": "^10.0.1", "@types/node": "^18.14.5", "chai": "^4.3.7", "dotenv": "^16.3.1", "envfile": "^6.18.0", - "ethers": "^5.7.2", + "ethers": "^6.5.1", "mocha": "^10.0.0", "prettier": "^2.8.7", "prettier-plugin-solidity": "^1.1.3", "ts-mocha": "^10.0.0", "typechain": "^8.1.1" } + }, + "universal/ts/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dev": true, + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "universal/ts/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "universal/ts/node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", + "dev": true + }, + "universal/ts/node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "dev": true + }, + "universal/ts/node_modules/ethers": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.1.tgz", + "integrity": "sha512-hdJ2HOxg/xx97Lm9HdCWk949BfYqYWpyw4//78SiwOLgASyfrNszfMUNB2joKjvGUdwhHfaiMMFFwacVVoLR9A==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "universal/ts/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "universal/ts/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } } } } diff --git a/solana/package.json b/solana/package.json index bb6d2dee..f1559b91 100644 --- a/solana/package.json +++ b/solana/package.json @@ -44,7 +44,7 @@ "anchor-0.29.0": "npm:@coral-xyz/anchor@^0.29.0", "bn.js": "^5.2.1", "dotenv": "^16.4.1", - "ethers": "^5.7.2", + "ethers": "^6.5.1", "sha3": "^2.1.4", "winston": "^3.13.0", "yargs": "^17.7.2" diff --git a/solana/ts/src/testing/mock.ts b/solana/ts/src/testing/mock.ts index 0b362151..2c8979f5 100644 --- a/solana/ts/src/testing/mock.ts +++ b/solana/ts/src/testing/mock.ts @@ -81,24 +81,24 @@ export async function postAndFetchVaa( } export class CircleAttester { - attester: ethers.utils.SigningKey; + attester: ethers.SigningKey; constructor() { - this.attester = new ethers.utils.SigningKey("0x" + GUARDIAN_KEY); + this.attester = new ethers.SigningKey("0x" + GUARDIAN_KEY); } createAttestation(message: Buffer | Uint8Array) { - const signature = this.attester.signDigest(ethers.utils.keccak256(message)); + const signature = this.attester.sign(ethers.keccak256(message)); const attestation = Buffer.alloc(65); let offset = 0; - attestation.set(ethers.utils.arrayify(signature.r), offset); + attestation.set(ethers.getBytes(signature.r), offset); offset += 32; - attestation.set(ethers.utils.arrayify(signature.s), offset); + attestation.set(ethers.getBytes(signature.s), offset); offset += 32; - const recoveryId = signature.recoveryParam; + const recoveryId = signature.v; attestation.writeUInt8(recoveryId < 27 ? recoveryId + 27 : recoveryId, offset); offset += 1; diff --git a/universal/ts/package.json b/universal/ts/package.json index 108c0e05..aea861b5 100644 --- a/universal/ts/package.json +++ b/universal/ts/package.json @@ -24,13 +24,12 @@ }, "devDependencies": { "envfile": "^6.18.0", - "@typechain/ethers-v5": "^10.2.0", "@types/chai": "^4.3.4", "@types/mocha": "^10.0.1", "@types/node": "^18.14.5", "chai": "^4.3.7", "dotenv": "^16.3.1", - "ethers": "^5.7.2", + "ethers": "^6.5.1", "mocha": "^10.0.0", "prettier": "^2.8.7", "prettier-plugin-solidity": "^1.1.3",