---
title: executePrepared
description: Re-check market state, simulate as the wallet, send the prepared call, and wait for a typed receipt.
---

> **For AI agents:** the complete documentation index is at [llms.txt](/llms.txt). Append `.md` to any page URL for its markdown version.

Sends a frozen `PreparedAction`. This is the write path for trades and other SDK actions.

Internally this is the viem pattern: `simulateContract` as the **wallet** account, then `sendTransaction`. It does not rewrite calldata. If the market moved, you get `StaleStateError` instead of a silent re-quote.

Floor actions (`raiseIfEligible`, `raiseManyIfEligible`) skip that market-stale check because `prepared.to` is the controller or Multicall3, not the FloorMarket. Use [raiseIfEligible](/developers/raise-if-eligible) or `sv3.transactions.sendPrepared` for those.

## Import

```ts
import { createSv3Client } from "@repo/contract-client";
```

## Usage

```ts
const prepared = await sv3.trade.prepareBuyForReserveBudget({
  market,
  amount: parseUsdc("1"),
  slippageBps: 100n,
});

const pending = await sv3.transactions.executePrepared(prepared);
const confirmed = await pending.wait();
confirmed.hash;
confirmed.events;
```

Flow:

1. Confirm `walletClient` and that `account` matches `prepared.account`.
2. Re-read `stateNonce` and `marketStateHash`. On mismatch throw `StaleStateError`.
3. `simulateContract` with the wallet account.
4. `sendTransaction`.
5. `wait` confirms and decodes protocol events.

`acceptStale: true` skips the nonce check but still re-simulates and never rewrites calldata.

## Return Value

`Promise<PendingProtocolTransaction>`

| Field        | Meaning                             |
| ------------ | ----------------------------------- |
| `hash`       | Transaction hash                    |
| `request`    | The simulated request that was sent |
| `simulation` | `simulateContract` result           |
| `wait()`     | See [wait](/developers/wait)        |

`wait()` returns `{ hash, receipt, events }`.

## Parameters

### prepared

- **Type:** `PreparedAction`

From `sv3.trade.prepare*`. Frozen: `to`, `data`, `functionName`, `args`, `deadline`, `constraints`.

```ts
await sv3.transactions.executePrepared(prepared);
```

### options.confirmations (optional)

- **Type:** `number`

Passed through to `wait`.

```ts
await sv3.transactions.executePrepared(prepared, { confirmations: 2 });
```

### options.acceptStale (optional)

- **Type:** `boolean`
- **Default:** `false`

```ts
await sv3.transactions.executePrepared(prepared, { acceptStale: true });
```

### options.permit (optional)

- **Type:** `PermitData`

Pass a collected EIP-2612 signature. [getRequirements](/developers/get-requirements) never sends `approve` itself.

```ts
await sv3.transactions.executePrepared(prepared, { permit });
```

## Error

| Error                       | When                                                          |
| --------------------------- | ------------------------------------------------------------- |
| `WalletClientRequiredError` | No wallet                                                     |
| `AccountMismatchError`      | Prepared account ≠ wallet                                     |
| `StaleStateError`           | Nonce or state hash moved                                     |
| `SimulationFailedError`     | `simulateContract` reverted; `cause` is `ProtocolRevertError` |
| `TransactionRejectedError`  | Wallet rejected the send                                      |
| `TransactionRevertedError`  | Mined revert; `cause` is decoded when possible                |

See [Errors](/developers/errors).

## Tips

- Always simulate as the connected account. Simulating as the zero address misses allowance and pause checks the wallet will hit.
- If you already have a hash (for example a wallet that sent outside the SDK), confirm with `sv3.transactions.wait(hash)` instead.
