---
title: raiseIfEligible
description: Prepare, simulate, and send the permissionless floor-raise call. The controller recomputes the plan on-chain.
---

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

Submits `FloorPolicyController.raiseIfEligible(market, witness)`. Any address may call it. The [product keeper](/protocol/keeper) is one client of this path, not a privileged role.

The witness grants no authority. The controller recomputes eligibility and the maximum-safe plan. Mismatch, expiry, or `newFloor < minNewFloorPriceWad` revert. The floor cannot decrease.

## Import

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

## Usage

```ts
const quote = await sv3.floor.quoteNextRaise(market);
if (!quote.eligibility.eligible) return;

const prepared = await sv3.floor.prepareRaiseIfEligible({
  market,
  witness: {
    policyVersion: quote.witness.policyVersion,
    expectedMarketStateNonce: quote.witness.expectedMarketStateNonce,
    expectedEngineStateHash: quote.witness.expectedEngineStateHash,
    expectedPlanHash: quote.witness.expectedPlanHash,
    deadline: quote.witness.deadline,
    minNewFloorPriceWad: quote.witness.minNewFloorPriceWad,
  },
});

const simulated = await sv3.floor.trySimulateRaiseIfEligible(prepared);
if (simulated.ok === false) {
  // FloorRaiseNotEligible is a race loss, not an incident
  return;
}

const pending = await sv3.floor.raiseIfEligible(
  { market, witness: quote.witness },
  {
    nonce,
    gas: simulated.gas,
    maxFeePerGas,
    maxPriorityFeePerGas,
  },
);
const confirmed = await sv3.floor.waitForFloorRaise(pending.hash);
```

Omit `witness` to re-quote inside `prepareRaiseIfEligible`. Keepers pass the discovered witness so they can detect a moved nonce before signing.

`sv3.transactions.executePrepared(prepared)` also works. Floor kinds skip the market-stale check on `prepared.to` because `to` is the controller, not the market.

## Many markets

Pack simulated raises. One call still goes to the controller. Several go through Multicall3 `aggregate3` with `allowFailure`, so one ineligible market does not revert the rest.

```ts
const pending = await sv3.floor.raiseManyIfEligible({
  calls: [{ market, calldata: prepared.data, gasEstimate: simulated.gas }],
});
```

Or encode first, then send with an explicit nonce (the keeper Durable Object path):

```ts
const encoded = sv3.floor.encodeRaiseBatch(controller, calls);
const pending = await sv3.floor.sendRaiseBatch(encoded, { nonce, gas: encoded.gasLimit });
```

## Return Value

`Promise<PendingProtocolTransaction>`

Same shape as [executePrepared](/developers/execute-prepared). Confirm with [wait](/developers/wait) or `sv3.floor.waitForFloorRaise`.

`trySimulateRaiseIfEligible` returns `{ ok: true, gas }` or `{ ok: false, errorName }` instead of throwing.

## Parameters

### params.market

- **Type:** `Address`

FloorMarket to raise.

### params.witness (optional)

- **Type:** `FloorRaiseWitnessInput`

Echo of the controller quote. If omitted, the SDK re-reads `quoteNextRaise`.

### options.nonce / gas / maxFeePerGas / maxPriorityFeePerGas (optional)

Passed through to viem `sendTransaction`. The keeper sets these from its nonce coordinator and gas cap. Unset, the wallet fills them.

Floor raises pay no bounty. Cap priority fees. Do not bid a gas auction to "win" a raise.

## Error

| Error                       | When                                                                                                  |
| --------------------------- | ----------------------------------------------------------------------------------------------------- |
| `WalletClientRequiredError` | No wallet on the client                                                                               |
| `SimulationFailedError`     | Revert; `cause` is `ProtocolRevertError` (`FloorRaiseNotEligible`, `Expired`, `StateNonceChanged`, …) |
| `TransactionRejectedError`  | Wallet or RPC rejected the send                                                                       |

`FloorRaiseNotEligible` after another actor raised is expected. Treat it as a race loss.

## Tips

- Encode with `sv3.floor.encodeRaiseIfEligible(market, witness)` when you need calldata without a wallet.
- `sv3.network.getBalance` / `getTransactionCount` / `getBlock` are the chain reads the keeper uses instead of calling `publicClient` from feature code.
- See [Floor keeper](/protocol/keeper) for operator behavior and trust assumptions.
