> ## Documentation Index
> Fetch the complete documentation index at: https://docs.calibri.io/llms.txt
> Use this file to discover all available pages before exploring further.

# The Safe

> Your per-member Gnosis Safe — deploy and register (operator-gasless), fund with USDC, and make it trade-ready with signed approvals.

Every self-custody member trades from a **Gnosis Safe** they alone own. The Safe
holds your USDC on-chain and is the maker of your orders. The operator deploys
and relays it gaslessly — you only ever sign.

It starts as **1-of-1**: one owner, either your wallet or the signer contract
derived from your passkey. It becomes **1-of-2** if you add a
[signing key](/non-custodial/signing-keys) — a second key of your own, where
either one alone can sign. Calibri is never an owner in any configuration.

## How the Safe fits in

What differs between members is **what owns the Safe** — see
[Your wallet options](/non-custodial/wallets):

* **Owner** — either your **wallet address (EOA)** (linked/SIWE wallet, or an
  email-derived address), or, for a passkey wallet, a **signer contract**
  derived from your WebAuthn credential. Either way, this is what **signs**.
* **Safe (proxy)** — the Gnosis Safe owned by that owner. This is the
  **maker** of your orders and the **destination** for deposits.

The owner also determines the signature type your orders use: `2`
(`POLY_GNOSIS_SAFE`) for a wallet EOA, `3` (`POLY_1271`) for a passkey signer
contract. The config below tells you which — see
[Signed orders](/non-custodial/signed-orders).

A member with neither a linked wallet nor a passkey is custodial-only.

## The bridge module

Every Safe is created with **one module** enabled: the **CctpBridgeModule**. It is
switched on by the Safe factory **in the same transaction that creates the Safe**, so no
Safe ever exists without it and nobody can set one up differently first.

A Safe module is a contract the Safe lets act **without owner signatures** — so what
matters is what the module's own, immutable code allows. This one allows exactly one
thing: moving that network's **USDC**, through Circle's CCTP, to **the same Safe address
on Polygon**. That is what lets USDC sent to your address on Ethereum, Base, Arbitrum or
Optimism reach your Safe on Polygon without you signing anything — see
[Deposits from other networks](/non-custodial/deposits-from-other-networks).

