> For the complete documentation index, see [llms.txt](https://docs.tallyprotocol.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tallyprotocol.xyz/smart-contracts/how-a-guarded-swap-works.md).

# How a guarded swap works

This page follows one `swapForShares` call through `_swap`.

## Preconditions the contract checks first

| Check                                                                                                                | Error                                                                         |
| -------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `block.timestamp <= deadline`                                                                                        | `Expired(deadline)`                                                           |
| `amountIn > 0`                                                                                                       | `ZeroAmount()`                                                                |
| `minShares > 0` (a zero floor would switch the guard off for a naive caller)                                         | `ZeroMinShares()`                                                             |
| `recipient != address(0)`                                                                                            | `ZeroAddress()`                                                               |
| `tokenIn != stock`                                                                                                   | `SameToken()`                                                                 |
| `router` is allow-listed and is neither `tokenIn` nor `stock`; its approve target is not `tokenIn` or `stock` either | `RouterNotAllowed(router)`                                                    |
| The stock asset is enabled                                                                                           | `AssetNotEnabled(stock)`                                                      |
| The issuer has not paused the stock                                                                                  | `TokenPaused(stock)`, or `PauseCheckFailed` if the pause state cannot be read |
| The multiplier can be read and is nonzero (Feed assets must be seeded and fresh)                                     | `MultiplierUnavailable`, `FeedNotSeeded`, `FeedStale`                         |

The pause check **fails closed**: a manager that reverts, returns the wrong size, or a token that reports no manager makes the swap revert instead of passing.

## The sequence

```
tokenIn.safeTransferFrom(caller, guard, amountIn)
tokenIn.forceApprove(approveTarget, amountIn)         // exact
(ok, ret) = router.call(routerData)                    // the aggregator's calldata
tokenIn.forceApprove(approveTarget, 0)                 // reset
out    = stock.balanceOf(guard) - stockBefore          // what actually arrived
shares = out * multiplier / 1e18
require(shares >= minShares)                           // InsufficientShares otherwise
stock.safeTransfer(recipient, out)
refund any unspent tokenIn to the caller
emit Guarded(...)
```

`routerData` was built by the aggregator with the guard as the buyer, which is why the guard can run it as its own transaction.

## The event

```solidity
event Guarded(
    address indexed user,
    address indexed recipient,
    address indexed stock,
    address tokenIn,
    uint256 amountIn,
    uint256 tokensOut,
    uint256 shares,
    uint256 multiplier,
    address router
);
```

The receipt page decodes this event: what was spent, how many tokens arrived, how many shares they were worth at which multiplier. That is the proof, and it is onchain.

## Failure modes seen in practice

| Symptom                                                | Cause                                                                                                                                                                              |
| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `InsufficientShares(shares, minShares)`                | The fill landed below the floor. Nothing is spent but the network fee.                                                                                                             |
| `RouterCallFailed(reason)`                             | The router reverted. A market-maker order that expired inside the block shows `RFQ_OrderExpired` in the nested reason.                                                             |
| `FailedInnerCall()` (`0x1425ea42`) from the aggregator | The swap ran out of gas. The API's gas figure is a placeholder (always 450,000); real routes used 437,968 to 1,024,000. Tally estimates and simulates at the exact limit it sends. |
| `TokenPaused(stock)`                                   | The issuer paused the token, for example around a session change.                                                                                                                  |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.tallyprotocol.xyz/smart-contracts/how-a-guarded-swap-works.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
