From 9b41eceb32d4452762f70516a19b5b17002648e4 Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Fri, 29 Sep 2023 10:26:07 +0200 Subject: [PATCH 1/7] feat: cip64 wip --- src/lib/CeloProvider.ts | 44 +- src/lib/CeloWallet.ts | 16 +- src/lib/transaction/utils.ts | 41 ++ src/lib/transactions.ts | 503 ++++++++++--- test/useContract.ts | 18 +- yarn.lock | 1343 +++++++++++++++------------------- 6 files changed, 1063 insertions(+), 902 deletions(-) create mode 100644 src/lib/transaction/utils.ts diff --git a/src/lib/CeloProvider.ts b/src/lib/CeloProvider.ts index e15f5dc..8edb5a0 100644 --- a/src/lib/CeloProvider.ts +++ b/src/lib/CeloProvider.ts @@ -5,26 +5,6 @@ import { parseCeloTransaction } from "./transactions"; const logger = new utils.Logger("CeloProvider"); export class CeloProvider extends providers.JsonRpcProvider { - constructor( - url?: utils.ConnectionInfo | string, - network?: providers.Networkish - ) { - super(url, network); - - // Override certain block formatting properties that don't exist on Celo blocks - // Reaches into https://github.com/ethers-io/ethers.js/blob/master/packages/providers/src.ts/formatter.ts - const blockFormat = this.formatter.formats.block; - blockFormat.gasLimit = () => BigNumber.from(0); - blockFormat.nonce = () => ""; - blockFormat.difficulty = () => 0; - - const blockWithTransactionsFormat = - this.formatter.formats.blockWithTransactions; - blockWithTransactionsFormat.gasLimit = () => BigNumber.from(0); - blockWithTransactionsFormat.nonce = () => ""; - blockWithTransactionsFormat.difficulty = () => 0; - } - /** * Override to parse transaction correctly * https://github.com/ethers-io/ethers.js/blob/master/packages/providers/src.ts/base-provider.ts @@ -33,17 +13,21 @@ export class CeloProvider extends providers.JsonRpcProvider { signedTransaction: string | Promise ): Promise { await this.getNetwork(); - const signedTx = await Promise.resolve(signedTransaction); - const hexTx = utils.hexlify(signedTx); - const tx = parseCeloTransaction(signedTx); + const hexTx = await Promise.resolve(signedTransaction).then((t) => + utils.hexlify(t) + ); + const tx = parseCeloTransaction(hexTx); + const blockNumber = await this._getInternalBlockNumber( + 100 + 2 * this.pollingInterval + ); try { const hash = await this.perform("sendTransaction", { signedTransaction: hexTx, }); - return this._wrapTransaction(tx, hash); - } catch (error: any) { - error.transaction = tx; - error.transactionHash = tx.hash; + return this._wrapTransaction(tx, hash, blockNumber); + } catch (error) { + (error).transaction = tx; + (error).transactionHash = tx.hash; throw error; } } @@ -74,15 +58,15 @@ export class CeloProvider extends providers.JsonRpcProvider { } static getNetwork(networkish: providers.Networkish): providers.Network { - const network = getNetwork(networkish == null ? 'celo' : networkish); + const network = getNetwork(networkish == null ? "celo" : networkish); if (network == null) { return logger.throwError( `unknown network: ${JSON.stringify(network)}`, utils.Logger.errors.UNSUPPORTED_OPERATION, { - operation: 'getNetwork', + operation: "getNetwork", value: networkish, - }, + } ); } return network; diff --git a/src/lib/CeloWallet.ts b/src/lib/CeloWallet.ts index a84d23a..fb2f56a 100644 --- a/src/lib/CeloWallet.ts +++ b/src/lib/CeloWallet.ts @@ -1,7 +1,9 @@ import { BigNumber, providers, utils, Wallet, Wordlist } from "ethers"; import type { CeloProvider } from "./CeloProvider"; import { + CeloTransaction, CeloTransactionRequest, + getTxType, serializeCeloTransaction, } from "./transactions"; @@ -20,11 +22,13 @@ export class CeloWallet extends Wallet { */ async populateTransaction( transaction: utils.Deferrable - ): Promise { + ): Promise { const tx: any = await utils.resolveProperties(transaction); if (tx.to != null) { - tx.to = Promise.resolve(tx.to).then((to) => this.resolveName(to)); + tx.to = Promise.resolve(tx.to).then((to) => + this.resolveName(to as string) + ); } if (tx.gasPrice == null) { tx.gasPrice = this.getGasPrice(); @@ -68,7 +72,7 @@ export class CeloWallet extends Wallet { }); } - return utils.resolveProperties(tx); + return utils.resolveProperties(tx); } /** @@ -111,10 +115,12 @@ export class CeloWallet extends Wallet { * https://github.com/ethers-io/ethers.js/blob/master/packages/abstract-signer/src.ts/index.ts */ async estimateGas( - transaction: utils.Deferrable + transaction: utils.Deferrable ): Promise { this._checkProvider("estimateGas"); - const tx = await utils.resolveProperties(transaction); + // @ts-expect-error + const tx: CeloTransaction = await utils.resolveProperties(transaction); + void getTxType(tx); return await this.provider.estimateGas(tx); } diff --git a/src/lib/transaction/utils.ts b/src/lib/transaction/utils.ts new file mode 100644 index 0000000..a84f1c2 --- /dev/null +++ b/src/lib/transaction/utils.ts @@ -0,0 +1,41 @@ +import { BigNumberish } from "ethers"; +import { hexlify } from "ethers/lib/utils"; + +function isEmpty(value: string | BigNumberish | undefined | null) { + return ( + value === undefined || + value === null || + value === "0" || + (typeof value == "string" + ? value.toLowerCase() === "0x" || value.toLowerCase() === "0x0" + : hexlify(value) === "0x0") + ); +} +function isPresent(value: string | BigNumberish | undefined | null) { + return !isEmpty(value); +} + +export function isEIP1559(tx: any): boolean { + return isPresent(tx.maxFeePerGas) && isPresent(tx.maxPriorityFeePerGas); +} + +export function isCIP64(tx: any) { + return ( + isEIP1559(tx) && + isPresent(tx.feeCurrency) && + !isPresent(tx.gatewayFeeRecipient) && + !isPresent(tx.gatewayFeeRecipient) + ); +} +export function isCIP42(tx: any): boolean { + return ( + isEIP1559(tx) && + (isPresent(tx.feeCurrency) || + isPresent(tx.gatewayFeeRecipient) || + isPresent(tx.gatewayFee)) + ); +} + +export function concatHex(values: string[]): `0x${string}` { + return `0x${values.reduce((acc, x) => acc + x.replace("0x", ""), "")}`; +} diff --git a/src/lib/transactions.ts b/src/lib/transactions.ts index fb9efe0..67ace4e 100644 --- a/src/lib/transactions.ts +++ b/src/lib/transactions.ts @@ -1,12 +1,14 @@ import { BigNumber, - BigNumberish, BytesLike, constants, providers, + Signature, Transaction, utils, } from "ethers"; +import { concatHex, isCIP42, isCIP64, isEIP1559 } from "./transaction/utils"; +import { accessListify, AccessListish } from "ethers/lib/utils"; // From https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L33 // Copied because it doesn't seem to be exported from 'ethers' anywhere @@ -25,28 +27,52 @@ const logger = new utils.Logger("celo/transactions"); export interface CeloTransactionRequest extends providers.TransactionRequest { feeCurrency?: string; gatewayFeeRecipient?: string; - gatewayFee?: BigNumberish; + gatewayFee?: string; } -export interface CeloTransaction extends Transaction { - feeCurrency?: string; +export interface CeloTransactionCip64 extends Transaction { + type: TxTypeToPrefix.cip64; + feeCurrency: string; +} + +export interface CeloTransactionCip42 extends Transaction { + type: TxTypeToPrefix.cip42; + feeCurrency: string; gatewayFeeRecipient?: string; - gatewayFee?: BigNumber; + gatewayFee?: string; +} + +export interface CeloTransactionEip1559 extends Transaction { + type: TxTypeToPrefix.eip1559; +} +export interface LegacyCeloTransaction extends Transaction { + type: undefined; + gasPrice: BigNumber; + feeCurrency: string; + gatewayFeeRecipient: string; + gatewayFee: BigNumber; +} + +export type CeloTransaction = + | LegacyCeloTransaction + | CeloTransactionCip64 + | CeloTransactionCip42 + | CeloTransactionEip1559; + +export enum TxTypeToPrefix { + cip42 = 0x7c, + cip64 = 0x7b, + eip1559 = 0x02, } -export const celoTransactionFields = [ - { name: "nonce", maxLength: 32, numeric: true }, - { name: "gasPrice", maxLength: 32, numeric: true }, - { name: "gasLimit", maxLength: 32, numeric: true }, - { name: "feeCurrency", length: 20 }, - { name: "gatewayFeeRecipient", length: 20 }, - { name: "gatewayFee", maxLength: 32, numeric: true }, - { name: "to", length: 20 }, - { name: "value", maxLength: 32, numeric: true }, - { name: "data" }, -]; - -export const celoAllowedTransactionKeys: { [key: string]: boolean } = { +interface Field { + maxLength?: number; + length?: number; + numeric?: true; + deprecated?: true; +} +export const celoAllowedTransactionKeys = { + type: true, chainId: true, data: true, gasLimit: true, @@ -57,52 +83,220 @@ export const celoAllowedTransactionKeys: { [key: string]: boolean } = { feeCurrency: true, gatewayFeeRecipient: true, gatewayFee: true, -}; + maxFeePerGas: true, + maxPriorityFeePerGas: true, + accessList: true, +} as const; + +type CeloFieldName = + | keyof Omit< + CeloTransactionRequest, + | "type" + | "chainId" + | "r" + | "s" + | "v" + | "hash" + | "accessList" + | "from" + | "customData" + | "ccipReadEnabled" + > + | "feeCurrency" + | "gatewayFeeRecipient" + | "gatewayFee"; + +export const celoTransactionFields: Record = { + nonce: { maxLength: 32, numeric: true } as Field, + gasPrice: { maxLength: 32, numeric: true } as Field, + gasLimit: { maxLength: 32, numeric: true } as Field, + feeCurrency: { length: 20 } as Field, + gatewayFeeRecipient: { length: 20 } as Field, + gatewayFee: { maxLength: 32, numeric: true } as Field, + to: { length: 20 } as Field, + value: { maxLength: 32, numeric: true } as Field, + data: {} as Field, + maxFeePerGas: { maxLength: 32, numeric: true } as Field, + maxPriorityFeePerGas: { maxLength: 32, numeric: true } as Field, +} as const; + +function formatCeloField(name: CeloFieldName, value: any) { + value = value || []; + + const fieldInfo = celoTransactionFields[name]; + const options: any = {}; + if (fieldInfo.numeric) { + options.hexPad = "left"; + } + value = utils.arrayify(utils.hexlify(value, options)); + + // Fixed-width field + if ( + fieldInfo.length && + value.length !== fieldInfo.length && + value.length > 0 + ) { + logger.throwArgumentError( + "invalid length for " + name, + "transaction:" + name, + value + ); + } + + // Variable-width (with a maximum) + if (fieldInfo.maxLength) { + value = utils.stripZeros(value); + if (value.length > fieldInfo.maxLength) { + logger.throwArgumentError( + "invalid length for " + name, + "transaction:" + name, + value + ); + } + } + + return utils.hexlify(value); +} + +export function getTxType(tx: CeloTransaction) { + if (isCIP64(tx)) { + // @ts-ignore + delete tx.gatewayFee; + // @ts-ignore + delete tx.gatewayFeeRecipient; + // @ts-ignore + delete tx.gasPrice; + return TxTypeToPrefix.cip64; + } else if (isCIP42(tx)) { + // @ts-ignore + delete tx.gasPrice; + return TxTypeToPrefix.cip42; + } else if (isEIP1559(tx)) { + // @ts-ignore + delete tx.feeCurrency; + // @ts-ignore + delete tx.gatewayFee; + // @ts-ignore + delete tx.gatewayFeeRecipient; + // @ts-ignore + delete tx.gasPrice; + return TxTypeToPrefix.eip1559; + } else { + return ""; + } +} + +function prepareEncodeTx( + tx: CeloTransaction, + signature?: Signature +): (string | Uint8Array)[] { + let raw: (string | Uint8Array)[] = []; + switch (tx.type) { + case TxTypeToPrefix.cip64: + // https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0064.md + // 0x7b || rlp([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, feeCurrency, signatureYParity, signatureR, signatureS]). + raw = [ + utils.hexlify(tx.chainId!), // NOTE: is this safe or nah? + utils.hexlify(tx.nonce!), // NOTE: is this safe or nah? + tx.maxPriorityFeePerGas ? utils.hexlify(tx.maxPriorityFeePerGas) : "0x", + tx.maxFeePerGas ? utils.hexlify(tx.maxFeePerGas) : "0x", + tx.gasLimit ? utils.hexlify(tx.gasLimit) : "0x", + tx.to || "0x", + tx.value ? utils.hexlify(tx.value) : "0x", + tx.data || "0x", + // @ts-expect-error + tx.accessList || [], + tx.feeCurrency || "0x", + ]; + break; + case TxTypeToPrefix.cip42: + // There shall be a typed transaction with the code 0x7c that has the following format: + // 0x7c || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, feecurrency, gatewayFeeRecipient, gatewayfee, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s]). + // This will be in addition to the type 0x02 transaction as specified in EIP-1559. + raw = [ + utils.hexlify(tx.chainId!), + utils.hexlify(tx.nonce!), + tx.maxPriorityFeePerGas ? utils.hexlify(tx.maxPriorityFeePerGas) : "0x", + tx.maxFeePerGas ? utils.hexlify(tx.maxFeePerGas) : "0x", + tx.gasLimit ? utils.hexlify(tx.gasLimit) : "0x", + tx.feeCurrency || "0x", + tx.gatewayFeeRecipient || "0x", + tx.gatewayFee || "0x", + tx.to || "0x", + tx.value ? utils.hexlify(tx.value) : "0x", + tx.data || "0x", + // @ts-expect-error + tx.accessList || [], + ]; + break; + case TxTypeToPrefix.eip1559: + // https://eips.ethereum.org/EIPS/eip-1559 + // 0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s]). + raw = [ + utils.hexlify(tx.chainId!), + utils.hexlify(tx.nonce!), + tx.maxPriorityFeePerGas ? utils.hexlify(tx.maxPriorityFeePerGas) : "0x", + tx.maxFeePerGas ? utils.hexlify(tx.maxFeePerGas) : "0x", + tx.gasLimit ? utils.hexlify(tx.gasLimit) : "0x", + tx.to || "0x", + tx.value ? utils.hexlify(tx.value) : "0x", + tx.data || "0x", + // @ts-expect-error + tx.accessList || [], + ]; + break; + default: + // This order should match the order in Geth. + // https://github.com/celo-org/celo-blockchain/blob/027dba2e4584936cc5a8e8993e4e27d28d5247b8/core/types/transaction.go#L65 + raw = [ + utils.hexlify(tx.nonce!), + tx.gasPrice ? utils.hexlify(tx.gasPrice) : "0x", + tx.gasLimit ? utils.hexlify(tx.gasLimit) : "0x", + tx.feeCurrency || "0x", + tx.gatewayFeeRecipient || "0x", + tx.gatewayFee ? utils.hexlify(tx.gatewayFee) : "0x", + tx.to || "0x", + tx.value ? utils.hexlify(tx.value) : "0x", + tx.data || "0x", + ]; + if (!signature) { + raw.push(...[utils.hexlify(tx.chainId!), "0x", "0x"]); + } + break; + } + + if (signature) { + raw.push( + ...[ + utils.hexlify(signature.v), + utils.stripZeros(utils.arrayify(signature.r)), + utils.stripZeros(utils.arrayify(signature.s)), + ] + ); + } + + return raw; +} // Almost identical to https://github.com/ethers-io/ethers.js/blob/master/packages/transactions/src.ts/index.ts#L85 // Need to override to use the celo tx prop whitelists above export function serializeCeloTransaction( - transaction: any, + transaction: CeloTransactionRequest, signature?: SignatureLike ): string { utils.checkProperties(transaction, celoAllowedTransactionKeys); - const raw: Array = []; + const txArgs: Partial> = + {}; - celoTransactionFields.forEach(function (fieldInfo) { - let value = (transaction)[fieldInfo.name] || []; - const options: any = {}; - if (fieldInfo.numeric) { - options.hexPad = "left"; - } - value = utils.arrayify(utils.hexlify(value, options)); - - // Fixed-width field - if ( - fieldInfo.length && - value.length !== fieldInfo.length && - value.length > 0 - ) { - logger.throwArgumentError( - "invalid length for " + fieldInfo.name, - "transaction:" + fieldInfo.name, - value + Object.entries(transaction).forEach(([fieldName, fieldValue]) => { + if (fieldName in celoTransactionFields) { + // @ts-expect-error + txArgs[fieldName as CeloFieldName] = formatCeloField( + fieldName as CeloFieldName, + fieldValue ); } - - // Variable-width (with a maximum) - if (fieldInfo.maxLength) { - value = utils.stripZeros(value); - if (value.length > fieldInfo.maxLength) { - logger.throwArgumentError( - "invalid length for " + fieldInfo.name, - "transaction:" + fieldInfo.name, - value - ); - } - } - - raw.push(utils.hexlify(value)); }); let chainId = 0; @@ -129,26 +323,29 @@ export function serializeCeloTransaction( // We have an EIP-155 transaction (chainId was specified and non-zero) if (chainId !== 0) { - raw.push(utils.hexlify(chainId)); // @TODO: hexValue? - raw.push("0x"); - raw.push("0x"); + txArgs["chainId"] = utils.hexlify(chainId); // @TODO: hexValue? } // Requesting an unsigned transation + // @ts-ignore + const type = getTxType(txArgs); + // @ts-expect-error + txArgs.type = type; if (!signature) { - return utils.RLP.encode(raw); + // @ts-expect-error + const raw = prepareEncodeTx(txArgs); + const encoded = utils.RLP.encode(raw); + return type ? concatHex([utils.hexlify(type), encoded]) : encoded; } // The splitSignature will ensure the transaction has a recoveryParam in the // case that the signTransaction function only adds a v. const sig = utils.splitSignature(signature); - // We pushed a chainId and null r, s on for hashing only; remove those let v = 27 + sig.recoveryParam; if (chainId !== 0) { - raw.pop(); - raw.pop(); - raw.pop(); + // NOTE: this makes the recoveryParam recovery custom in `parseCeloTransaction` + // see line: v += chainId * 2 + 8; // If an EIP-155 v (directly or indirectly; maybe _vs) was provided, check it! @@ -166,12 +363,10 @@ export function serializeCeloTransaction( signature ); } - - raw.push(utils.hexlify(v)); - raw.push(utils.stripZeros(utils.arrayify(sig.r))); - raw.push(utils.stripZeros(utils.arrayify(sig.s))); - - return utils.RLP.encode(raw); + // @ts-expect-error + const raw = prepareEncodeTx(txArgs, { ...sig, v }); + const encoded = utils.RLP.encode(raw); + return type ? concatHex([utils.hexlify(type), encoded]) : encoded; } // Based on https://github.com/ethers-io/ethers.js/blob/0234cfbbef76b7f7a53efe4c434cc6d8892bf404/packages/transactions/src.ts/index.ts#L165 @@ -179,74 +374,116 @@ export function serializeCeloTransaction( export function parseCeloTransaction( rawTransaction: utils.BytesLike ): CeloTransaction { - const transaction = utils.RLP.decode(rawTransaction); - - if (transaction.length !== 12 && transaction.length !== 9) { - logger.throwArgumentError( - "invalid raw transaction", - "rawTransaction", - rawTransaction - ); + const [type, transaction] = prepareParseRawTransaction(rawTransaction); + + let tx: CeloTransaction; + switch (type!) { + case TxTypeToPrefix.cip64: + tx = { + type: TxTypeToPrefix.cip64, + chainId: handleNumber(transaction[0]).toNumber(), + nonce: handleNumber(transaction[1]).toNumber(), + maxPriorityFeePerGas: transaction[2], + maxFeePerGas: transaction[3], + gasLimit: handleNumber(transaction[4]), + to: handleAddress(transaction[5]), + value: handleNumber(transaction[6]), + data: transaction[7], + // accessList: handleAccessList(transaction[8]), + feeCurrency: handleAddress(transaction[9]), + } as CeloTransactionCip64; + break; + case TxTypeToPrefix.cip42: + tx = { + type: TxTypeToPrefix.cip42, + chainId: handleNumber(transaction[0]).toNumber(), + nonce: handleNumber(transaction[1]).toNumber(), + maxPriorityFeePerGas: transaction[2], + maxFeePerGas: transaction[3], + gasLimit: handleNumber(transaction[4]), + feeCurrency: handleAddress(transaction[5]), + gatewayFeeRecipient: handleAddress(transaction[6]), + gatewayFee: transaction[7] as string, + to: handleAddress(transaction[8]), + value: handleNumber(transaction[9]), + data: transaction[10], + accessList: handleAccessList(transaction[11]), + } as CeloTransactionCip42; + break; + case TxTypeToPrefix.eip1559: + tx = { + type: TxTypeToPrefix.eip1559, + chainId: handleNumber(transaction[0]).toNumber(), + nonce: handleNumber(transaction[1]).toNumber(), + maxPriorityFeePerGas: transaction[2], + maxFeePerGas: transaction[3], + gasLimit: handleNumber(transaction[4]), + to: handleAddress(transaction[5]), + value: handleNumber(transaction[6]), + data: transaction[7], + accessList: handleAccessList(transaction[8]), + } as CeloTransactionEip1559; + break; + default: + tx = { + nonce: handleNumber(transaction[0]).toNumber(), + gasPrice: handleNumber(transaction[1]), + gasLimit: handleNumber(transaction[2]), + feeCurrency: handleAddress(transaction[3]), + gatewayFeeRecipient: handleAddress(transaction[4]), + gatewayFee: handleNumber(transaction[5]), + to: handleAddress(transaction[6]), + value: handleNumber(transaction[7]), + data: transaction[8], + chainId: handleNumber(transaction[9]).toNumber(), + } as LegacyCeloTransaction; + break; } - const tx: CeloTransaction = { - nonce: handleNumber(transaction[0]).toNumber(), - gasPrice: handleNumber(transaction[1]), - gasLimit: handleNumber(transaction[2]), - feeCurrency: handleAddress(transaction[3]), - gatewayFeeRecipient: handleAddress(transaction[4]), - gatewayFee: handleNumber(transaction[5]), - to: handleAddress(transaction[6]), - value: handleNumber(transaction[7]), - data: transaction[8], - chainId: 0, - }; - // Legacy unsigned transaction - if (transaction.length === 9) { + if (!isSigned(type!, transaction)) { return tx; } + const digest = utils.keccak256( + serializeCeloTransaction(tx as CeloTransactionRequest) + ); + try { - tx.v = BigNumber.from(transaction[9]).toNumber(); + tx.v = BigNumber.from(transaction.at(-3)).toNumber(); } catch (error) { console.log(error); return tx; } - tx.r = utils.hexZeroPad(transaction[10], 32); - tx.s = utils.hexZeroPad(transaction[11], 32); + tx.r = utils.hexZeroPad(transaction.at(-2), 32); + tx.s = utils.hexZeroPad(transaction.at(-1), 32); if (BigNumber.from(tx.r).isZero() && BigNumber.from(tx.s).isZero()) { // EIP-155 unsigned transaction tx.chainId = tx.v; tx.v = 0; } else { - // Signed Tranasaction + // Signed Transaction - tx.chainId = Math.floor((tx.v - 35) / 2); + const chainId = Math.max(0, Math.floor((tx.v - 35) / 2)); + tx.chainId = chainId; if (tx.chainId < 0) { tx.chainId = 0; } let recoveryParam = tx.v - 27; - - const raw = transaction.slice(0, 6); - if (tx.chainId !== 0) { - raw.push(utils.hexlify(tx.chainId)); - raw.push("0x"); - raw.push("0x"); + // NOTE: inverse operation that was done in `serializeCeloTransaction` recoveryParam -= tx.chainId * 2 + 8; } - const digest = utils.keccak256(utils.RLP.encode(raw)); try { // TODO there may be an issue here with incorrect from address extraction tx.from = utils.recoverAddress(digest, { r: utils.hexlify(tx.r), s: utils.hexlify(tx.s), - recoveryParam: recoveryParam, + recoveryParam, }); } catch (error) { console.log(error); @@ -255,6 +492,7 @@ export function parseCeloTransaction( tx.hash = utils.keccak256(rawTransaction); } + console.log(tx); return tx; } @@ -275,3 +513,64 @@ function handleNumber(value: string): BigNumber { } return BigNumber.from(value); } + +function handleAccessList(value: string): AccessListish | "0x" { + if (value === "0x") { + return accessListify([]); + } + // TODO: use value + return accessListify([]); +} + +const baseTxLengths = { + [TxTypeToPrefix.cip64]: { unsigned: 10, signed: 13 }, + [TxTypeToPrefix.cip42]: { unsigned: 12, signed: 15 }, + [TxTypeToPrefix.eip1559]: { unsigned: 9, signed: 12 }, + "celo-legacy": { unsigned: 12, signed: 12 }, +} as const; + +// const nonceToIndices = { +// [TxTypeToPrefix.cip64]: { nonceIndex: 1, toIndex: 5 }, +// [TxTypeToPrefix.cip42]: { nonceIndex: 1, toIndex: 8 }, +// [TxTypeToPrefix.eip1559]: { nonceIndex: 1, toIndex: 5 }, +// "celo-legacy": { nonceIndex: 0, toIndex: 6 }, +// } as const; + +function isSigned(type: TxTypeToPrefix, transaction: string[]) { + const { signed } = baseTxLengths[type || "celo-legacy"]; + return transaction.length === signed; +} + +function isCorrectLength(type: TxTypeToPrefix, transaction: string[]) { + const { unsigned } = baseTxLengths[type || "celo-legacy"]; + return transaction.length === unsigned || isSigned(type, transaction); +} + +function prepareParseRawTransaction( + rawTransaction: utils.BytesLike +): [TxTypeToPrefix | undefined, any[]] { + let rawStr = rawTransaction.toString(); + let type: TxTypeToPrefix | undefined; + for (type of [ + TxTypeToPrefix.cip64, + TxTypeToPrefix.cip42, + TxTypeToPrefix.eip1559, + ]) { + const prefix = utils.hexlify(type); + if (rawStr.startsWith(prefix)) { + rawStr = `0x${rawStr.slice(prefix.length)}`; + break; + } + } + + const transaction = utils.RLP.decode(rawStr); + if (!isCorrectLength(type!, transaction)) { + logger.throwArgumentError( + "invalid raw transaction", + "{type, rawTransaction}", + { type: type!, rawTransaction } + ); + } + + return [type!, transaction]; +} diff --git a/test/useContract.ts b/test/useContract.ts index 2232894..ea8e7c9 100644 --- a/test/useContract.ts +++ b/test/useContract.ts @@ -5,15 +5,16 @@ import { getSigner } from "./utils"; async function main() { const signer = getSigner(); - console.info("Getting account balance for:", signer.address); + // console.info("Getting account balance for:", signer.address); const balance = await signer.getBalance(); console.info("Balance:", balance.toString()); - console.info("Sending 1 CELO wei", signer.address); + // console.info("Sending 1 CELO wei", signer.address); const txResponse1 = await signer.sendTransaction({ to: signer.address, value: BigNumber.from("1"), }); + // Or, alternatively, break apart signing and sending: // const signedTx = await signer.signTransaction({ // to: signer.address, @@ -24,6 +25,19 @@ async function main() { const txReceipt1 = await txResponse1.wait(); console.info("Funds sent. Hash:", txReceipt1.transactionHash); + console.info("Sending 1 CELO wei with cUSD feeCurrency"); + const txResponse1feeCurrency = await signer.sendTransaction({ + to: signer.address, + value: BigNumber.from("1"), + feeCurrency: CUSD_ADDRESS, + maxFeePerGas: BigNumber.from(5000000000), + maxPriorityFeePerGas: BigNumber.from(5000000000), + }); + const txReceipt1FeeCurency = await txResponse1feeCurrency.wait(); + console.info( + `CELO w/ feeCurrency payment hash: ${txReceipt1FeeCurency.transactionHash}` + ); + const stableToken = new Contract(CUSD_ADDRESS, STABLE_TOKEN_ABI, signer); console.info("Getting cUSD balance"); diff --git a/yarn.lock b/yarn.lock index c3382b4..199598d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,763 +1,580 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 6 - cacheKey: 8 - -"@celo-tools/celo-ethers-wrapper@workspace:.": - version: 0.0.0-use.local - resolution: "@celo-tools/celo-ethers-wrapper@workspace:." - dependencies: - "@types/node": ^16.11.10 - ethers: ^5.6.8 - ts-node: ^10.8.1 - typescript: ^4.5.2 - peerDependencies: - ethers: ^5 - languageName: unknown - linkType: soft - -"@cspotcode/source-map-support@npm:^0.8.0": - version: 0.8.1 - resolution: "@cspotcode/source-map-support@npm:0.8.1" - dependencies: - "@jridgewell/trace-mapping": 0.3.9 - checksum: 5718f267085ed8edb3e7ef210137241775e607ee18b77d95aa5bd7514f47f5019aa2d82d96b3bf342ef7aa890a346fa1044532ff7cc3009e7d24fce3ce6200fa - languageName: node - linkType: hard - -"@ethersproject/abi@npm:5.6.3, @ethersproject/abi@npm:^5.6.3": - version: 5.6.3 - resolution: "@ethersproject/abi@npm:5.6.3" - dependencies: - "@ethersproject/address": ^5.6.1 - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/constants": ^5.6.1 - "@ethersproject/hash": ^5.6.1 - "@ethersproject/keccak256": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/properties": ^5.6.0 - "@ethersproject/strings": ^5.6.1 - checksum: 64b89ca153c22dbe95cc024abac7e08849f92b9b33b024b67da6ac127706d37fcbd36cf5713a462b8c3371b49664c4181ca4ab81e6ee55413ea5265e8b59f175 - languageName: node - linkType: hard - -"@ethersproject/abstract-provider@npm:5.6.1, @ethersproject/abstract-provider@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/abstract-provider@npm:5.6.1" - dependencies: - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/networks": ^5.6.3 - "@ethersproject/properties": ^5.6.0 - "@ethersproject/transactions": ^5.6.2 - "@ethersproject/web": ^5.6.1 - checksum: a1be8035d9e67fd41a336e2d38f5cf03b7a2590243749b4cf807ad73906b5a298e177ebe291cb5b54262ded4825169bf82968e0e5b09fbea17444b903faeeab0 - languageName: node - linkType: hard - -"@ethersproject/abstract-signer@npm:5.6.2, @ethersproject/abstract-signer@npm:^5.6.2": - version: 5.6.2 - resolution: "@ethersproject/abstract-signer@npm:5.6.2" - dependencies: - "@ethersproject/abstract-provider": ^5.6.1 - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/properties": ^5.6.0 - checksum: 09f3dd1309b37bb3803057d618e4a831668e010e22047f52f1719f2b6f50b63805f1bec112b1603880d6c6b7d403ed187611ff1b14ae1f151141ede186a04996 - languageName: node - linkType: hard - -"@ethersproject/address@npm:5.6.1, @ethersproject/address@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/address@npm:5.6.1" - dependencies: - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/keccak256": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/rlp": ^5.6.1 - checksum: 262096ef05a1b626c161a72698a5d8b06aebf821fe01a1651ab40f80c29ca2481b96be7f972745785fd6399906509458c4c9a38f3bc1c1cb5afa7d2f76f7309a - languageName: node - linkType: hard - -"@ethersproject/base64@npm:5.6.1, @ethersproject/base64@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/base64@npm:5.6.1" - dependencies: - "@ethersproject/bytes": ^5.6.1 - checksum: d21c5c297e1b8bc48fe59012c0cd70a90df7772fac07d9cc3da499d71d174d9f48edfd83495d4a1496cb70e8d1b33fb5b549a9529c5c2f97bb3a07d3f33a3fe8 - languageName: node - linkType: hard - -"@ethersproject/basex@npm:5.6.1, @ethersproject/basex@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/basex@npm:5.6.1" - dependencies: - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/properties": ^5.6.0 - checksum: a14b75d2c25d0ac00ce0098e5bd338d4cce7a68c583839b2bc4e3512ffcb14498b18cbcb4e05b695d216d2a23814d0c335385f35b3118735cc4895234db5ae1c - languageName: node - linkType: hard - -"@ethersproject/bignumber@npm:5.6.2, @ethersproject/bignumber@npm:^5.6.2": - version: 5.6.2 - resolution: "@ethersproject/bignumber@npm:5.6.2" - dependencies: - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - bn.js: ^5.2.1 - checksum: 9cf31c10274f1b6d45b16aed29f43729e8f5edec38c8ec8bb90d6b44f0eae14fda6519536228d23916a375ce11e71a77279a912d653ea02503959910b6bf9de7 - languageName: node - linkType: hard - -"@ethersproject/bytes@npm:5.6.1, @ethersproject/bytes@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/bytes@npm:5.6.1" - dependencies: - "@ethersproject/logger": ^5.6.0 - checksum: d06ffe3bf12aa8a6588d99b82e40b46a2cbb8b057fc650aad836e3e8c95d4559773254eeeb8fed652066dcf8082e527e37cd2b9fff7ac8cabc4de7c49459a7eb - languageName: node - linkType: hard - -"@ethersproject/constants@npm:5.6.1, @ethersproject/constants@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/constants@npm:5.6.1" - dependencies: - "@ethersproject/bignumber": ^5.6.2 - checksum: 3c6abcee60f1620796dc40210a638b601ad8a2d3f6668a69c42a5ca361044f21296b16d1d43b8a00f7c28b385de4165983a8adf671e0983f5ef07459dfa84997 - languageName: node - linkType: hard - -"@ethersproject/contracts@npm:5.6.2": - version: 5.6.2 - resolution: "@ethersproject/contracts@npm:5.6.2" - dependencies: - "@ethersproject/abi": ^5.6.3 - "@ethersproject/abstract-provider": ^5.6.1 - "@ethersproject/abstract-signer": ^5.6.2 - "@ethersproject/address": ^5.6.1 - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/constants": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/properties": ^5.6.0 - "@ethersproject/transactions": ^5.6.2 - checksum: c5a36ce3d0b88dc80db0135aaf39a71c0f14e262fd14172ae557d8943e69d3a2ba52c8f73f67639db0c235ea51155a97ff3584d431b92686f4c711b1004e6f87 - languageName: node - linkType: hard - -"@ethersproject/hash@npm:5.6.1, @ethersproject/hash@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/hash@npm:5.6.1" - dependencies: - "@ethersproject/abstract-signer": ^5.6.2 - "@ethersproject/address": ^5.6.1 - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/keccak256": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/properties": ^5.6.0 - "@ethersproject/strings": ^5.6.1 - checksum: 1338b578a51bc5cb692c17b1cabc51e484e9e3e009c4ffec13032332fc7e746c115968de1c259133cdcdad55fa96c5c8a5144170190c62b968a3fedb5b1d2cdb - languageName: node - linkType: hard - -"@ethersproject/hdnode@npm:5.6.2, @ethersproject/hdnode@npm:^5.6.2": - version: 5.6.2 - resolution: "@ethersproject/hdnode@npm:5.6.2" - dependencies: - "@ethersproject/abstract-signer": ^5.6.2 - "@ethersproject/basex": ^5.6.1 - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/pbkdf2": ^5.6.1 - "@ethersproject/properties": ^5.6.0 - "@ethersproject/sha2": ^5.6.1 - "@ethersproject/signing-key": ^5.6.2 - "@ethersproject/strings": ^5.6.1 - "@ethersproject/transactions": ^5.6.2 - "@ethersproject/wordlists": ^5.6.1 - checksum: b096882ac75d6738c085bf7cdaaf06b6b89055b8e98469df4abf00d600a6131299ec25ca3bc71986cc79d70ddf09ec00258e7ce7e94c45d5ffb83aa616eaaaae - languageName: node - linkType: hard - -"@ethersproject/json-wallets@npm:5.6.1, @ethersproject/json-wallets@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/json-wallets@npm:5.6.1" - dependencies: - "@ethersproject/abstract-signer": ^5.6.2 - "@ethersproject/address": ^5.6.1 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/hdnode": ^5.6.2 - "@ethersproject/keccak256": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/pbkdf2": ^5.6.1 - "@ethersproject/properties": ^5.6.0 - "@ethersproject/random": ^5.6.1 - "@ethersproject/strings": ^5.6.1 - "@ethersproject/transactions": ^5.6.2 - aes-js: 3.0.0 - scrypt-js: 3.0.1 - checksum: 811b3596aaf1c1a64a8acef0c4fe0123a660349e6cbd5e970b1f9461966fd06858be0f154543bbd962a0ef0d369db52c6254c6b5264c172d44315085a2a6c454 - languageName: node - linkType: hard - -"@ethersproject/keccak256@npm:5.6.1, @ethersproject/keccak256@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/keccak256@npm:5.6.1" - dependencies: - "@ethersproject/bytes": ^5.6.1 - js-sha3: 0.8.0 - checksum: fdc950e22a1aafc92fdf749cdc5b8952b85e8cee8872d807c5f40be31f58675d30e0eca5e676876b93f2cd22ac63a344d384d116827ee80928c24b7c299991f5 - languageName: node - linkType: hard - -"@ethersproject/logger@npm:5.6.0, @ethersproject/logger@npm:^5.6.0": - version: 5.6.0 - resolution: "@ethersproject/logger@npm:5.6.0" - checksum: 6eee38a973c7a458552278971c109a3e5df3c257e433cb959da9a287ea04628d1f510d41b83bd5f9da5ddc05d97d307ed2162a9ba1b4fcc50664e4f60061636c - languageName: node - linkType: hard - -"@ethersproject/networks@npm:5.6.3, @ethersproject/networks@npm:^5.6.3": - version: 5.6.3 - resolution: "@ethersproject/networks@npm:5.6.3" - dependencies: - "@ethersproject/logger": ^5.6.0 - checksum: 94d2981eeed0accb69124cfb9a807552ada98b370415c9d906018bd70a33bc5a1286ff01eb2a3ce213c12334fcc7ab635ad0429f25a687b9b8f34d26d21df74b - languageName: node - linkType: hard - -"@ethersproject/pbkdf2@npm:5.6.1, @ethersproject/pbkdf2@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/pbkdf2@npm:5.6.1" - dependencies: - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/sha2": ^5.6.1 - checksum: 316006373828a189bf22b7a08df7dd7ffe24e5f2c83e6d09d922ce663892cc14c7d27524dc4e51993d51e4464a7b7ce5e7b23453bdc85e3c6d4d5c41aa7227cf - languageName: node - linkType: hard - -"@ethersproject/properties@npm:5.6.0, @ethersproject/properties@npm:^5.6.0": - version: 5.6.0 - resolution: "@ethersproject/properties@npm:5.6.0" - dependencies: - "@ethersproject/logger": ^5.6.0 - checksum: adcb6a843dcdf809262d77d6fbe52acdd48703327b298f78e698b76784e89564fb81791d27eaee72b1a6aaaf5688ea2ae7a95faabdef8b4aecc99989fec55901 - languageName: node - linkType: hard - -"@ethersproject/providers@npm:5.6.8": - version: 5.6.8 - resolution: "@ethersproject/providers@npm:5.6.8" - dependencies: - "@ethersproject/abstract-provider": ^5.6.1 - "@ethersproject/abstract-signer": ^5.6.2 - "@ethersproject/address": ^5.6.1 - "@ethersproject/base64": ^5.6.1 - "@ethersproject/basex": ^5.6.1 - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/constants": ^5.6.1 - "@ethersproject/hash": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/networks": ^5.6.3 - "@ethersproject/properties": ^5.6.0 - "@ethersproject/random": ^5.6.1 - "@ethersproject/rlp": ^5.6.1 - "@ethersproject/sha2": ^5.6.1 - "@ethersproject/strings": ^5.6.1 - "@ethersproject/transactions": ^5.6.2 - "@ethersproject/web": ^5.6.1 - bech32: 1.1.4 - ws: 7.4.6 - checksum: 27dc2005e1ae7a6d498bb0bbacc6ad1f7164a599cf5aaad7c51cfd7c4d36d0cc5c7c40ba504f9017c746e8a0f008f15ad24e9961816793b49755dcb5c01540c0 - languageName: node - linkType: hard - -"@ethersproject/random@npm:5.6.1, @ethersproject/random@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/random@npm:5.6.1" - dependencies: - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - checksum: 55517d65eee6dcc0848ef10a825245d61553a6c1bec15d2f69d9430ce4568d9af32013e2aa96c8336545465a24a1fd04defbe9e9f76a5ee110dc5128d4111c11 - languageName: node - linkType: hard - -"@ethersproject/rlp@npm:5.6.1, @ethersproject/rlp@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/rlp@npm:5.6.1" - dependencies: - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - checksum: 43a281d0e7842606e2337b5552c13f4b5dad209dce173de39ef6866e02c9d7b974f1cae945782f4c4b74a8e22d8272bfd0348c1cd1bfeb2c278078ef95565488 - languageName: node - linkType: hard - -"@ethersproject/sha2@npm:5.6.1, @ethersproject/sha2@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/sha2@npm:5.6.1" - dependencies: - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - hash.js: 1.1.7 - checksum: 04313cb4a8e24ce8b5736f9d08906764fbfdab19bc64adef363cf570defa72926d8faae19aed805e1caee737f5efecdc60a4c89fd2b1ee2b3ba0eb9555cae3ae - languageName: node - linkType: hard - -"@ethersproject/signing-key@npm:5.6.2, @ethersproject/signing-key@npm:^5.6.2": - version: 5.6.2 - resolution: "@ethersproject/signing-key@npm:5.6.2" - dependencies: - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/properties": ^5.6.0 - bn.js: ^5.2.1 - elliptic: 6.5.4 - hash.js: 1.1.7 - checksum: 7889d0934c9664f87e7b7e021794e2d2ddb2e81c1392498e154cf2d5909b922d74d3df78cec44187f63dc700eddad8f8ea5ded47d2082a212a591818014ca636 - languageName: node - linkType: hard - -"@ethersproject/solidity@npm:5.6.1": - version: 5.6.1 - resolution: "@ethersproject/solidity@npm:5.6.1" - dependencies: - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/keccak256": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/sha2": ^5.6.1 - "@ethersproject/strings": ^5.6.1 - checksum: a31bd7b98314824d15e28350ee1a21c10e32d2f71579b46c72eab06b895dba147efe966874444a30b17846f9c2ad74043152ec49d4401148262afffb30727087 - languageName: node - linkType: hard - -"@ethersproject/strings@npm:5.6.1, @ethersproject/strings@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/strings@npm:5.6.1" - dependencies: - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/constants": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - checksum: dcf33c2ddb22a48c3d7afc151a5f37e5a4da62a742a298988d517dc9adfaff9c5a0ebd8f476ec9792704cfc8142abd541e97432bc47cb121093edac7a5cfaf22 - languageName: node - linkType: hard - -"@ethersproject/transactions@npm:5.6.2, @ethersproject/transactions@npm:^5.6.2": - version: 5.6.2 - resolution: "@ethersproject/transactions@npm:5.6.2" - dependencies: - "@ethersproject/address": ^5.6.1 - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/constants": ^5.6.1 - "@ethersproject/keccak256": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/properties": ^5.6.0 - "@ethersproject/rlp": ^5.6.1 - "@ethersproject/signing-key": ^5.6.2 - checksum: 5cf13936ce406f97b71fc1e99090698c2e4276dcb17c5a022aa3c3f55825961edcb53d4a59166acab797275afa45fb93f1b9b602ebc709da6afa66853f849609 - languageName: node - linkType: hard - -"@ethersproject/units@npm:5.6.1": - version: 5.6.1 - resolution: "@ethersproject/units@npm:5.6.1" - dependencies: - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/constants": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - checksum: 79cc7c35181fc3bd76fc33d95f1c8d2a20a6339dfc22745184967481b66e0782ee12bbf75b4269119152cbd23bf7980b900978d885b5da72cfb74cf897411065 - languageName: node - linkType: hard - -"@ethersproject/wallet@npm:5.6.2": - version: 5.6.2 - resolution: "@ethersproject/wallet@npm:5.6.2" - dependencies: - "@ethersproject/abstract-provider": ^5.6.1 - "@ethersproject/abstract-signer": ^5.6.2 - "@ethersproject/address": ^5.6.1 - "@ethersproject/bignumber": ^5.6.2 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/hash": ^5.6.1 - "@ethersproject/hdnode": ^5.6.2 - "@ethersproject/json-wallets": ^5.6.1 - "@ethersproject/keccak256": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/properties": ^5.6.0 - "@ethersproject/random": ^5.6.1 - "@ethersproject/signing-key": ^5.6.2 - "@ethersproject/transactions": ^5.6.2 - "@ethersproject/wordlists": ^5.6.1 - checksum: 88603a4797b8f489c76671ff096ad3630ad1226640032594cfb3376398b41c1c4875076f1cf6521854c42e4496cafd2171e6dc301669cbf6c972ba13e97be5b0 - languageName: node - linkType: hard - -"@ethersproject/web@npm:5.6.1, @ethersproject/web@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/web@npm:5.6.1" - dependencies: - "@ethersproject/base64": ^5.6.1 - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/properties": ^5.6.0 - "@ethersproject/strings": ^5.6.1 - checksum: 4acb62bb04431f5a1b1ec27e88847087676dd2fd72ba40c789f2885493e5eed6b6d387d5b47d4cdfc2775bcbe714e04bfaf0d04a6f30e929310384362e6be429 - languageName: node - linkType: hard - -"@ethersproject/wordlists@npm:5.6.1, @ethersproject/wordlists@npm:^5.6.1": - version: 5.6.1 - resolution: "@ethersproject/wordlists@npm:5.6.1" - dependencies: - "@ethersproject/bytes": ^5.6.1 - "@ethersproject/hash": ^5.6.1 - "@ethersproject/logger": ^5.6.0 - "@ethersproject/properties": ^5.6.0 - "@ethersproject/strings": ^5.6.1 - checksum: 3be4f300705b3f4f2b1dfa3948aac2e5030ab6216086578ec5cd2fad130b6b30d2a6a3c54d94c6669601ed62b56e7052232bc0a934a451ef3320fd6513734729 - languageName: node - linkType: hard - -"@jridgewell/resolve-uri@npm:^3.0.3": - version: 3.0.7 - resolution: "@jridgewell/resolve-uri@npm:3.0.7" - checksum: 94f454f4cef8f0acaad85745fd3ca6cd0d62ef731cf9f952ecb89b8b2ce5e20998cd52be31311cedc5fa5b28b1708a15f3ad9df0fe1447ee4f42959b036c4b5b - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.10": - version: 1.4.13 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.13" - checksum: f14449096f60a5f921262322fef65ce0bbbfb778080b3b20212080bcefdeba621c43a58c27065bd536ecb4cc767b18eb9c45f15b6b98a4970139572b60603a1c - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:0.3.9": - version: 0.3.9 - resolution: "@jridgewell/trace-mapping@npm:0.3.9" - dependencies: - "@jridgewell/resolve-uri": ^3.0.3 - "@jridgewell/sourcemap-codec": ^1.4.10 - checksum: d89597752fd88d3f3480845691a05a44bd21faac18e2185b6f436c3b0fd0c5a859fbbd9aaa92050c4052caf325ad3e10e2e1d1b64327517471b7d51babc0ddef - languageName: node - linkType: hard - -"@tsconfig/node10@npm:^1.0.7": - version: 1.0.9 - resolution: "@tsconfig/node10@npm:1.0.9" - checksum: a33ae4dc2a621c0678ac8ac4bceb8e512ae75dac65417a2ad9b022d9b5411e863c4c198b6ba9ef659e14b9fb609bbec680841a2e84c1172df7a5ffcf076539df - languageName: node - linkType: hard - -"@tsconfig/node12@npm:^1.0.7": - version: 1.0.11 - resolution: "@tsconfig/node12@npm:1.0.11" - checksum: 5ce29a41b13e7897a58b8e2df11269c5395999e588b9a467386f99d1d26f6c77d1af2719e407621412520ea30517d718d5192a32403b8dfcc163bf33e40a338a - languageName: node - linkType: hard - -"@tsconfig/node14@npm:^1.0.0": - version: 1.0.3 - resolution: "@tsconfig/node14@npm:1.0.3" - checksum: 19275fe80c4c8d0ad0abed6a96dbf00642e88b220b090418609c4376e1cef81bf16237bf170ad1b341452feddb8115d8dd2e5acdfdea1b27422071163dc9ba9d - languageName: node - linkType: hard - -"@tsconfig/node16@npm:^1.0.2": - version: 1.0.3 - resolution: "@tsconfig/node16@npm:1.0.3" - checksum: 3a8b657dd047495b7ad23437d6afd20297ce90380ff0bdee93fc7d39a900dbd8d9e26e53ff6b465e7967ce2adf0b218782590ce9013285121e6a5928fbd6819f - languageName: node - linkType: hard - -"@types/node@npm:^16.11.10": - version: 16.11.10 - resolution: "@types/node@npm:16.11.10" - checksum: 9c79419c5c3d92d5825bffa30f3668533f598d8b63a73ea7fc24e47f162bdbed92b0f8e4f4261cc3314b39cee050e303366d2aa154abc95c63a572a110b8c160 - languageName: node - linkType: hard - -"acorn-walk@npm:^8.1.1": - version: 8.2.0 - resolution: "acorn-walk@npm:8.2.0" - checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 - languageName: node - linkType: hard - -"acorn@npm:^8.4.1": - version: 8.7.1 - resolution: "acorn@npm:8.7.1" - bin: - acorn: bin/acorn - checksum: aca0aabf98826717920ac2583fdcad0a6fbe4e583fdb6e843af2594e907455aeafe30b1e14f1757cd83ce1776773cf8296ffc3a4acf13f0bd3dfebcf1db6ae80 - languageName: node - linkType: hard - -"aes-js@npm:3.0.0": - version: 3.0.0 - resolution: "aes-js@npm:3.0.0" - checksum: 251e26d533cd1a915b44896b17d5ed68c24a02484cfdd2e74ec700a309267db96651ea4eb657bf20aac32a3baa61f6e34edf8e2fec2de440a655da9942d334b8 - languageName: node - linkType: hard - -"arg@npm:^4.1.0": - version: 4.1.3 - resolution: "arg@npm:4.1.3" - checksum: 544af8dd3f60546d3e4aff084d451b96961d2267d668670199692f8d054f0415d86fc5497d0e641e91546f0aa920e7c29e5250e99fc89f5552a34b5d93b77f43 - languageName: node - linkType: hard - -"bech32@npm:1.1.4": - version: 1.1.4 - resolution: "bech32@npm:1.1.4" - checksum: 0e98db619191548390d6f09ff68b0253ba7ae6a55db93dfdbb070ba234c1fd3308c0606fbcc95fad50437227b10011e2698b89f0181f6e7f845c499bd14d0f4b - languageName: node - linkType: hard - -"bn.js@npm:^4.11.9": - version: 4.12.0 - resolution: "bn.js@npm:4.12.0" - checksum: 39afb4f15f4ea537b55eaf1446c896af28ac948fdcf47171961475724d1bb65118cca49fa6e3d67706e4790955ec0e74de584e45c8f1ef89f46c812bee5b5a12 - languageName: node - linkType: hard - -"bn.js@npm:^5.2.1": - version: 5.2.1 - resolution: "bn.js@npm:5.2.1" - checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3 - languageName: node - linkType: hard - -"brorand@npm:^1.1.0": - version: 1.1.0 - resolution: "brorand@npm:1.1.0" - checksum: 8a05c9f3c4b46572dec6ef71012b1946db6cae8c7bb60ccd4b7dd5a84655db49fe043ecc6272e7ef1f69dc53d6730b9e2a3a03a8310509a3d797a618cbee52be - languageName: node - linkType: hard - -"create-require@npm:^1.1.0": - version: 1.1.1 - resolution: "create-require@npm:1.1.1" - checksum: a9a1503d4390d8b59ad86f4607de7870b39cad43d929813599a23714831e81c520bddf61bcdd1f8e30f05fd3a2b71ae8538e946eb2786dc65c2bbc520f692eff - languageName: node - linkType: hard - -"diff@npm:^4.0.1": - version: 4.0.2 - resolution: "diff@npm:4.0.2" - checksum: f2c09b0ce4e6b301c221addd83bf3f454c0bc00caa3dd837cf6c127d6edf7223aa2bbe3b688feea110b7f262adbfc845b757c44c8a9f8c0c5b15d8fa9ce9d20d - languageName: node - linkType: hard - -"elliptic@npm:6.5.4": - version: 6.5.4 - resolution: "elliptic@npm:6.5.4" - 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 - checksum: d56d21fd04e97869f7ffcc92e18903b9f67f2d4637a23c860492fbbff5a3155fd9ca0184ce0c865dd6eb2487d234ce9551335c021c376cd2d3b7cb749c7d10f4 - languageName: node - linkType: hard - -"ethers@npm:^5.6.8": - version: 5.6.8 - resolution: "ethers@npm:5.6.8" - dependencies: - "@ethersproject/abi": 5.6.3 - "@ethersproject/abstract-provider": 5.6.1 - "@ethersproject/abstract-signer": 5.6.2 - "@ethersproject/address": 5.6.1 - "@ethersproject/base64": 5.6.1 - "@ethersproject/basex": 5.6.1 - "@ethersproject/bignumber": 5.6.2 - "@ethersproject/bytes": 5.6.1 - "@ethersproject/constants": 5.6.1 - "@ethersproject/contracts": 5.6.2 - "@ethersproject/hash": 5.6.1 - "@ethersproject/hdnode": 5.6.2 - "@ethersproject/json-wallets": 5.6.1 - "@ethersproject/keccak256": 5.6.1 - "@ethersproject/logger": 5.6.0 - "@ethersproject/networks": 5.6.3 - "@ethersproject/pbkdf2": 5.6.1 - "@ethersproject/properties": 5.6.0 - "@ethersproject/providers": 5.6.8 - "@ethersproject/random": 5.6.1 - "@ethersproject/rlp": 5.6.1 - "@ethersproject/sha2": 5.6.1 - "@ethersproject/signing-key": 5.6.2 - "@ethersproject/solidity": 5.6.1 - "@ethersproject/strings": 5.6.1 - "@ethersproject/transactions": 5.6.2 - "@ethersproject/units": 5.6.1 - "@ethersproject/wallet": 5.6.2 - "@ethersproject/web": 5.6.1 - "@ethersproject/wordlists": 5.6.1 - checksum: 3ef1e1509e96029839330bef465c368fee140d98c4fb23d743a0904b7ebdf70fa3c79683a2350355c9400497a5c179fe988d84a2b578d756f09c80462a94f614 - languageName: node - linkType: hard - -"hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": - version: 1.1.7 - resolution: "hash.js@npm:1.1.7" - dependencies: - inherits: ^2.0.3 - minimalistic-assert: ^1.0.1 - checksum: e350096e659c62422b85fa508e4b3669017311aa4c49b74f19f8e1bc7f3a54a584fdfd45326d4964d6011f2b2d882e38bea775a96046f2a61b7779a979629d8f - languageName: node - linkType: hard - -"hmac-drbg@npm:^1.0.1": - version: 1.0.1 - resolution: "hmac-drbg@npm:1.0.1" - dependencies: - hash.js: ^1.0.3 - minimalistic-assert: ^1.0.0 - minimalistic-crypto-utils: ^1.0.1 - checksum: bd30b6a68d7f22d63f10e1888aee497d7c2c5c0bb469e66bbdac99f143904d1dfe95f8131f95b3e86c86dd239963c9d972fcbe147e7cffa00e55d18585c43fe0 - languageName: node - linkType: hard - -"inherits@npm:^2.0.3, inherits@npm:^2.0.4": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 - languageName: node - linkType: hard - -"js-sha3@npm:0.8.0": - version: 0.8.0 - resolution: "js-sha3@npm:0.8.0" - checksum: 75df77c1fc266973f06cce8309ce010e9e9f07ec35ab12022ed29b7f0d9c8757f5a73e1b35aa24840dced0dea7059085aa143d817aea9e188e2a80d569d9adce - languageName: node - linkType: hard - -"make-error@npm:^1.1.1": - version: 1.3.6 - resolution: "make-error@npm:1.3.6" - checksum: b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 - languageName: node - linkType: hard - -"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": - version: 1.0.1 - resolution: "minimalistic-assert@npm:1.0.1" - checksum: cc7974a9268fbf130fb055aff76700d7e2d8be5f761fb5c60318d0ed010d839ab3661a533ad29a5d37653133385204c503bfac995aaa4236f4e847461ea32ba7 - languageName: node - linkType: hard - -"minimalistic-crypto-utils@npm:^1.0.1": - version: 1.0.1 - resolution: "minimalistic-crypto-utils@npm:1.0.1" - checksum: 6e8a0422b30039406efd4c440829ea8f988845db02a3299f372fceba56ffa94994a9c0f2fd70c17f9969eedfbd72f34b5070ead9656a34d3f71c0bd72583a0ed - languageName: node - linkType: hard - -"scrypt-js@npm:3.0.1": - version: 3.0.1 - resolution: "scrypt-js@npm:3.0.1" - checksum: b7c7d1a68d6ca946f2fbb0778e0c4ec63c65501b54023b2af7d7e9f48fdb6c6580d6f7675cd53bda5944c5ebc057560d5a6365079752546865defb3b79dea454 - languageName: node - linkType: hard - -"ts-node@npm:^10.8.1": - version: 10.8.1 - resolution: "ts-node@npm:10.8.1" - dependencies: - "@cspotcode/source-map-support": ^0.8.0 - "@tsconfig/node10": ^1.0.7 - "@tsconfig/node12": ^1.0.7 - "@tsconfig/node14": ^1.0.0 - "@tsconfig/node16": ^1.0.2 - acorn: ^8.4.1 - acorn-walk: ^8.1.1 - arg: ^4.1.0 - create-require: ^1.1.0 - diff: ^4.0.1 - make-error: ^1.1.1 - v8-compile-cache-lib: ^3.0.1 - yn: 3.1.1 - peerDependencies: - "@swc/core": ">=1.2.50" - "@swc/wasm": ">=1.2.50" - "@types/node": "*" - typescript: ">=2.7" - peerDependenciesMeta: - "@swc/core": - optional: true - "@swc/wasm": - optional: true - bin: - ts-node: dist/bin.js - ts-node-cwd: dist/bin-cwd.js - ts-node-esm: dist/bin-esm.js - ts-node-script: dist/bin-script.js - ts-node-transpile-only: dist/bin-transpile.js - ts-script: dist/bin-script-deprecated.js - checksum: 7d1aa7aa3ae1c0459c4922ed0dbfbade442cfe0c25aebaf620cdf1774f112c8d7a9b14934cb6719274917f35b2c503ba87bcaf5e16a0d39ba0f68ce3e7728363 - languageName: node - linkType: hard - -"typescript@npm:^4.5.2": - version: 4.5.2 - resolution: "typescript@npm:4.5.2" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 74f9ce65d532bdf5d0214b3f60cf37992180023388c87a11ee6f838a803067ef0b63c600fa501b0deb07f989257dce1e244c9635ed79feca40bbccf6e0aa1ebc - languageName: node - linkType: hard - -"typescript@patch:typescript@^4.5.2#~builtin": - version: 4.5.2 - resolution: "typescript@patch:typescript@npm%3A4.5.2#~builtin::version=4.5.2&hash=bcec9a" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: e25e689eba64f7da7cfc43f8ea76cac7176b56caba42655f0a4cb29c0b7c36e67ca54f33df95902859f56108464245d8b45bcdfe21e3d66d9560feb8db780246 - languageName: node - linkType: hard - -"v8-compile-cache-lib@npm:^3.0.1": - version: 3.0.1 - resolution: "v8-compile-cache-lib@npm:3.0.1" - checksum: 78089ad549e21bcdbfca10c08850022b22024cdcc2da9b168bcf5a73a6ed7bf01a9cebb9eac28e03cd23a684d81e0502797e88f3ccd27a32aeab1cfc44c39da0 - languageName: node - linkType: hard - -"ws@npm:7.4.6": - version: 7.4.6 - resolution: "ws@npm:7.4.6" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 3a990b32ed08c72070d5e8913e14dfcd831919205be52a3ff0b4cdd998c8d554f167c9df3841605cde8b11d607768cacab3e823c58c96a5c08c987e093eb767a - languageName: node - linkType: hard - -"yn@npm:3.1.1": - version: 3.1.1 - resolution: "yn@npm:3.1.1" - checksum: 2c487b0e149e746ef48cda9f8bad10fc83693cd69d7f9dcd8be4214e985de33a29c9e24f3c0d6bcf2288427040a8947406ab27f7af67ee9456e6b84854f02dd6 - languageName: node - linkType: hard +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" + integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== + 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" + +"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" + integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== + 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" + +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" + integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== + 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" + +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" + integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== + 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" + +"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" + integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + +"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" + integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" + integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" + integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" + integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + +"@ethersproject/contracts@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" + integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== + 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" + +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" + integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== + 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" + +"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" + integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== + 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" + +"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" + integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== + 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" + +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" + integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" + integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== + +"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" + integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" + integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" + integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== + dependencies: + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/providers@5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + 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" + +"@ethersproject/random@5.7.0", "@ethersproject/random@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" + integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" + integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" + integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" + integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== + 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" + +"@ethersproject/solidity@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" + integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== + 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" + +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" + integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" + integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== + 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" + +"@ethersproject/units@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" + integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + +"@ethersproject/wallet@5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" + integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== + 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" + +"@ethersproject/web@5.7.1", "@ethersproject/web@^5.7.0": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" + integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== + 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" + +"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.7.0": + version "5.7.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" + integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== + 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" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/node@^16.11.10": + version "16.18.54" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.54.tgz#4a63bdcea5b714f546aa27406a1c60621236a132" + integrity sha512-oTmGy68gxZZ21FhTJVVvZBYpQHEBZxHKTsGshobMqm9qWpbqdZsA5jvsuPZcHu0KwpmLrOHWPdEfg7XDpNT9UA== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +elliptic@6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + 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" + +ethers@^5.6.8: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + 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" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +scrypt-js@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +ts-node@^10.8.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +typescript@^4.5.2: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From 2953bf00c0c57fe96c0d01a534e26b564e018821 Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Mon, 2 Oct 2023 09:36:27 +0200 Subject: [PATCH 2/7] chore: upgrade to ethers@5.7.2 --- package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2aad6dd..c601429 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "devDependencies": { "@types/node": "^16.11.10", - "ethers": "^5.6.8", + "ethers": "^5.7.2", "ts-node": "^10.8.1", "typescript": "^4.5.2" }, diff --git a/yarn.lock b/yarn.lock index 199598d..bb01cb8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -457,7 +457,7 @@ elliptic@6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -ethers@^5.6.8: +ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== From caa0b60132478ba8776e6858d594a48cacda069c Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Mon, 2 Oct 2023 10:27:37 +0200 Subject: [PATCH 3/7] fix: legacy-celo serialization --- src/lib/transaction/utils.ts | 14 +++++++++++ src/lib/transactions.ts | 48 +++++++++++++++++++++--------------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/lib/transaction/utils.ts b/src/lib/transaction/utils.ts index a84f1c2..38c8f90 100644 --- a/src/lib/transaction/utils.ts +++ b/src/lib/transaction/utils.ts @@ -39,3 +39,17 @@ export function isCIP42(tx: any): boolean { export function concatHex(values: string[]): `0x${string}` { return `0x${values.reduce((acc, x) => acc + x.replace("0x", ""), "")}`; } + +export function omit( + object: T, + ...keys: K +): { + [Key in keyof T as Key extends K ? never : Key]: T[Key]; +} { + return Object.keys(object) + .filter((key) => !keys.includes(key as keyof T)) + .reduce((acc, key) => { + acc[key as keyof T] = object[key as keyof T]; + return acc; + }, {} as T); +} diff --git a/src/lib/transactions.ts b/src/lib/transactions.ts index 67ace4e..bd601f9 100644 --- a/src/lib/transactions.ts +++ b/src/lib/transactions.ts @@ -7,7 +7,13 @@ import { Transaction, utils, } from "ethers"; -import { concatHex, isCIP42, isCIP64, isEIP1559 } from "./transaction/utils"; +import { + concatHex, + isCIP42, + isCIP64, + isEIP1559, + omit, +} from "./transaction/utils"; import { accessListify, AccessListish } from "ethers/lib/utils"; // From https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L33 @@ -374,7 +380,7 @@ export function serializeCeloTransaction( export function parseCeloTransaction( rawTransaction: utils.BytesLike ): CeloTransaction { - const [type, transaction] = prepareParseRawTransaction(rawTransaction); + const [type, transaction] = splitTypeAndRawTx(rawTransaction); let tx: CeloTransaction; switch (type!) { @@ -394,6 +400,7 @@ export function parseCeloTransaction( } as CeloTransactionCip64; break; case TxTypeToPrefix.cip42: + // untested tx = { type: TxTypeToPrefix.cip42, chainId: handleNumber(transaction[0]).toNumber(), @@ -411,6 +418,7 @@ export function parseCeloTransaction( } as CeloTransactionCip42; break; case TxTypeToPrefix.eip1559: + // untested tx = { type: TxTypeToPrefix.eip1559, chainId: handleNumber(transaction[0]).toNumber(), @@ -445,10 +453,6 @@ export function parseCeloTransaction( return tx; } - const digest = utils.keccak256( - serializeCeloTransaction(tx as CeloTransactionRequest) - ); - try { tx.v = BigNumber.from(transaction.at(-3)).toNumber(); } catch (error) { @@ -465,13 +469,18 @@ export function parseCeloTransaction( tx.v = 0; } else { // Signed Transaction - const chainId = Math.max(0, Math.floor((tx.v - 35) / 2)); tx.chainId = chainId; if (tx.chainId < 0) { tx.chainId = 0; } + // NOTE: Serialization needs to happen here because chainId may not populated before + const serialized = serializeCeloTransaction( + omit(tx, "v", "r", "s") as CeloTransactionRequest + ); + const digest = utils.keccak256(serialized); + let recoveryParam = tx.v - 27; if (tx.chainId !== 0) { // NOTE: inverse operation that was done in `serializeCeloTransaction` @@ -492,7 +501,6 @@ export function parseCeloTransaction( tx.hash = utils.keccak256(rawTransaction); } - console.log(tx); return tx; } @@ -529,16 +537,15 @@ const baseTxLengths = { "celo-legacy": { unsigned: 12, signed: 12 }, } as const; -// const nonceToIndices = { -// [TxTypeToPrefix.cip64]: { nonceIndex: 1, toIndex: 5 }, -// [TxTypeToPrefix.cip42]: { nonceIndex: 1, toIndex: 8 }, -// [TxTypeToPrefix.eip1559]: { nonceIndex: 1, toIndex: 5 }, -// "celo-legacy": { nonceIndex: 0, toIndex: 6 }, -// } as const; - function isSigned(type: TxTypeToPrefix, transaction: string[]) { - const { signed } = baseTxLengths[type || "celo-legacy"]; - return transaction.length === signed; + if (type) { + const { signed } = baseTxLengths[type]; + return transaction.length === signed; + } + + const r = transaction.at(-2) || "0x"; + const s = transaction.at(-1) || "0x"; + return r !== "0x" && s !== "0x"; } function isCorrectLength(type: TxTypeToPrefix, transaction: string[]) { @@ -546,19 +553,20 @@ function isCorrectLength(type: TxTypeToPrefix, transaction: string[]) { return transaction.length === unsigned || isSigned(type, transaction); } -function prepareParseRawTransaction( +function splitTypeAndRawTx( rawTransaction: utils.BytesLike ): [TxTypeToPrefix | undefined, any[]] { let rawStr = rawTransaction.toString(); let type: TxTypeToPrefix | undefined; - for (type of [ + for (const _type of [ TxTypeToPrefix.cip64, TxTypeToPrefix.cip42, TxTypeToPrefix.eip1559, ]) { - const prefix = utils.hexlify(type); + const prefix = utils.hexlify(_type); if (rawStr.startsWith(prefix)) { rawStr = `0x${rawStr.slice(prefix.length)}`; + type = _type; break; } } From ddd8d28d527a1de7c51aff2ef4e071aeea1eb9c4 Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Mon, 2 Oct 2023 17:59:28 +0200 Subject: [PATCH 4/7] fix: cip64 is ALIVE --- src/lib/CeloProvider.ts | 44 +++++++++++- src/lib/CeloWallet.ts | 14 ++-- src/lib/transaction/utils.ts | 10 ++- src/lib/transactions.ts | 127 +++++++++++++++++++++++------------ test/useContract.ts | 53 ++++++++------- 5 files changed, 176 insertions(+), 72 deletions(-) diff --git a/src/lib/CeloProvider.ts b/src/lib/CeloProvider.ts index 8edb5a0..9f3e531 100644 --- a/src/lib/CeloProvider.ts +++ b/src/lib/CeloProvider.ts @@ -1,6 +1,6 @@ import { BigNumber, providers, utils } from "ethers"; import { getNetwork } from "./networks"; -import { parseCeloTransaction } from "./transactions"; +import { CeloTransactionRequest, parseCeloTransaction } from "./transactions"; const logger = new utils.Logger("CeloProvider"); @@ -54,6 +54,22 @@ export class CeloProvider extends providers.JsonRpcProvider { return ["eth_gasPrice", param]; } + if (method === "estimateGas") { + // NOTE: somehow estimategas trims lots of fields + // this overrides it + const tx = { + // @ts-expect-error + ...this.constructor.hexlifyTransaction(params.transaction, { + feeCurrency: true, + from: true, + }), + }; + if (params.transaction.feeCurrency) { + tx.feeCurrency = params.transaction.feeCurrency; + } + return ["eth_estimateGas", [tx]]; + } + return super.prepareRequest(method, params); } @@ -71,4 +87,30 @@ export class CeloProvider extends providers.JsonRpcProvider { } return network; } + + async estimateGas( + transaction: utils.Deferrable + ): Promise { + // NOTE: Overrides the ethers method to make sure feeCurrency and from are sent + // to the rpc node + await this.getNetwork(); + const params = await utils.resolveProperties({ + transaction, + }); + const result = await this.perform("estimateGas", params); + try { + return BigNumber.from(result); + } catch (error) { + return logger.throwError( + "bad result from backend", + utils.Logger.errors.SERVER_ERROR, + { + method: "estimateGas", + params, + result, + error, + } + ); + } + } } diff --git a/src/lib/CeloWallet.ts b/src/lib/CeloWallet.ts index fb2f56a..5ebcf04 100644 --- a/src/lib/CeloWallet.ts +++ b/src/lib/CeloWallet.ts @@ -6,6 +6,7 @@ import { getTxType, serializeCeloTransaction, } from "./transactions"; +import { adjustForGasInflation } from "./transaction/utils"; const logger = new utils.Logger("CeloWallet"); @@ -24,15 +25,21 @@ export class CeloWallet extends Wallet { transaction: utils.Deferrable ): Promise { const tx: any = await utils.resolveProperties(transaction); - if (tx.to != null) { tx.to = Promise.resolve(tx.to).then((to) => this.resolveName(to as string) ); } - if (tx.gasPrice == null) { + + if (tx.from == null) { + tx.from = this.address; + } + + const type = getTxType(tx); + if (!type && tx.gasPrice == null) { tx.gasPrice = this.getGasPrice(); } + if (tx.nonce == null) { tx.nonce = this.getTransactionCount("pending"); } @@ -120,8 +127,7 @@ export class CeloWallet extends Wallet { this._checkProvider("estimateGas"); // @ts-expect-error const tx: CeloTransaction = await utils.resolveProperties(transaction); - void getTxType(tx); - return await this.provider.estimateGas(tx); + return this.provider.estimateGas(tx).then(adjustForGasInflation); } /** diff --git a/src/lib/transaction/utils.ts b/src/lib/transaction/utils.ts index 38c8f90..d0f8478 100644 --- a/src/lib/transaction/utils.ts +++ b/src/lib/transaction/utils.ts @@ -1,4 +1,4 @@ -import { BigNumberish } from "ethers"; +import { BigNumber, BigNumberish } from "ethers"; import { hexlify } from "ethers/lib/utils"; function isEmpty(value: string | BigNumberish | undefined | null) { @@ -53,3 +53,11 @@ export function omit( return acc; }, {} as T); } + +export function adjustForGasInflation(gas: BigNumber): BigNumber { + // NOTE: Don't ask me + const GAS_INFLATION_FACTOR = 1.3; + + // NOTE: prevent floating point math + return gas.mul(Math.floor(GAS_INFLATION_FACTOR * 100)).div(100); +} diff --git a/src/lib/transactions.ts b/src/lib/transactions.ts index bd601f9..44f6e58 100644 --- a/src/lib/transactions.ts +++ b/src/lib/transactions.ts @@ -16,6 +16,9 @@ import { } from "./transaction/utils"; import { accessListify, AccessListish } from "ethers/lib/utils"; +// NOTE: Black magic +const Y_PARITY_EIP_2098 = 27; + // From https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L33 // Copied because it doesn't seem to be exported from 'ethers' anywhere type SignatureLike = @@ -274,7 +277,8 @@ function prepareEncodeTx( if (signature) { raw.push( ...[ - utils.hexlify(signature.v), + // NOTE: Somehow geth cannot parse `0x00` because it's dumb + signature.v ? utils.hexlify(signature.v) : "0x", utils.stripZeros(utils.arrayify(signature.r)), utils.stripZeros(utils.arrayify(signature.s)), ] @@ -348,27 +352,42 @@ export function serializeCeloTransaction( // case that the signTransaction function only adds a v. const sig = utils.splitSignature(signature); - let v = 27 + sig.recoveryParam; - if (chainId !== 0) { - // NOTE: this makes the recoveryParam recovery custom in `parseCeloTransaction` - // see line: - v += chainId * 2 + 8; - - // If an EIP-155 v (directly or indirectly; maybe _vs) was provided, check it! - if (sig.v > 28 && sig.v !== v) { - logger.throwArgumentError( - "transaction.chainId/signature.v mismatch", - "signature", - signature - ); - } - } else if (sig.v !== v) { - logger.throwArgumentError( - "transaction.chainId/signature.v mismatch", - "signature", - signature - ); + let v = sig.v - Y_PARITY_EIP_2098; + if (txArgs.type) { + // cip64,cip42, eip-1559 + // noop + } else { + // celo-legacy + v = sig.v + chainId * 2 + 35; } + + // TODO: rossy cleanup nico + // let v = 27 + sig.recoveryParam; + // if (chainId !== 0) { + // // NOTE: this makes the recoveryParam recovery custom in `parseCeloTransaction` + // // see line: + // if (txArgs.type) { + // // cip64,cip42, eip-1559 + // } else { + // // celo-legacy + // v += chainId * 2 + 8; + // } + + // // If an EIP-155 v (directly or indirectly; maybe _vs) was provided, check it! + // if (sig.v > 28 && sig.v !== v) { + // logger.throwArgumentError( + // "transaction.chainId/signature.v mismatch", + // "signature", + // signature + // ); + // } + // } else if (sig.v !== v) { + // logger.throwArgumentError( + // "transaction.chainId/signature.v mismatch", + // "signature", + // signature + // ); + // } // @ts-expect-error const raw = prepareEncodeTx(txArgs, { ...sig, v }); const encoded = utils.RLP.encode(raw); @@ -389,13 +408,13 @@ export function parseCeloTransaction( type: TxTypeToPrefix.cip64, chainId: handleNumber(transaction[0]).toNumber(), nonce: handleNumber(transaction[1]).toNumber(), - maxPriorityFeePerGas: transaction[2], - maxFeePerGas: transaction[3], + maxPriorityFeePerGas: handleNumber(transaction[2]), + maxFeePerGas: handleNumber(transaction[3]), gasLimit: handleNumber(transaction[4]), to: handleAddress(transaction[5]), value: handleNumber(transaction[6]), data: transaction[7], - // accessList: handleAccessList(transaction[8]), + accessList: handleAccessList(transaction[8]), feeCurrency: handleAddress(transaction[9]), } as CeloTransactionCip64; break; @@ -405,8 +424,8 @@ export function parseCeloTransaction( type: TxTypeToPrefix.cip42, chainId: handleNumber(transaction[0]).toNumber(), nonce: handleNumber(transaction[1]).toNumber(), - maxPriorityFeePerGas: transaction[2], - maxFeePerGas: transaction[3], + maxPriorityFeePerGas: handleNumber(transaction[2]), + maxFeePerGas: handleNumber(transaction[3]), gasLimit: handleNumber(transaction[4]), feeCurrency: handleAddress(transaction[5]), gatewayFeeRecipient: handleAddress(transaction[6]), @@ -423,8 +442,8 @@ export function parseCeloTransaction( type: TxTypeToPrefix.eip1559, chainId: handleNumber(transaction[0]).toNumber(), nonce: handleNumber(transaction[1]).toNumber(), - maxPriorityFeePerGas: transaction[2], - maxFeePerGas: transaction[3], + maxPriorityFeePerGas: handleNumber(transaction[2]), + maxFeePerGas: handleNumber(transaction[3]), gasLimit: handleNumber(transaction[4]), to: handleAddress(transaction[5]), value: handleNumber(transaction[6]), @@ -454,7 +473,7 @@ export function parseCeloTransaction( } try { - tx.v = BigNumber.from(transaction.at(-3)).toNumber(); + tx.v = handleNumber(transaction.at(-3)).toNumber(); } catch (error) { console.log(error); return tx; @@ -463,17 +482,36 @@ export function parseCeloTransaction( tx.r = utils.hexZeroPad(transaction.at(-2), 32); tx.s = utils.hexZeroPad(transaction.at(-1), 32); - if (BigNumber.from(tx.r).isZero() && BigNumber.from(tx.s).isZero()) { - // EIP-155 unsigned transaction + // EIP-155 unsigned transaction + if (handleNumber(tx.r).isZero() && handleNumber(tx.s).isZero()) { tx.chainId = tx.v; tx.v = 0; - } else { - // Signed Transaction - const chainId = Math.max(0, Math.floor((tx.v - 35) / 2)); - tx.chainId = chainId; - if (tx.chainId < 0) { - tx.chainId = 0; + } + // Signed Transaction + else { + let chainId: number; + let recoveryParam = tx.v; + if (tx.type) { + // cip64, cip42, eip-1559 + // noop, chainId is in tx + chainId = tx.chainId; + } else { + // celo-legacy + chainId = Math.max(0, Math.floor((tx.v - 35) / 2)); + tx.chainId = chainId; + recoveryParam = tx.v + Y_PARITY_EIP_2098; + recoveryParam -= tx.chainId * 2 + 35; } + // // NOTE: is this condition even correct now? + // if (!tx.chainId) { + // const chainId = Math.max(0, Math.floor((tx.v - 35) / 2)); + // tx.chainId = chainId; + // } + // let recoveryParam = tx.v - 27; + // if (tx.chainId !== 0) { + // // NOTE: inverse operation that was done in `serializeCeloTransaction` + // recoveryParam -= tx.chainId * 2 + 8; + // } // NOTE: Serialization needs to happen here because chainId may not populated before const serialized = serializeCeloTransaction( @@ -481,12 +519,6 @@ export function parseCeloTransaction( ); const digest = utils.keccak256(serialized); - let recoveryParam = tx.v - 27; - if (tx.chainId !== 0) { - // NOTE: inverse operation that was done in `serializeCeloTransaction` - recoveryParam -= tx.chainId * 2 + 8; - } - try { // TODO there may be an issue here with incorrect from address extraction tx.from = utils.recoverAddress(digest, { @@ -501,6 +533,15 @@ export function parseCeloTransaction( tx.hash = utils.keccak256(rawTransaction); } + console.log("---------"); + console.log("Raw signed Tx", rawTransaction); + console.log("---------"); + console.log("RLP decoded Tx", transaction); + console.log("---------"); + console.log("Inferred type", type!); + console.log("---------"); + console.log("Parsed TX from raw signed:", tx); + console.log("---------"); return tx; } diff --git a/test/useContract.ts b/test/useContract.ts index ea8e7c9..965ebf6 100644 --- a/test/useContract.ts +++ b/test/useContract.ts @@ -1,19 +1,22 @@ -import { BigNumber, Contract } from "ethers"; -import { CUSD_ADDRESS } from "./consts"; -import { STABLE_TOKEN_ABI } from "./stableToken"; +import { BigNumber } from "ethers"; +// import { CUSD_ADDRESS } from "./consts"; +// import { STABLE_TOKEN_ABI } from "./stableToken"; import { getSigner } from "./utils"; +import { CUSD_ADDRESS } from "./consts"; +// import { parseCeloTransaction } from "../src/lib/transactions"; +// import { parseCeloTransaction } from "../src/lib/transactions"; async function main() { const signer = getSigner(); // console.info("Getting account balance for:", signer.address); - const balance = await signer.getBalance(); - console.info("Balance:", balance.toString()); + // const balance = await signer.getBalance(); + // console.info("Balance:", balance.toString()); // console.info("Sending 1 CELO wei", signer.address); - const txResponse1 = await signer.sendTransaction({ - to: signer.address, - value: BigNumber.from("1"), - }); + // const txResponse1 = await signer.sendTransaction({ + // to: signer.address, + // value: BigNumber.from("1"), + // }); // Or, alternatively, break apart signing and sending: // const signedTx = await signer.signTransaction({ @@ -22,9 +25,13 @@ async function main() { // }); // const provider = signer.provider; // const txResponse1 = await provider.sendTransaction(signedTx); - const txReceipt1 = await txResponse1.wait(); - console.info("Funds sent. Hash:", txReceipt1.transactionHash); - + // const txReceipt1 = await txResponse1.wait(); + // console.info("Funds sent. Hash:", txReceipt1.transactionHash); + // console.log( + // parseCeloTransaction( + // "0x7bf88b82f37082050484313da74884362a38028301688c94325f890e573880311cfbadfe8ec3d51ffdd97a7687038d7ea4c6800080c09462492a644a588fd904270bed06ad52b9abfea1ae01a0920e75c798a225d5bd1b1e5c66babdc51943f39b32694d1819f99e5d33353b76a014473654adc9d03fe8de4fe275c1054b5b73d23095fecf7630e2b3a78322e0a2" + // ) + // ); console.info("Sending 1 CELO wei with cUSD feeCurrency"); const txResponse1feeCurrency = await signer.sendTransaction({ to: signer.address, @@ -38,19 +45,19 @@ async function main() { `CELO w/ feeCurrency payment hash: ${txReceipt1FeeCurency.transactionHash}` ); - const stableToken = new Contract(CUSD_ADDRESS, STABLE_TOKEN_ABI, signer); + // const stableToken = new Contract(CUSD_ADDRESS, STABLE_TOKEN_ABI, signer); - console.info("Getting cUSD balance"); - const stableBalance = await stableToken.balanceOf(signer.address); - console.info(`cUSD balance: ${stableBalance.toString()}`); + // console.info("Getting cUSD balance"); + // const stableBalance = await stableToken.balanceOf(signer.address); + // console.info(`cUSD balance: ${stableBalance.toString()}`); - console.info("Sending 1 cUSD wei"); - const txResponse2 = await stableToken.transfer( - signer.address, - BigNumber.from("1") - ); - const txReceipt2 = await txResponse2.wait(); - console.info(`cUSD payment hash: ${txReceipt2.transactionHash}`); + // console.info("Sending 1 cUSD wei"); + // const txResponse2 = await stableToken.transfer( + // signer.address, + // BigNumber.from("1") + // ); + // const txReceipt2 = await txResponse2.wait(); + // console.info(`cUSD payment hash: ${txReceipt2.transactionHash}`); } main() From 71ae5fe1d269bb6a7468c48c1c9b3d30dd8b602e Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Mon, 2 Oct 2023 18:16:12 +0200 Subject: [PATCH 5/7] fix: legacy-celo v/r/s black magic --- src/lib/transactions.ts | 92 ++++++++++++++--------------------------- test/useContract.ts | 57 +++++++++++-------------- 2 files changed, 56 insertions(+), 93 deletions(-) diff --git a/src/lib/transactions.ts b/src/lib/transactions.ts index 44f6e58..0d02c91 100644 --- a/src/lib/transactions.ts +++ b/src/lib/transactions.ts @@ -18,6 +18,7 @@ import { accessListify, AccessListish } from "ethers/lib/utils"; // NOTE: Black magic const Y_PARITY_EIP_2098 = 27; +const BULLSHIT_NUMBER = 8; // From https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L33 // Copied because it doesn't seem to be exported from 'ethers' anywhere @@ -352,42 +353,34 @@ export function serializeCeloTransaction( // case that the signTransaction function only adds a v. const sig = utils.splitSignature(signature); - let v = sig.v - Y_PARITY_EIP_2098; + let v: number; if (txArgs.type) { // cip64,cip42, eip-1559 - // noop + v = sig.v - Y_PARITY_EIP_2098; } else { // celo-legacy - v = sig.v + chainId * 2 + 35; + v = Y_PARITY_EIP_2098 + sig.recoveryParam; + + if (chainId !== 0) { + v += chainId * 2 + BULLSHIT_NUMBER; + + // If an EIP-155 v (directly or indirectly; maybe _vs) was provided, check it! + if (sig.v > Y_PARITY_EIP_2098 + 1 && sig.v !== v) { + logger.throwArgumentError( + "transaction.chainId/signature.v mismatch", + "signature", + signature + ); + } + } else if (sig.v !== v) { + logger.throwArgumentError( + "transaction.chainId/signature.v mismatch", + "signature", + signature + ); + } } - // TODO: rossy cleanup nico - // let v = 27 + sig.recoveryParam; - // if (chainId !== 0) { - // // NOTE: this makes the recoveryParam recovery custom in `parseCeloTransaction` - // // see line: - // if (txArgs.type) { - // // cip64,cip42, eip-1559 - // } else { - // // celo-legacy - // v += chainId * 2 + 8; - // } - - // // If an EIP-155 v (directly or indirectly; maybe _vs) was provided, check it! - // if (sig.v > 28 && sig.v !== v) { - // logger.throwArgumentError( - // "transaction.chainId/signature.v mismatch", - // "signature", - // signature - // ); - // } - // } else if (sig.v !== v) { - // logger.throwArgumentError( - // "transaction.chainId/signature.v mismatch", - // "signature", - // signature - // ); - // } // @ts-expect-error const raw = prepareEncodeTx(txArgs, { ...sig, v }); const encoded = utils.RLP.encode(raw); @@ -484,34 +477,20 @@ export function parseCeloTransaction( // EIP-155 unsigned transaction if (handleNumber(tx.r).isZero() && handleNumber(tx.s).isZero()) { - tx.chainId = tx.v; - tx.v = 0; + if (!type) { + tx.chainId = tx.v; + tx.v = 0; + } } // Signed Transaction else { - let chainId: number; let recoveryParam = tx.v; - if (tx.type) { - // cip64, cip42, eip-1559 - // noop, chainId is in tx - chainId = tx.chainId; - } else { + if (!type) { // celo-legacy - chainId = Math.max(0, Math.floor((tx.v - 35) / 2)); - tx.chainId = chainId; - recoveryParam = tx.v + Y_PARITY_EIP_2098; - recoveryParam -= tx.chainId * 2 + 35; + tx.chainId = Math.max(0, Math.floor((tx.v - 35) / 2)); + recoveryParam = tx.v - Y_PARITY_EIP_2098; + recoveryParam -= tx.chainId * 2 + BULLSHIT_NUMBER; } - // // NOTE: is this condition even correct now? - // if (!tx.chainId) { - // const chainId = Math.max(0, Math.floor((tx.v - 35) / 2)); - // tx.chainId = chainId; - // } - // let recoveryParam = tx.v - 27; - // if (tx.chainId !== 0) { - // // NOTE: inverse operation that was done in `serializeCeloTransaction` - // recoveryParam -= tx.chainId * 2 + 8; - // } // NOTE: Serialization needs to happen here because chainId may not populated before const serialized = serializeCeloTransaction( @@ -533,15 +512,6 @@ export function parseCeloTransaction( tx.hash = utils.keccak256(rawTransaction); } - console.log("---------"); - console.log("Raw signed Tx", rawTransaction); - console.log("---------"); - console.log("RLP decoded Tx", transaction); - console.log("---------"); - console.log("Inferred type", type!); - console.log("---------"); - console.log("Parsed TX from raw signed:", tx); - console.log("---------"); return tx; } diff --git a/test/useContract.ts b/test/useContract.ts index 965ebf6..c01b3ef 100644 --- a/test/useContract.ts +++ b/test/useContract.ts @@ -1,22 +1,19 @@ -import { BigNumber } from "ethers"; -// import { CUSD_ADDRESS } from "./consts"; -// import { STABLE_TOKEN_ABI } from "./stableToken"; -import { getSigner } from "./utils"; +import { BigNumber, Contract } from "ethers"; import { CUSD_ADDRESS } from "./consts"; -// import { parseCeloTransaction } from "../src/lib/transactions"; -// import { parseCeloTransaction } from "../src/lib/transactions"; +import { STABLE_TOKEN_ABI } from "./stableToken"; +import { getSigner } from "./utils"; async function main() { const signer = getSigner(); - // console.info("Getting account balance for:", signer.address); - // const balance = await signer.getBalance(); - // console.info("Balance:", balance.toString()); + console.info("Getting account balance for:", signer.address); + const balance = await signer.getBalance(); + console.info("Balance:", balance.toString()); - // console.info("Sending 1 CELO wei", signer.address); - // const txResponse1 = await signer.sendTransaction({ - // to: signer.address, - // value: BigNumber.from("1"), - // }); + console.info("Sending 1 CELO wei", signer.address); + const txResponse1 = await signer.sendTransaction({ + to: signer.address, + value: BigNumber.from("1"), + }); // Or, alternatively, break apart signing and sending: // const signedTx = await signer.signTransaction({ @@ -25,13 +22,9 @@ async function main() { // }); // const provider = signer.provider; // const txResponse1 = await provider.sendTransaction(signedTx); - // const txReceipt1 = await txResponse1.wait(); - // console.info("Funds sent. Hash:", txReceipt1.transactionHash); - // console.log( - // parseCeloTransaction( - // "0x7bf88b82f37082050484313da74884362a38028301688c94325f890e573880311cfbadfe8ec3d51ffdd97a7687038d7ea4c6800080c09462492a644a588fd904270bed06ad52b9abfea1ae01a0920e75c798a225d5bd1b1e5c66babdc51943f39b32694d1819f99e5d33353b76a014473654adc9d03fe8de4fe275c1054b5b73d23095fecf7630e2b3a78322e0a2" - // ) - // ); + const txReceipt1 = await txResponse1.wait(); + console.info("Funds sent. Hash:", txReceipt1.transactionHash); + console.info("Sending 1 CELO wei with cUSD feeCurrency"); const txResponse1feeCurrency = await signer.sendTransaction({ to: signer.address, @@ -45,19 +38,19 @@ async function main() { `CELO w/ feeCurrency payment hash: ${txReceipt1FeeCurency.transactionHash}` ); - // const stableToken = new Contract(CUSD_ADDRESS, STABLE_TOKEN_ABI, signer); + const stableToken = new Contract(CUSD_ADDRESS, STABLE_TOKEN_ABI, signer); - // console.info("Getting cUSD balance"); - // const stableBalance = await stableToken.balanceOf(signer.address); - // console.info(`cUSD balance: ${stableBalance.toString()}`); + console.info("Getting cUSD balance"); + const stableBalance = await stableToken.balanceOf(signer.address); + console.info(`cUSD balance: ${stableBalance.toString()}`); - // console.info("Sending 1 cUSD wei"); - // const txResponse2 = await stableToken.transfer( - // signer.address, - // BigNumber.from("1") - // ); - // const txReceipt2 = await txResponse2.wait(); - // console.info(`cUSD payment hash: ${txReceipt2.transactionHash}`); + console.info("Sending 1 cUSD wei"); + const txResponse2 = await stableToken.transfer( + signer.address, + BigNumber.from("1") + ); + const txReceipt2 = await txResponse2.wait(); + console.info(`cUSD payment hash: ${txReceipt2.transactionHash}`); } main() From b3b9a5c1d2a473bfe030fa6d290c0a6b4703d919 Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Mon, 2 Oct 2023 18:33:27 +0200 Subject: [PATCH 6/7] chore: remove deprecated cip42 --- src/lib/CeloProvider.ts | 27 +++++++++++----- src/lib/transactions.ts | 68 ++--------------------------------------- test/useContract.ts | 34 ++++++++++++++++++--- 3 files changed, 53 insertions(+), 76 deletions(-) diff --git a/src/lib/CeloProvider.ts b/src/lib/CeloProvider.ts index 9f3e531..6dda604 100644 --- a/src/lib/CeloProvider.ts +++ b/src/lib/CeloProvider.ts @@ -57,16 +57,29 @@ export class CeloProvider extends providers.JsonRpcProvider { if (method === "estimateGas") { // NOTE: somehow estimategas trims lots of fields // this overrides it + const extraneous_keys = [ + ["from", (x: string) => x], + ["feeCurrency", utils.hexlify], + ["gatewayFeeRecipient", (x: string) => x], + ["gatewayFee", utils.hexlify], + ] as const; + const tx = { // @ts-expect-error - ...this.constructor.hexlifyTransaction(params.transaction, { - feeCurrency: true, - from: true, - }), + ...this.constructor.hexlifyTransaction( + params.transaction, + extraneous_keys.reduce((acc, [key]) => { + acc[key] = true; + return acc; + }, {} as Record) + ), }; - if (params.transaction.feeCurrency) { - tx.feeCurrency = params.transaction.feeCurrency; - } + extraneous_keys.forEach(([key, fn]) => { + if (params.transaction[key]) { + tx[key] = fn(params.transaction[key]); + } + }); + return ["eth_estimateGas", [tx]]; } diff --git a/src/lib/transactions.ts b/src/lib/transactions.ts index 0d02c91..90706ad 100644 --- a/src/lib/transactions.ts +++ b/src/lib/transactions.ts @@ -7,13 +7,7 @@ import { Transaction, utils, } from "ethers"; -import { - concatHex, - isCIP42, - isCIP64, - isEIP1559, - omit, -} from "./transaction/utils"; +import { concatHex, isCIP64, isEIP1559, omit } from "./transaction/utils"; import { accessListify, AccessListish } from "ethers/lib/utils"; // NOTE: Black magic @@ -45,13 +39,6 @@ export interface CeloTransactionCip64 extends Transaction { feeCurrency: string; } -export interface CeloTransactionCip42 extends Transaction { - type: TxTypeToPrefix.cip42; - feeCurrency: string; - gatewayFeeRecipient?: string; - gatewayFee?: string; -} - export interface CeloTransactionEip1559 extends Transaction { type: TxTypeToPrefix.eip1559; } @@ -66,11 +53,9 @@ export interface LegacyCeloTransaction extends Transaction { export type CeloTransaction = | LegacyCeloTransaction | CeloTransactionCip64 - | CeloTransactionCip42 | CeloTransactionEip1559; export enum TxTypeToPrefix { - cip42 = 0x7c, cip64 = 0x7b, eip1559 = 0x02, } @@ -177,10 +162,6 @@ export function getTxType(tx: CeloTransaction) { // @ts-ignore delete tx.gasPrice; return TxTypeToPrefix.cip64; - } else if (isCIP42(tx)) { - // @ts-ignore - delete tx.gasPrice; - return TxTypeToPrefix.cip42; } else if (isEIP1559(tx)) { // @ts-ignore delete tx.feeCurrency; @@ -219,26 +200,6 @@ function prepareEncodeTx( tx.feeCurrency || "0x", ]; break; - case TxTypeToPrefix.cip42: - // There shall be a typed transaction with the code 0x7c that has the following format: - // 0x7c || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, feecurrency, gatewayFeeRecipient, gatewayfee, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s]). - // This will be in addition to the type 0x02 transaction as specified in EIP-1559. - raw = [ - utils.hexlify(tx.chainId!), - utils.hexlify(tx.nonce!), - tx.maxPriorityFeePerGas ? utils.hexlify(tx.maxPriorityFeePerGas) : "0x", - tx.maxFeePerGas ? utils.hexlify(tx.maxFeePerGas) : "0x", - tx.gasLimit ? utils.hexlify(tx.gasLimit) : "0x", - tx.feeCurrency || "0x", - tx.gatewayFeeRecipient || "0x", - tx.gatewayFee || "0x", - tx.to || "0x", - tx.value ? utils.hexlify(tx.value) : "0x", - tx.data || "0x", - // @ts-expect-error - tx.accessList || [], - ]; - break; case TxTypeToPrefix.eip1559: // https://eips.ethereum.org/EIPS/eip-1559 // 0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s]). @@ -355,7 +316,7 @@ export function serializeCeloTransaction( let v: number; if (txArgs.type) { - // cip64,cip42, eip-1559 + // cip64, eip-1559 v = sig.v - Y_PARITY_EIP_2098; } else { // celo-legacy @@ -411,24 +372,6 @@ export function parseCeloTransaction( feeCurrency: handleAddress(transaction[9]), } as CeloTransactionCip64; break; - case TxTypeToPrefix.cip42: - // untested - tx = { - type: TxTypeToPrefix.cip42, - chainId: handleNumber(transaction[0]).toNumber(), - nonce: handleNumber(transaction[1]).toNumber(), - maxPriorityFeePerGas: handleNumber(transaction[2]), - maxFeePerGas: handleNumber(transaction[3]), - gasLimit: handleNumber(transaction[4]), - feeCurrency: handleAddress(transaction[5]), - gatewayFeeRecipient: handleAddress(transaction[6]), - gatewayFee: transaction[7] as string, - to: handleAddress(transaction[8]), - value: handleNumber(transaction[9]), - data: transaction[10], - accessList: handleAccessList(transaction[11]), - } as CeloTransactionCip42; - break; case TxTypeToPrefix.eip1559: // untested tx = { @@ -543,7 +486,6 @@ function handleAccessList(value: string): AccessListish | "0x" { const baseTxLengths = { [TxTypeToPrefix.cip64]: { unsigned: 10, signed: 13 }, - [TxTypeToPrefix.cip42]: { unsigned: 12, signed: 15 }, [TxTypeToPrefix.eip1559]: { unsigned: 9, signed: 12 }, "celo-legacy": { unsigned: 12, signed: 12 }, } as const; @@ -569,11 +511,7 @@ function splitTypeAndRawTx( ): [TxTypeToPrefix | undefined, any[]] { let rawStr = rawTransaction.toString(); let type: TxTypeToPrefix | undefined; - for (const _type of [ - TxTypeToPrefix.cip64, - TxTypeToPrefix.cip42, - TxTypeToPrefix.eip1559, - ]) { + for (const _type of [TxTypeToPrefix.cip64, TxTypeToPrefix.eip1559]) { const prefix = utils.hexlify(_type); if (rawStr.startsWith(prefix)) { rawStr = `0x${rawStr.slice(prefix.length)}`; diff --git a/test/useContract.ts b/test/useContract.ts index c01b3ef..b73481d 100644 --- a/test/useContract.ts +++ b/test/useContract.ts @@ -25,17 +25,43 @@ async function main() { const txReceipt1 = await txResponse1.wait(); console.info("Funds sent. Hash:", txReceipt1.transactionHash); - console.info("Sending 1 CELO wei with cUSD feeCurrency"); - const txResponse1feeCurrency = await signer.sendTransaction({ + console.info( + "[celo-legacy] Sending 1 CELO wei with cUSD feeCurrency", + signer.address + ); + const txResponseLegacy = await signer.sendTransaction({ + to: signer.address, + value: BigNumber.from("1"), + feeCurrency: CUSD_ADDRESS, + }); + const txReceiptLegacy = await txResponseLegacy.wait(); + console.info( + `[celo-legacy] CELO w/ feeCurrency payment hash: ${txReceiptLegacy.transactionHash}` + ); + + console.info("[cip64] Sending 1 CELO wei with cUSD feeCurrency"); + const txResponseCip64 = await signer.sendTransaction({ to: signer.address, value: BigNumber.from("1"), feeCurrency: CUSD_ADDRESS, maxFeePerGas: BigNumber.from(5000000000), maxPriorityFeePerGas: BigNumber.from(5000000000), }); - const txReceipt1FeeCurency = await txResponse1feeCurrency.wait(); + const txReceiptCip64 = await txResponseCip64.wait(); + console.info( + `[cip64] CELO w/ feeCurrency payment hash: ${txReceiptCip64.transactionHash}` + ); + + console.info("[eip1559] Sending 1 CELO wei"); + const txResponseEip1559 = await signer.sendTransaction({ + to: signer.address, + value: BigNumber.from("1"), + maxFeePerGas: BigNumber.from(5000000000), + maxPriorityFeePerGas: BigNumber.from(5000000000), + }); + const txReceiptEip1559 = await txResponseEip1559.wait(); console.info( - `CELO w/ feeCurrency payment hash: ${txReceipt1FeeCurency.transactionHash}` + `[eip1559] CELO payment hash: ${txReceiptEip1559.transactionHash}` ); const stableToken = new Contract(CUSD_ADDRESS, STABLE_TOKEN_ABI, signer); From c64f90406c8971bc8811a98de266bd18880f6cca Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Wed, 4 Oct 2023 08:14:21 +0200 Subject: [PATCH 7/7] refactor: some comments review adjustments --- src/consts.ts | 7 +++++++ src/lib/CeloProvider.ts | 3 +-- src/lib/CeloWallet.ts | 5 ++--- src/lib/transaction/utils.ts | 6 +++--- src/lib/transactions.ts | 13 +++++-------- 5 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 src/consts.ts diff --git a/src/consts.ts b/src/consts.ts new file mode 100644 index 0000000..7657716 --- /dev/null +++ b/src/consts.ts @@ -0,0 +1,7 @@ +export const Y_PARITY_EIP_2098 = 27; +export const EIP155_NUMBER = 35; +// NOTE: Black magic number, unsure where it comes from +export const EIGHT = 8; + +// NOTE: Logic stolen from https://github.com/celo-org/celo-monorepo/blob/e7ebc92cb0715dc56c9d7f613dca81e076541cf3/packages/sdk/connect/src/connection.ts#L382-L396 +export const GAS_INFLATION_FACTOR = 1.3; diff --git a/src/lib/CeloProvider.ts b/src/lib/CeloProvider.ts index 6dda604..cd9fbde 100644 --- a/src/lib/CeloProvider.ts +++ b/src/lib/CeloProvider.ts @@ -65,8 +65,7 @@ export class CeloProvider extends providers.JsonRpcProvider { ] as const; const tx = { - // @ts-expect-error - ...this.constructor.hexlifyTransaction( + ...providers.JsonRpcProvider.hexlifyTransaction( params.transaction, extraneous_keys.reduce((acc, [key]) => { acc[key] = true; diff --git a/src/lib/CeloWallet.ts b/src/lib/CeloWallet.ts index 5ebcf04..3b632db 100644 --- a/src/lib/CeloWallet.ts +++ b/src/lib/CeloWallet.ts @@ -122,11 +122,10 @@ export class CeloWallet extends Wallet { * https://github.com/ethers-io/ethers.js/blob/master/packages/abstract-signer/src.ts/index.ts */ async estimateGas( - transaction: utils.Deferrable + transaction: utils.Deferrable ): Promise { this._checkProvider("estimateGas"); - // @ts-expect-error - const tx: CeloTransaction = await utils.resolveProperties(transaction); + const tx = await utils.resolveProperties(transaction); return this.provider.estimateGas(tx).then(adjustForGasInflation); } diff --git a/src/lib/transaction/utils.ts b/src/lib/transaction/utils.ts index d0f8478..7b9d9b9 100644 --- a/src/lib/transaction/utils.ts +++ b/src/lib/transaction/utils.ts @@ -1,5 +1,6 @@ import { BigNumber, BigNumberish } from "ethers"; import { hexlify } from "ethers/lib/utils"; +import { GAS_INFLATION_FACTOR } from "../../consts"; function isEmpty(value: string | BigNumberish | undefined | null) { return ( @@ -11,6 +12,7 @@ function isEmpty(value: string | BigNumberish | undefined | null) { : hexlify(value) === "0x0") ); } + function isPresent(value: string | BigNumberish | undefined | null) { return !isEmpty(value); } @@ -27,6 +29,7 @@ export function isCIP64(tx: any) { !isPresent(tx.gatewayFeeRecipient) ); } + export function isCIP42(tx: any): boolean { return ( isEIP1559(tx) && @@ -55,9 +58,6 @@ export function omit( } export function adjustForGasInflation(gas: BigNumber): BigNumber { - // NOTE: Don't ask me - const GAS_INFLATION_FACTOR = 1.3; - // NOTE: prevent floating point math return gas.mul(Math.floor(GAS_INFLATION_FACTOR * 100)).div(100); } diff --git a/src/lib/transactions.ts b/src/lib/transactions.ts index 90706ad..b22b0b7 100644 --- a/src/lib/transactions.ts +++ b/src/lib/transactions.ts @@ -9,10 +9,7 @@ import { } from "ethers"; import { concatHex, isCIP64, isEIP1559, omit } from "./transaction/utils"; import { accessListify, AccessListish } from "ethers/lib/utils"; - -// NOTE: Black magic -const Y_PARITY_EIP_2098 = 27; -const BULLSHIT_NUMBER = 8; +import { EIGHT, EIP155_NUMBER, Y_PARITY_EIP_2098 } from "../consts"; // From https://github.com/ethers-io/ethers.js/blob/master/packages/bytes/src.ts/index.ts#L33 // Copied because it doesn't seem to be exported from 'ethers' anywhere @@ -290,7 +287,7 @@ export function serializeCeloTransaction( signature.v > 28 ) { // No chainId provided, but the signature is signing with EIP-155; derive chainId - chainId = Math.floor((signature.v - 35) / 2); + chainId = Math.floor((signature.v - EIP155_NUMBER) / 2); } // We have an EIP-155 transaction (chainId was specified and non-zero) @@ -323,7 +320,7 @@ export function serializeCeloTransaction( v = Y_PARITY_EIP_2098 + sig.recoveryParam; if (chainId !== 0) { - v += chainId * 2 + BULLSHIT_NUMBER; + v += chainId * 2 + EIGHT; // If an EIP-155 v (directly or indirectly; maybe _vs) was provided, check it! if (sig.v > Y_PARITY_EIP_2098 + 1 && sig.v !== v) { @@ -430,9 +427,9 @@ export function parseCeloTransaction( let recoveryParam = tx.v; if (!type) { // celo-legacy - tx.chainId = Math.max(0, Math.floor((tx.v - 35) / 2)); + tx.chainId = Math.max(0, Math.floor((tx.v - EIP155_NUMBER) / 2)); recoveryParam = tx.v - Y_PARITY_EIP_2098; - recoveryParam -= tx.chainId * 2 + BULLSHIT_NUMBER; + recoveryParam -= tx.chainId * 2 + EIGHT; } // NOTE: Serialization needs to happen here because chainId may not populated before