| The module can | The module cannot |
| - | - |
| Move the network's USDC to **your own Safe address on Polygon**, through Circle | Send funds anywhere else — the destination is fixed in code, not a parameter or a setting |
| Pay **one** fee per bridge to Calibri's treasury, only when Calibri's relayer calls it — at most 10 USDC and at most 20% of the amount, unless you accepted a higher fee for that deposit ([when gas is high](/non-custodial/deposits-from-other-networks#when-ethereum-gas-is-high)) | Move any other token, or ETH |
| Be called by **anyone** with a zero fee — including you, if Calibri is gone | Delegatecall, or change your Safe's owners or settings |

On **Polygon** the module is present but does nothing: there is no route from Polygon to
itself.

**Withdrawals to other networks do not use the module.** They leave your Safe on Polygon as
an ordinary Safe transaction you sign, which calls **Circle's messenger directly from the
Safe** — no module and no Calibri contract is involved, and the destination address is
part of what you sign. See
[Withdrawals to other networks](/non-custodial/withdrawals-to-other-networks).

Your Safe has **the same address on every supported network**, because the factory and
the Safe implementation sit at the same address on each. On a network other than Polygon
the Safe is created only when it is first needed, by the same permissionless factory, with
**the same owner** your Polygon Safe was created with. Calibri is never an owner there
either.

<Warning>
  **Passkey wallets:** your signer contract exists only on Polygon, so no signature from you can be checked on another network. There, the module cannot be switched off and is the only way USDC can leave your Safe — and anything other than USDC sent there cannot be moved today. A [signing key](/non-custodial/signing-keys) added on Polygon does not carry over to other networks. See [the caveats](/non-custodial/deposits-from-other-networks#the-caveats).
</Warning>

## 1. Deploy & register (operator-gasless)

You do not deploy the Safe yourself. When you first read your CTF config, Calibri
**ensures your Safe exists** — the operator deploys it gaslessly (idempotent) and
returns the derived Safe address, then registers it so on-chain transfers to it
are credited back to your account.

Read your member-level wallet config:

**`GET /api/v2/atlas/account/wallet`**

Returns your funding config: `proxy_address` (your Safe), `owner_address` (your Safe's owner — your EOA, or your passkey signer contract), `usdc_address`, `exchange_address`, `conditional_tokens_address`, `chain_id`, `blockchain_key`, `domain_name`, `signature_type`, `safe_setup`, and `safe_status`.

```json theme={null}
{
  "exchange_address": "0x… (Calibri's CTF Exchange)",
  "conditional_tokens_address": "0x…",
  "usdc_address": "0x…",
  "chain_id": 137,
  "blockchain_key": "polygon-mainnet",
  "domain_name": "Calibri CTF Prediction Markets",
  "proxy_address": "0x… (your Safe — deposit destination + order maker)",
  "owner_address": "0x… (your EOA, or your passkey signer contract)",
  "signature_type": 2,
  "safe_setup": { "ready": true, "calls": [] },
  "safe_status": "ready"
}
```

<Warning>
  Read every value above from the API rather than copying it from this page. `domain_name` in particular is hashed into every order signature, so a stale copy produces a signature that will not recover.
</Warning>

`safe_status` values:

| Value | Meaning |
| - | - |
| `ready` | Safe exists and is set up — you can trade |
| `setup_required` | Safe exists but approvals are still outstanding — sign and relay `safe_setup.calls` first |
| `error` | Lookup failed; retryable (the Safe is not presented as absent) |
| `unavailable` | You have an owner but no Safe factory is available |
| `unlinked` | Custodial-only — no wallet linked and no passkey enrolled |

<Warning>
  Do not trade on `setup_required`. An order placed before the approvals land will **rest on the book and then fail to settle** — worse than being rejected outright. Only `ready` is safe to trade on.
</Warning>

<Note>
  For a specific market, use `GET /api/v2/atlas/account/wallet/markets/:id` instead. It returns the same funding config **plus** the market's `condition_id`, `yes_token_id`, and `no_token_id`. It returns `404` for a custodial-only market. See [Signed orders](/non-custodial/signed-orders).
</Note>

## 2. Fund the Safe with USDC

Send USDC to your Safe address (`proxy_address`) on-chain — from any wallet or
exchange. Your off-chain [`balance_safe`](/non-custodial/balances) mirror is
credited once the transfer confirms.

USDC sent to the same address on Ethereum, Base, Arbitrum or Optimism is bridged to
this Safe on Polygon by the module above and credited the same way, less the bridge fee —
see [Deposits from other networks](/non-custodial/deposits-from-other-networks).

<Warning>
  The Safe must **actually hold USDC on-chain**. On-chain settlement pulls your real collateral from the Safe when a trade matches; `balance_safe` is only Calibri's mirror of that on-chain balance.
</Warning>

## 3. Make the Safe trade-ready

Before its first trade, the Safe must grant three on-chain approvals:

1. Approve **USDC → the exchange** — collateral for your fills
2. `setApprovalForAll` on **ConditionalTokens → the exchange** — your outcome tokens
3. Approve **USDC → the operator**, capped — the taker fee pulled at settlement

The third is deliberately **bounded**, not unlimited: it covers many trades and
depletes as fees are collected. When it runs low the config asks you to sign
once more to top it up, so setup can recur — it is not strictly one-time. A
capped allowance means a compromised operator key could take at most that
remaining amount, never your Safe balance.

These come back in the config as `safe_setup.calls` — a list of
`{ to, data, operation, nonce, hash }`. Sign each as a Safe `SafeTx` (EIP-712)
with your Safe's owner and relay it (see below).

Handle both shapes: the approvals may arrive batched through Safe's
**MultiSend** as a **single** call with `operation: 1` (`DELEGATECALL`) — one
signature instead of three — or as three separate calls at sequential Safe
nonces, which must be relayed **in order**. Either way, when setup is complete
the config reports:

```json theme={null}
"safe_setup": { "ready": true, "calls": [] }
```

### Relaying a setup call

**`POST /api/v2/atlas/account/wallet/relay`**

Submits a signed Safe transaction. The operator executes `Safe.execTransaction` and pays gas.

Request body:

```json theme={null}
{
  "safe": "0x… (must be your own Safe)",
  "to": "0x… (the exchange, for approvals)",
  "value": "0",
  "data": "0x… (encoded approve / setApprovalForAll)",
  "operation": 0,
  "signature": "0x… (your SafeTx signature — EOA ECDSA, or an EIP-1271 contract signature for a passkey)"
}
```

Required fields: `safe`, `to`, `data`, `signature`. `value` defaults to `"0"`
and `operation` to `0`. Calibri rejects with `400 safe does not belong to this
member` unless `safe` equals your own derived Safe address, then forwards to the
operator relayer.

Response:

```json theme={null}
{ "tx": "0x… (submitted tx hash, or null)" }
```

### The SafeTx typed data

The same `SafeTx` EIP-712 structure is used for setup approvals, redemption, and
withdrawals:

```
domain: { verifyingContract: <your Safe address>, chainId }   // name/version omitted
SafeTx(
  address to, uint256 value, bytes data, uint8 operation,
  uint256 safeTxGas, uint256 baseGas, uint256 gasPrice,
  address gasToken, address refundReceiver, uint256 nonce
)
```

Use `value = safeTxGas = baseGas = gasPrice = 0`, `gasToken = refundReceiver =
0x0`, `operation = 0` (CALL), and `nonce` = the Safe's current on-chain
`nonce()`.

A withdrawal to another network is the exception: Calibri builds it for you as one
**MultiSendCallOnly** batch (`operation = 1`) returned with its quote — the fee transfer,
the USDC approval to Circle's messenger, and Circle's `depositForBurn`. Sign it exactly as
returned and relay it with the quote's `quote_id`; Calibri relays such a batch only when it
matches that quote byte for byte, once. See
[Withdrawals to other networks](/non-custodial/withdrawals-to-other-networks).

## Next steps

* [Signed orders](/non-custodial/signed-orders) — build and sign an EIP-712 order once the Safe is ready
* [Redeeming winnings](/non-custodial/redeeming-winnings) — the same relay path is used to claim payouts
* [Deposits from other networks](/non-custodial/deposits-from-other-networks) — USDC on Ethereum, Base, Arbitrum or Optimism, bridged here
* [Withdrawals to other networks](/non-custodial/withdrawals-to-other-networks) — USDC from this Safe to an address on Ethereum, Base, Arbitrum or Optimism


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.