Skip to content

Commit

Permalink
feat(smart): allow overriding nonce for smart accounts (#3782)
Browse files Browse the repository at this point in the history
<!-- start pr-codex -->

## PR-Codex overview
The focus of this PR is to allow overriding the nonce for smart accounts in the `thirdweb` package.

### Detailed summary
- Added the ability to override nonce for smart accounts
- Exported `generateRandomUint192` function
- Updated imports and added new functions in `userop.ts` file
- Modified `createUnsignedUserOp` function to use custom nonce logic

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->
  • Loading branch information
joaquim-verges committed Jul 24, 2024
1 parent e7581fc commit c82c524
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/nervous-fans-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---

Allow overriding nonce for smart accounts
46 changes: 42 additions & 4 deletions packages/thirdweb/src/wallets/smart/lib/userop.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { concat } from "viem";
import type { Chain } from "../../../chains/types.js";
import type { ThirdwebContract } from "../../../contract/contract.js";
import type { ThirdwebClient } from "../../../client/client.js";
import {
type ThirdwebContract,
getContract,
} from "../../../contract/contract.js";
import { getNonce } from "../../../extensions/erc4337/__generated__/IEntryPoint/read/getNonce.js";
import { getDefaultGasOverrides } from "../../../gas/fee-data.js";
import { encode } from "../../../transaction/actions/encode.js";
import type { PreparedTransaction } from "../../../transaction/prepare-transaction.js";
Expand Down Expand Up @@ -30,7 +35,7 @@ import {
getDefaultBundlerUrl,
} from "./constants.js";
import { getPaymasterAndData } from "./paymaster.js";
import { randomNonce } from "./utils.js";
import { generateRandomUint192 } from "./utils.js";

/**
* Wait for the user operation to be mined.
Expand Down Expand Up @@ -156,8 +161,13 @@ export async function createUnsignedUserOp(args: {
}
}

// const nonce = BigInt(transaction.nonce || randomNonce());
const nonce = randomNonce(); // FIXME getNonce should be overrideable by the wallet
const nonce = await getAccountNonce({
accountContract,
chain,
client,
entrypointAddress: overrides?.entrypointAddress,
getNonceOverride: overrides?.getAccountNonce,
});

const partialOp: UserOperation = {
sender: accountContract.address,
Expand Down Expand Up @@ -299,6 +309,34 @@ async function getAccountInitCode(options: {
return concat([factoryContract.address as Hex, await encode(deployTx)]);
}

async function getAccountNonce(options: {
accountContract: ThirdwebContract;
chain: Chain;
client: ThirdwebClient;
entrypointAddress?: string;
getNonceOverride?: (accountContract: ThirdwebContract) => Promise<bigint>;
}) {
const {
accountContract,
chain,
client,
entrypointAddress,
getNonceOverride,
} = options;
if (getNonceOverride) {
return getNonceOverride(accountContract);
}

Check warning on line 328 in packages/thirdweb/src/wallets/smart/lib/userop.ts

View check run for this annotation

Codecov / codecov/patch

packages/thirdweb/src/wallets/smart/lib/userop.ts#L327-L328

Added lines #L327 - L328 were not covered by tests
return getNonce({
contract: getContract({
address: entrypointAddress || ENTRYPOINT_ADDRESS_v0_6,
chain,
client,
}),
key: generateRandomUint192(),
sender: accountContract.address,
});
}

/**
* Get the hash of a user operation.
* @param args - The user operation, entrypoint address, and chain ID
Expand Down
2 changes: 1 addition & 1 deletion packages/thirdweb/src/wallets/smart/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Chain } from "../../../chains/types.js";
import { isHex, numberToHex, toHex } from "../../../utils/encoding/hex.js";
import type { UserOperation, UserOperationHexed } from "../types.js";

const generateRandomUint192 = (): bigint => {
export const generateRandomUint192 = (): bigint => {
const rand1 = BigInt(Math.floor(Math.random() * 0x100000000));
const rand2 = BigInt(Math.floor(Math.random() * 0x100000000));
const rand3 = BigInt(Math.floor(Math.random() * 0x100000000));
Expand Down
1 change: 1 addition & 0 deletions packages/thirdweb/src/wallets/smart/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export type SmartWalletOptions = Prettify<
accountContract: ThirdwebContract,
transactions: SendTransactionOption[],
) => PreparedTransaction;
getAccountNonce?: (accountContract: ThirdwebContract) => Promise<bigint>;
};
} & (
| {
Expand Down

0 comments on commit c82c524

Please sign in to comment.