Skip to content

Commit

Permalink
[SDK] Fix: Use transaction-specified chain in smart account (#5865)
Browse files Browse the repository at this point in the history
<!-- start pr-codex -->

## PR-Codex overview
This PR focuses on fixing chain switching in smart account transactions within the `thirdweb` SDK and adding tests for sending transactions across different chains.

### Detailed summary
- Updated the logic for `accountContract` in `packages/thirdweb/src/wallets/smart/index.ts` to handle chain switching.
- Added a new test in `packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts` to verify sending transactions on another chain.
- Introduced similar test functionality in `packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts`.

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

<!-- end pr-codex -->
  • Loading branch information
gregfromstl committed Jan 2, 2025
1 parent 6c5594b commit a9547c5
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/fair-planes-doubt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---

SDK: Fix chain switching in smart account transactions
17 changes: 16 additions & 1 deletion packages/thirdweb/src/wallets/smart/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,15 +240,30 @@ async function createSmartAccount(
} else {
paymasterOverride = options.overrides?.paymaster;
}

const accountContractForTransaction = (() => {
// If this transaction is for a different chain than the initial one, get the account contract for that chain
if (transaction.chainId !== accountContract.chain.id) {
return getContract({
address: account.address,
chain: getCachedChain(transaction.chainId),
client: options.client,
});
}
// Default to the existing account contract
return accountContract;
})();

const executeTx = prepareExecute({
accountContract,
accountContract: accountContractForTransaction,
transaction,
executeOverride: options.overrides?.execute,
});
return _sendUserOp({
executeTx,
options: {
...options,
chain: getCachedChain(transaction.chainId),
overrides: {
...options.overrides,
paymaster: paymasterOverride,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { verifySignature } from "../../auth/verify-signature.js";
import { type ThirdwebContract, getContract } from "../../contract/contract.js";
import { parseEventLogs } from "../../event/actions/parse-logs.js";

import { TEST_WALLET_A } from "~test/addresses.js";
import { verifyTypedData } from "../../auth/verify-typed-data.js";
import { baseSepolia } from "../../chains/chain-definitions/base-sepolia.js";
import { sepolia } from "../../chains/chain-definitions/sepolia.js";
import {
addAdmin,
Expand All @@ -18,6 +20,7 @@ import { estimateGasCost } from "../../transaction/actions/estimate-gas-cost.js"
import { sendAndConfirmTransaction } from "../../transaction/actions/send-and-confirm-transaction.js";
import { sendBatchTransaction } from "../../transaction/actions/send-batch-transaction.js";
import { waitForReceipt } from "../../transaction/actions/wait-for-tx-receipt.js";
import { prepareTransaction } from "../../transaction/prepare-transaction.js";
import { getAddress } from "../../utils/address.js";
import { isContractDeployed } from "../../utils/bytecode/is-contract-deployed.js";
import { sleep } from "../../utils/sleep.js";
Expand Down Expand Up @@ -107,6 +110,20 @@ describe.runIf(process.env.TW_SECRET_KEY)(
expect(isValid).toEqual(true);
});

it("can send a transaction on another chain", async () => {
const tx = await sendAndConfirmTransaction({
transaction: prepareTransaction({
to: TEST_WALLET_A,
client: TEST_CLIENT,
chain: baseSepolia,
value: 0n,
}),
// biome-ignore lint/style/noNonNullAssertion: Just trust me
account: wallet.getAccount()!,
});
expect(tx.transactionHash).toHaveLength(66);
});

it("should revert on unsuccessful transactions", async () => {
const tx = sendAndConfirmTransaction({
transaction: setContractURI({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { beforeAll, describe, expect, it } from "vitest";
import { TEST_WALLET_A } from "~test/addresses.js";
import { TEST_CLIENT } from "../../../test/src/test-clients.js";
import { typedData } from "../../../test/src/typed-data.js";
import { verifySignature } from "../../auth/verify-signature.js";
Expand Down Expand Up @@ -309,6 +310,20 @@ describe.runIf(process.env.TW_SECRET_KEY).sequential(
expect(wallet.getChain()?.id).toEqual(baseSepolia.id);
});

it("can send a transaction on another chain", async () => {
const tx = await sendAndConfirmTransaction({
transaction: prepareTransaction({
to: TEST_WALLET_A,
client: TEST_CLIENT,
chain: baseSepolia,
value: 0n,
}),
// biome-ignore lint/style/noNonNullAssertion: Just trust me
account: wallet.getAccount()!,
});
expect(tx.transactionHash).toHaveLength(66);
});

it("can execute 2 tx in parallel", async () => {
const newSmartWallet = smartWallet({
chain,
Expand Down

0 comments on commit a9547c5

Please sign in to comment.