Skip to content

Commit

Permalink
chore: remove ethers
Browse files Browse the repository at this point in the history
  • Loading branch information
joepegler committed Aug 30, 2024
1 parent cdc316f commit c467d04
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 82 deletions.
61 changes: 35 additions & 26 deletions src/account/NexusSmartAccount.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ethers } from "ethers"
import {
type AbiParameter,
type Address,
type GetContractReturnType,
type Hash,
Expand All @@ -16,15 +16,16 @@ import {
getAddress,
getContract,
keccak256,
pad,
parseAbi,
parseAbiParameters,
toBytes
toBytes,
toHex
} from "viem"
import contracts from "../__contracts"
import { NexusAbi } from "../__contracts/abi"
import {
Bundler,
Executions,
type GetUserOperationGasPriceReturnType,
type UserOpReceipt,
type UserOpResponse
Expand Down Expand Up @@ -761,28 +762,32 @@ export class NexusSmartAccount extends BaseSmartContractAccount {
* @returns encoded data for executeBatch function
*/
async encodeExecuteBatch(transactions: Transaction[]): Promise<Hex> {
// return accountContract.interface.encodeFunctionData("execute_ncC", [to, value, data]) as Hex;
const mode = EXECUTE_BATCH
// TODO: Use viem instead of ethers
const execs: { target: Hex; value: bigint; callData: Hex }[] = []
for (const tx of transactions) {
execs.push({
target: tx.to as Hex,
callData: (tx.data ?? "0x") as Hex,
value: BigInt(tx.value ?? 0n)
})
const executionAbiParams: AbiParameter = {
type: "tuple[]",
components: [
{ name: "target", type: "address" },
{ name: "value", type: "uint256" },
{ name: "callData", type: "bytes" }
]
}
const executionCalldataPrep = ethers.AbiCoder.defaultAbiCoder().encode(
[Executions],
[execs]
) as Hex

const executions = transactions.map((tx) => ({
target: tx.to,
callData: tx.data ?? "0x",
value: BigInt(tx.value ?? 0n)
}))

const executionCalldataPrep = encodeAbiParameters(
[executionAbiParams],
[executions]
)

return encodeFunctionData({
abi: parseAbi([
"function execute(bytes32 mode, bytes calldata executionCalldata) external"
]),
functionName: "execute",
args: [mode, executionCalldataPrep]
args: [EXECUTE_BATCH, executionCalldataPrep]
})
}

Expand Down Expand Up @@ -1081,14 +1086,18 @@ export class NexusSmartAccount extends BaseSmartContractAccount {
maxFeePerGas: BigNumberish,
maxPriorityFeePerGas: BigNumberish
) {
const gasFees = ethers.solidityPacked(
["uint128", "uint128"],
[maxPriorityFeePerGas, maxFeePerGas]
) as Hex
const accountGasLimits = ethers.solidityPacked(
["uint128", "uint128"],
[callGasLimit, verificationGasLimit]
) as Hex
const gasFees = concat([
pad(toHex(maxPriorityFeePerGas ?? 0n), {
size: 16
}),
pad(toHex(maxFeePerGas ?? 0n), { size: 16 })
])
const accountGasLimits = concat([
pad(toHex(verificationGasLimit ?? 0n), {
size: 16
}),
pad(toHex(callGasLimit ?? 0n), { size: 16 })
])

return { gasFees, accountGasLimits }
}
Expand Down
23 changes: 13 additions & 10 deletions src/bundler/utils/Constants.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { concat, pad } from "viem"
import {
CALLTYPE_BATCH,
CALLTYPE_SINGLE,
EXECTYPE_DEFAULT,
EXECTYPE_DELEGATE,
EXECTYPE_TRY,
MODE_DEFAULT,
MODE_PAYLOAD,
UNUSED
} from "./Types"

// define mode and exec type enums
export const CALLTYPE_SINGLE = "0x00" // 1 byte
export const CALLTYPE_BATCH = "0x01" // 1 byte
export const EXECTYPE_DEFAULT = "0x00" // 1 byte
export const EXECTYPE_TRY = "0x01" // 1 byte
export const EXECTYPE_DELEGATE = "0xFF" // 1 byte
export const MODE_DEFAULT = "0x00000000" // 4 bytes
export const UNUSED = "0x00000000" // 4 bytes
export const MODE_PAYLOAD = "0x00000000000000000000000000000000000000000000" // 22 bytes
export const ERC1271_MAGICVALUE = "0x1626ba7e"
export const ERC1271_INVALID = "0xffffffff"
export const GENERIC_FALLBACK_SELECTOR = "0xcb5baf0f"

export const UserOpReceiptIntervals: { [key in number]?: number } = {
[1]: 10000
Expand Down
27 changes: 0 additions & 27 deletions src/bundler/utils/Types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ParamType } from "ethers"
import type { Address, Chain, Hash, Hex, Log } from "viem"
import type { UserOperationStruct } from "../../account"

Expand Down Expand Up @@ -150,29 +149,3 @@ export type BundlerEstimateUserOpGasResponse = {
paymasterVerificationGasLimit?: Hex | null
paymasterPostOpGasLimit?: Hex | null
}

// define mode and exec type enums
export const CALLTYPE_SINGLE = "0x00" // 1 byte
export const CALLTYPE_BATCH = "0x01" // 1 byte
export const EXECTYPE_DEFAULT = "0x00" // 1 byte
export const EXECTYPE_TRY = "0x01" // 1 byte
export const EXECTYPE_DELEGATE = "0xFF" // 1 byte
export const MODE_DEFAULT = "0x00000000" // 4 bytes
export const UNUSED = "0x00000000" // 4 bytes
export const MODE_PAYLOAD = "0x00000000000000000000000000000000000000000000" // 22 bytes
export const ERC1271_MAGICVALUE = "0x1626ba7e"
export const ERC1271_INVALID = "0xffffffff"

export const GENERIC_FALLBACK_SELECTOR = "0xcb5baf0f"

export const Executions = ParamType.from({
type: "tuple(address,uint256,bytes)[]",
baseType: "tuple",
name: "executions",
arrayLength: null,
components: [
{ name: "target", type: "address" },
{ name: "value", type: "uint256" },
{ name: "callData", type: "bytes" }
]
})
76 changes: 57 additions & 19 deletions tests/account.read.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { JsonRpcProvider, Wallet } from "ethers"
import { JsonRpcProvider, ParamType, Wallet, ethers } from "ethers"
import {
http,
type AbiParameter,
type Account,
type Chain,
type Hex,
Expand Down Expand Up @@ -47,7 +48,11 @@ import {
toTestClient,
topUp
} from "./src/testUtils"
import type { MasterClient, NetworkConfig } from "./src/testUtils"
import type {
MasterClient,
NetworkConfig,
NetworkConfigWithBundler
} from "./src/testUtils"

const NETWORK_TYPE: TestFileNetworkType = "COMMON_LOCALHOST"

Expand Down Expand Up @@ -112,23 +117,6 @@ describe("account.read", () => {
])
})

test("should send eth", async () => {
const balanceBefore = await testClient.getBalance({
address: recipientAccount.address
})
const tx: Transaction = {
to: recipientAccount.address,
value: 1n
}
const { wait } = await smartAccount.sendTransaction(tx)
const { success } = await wait()
const balanceAfter = await testClient.getBalance({
address: recipientAccount.address
})
expect(success).toBe(true)
expect(balanceAfter - balanceBefore).toBe(1n)
})

test.skip("should estimate gas for minting an NFT", async () => {
const encodedCall = encodeFunctionData({
abi: CounterAbi,
Expand Down Expand Up @@ -734,6 +722,56 @@ describe("account.read", () => {
}
})

test("should have consistent behaviour between ethers.AbiCoder.defaultAbiCoder() and viem.encodeAbiParameters()", async () => {
const expectedResult =
"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000090f79bf6eb2c4f870365e785982e1f101e93b90600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090f79bf6eb2c4f870365e785982e1f101e93b906000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"

const Executions = ParamType.from({
type: "tuple(address,uint256,bytes)[]",
baseType: "tuple",
name: "executions",
arrayLength: null,
components: [
{ name: "target", type: "address" },
{ name: "value", type: "uint256" },
{ name: "callData", type: "bytes" }
]
})

const viemExecutions: AbiParameter = {
type: "tuple[]",
components: [
{ name: "target", type: "address" },
{ name: "value", type: "uint256" },
{ name: "callData", type: "bytes" }
]
}

const txs = [
{
target: "0x90F79bf6EB2c4f870365E785982E1f101E93b906",
callData: "0x",
value: 1n
},
{
target: "0x90F79bf6EB2c4f870365E785982E1f101E93b906",
callData: "0x",
value: 1n
}
]

const executionCalldataPrepWithEthers =
ethers.AbiCoder.defaultAbiCoder().encode([Executions], [txs])

const executionCalldataPrepWithViem = encodeAbiParameters(
[viemExecutions],
[txs]
)

expect(executionCalldataPrepWithEthers).toBe(expectedResult)
expect(executionCalldataPrepWithViem).toBe(expectedResult)
})

// test.skip("should call isValidSignature for deployed smart account", async () => {
// const smartAccount = await createSmartAccountClient({
// signer: walletClient,
Expand Down
17 changes: 17 additions & 0 deletions tests/account.write.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,23 @@ describe("account.write", () => {
expect(balanceAfter - balanceBefore).toBe(1n)
})

test("should send eth twice", async () => {
const balanceBefore = await testClient.getBalance({
address: recipientAccount.address
})
const tx: Transaction = {
to: recipientAccount.address,
value: 1n
}
const { wait } = await smartAccount.sendTransaction([tx, tx])
const { success } = await wait()
const balanceAfter = await testClient.getBalance({
address: recipientAccount.address
})
expect(success).toBe(true)
expect(balanceAfter - balanceBefore).toBe(2n)
})

// test("install a mock Hook module", async () => {
// const isSupported = await smartAccount.supportsModule(ModuleType.Hook)
// console.log(isSupported, "is supported")
Expand Down

0 comments on commit c467d04

Please sign in to comment.