# Exit without the website

> How BotradixSalida handles exit requests, self-execution after 24 hours, withdrawals and order cancellation, with their limits.

Source: https://docs.botradix.com/exit/

BotradixSalida provides functions to request a DEX exit, execute your own exit, withdraw available funds and cancel orders without using the BotRadix website. Your account functions use the wallet sending the transaction as the owner; they do not let you choose another recipient. The exit contract does not hold your collateral: it communicates with the router, and payments go from CrossMargin to your wallet.

> [!CAUTION]
> Use only the address `0x43473B3684ccB5d9d57D119f2A6bc7B9B1f5EEe5`, on Base. Type it yourself on basescan.org or compare it character by character; do not follow addresses or links received in messages, ads or social networks, even if they claim to come from BotRadix. In the **Contract** tab, BaseScan must show the code at that address as verified; if it does not, do not continue. This exit never needs your recovery phrase or private key: do not share them with anyone.

> [!IMPORTANT]
> This guide describes the mechanism, not the state of an account or the router configuration at this moment. The periods and limits are those of the router Salida was deployed for; check its read functions before acting. **There is no guaranteed deadline for closing positions or receiving payment.**

## Step by step

A summary of the full exit. Each step is detailed in the sections below; the names are those of BotradixSalida's verified code (English / Spanish, they do the same).

