Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update ethers v5 utilities to ethers v6 #455

Draft
wants to merge 13 commits into
base: v4-ethers-v6
Choose a base branch
from
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
"@ethersproject/bignumber": "^5.1.1",
"@ethersproject/bytes": "^5.0.8",
"async-mutex": "^0.4.0",
"ethers": "^5.1.0"
"ethers": "^5.1.0",
"ethers-v6": "npm:ethers@^6.11.1"
},
"devDependencies": {
"@arbitrum/nitro-contracts": "^1.1.1",
Expand Down
3 changes: 2 additions & 1 deletion scripts/deployStandard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { constants, BigNumber, utils } from 'ethers'
import { MultiCaller } from '../src'
import axios from 'axios'
import prompt from 'prompts'
import { ZeroAddress } from 'ethers-v6'
dotenv.config()

const privKey = process.env.PRIVKEY as string
Expand Down Expand Up @@ -106,7 +107,7 @@ const main = async () => {
l1TokenAddress,
l1Provider
)
if (l2TokenAddress === constants.AddressZero) {
if (l2TokenAddress === ZeroAddress) {
throw new Error(`${l1TokenAddress} can't be bridged`)
}

Expand Down
5 changes: 2 additions & 3 deletions src/lib/assetBridger/assetBridger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
/* eslint-env node */
'use strict'

import { constants } from 'ethers'

import { ZeroAddress } from 'ethers-v6'
import { ParentContractTransaction } from '../message/ParentTransaction'
import { ChildContractTransaction } from '../message/ChildTransaction'

Expand Down Expand Up @@ -66,7 +65,7 @@ export abstract class AssetBridger<DepositParams, WithdrawParams> {
* @returns {boolean}
*/
protected get nativeTokenIsEth() {
return !this.nativeToken || this.nativeToken === constants.AddressZero
return !this.nativeToken || this.nativeToken === ZeroAddress
}

/**
Expand Down
13 changes: 7 additions & 6 deletions src/lib/inbox/inbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

import { Signer } from '@ethersproject/abstract-signer'
import { Block, Provider } from '@ethersproject/abstract-provider'
import { BigNumber, ContractTransaction, ethers, Overrides } from 'ethers'
import { BigNumber, ContractTransaction, Overrides } from 'ethers'
import { ZeroAddress, hexlify, solidityPacked, toBeArray } from 'ethers-v6'
import { TransactionRequest } from '@ethersproject/providers'

import { Bridge } from '../abi/Bridge'
Expand Down Expand Up @@ -107,7 +108,7 @@ export class InboxTools {
if (
childChainTransactionRequest.to === '0x' ||
!isDefined(childChainTransactionRequest.to) ||
childChainTransactionRequest.to === ethers.constants.AddressZero
childChainTransactionRequest.to === ZeroAddress
) {
return true
}
Expand All @@ -132,7 +133,7 @@ export class InboxTools {
childChainTransactionRequest
)
const gasComponents = await nodeInterface.callStatic.gasEstimateComponents(
childChainTransactionRequest.to || ethers.constants.AddressZero,
childChainTransactionRequest.to || ZeroAddress,
contractCreation,
childChainTransactionRequest.data,
{
Expand Down Expand Up @@ -358,9 +359,9 @@ export class InboxTools {
this.parentChainSigner
)

const sendData = ethers.utils.solidityPack(
const sendData = solidityPacked(
['uint8', 'bytes'],
[ethers.utils.hexlify(InboxMessageKind.L2MessageType_signedTx), signedTx]
[hexlify(toBeArray(InboxMessageKind.L2MessageType_signedTx)), signedTx]
)

return await delayedInbox.functions.sendL2Message(sendData)
Expand Down Expand Up @@ -410,7 +411,7 @@ export class InboxTools {
// however, it is needed when we call to estimateArbitrumGas, so
// we add a zero address here.
if (!isDefined(tx.to)) {
tx.to = ethers.constants.AddressZero
tx.to = ZeroAddress
}

//estimate gas on child chain
Expand Down
46 changes: 21 additions & 25 deletions src/lib/message/ParentToChildMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import { Provider } from '@ethersproject/abstract-provider'
import { Signer } from '@ethersproject/abstract-signer'
import { ContractTransaction } from '@ethersproject/contracts'
import { BigNumber } from '@ethersproject/bignumber'
import { concat, zeroPad } from '@ethersproject/bytes'
import { concat } from '@ethersproject/bytes'
import { getAddress } from '@ethersproject/address'
import { keccak256 } from '@ethersproject/keccak256'
import { ZeroAddress, toBeArray, encodeRlp, zeroPadValue } from 'ethers-v6'

import { ArbRetryableTx__factory } from '../abi/factories/ArbRetryableTx__factory'
import {
Expand All @@ -36,7 +37,7 @@ import {
SignerOrProvider,
} from '../dataEntities/signerOrProvider'
import { ArbSdkError } from '../dataEntities/errors'
import { ethers, Overrides } from 'ethers'
import { Overrides } from 'ethers'
import { ChildTransactionReceipt, RedeemTransaction } from './ChildTransaction'
import { getArbitrumNetwork } from '../../lib/dataEntities/networks'
import { RetryableMessageParams } from '../dataEntities/message'
Expand Down Expand Up @@ -140,23 +141,23 @@ export abstract class ParentToChildMessage {
data: string
): string {
const formatNumber = (value: BigNumber): Uint8Array => {
return ethers.utils.stripZeros(value.toHexString())
return toBeArray(value.toHexString())
}

const chainId = BigNumber.from(chainChainId)
const msgNum = BigNumber.from(messageNumber)

const fields: any[] = [
formatNumber(chainId),
zeroPad(formatNumber(msgNum), 32),
zeroPadValue(formatNumber(msgNum), 32),
fromAddress,
formatNumber(parentChainBaseFee),

formatNumber(parentChainValue),
formatNumber(maxFeePerGas),
formatNumber(gasLimit),
// when destAddress is 0x0, arbos treat that as nil
destAddress === ethers.constants.AddressZero ? '0x' : destAddress,
destAddress === ZeroAddress ? '0x' : destAddress,
formatNumber(chainCallValue),
callValueRefundAddress,
formatNumber(maxSubmissionFee),
Expand All @@ -165,12 +166,10 @@ export abstract class ParentToChildMessage {
]

// arbitrum submit retry transactions have type 0x69
const rlpEnc = ethers.utils.hexConcat([
'0x69',
ethers.utils.RLP.encode(fields),
])
const rlpEnc = concat(['0x69', encodeRlp(fields)])

return ethers.utils.keccak256(rlpEnc)
const hash = keccak256(rlpEnc)
return hash
}

public static fromEventComponents<T extends SignerOrProvider>(
Expand Down Expand Up @@ -571,32 +570,32 @@ export class ParentToChildMessageReaderClassic {

this.retryableCreationId = keccak256(
concat([
zeroPad(BigNumber.from(chainId).toHexString(), 32),
zeroPad(bitFlip(this.messageNumber).toHexString(), 32),
zeroPadValue(BigNumber.from(chainId).toHexString(), 32),
zeroPadValue(bitFlip(this.messageNumber).toHexString(), 32),
])
)

this.autoRedeemId = keccak256(
concat([
zeroPad(this.retryableCreationId, 32),
zeroPad(BigNumber.from(1).toHexString(), 32),
zeroPadValue(this.retryableCreationId, 32),
zeroPadValue(BigNumber.from(1).toHexString(), 32),
])
)

this.chainTxHash = keccak256(
concat([
zeroPad(this.retryableCreationId, 32),
zeroPad(BigNumber.from(0).toHexString(), 32),
zeroPadValue(this.retryableCreationId, 32),
zeroPadValue(BigNumber.from(0).toHexString(), 32),
])
)
}

private calculateChainDerivedHash(retryableCreationId: string): string {
return keccak256(
concat([
zeroPad(retryableCreationId, 32),
zeroPadValue(retryableCreationId, 32),
// BN 0 meaning Chain TX
zeroPad(BigNumber.from(0).toHexString(), 32),
zeroPadValue(BigNumber.from(0).toHexString(), 32),
])
)
}
Expand Down Expand Up @@ -769,7 +768,7 @@ export class EthDepositMessage {
value: BigNumber
): string {
const formatNumber = (numberVal: BigNumber): Uint8Array => {
return ethers.utils.stripZeros(numberVal.toHexString())
return toBeArray(numberVal.toHexString())
}

const chainId = BigNumber.from(chainChainId)
Expand All @@ -778,19 +777,16 @@ export class EthDepositMessage {
// https://github.com/OffchainLabs/go-ethereum/blob/07e017aa73e32be92aadb52fa327c552e1b7b118/core/types/arb_types.go#L302-L308
const fields = [
formatNumber(chainId),
zeroPad(formatNumber(msgNum), 32),
zeroPadValue(formatNumber(msgNum), 32),
getAddress(fromAddress),
getAddress(toAddress),
formatNumber(value),
]

// arbitrum eth deposit transactions have type 0x64
const rlpEnc = ethers.utils.hexConcat([
'0x64',
ethers.utils.RLP.encode(fields),
])
const rlpEnc = concat(['0x64', encodeRlp(fields)])

return ethers.utils.keccak256(rlpEnc)
return keccak256(rlpEnc)
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/lib/utils/eventFetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import { Provider, BlockTag, Filter } from '@ethersproject/abstract-provider'
import { Contract, Event } from '@ethersproject/contracts'
import { constants } from 'ethers'
import { ZeroAddress } from 'ethers-v6'
import { TypedEvent, TypedEventFilter } from '../abi/common'
import { EventArgs, TypeChainContractFactory } from '../dataEntities/event'

Expand Down Expand Up @@ -67,7 +67,7 @@ export class EventFetcher {
}
): Promise<FetchedEvent<TEventOf<TEventFilter>>[]> {
const contract = contractFactory.connect(
filter.address || constants.AddressZero,
filter.address || ZeroAddress,
this.provider
)
const eventFilter = topicGenerator(contract)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
'use strict'

import { expect } from 'chai'
import { ethers, constants, Wallet } from 'ethers'
import { constants, Wallet } from 'ethers'
import dotenv from 'dotenv'

import { parseEther } from '@ethersproject/units'
import { parseEther } from 'ethers-v6'

import {
fundParentSigner as fundParentSignerEther,
Expand Down Expand Up @@ -52,7 +52,7 @@ describeOnlyWhenCustomGasToken(
it('approves the custom fee token to be spent by the Inbox on the parent chain (arbitrary amount, using params)', async function () {
const { ethBridger, nativeTokenContract, parentSigner } =
await testSetup()
const amount = ethers.utils.parseEther('1')
const amount = parseEther('1')

await fundParentSignerEther(parentSigner)
await fundParentCustomFeeToken(parentSigner)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { StaticJsonRpcProvider } from '@ethersproject/providers'
import { Signer, Wallet, ethers, utils } from 'ethers'
import { Signer, Wallet, utils } from 'ethers'
import { ZeroAddress } from 'ethers-v6'

import {
testSetup as _testSetup,
Expand All @@ -16,7 +17,7 @@ const localNetworks = () => getLocalNetworksFromFile()

export function isArbitrumNetworkWithCustomFeeToken(): boolean {
const nt = localNetworks().l2Network.nativeToken
return typeof nt !== 'undefined' && nt !== ethers.constants.AddressZero
return typeof nt !== 'undefined' && nt !== ZeroAddress
}

export async function testSetup() {
Expand Down
13 changes: 7 additions & 6 deletions tests/integration/customerc20.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
'use strict'

import { expect } from 'chai'
import { Signer, Wallet, constants, utils, ethers } from 'ethers'
import { Signer, Wallet, utils } from 'ethers'
import { ZeroAddress, parseEther } from 'ethers-v6'
import { BigNumber } from '@ethersproject/bignumber'
import { Logger, LogLevel } from '@ethersproject/logger'
Logger.setLogLevel(LogLevel.ERROR)
Expand Down Expand Up @@ -163,7 +164,7 @@ const registerCustomToken = async (
childChain.tokenBridge.l1GatewayRouter
)
await l1CustomToken.deployed()
const amount = ethers.utils.parseEther('1')
const amount = parseEther('1')

if (isArbitrumNetworkWithCustomFeeToken()) {
const approvalTx = await ERC20__factory.connect(
Expand Down Expand Up @@ -199,28 +200,28 @@ const registerCustomToken = async (
expect(
startL1GatewayAddress,
'Start l1GatewayAddress not equal empty address'
).to.eq(constants.AddressZero)
).to.eq(ZeroAddress)
const startL2GatewayAddress = await l2GatewayRouter.l1TokenToGateway(
l2CustomToken.address
)
expect(
startL2GatewayAddress,
'Start l2GatewayAddress not equal empty address'
).to.eq(constants.AddressZero)
).to.eq(ZeroAddress)
const startL1Erc20Address = await l1CustomGateway.l1ToL2Token(
l1CustomToken.address
)
expect(
startL1Erc20Address,
'Start l1Erc20Address not equal empty address'
).to.eq(constants.AddressZero)
).to.eq(ZeroAddress)
const startL2Erc20Address = await l2CustomGateway.l1ToL2Token(
l1CustomToken.address
)
expect(
startL2Erc20Address,
'Start l2Erc20Address not equal empty address'
).to.eq(constants.AddressZero)
).to.eq(ZeroAddress)

// send the messages
const regTx = await adminErc20Bridger.registerCustomToken(
Expand Down
12 changes: 5 additions & 7 deletions tests/integration/sendChildmsg.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
;('use strict')

import { BigNumber, ethers, Signer } from 'ethers'
import { Transaction } from 'ethers-v6'
import { InboxTools } from '../../src/lib/inbox/inbox'
import {
getArbitrumNetwork,
Expand Down Expand Up @@ -75,7 +76,7 @@ describe('Send signedTx to child chain using inbox', async () => {
)
const parentStatus = parentTransactionReceipt?.status
expect(parentStatus).to.equal(1, 'parent txn failed')
const childTx = ethers.utils.parseTransaction(signedMsg)
const childTx = Transaction.from(signedMsg)
const childTxhash = childTx.hash!
const childTxReceipt = await childDeployer.provider!.waitForTransaction(
childTxhash
Expand All @@ -101,7 +102,7 @@ describe('Send signedTx to child chain using inbox', async () => {
await sendSignedTx(testState, info)
const parentStatus = parentTransactionReceipt?.status
expect(parentStatus).to.equal(1)
const childTxhash = ethers.utils.parseTransaction(signedMsg).hash!
const childTxhash = Transaction.from(signedMsg).hash!
const childTxReceipt = await childDeployer.provider!.waitForTransaction(
childTxhash
)
Expand Down Expand Up @@ -131,11 +132,8 @@ describe('Send signedTx to child chain using inbox', async () => {
const enoughFeeTx = await sendSignedTx(testState, info)
const enoughFeeParentStatus = enoughFeeTx.parentTransactionReceipt?.status
expect(enoughFeeParentStatus).to.equal(1)
const childLowFeeTxhash = ethers.utils.parseTransaction(lowFeeTx.signedMsg)
.hash!
const childEnoughFeeTxhash = ethers.utils.parseTransaction(
enoughFeeTx.signedMsg
).hash!
const childLowFeeTxhash = Transaction.from(lowFeeTx.signedMsg).hash!
const childEnoughFeeTxhash = Transaction.from(enoughFeeTx.signedMsg).hash!

const childTEnoughFeeReceipt =
await childDeployer.provider!.waitForTransaction(childEnoughFeeTxhash)
Expand Down
Loading
Loading