1. **Open Salida on BaseScan.** On **basescan.org**, type the address `0x43473B3684ccB5d9d57D119f2A6bc7B9B1f5EEe5` yourself and check that the **Contract** tab shows the code as verified.
2. **Read your status.** In **Contract → Read Contract**, expand `status` (or `estado`). In the `account` (or `cuenta`) field enter your wallet address and click **Query**. Check that `forwarder` is the Salida address and note `requestedAt`, `openPositions` and `openOrders`.
3. **Connect your wallet.** In **Contract → Write Contract**, click **Connect to Web3**. Use the wallet that owns the account, on **Base (chain ID 8453)**, with some **ETH on Base** for gas.
4. **Request the exit.** In Write Contract, `exitDex` (or `salirDelDex`), with no parameters: click **Write** and confirm in your wallet. Your account stops accepting new positions. If you had no positions or orders, the exit can complete in that same transaction.
5. **Cancel your orders, if `openOrders` is above 0.** `cancelOrders` (or `cancelarOrdenes`); in the `ids` field enter the list of your order IDs in brackets, for example `[123,456]` (how to find them: section 2).
6. **Wait for the period.** The BotRadix keeper may close your positions earlier. Otherwise, from `selfExecutableAt`, **24 hours** after the request, you can execute the exit yourself. With a confirmed emergency (`emergencyAt` other than 0) there is no wait, but only positions in fixed markets close.
7. **Execute your exit.** `executeMyExit` (or `ejecutarMiSalida`): the block without fields attempts to close up to **8** positions; the one with `maxPositions` (or `maxPosiciones`) accepts **1 to 16**. Repeat while `openPositions` is above 0 and valid prices are available. **Before confirming, raise the gas limit in your wallet to 8,000,000 by hand** (16,000,000 if you use `maxPositions` 16): with the limit the wallet computes, the transaction can succeed without closing any position, because the contract skips the closes it has no gas left for. You only pay for the gas used.
8. **Withdraw everything.** With `openPositions` at 0 and no orders, `withdrawAll` (or `retirarTodo`), with no parameters. Check the USDC and BAQ transfers to your wallet in the transaction and read `status` again. If withdrawals are paused, repeat after the pause.
9. **If something reverts or makes no progress**, do not repeat the same call: read `status` and find your case in [If it reverts or makes no progress](#if-it-reverts-or-makes-no-progress). If you cannot find the cause, keep the hash and write to [support@botradix.com](mailto:support@botradix.com).

Want to cancel the request instead of exiting? Use `cancelExit` (or `cancelarSalida`), with no parameters. None of this guarantees a deadline for closing or payment: it depends on prices, orders, debts, pauses and liquidity (Terms, section 22).

## Before starting

1. Open [BotradixSalida on basescan.org](https://basescan.org/address/0x43473B3684ccB5d9d57D119f2A6bc7B9B1f5EEe5#code). Check the full address, `0x43473B3684ccB5d9d57D119f2A6bc7B9B1f5EEe5`, and that the **Contract** tab shows the code as verified.
2. **Before connecting or sending anything**, open **Contract → Read Contract**. Expand `status` (alias `estado`), enter your wallet address in `account` (or `cuenta`) and click **Query**. In the returned tuple, `forwarder` must be **the Salida address above**. If it is zero, different, or the read fails, do not continue through this Salida: check the address and router configuration. Also read `ROUTER()` and compare it with the [official addresses](https://docs.botradix.com/security-contracts/).
3. Set your wallet to **Base mainnet, chain ID 8453**, with **ETH on Base for gas**. Use the wallet that owns the positions and collateral; your account functions act on the signer.
4. At the same Salida address, open **Write Contract**, click **Connect to Web3**, choose your wallet and check the connected account and network. Connecting does not execute an exit.
5. For each action below, expand the block with that name, fill in its parameters, click **Write** and confirm the transaction in your wallet. Open its hash, wait for confirmation and query `status(yourAddress)` again in **Read Contract**. Recheck `forwarder` before further actions; an earlier read does not prevent later router changes.

Reads do not change state or require a transaction. Dates are Unix timestamps in **seconds**, not countdowns or local times.

| Field in `status(yourAddress)` | How to interpret it |
|---|---|
| `requestedAt` | Zero: no pending request. A nonzero value: the request timestamp. |
| `selfExecutableAt` | The ordinary time from which you can execute your exit; a prior request is required. A confirmed emergency skips the wait even if this field still shows the ordinary time. |
| `openPositions`, `openOrders` | Counts of remaining positions and orders. These are not ID lists. |
| `withdrawalsPaused`, `withdrawalsPausedUntil` | Whether withdrawals are paused and when the pause ends. |
| `emergencyChallengeAt`, `emergencyAt` | The first indicates a challenge; only `emergencyAt != 0` indicates a confirmed emergency. |
| `emergencyPending`, `unsettledAccounts`, `distributionOpenedAt` | Your account's pending settlement, the global count of unsettled accounts, and the distribution opening time (`0`: not open yet). |
| `emergencyClaimUSDC`, `deferredUSDC` | Emergency claim and deferred payment; these are not free funds already received. |

## Your account functions

The functions have Spanish and English aliases that follow the same path.

| Action | Spanish name | English name |
|---|---|---|
| Request an exit | `salirDelDex()` | `exitDex()` |
| Execute your exit | `ejecutarMiSalida()` or `ejecutarMiSalida(uint256)` | `executeMyExit()` or `executeMyExit(uint256)` |
| Withdraw what is available | `retirarTodo()` | `withdrawAll()` |
| Cancel your orders | `cancelarOrdenes(uint256[])` | `cancelOrders(uint256[])` |
| Cancel the exit request | `cancelarSalida()` | `cancelExit()` |

The return values described below are contract results. **A receipt marked `Success` does not usually display those values or prove that everything was withdrawn**: check the `status` reads and the transfers to your wallet. `SalidaUsada` identifies the action sent, not completion of the process.

### 1. Request an exit

In **Write Contract**, use `exitDex()` or `salirDelDex()`, with no parameters. It records the request and locks new positions for the account. If there are no open positions or orders, it attempts to complete withdrawal in that transaction, subject to the other checks. Repeating a pending request keeps its original timestamp; it does not restart the 24-hour wait.

It returns `1` if the exit completed in that transaction and `0` if it remains pending. Check `requestedAt`, `selfExecutableAt`, `openPositions` and `openOrders`. A `0` is not itself a failure: continue with pending orders and positions. A `1` does not guarantee payment of unbacked deferred amounts or unpaid claims.

The keeper can cancel orders and close positions using valid prices observed **at or after the request**. Execution within seconds is not promised. Price, funding and liquidation risk remain during the wait.

### 2. Cancel pending orders

The IDs this function takes are those of the router's `DexOrderCreated` events, the router being the address returned by `ROUTER()`. On BaseScan, open that address and look in its **Events** for the `DexOrderCreated` events of your wallet: in that event, the first indexed value is the order ID, the second the owner wallet and the third the `pairId`. Copy only the order IDs, never the `pairId`. Return to **Salida's Write Contract**, expand `cancelOrders` or `cancelarOrdenes` and enter the list in `ids`, for example `[123,456]`, **replacing those numbers with your actual IDs**.

It needs no prices and returns no value. Check that `openOrders` goes down. An order of yours that was already executed or cancelled is ignored; an order of another wallet, or an ID that is not yours, reverts the whole transaction.

Cancelling orders does not by itself close all positions. The self-execution function does not enumerate and automatically cancel all your entry orders: check `openOrders` and cancel any remaining ones so the exit can complete and their reserves can be released.

### 3. Execute your exit after 24 hours

If the request remains pending, read `status(yourAddress)` and use `executeMyExit` or `ejecutarMiSalida` in **Write Contract** once `selfExecutableAt` is reached, **24 hours after the request**. A confirmed emergency (`emergencyAt != 0`) removes that wait, but you must still request the exit with `exitDex()` first; opening a challenge is not enough.

BaseScan shows two versions with the same name: the block **without input fields** attempts to close up to **8 positions**; the one with `maxPositions` (or `maxPosiciones`) lets you enter a batch size of **1 to 16**. Available gas can reduce the amount processed. Multiple calls may be needed.

For an unfrozen market, both price legs must have an open session, have been observed at or after the request, be at most **10 minutes** old, not be dated in the future and meet their confidence limits. A frozen market uses its fixed price. **During an emergency, only positions in frozen markets can close.** Positions without a usable price are skipped and remain open.

It returns `(closed, remaining, finished)`: positions closed in this call, positions still open, and `1` if the exit completed (`0` otherwise). Check `status(yourAddress)` after each batch. Repeat while positions remain and price conditions are met; if there is no progress, check the causes below. If orders, debts, an effective pause or pending emergency settlement remain, closing the last position may not complete withdrawal. **During an emergency, finish with `withdrawAll()`**, even if no positions remain. Reaching 24 hours enables a call; it does not trigger a transaction or guarantee available prices or funds.

### 4. Withdraw what is available

Once `openPositions` is `0`, cancel any remaining orders first and use `withdrawAll()` or `retirarTodo()` in **Write Contract**, with no parameters. It needs no prices or prior exit request. With open positions it reverts with `DexPositionsOpen`. It attempts to settle and collect applicable emergency payments, claim deferred payments that now have backing, and withdraw available free USDC and BAQ to the owner wallet.

It returns no value: check the USDC and BAQ transfers to your wallet in that transaction and the new state. A successful transaction can reflect a partial withdrawal or a zero amount; it does not by itself prove that nothing remains pending. During a pause the router emits `DexExitAwaitingWithdrawal` and stops withdrawal **without necessarily reverting the transaction**. Repeat once the pause ends.

Order reserves are not withdrawn; cross debt or pending settlement can also prevent completion. Calling this function does not turn an unbacked deferred payment into withdrawable balance. During an emergency, distribution requires no open position anywhere in the DEX and every account to be settled. If `distributionOpenedAt` is still `0` or a claim remains, call again once those conditions are met; payment may be partial, with a deferred remainder.

### Cancel the request

To cancel a pending request, use `cancelExit()` or `cancelarSalida()`, with no parameters, in **Write Contract**. It returns no value: check that `requestedAt` is back to `0`. It removes that request's lock on new positions; it does not remove an emergency or other protocol restrictions. It does not restore closed positions or cancelled orders, or reverse confirmed transactions. A later exit request starts a new ordinary wait.

## If it reverts or makes no progress

If BaseScan or the wallet warns that the call would revert, check the cause before signing. A transaction confirmed as failed keeps no changes from that call but consumes gas. Do not repeat it without addressing the condition that prevents it. Salida forwards the call to the router: if the router's code does not appear as verified on BaseScan, the error reason may show as a hexadecimal code instead of a name. The `status` and `market` reads tell you which situation you are in.

| Situation | What to do |
|---|---|
| `executeMyExit()` or `cancelExit()` would fail and `requestedAt` is `0` | There is no pending request. If you want to exit and positions remain, request the exit with `exitDex()` first. If the exit already completed, you do not need to cancel it. |
| `executeMyExit()` would fail before `selfExecutableAt` | Wait until that time, unless an emergency is confirmed (`emergencyAt != 0`). |
| `withdrawAll()` reverts with `DexPositionsOpen` | Positions remain: request an exit if needed, close them with `executeMyExit()` when eligible and read the state again. |
| Any of your account functions would fail with no other visible cause | Check that `forwarder` is this Salida address, the connected account and, for `cancelOrders`, that every ID belongs to an order of your wallet. Adding gas does not fix it. |
| `DexExitAwaitingWithdrawal` or `withdrawalsPaused == true` | Withdrawal is waiting, not necessarily reverting. Read `withdrawalsPausedUntil` and retry withdrawal after the pause. |
| `withdrawAll()` succeeds but not everything arrives | A pause, orders with reserved funds, cross debt, a pending settlement or an unbacked deferred payment may remain. Check `openOrders`, `deferredUSDC`, `emergencyPending` and the pause; if the reads do not explain it, report the hash to support. |
| No positions closed, or `finished == 0` | There may be no valid price, too little gas for another position, orders, debt or pending settlement. Read the counters and market state; during an emergency the market may still need fixing. A successful call does not force those conditions to be met. |
| Insufficient gas | Check ETH on Base and the estimate. For self-execution, try a smaller batch, such as `maxPositions = 1`; split order lists into smaller batches. |
| A community function would fail | The challenge or emergency is not in the required state, or its period has not elapsed. Read `status` (`emergencyChallengeAt`, `emergencyAt`) and `market(pairId)` (`challengeOpenedAt`, `settleAfter`, `frozenKind`) again before retrying. |
| `confirmEmergency` would fail with a market list | Read the complete, ascending list from `marketsWithPositions()` again; do not invent IDs or use a shortened list. |
| `settleMarket` would fail although `settleAfter` has passed | There may be no observation to fix the price with: reaching the deadline does not create a price. Check `market(pairId)` and report the problem. |

If you cannot identify the cause, keep the hash and visible error and contact [support@botradix.com](mailto:support@botradix.com). Waiting or repeating the same call is not guaranteed to complete it.

## Pauses, missing prices and emergency

Under the rules of the router Salida was deployed for, each withdrawal pause expires after 72 hours, requires 24 hours without a pause before the next one and does not apply during a confirmed emergency. Other payment constraints can remain after expiry.

The **community functions** are also in **Salida's Write Contract**. Anyone can pay gas to call them when their conditions are met. Results and payments belong to each account owner; submitting the transaction gives no right to anyone else's funds. They do not activate automatically when your request reaches 24 hours.

| English function / Spanish alias | Conditions and result |
|---|---|
| `openEmergencyChallenge()` / `abrirDesafioEmergencia()` | Opens the public **72-hour** challenge if positions exist in the DEX and there is no emergency yet. Read `emergencyChallengeAt`. |
| `confirmEmergency(markets)` / `confirmarEmergencia(mercados)` | After 72 hours, get the **complete, ascending** `bytes32[]` list from `marketsWithPositions()` / `mercadosConPosiciones()` in **Read Contract** and paste it into `markets` (or `mercados`) in **Write Contract**. Returns `true` if it activates the emergency. An observation of USDC or a market with positions since the challenge opened, even with a closed session, clears the challenge and returns `false`. Check `emergencyAt`. |
| `fixEmergencyMarkets(markets)` / `fijarMercadosEmergencia(mercados)` | During an emergency, fixes the remaining markets with positions; returns how many it fixed. Use the market IDs from the read above and repeat if gas left work pending. Price and funding are fixed at the emergency instant even if fixing finishes later. |
| `challengeMarket(pairId)` / `desafiarMercado(pairId)` | Opens the **3-day** challenge for a market with positions that is not frozen. `pairId` is the pair's number, not a `bytes32` market ID. Read `market(pairId)` / `mercado(pairId)`, including `challengeOpenedAt` and `settleAfter`. |
| `settleMarket(pairId)` / `liquidarMercado(pairId)` | From `settleAfter`, with no observations since the challenge, freezes the market at its last observed price and fixes its funding. Returns `true` when it freezes the market; a later observation clears the challenge and returns `false`. Check `frozenKind` and `frozenPriceX18` in `market`. |
| `closeFrozen(positions, orders)` / `cerrarCongeladas(posiciones, ordenes)` | Takes two ID lists, closes positions in frozen markets and cancels their orders; during an emergency it can cancel any order. Returns `(positions closed, orders cancelled)`. Batches may be needed; results stay in the owners' accounts. |
| `settleAccounts(accounts)` / `liquidarCuentas(cuentas)` | During an emergency, settles the listed accounts with no positions or orders; returns how many it settled. Net gain: a claim. Net loss: cash, then committed BAQ backing. Accounts not yet eligible are skipped. |
| `payEmergencyClaims(accounts)` / `cobrarReparto(cuentas)` | With no positions anywhere in the DEX and all accounts settled, opens distribution and credits each owner's share to their CrossMargin account. Returns the total amount paid, not the number of accounts; `0` can mean distribution cannot open yet. Each owner finishes with `withdrawAll()` to withdraw to their wallet. |

A confirmed emergency is final for this DEX and stops trading; the administrator can declare it without the public challenge. Distribution applies the same fixed percentage to everyone: the smaller of 100% and available liquidity (vault, insurance and emergency reserves, excluding reserves for earlier deferred payments) divided by claims, subject to rounding. Any shortfall remains deferred, without a guaranteed payment deadline. Challenges, batches and distribution require transactions; no clock executes them automatically.

## What this exit depends on

BotradixSalida has no administrator or upgrade mechanism of its own, but **depends on the router and CrossMargin**. The router must recognize it as the `forwarder`. While configuration is open, administration can replace or disconnect it using `setDexExitForwarder(address(0))` and can change the logic processing exits without mandatory advance notice. A return to an earlier router version can leave Salida unusable even if its address still exists. After the sealing provided for by this code, Salida can no longer be disconnected and router modules can only change through the advance-notice gate, with a committed minimum of at least 72 hours. This describes the sealing rules; it does not claim sealing is active. Administrative changes are public transactions on Base.

Leaving without the website removes dependence on that interface, but not on the Base network, prices, deployed code, account conditions or liquidity. See [Security and contracts](https://docs.botradix.com/security-contracts/), [Risks](https://docs.botradix.com/risks/) and [Terms §22: independent exit, pauses and emergency](https://botradix.com/terms?lang=en#dex-exit), together with sections 23–24 on administration and deferred payments.
