> For the complete documentation index, see [llms.txt](https://docs.sail.money/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sail.money/protocol/permissions/shared-templates.md).

# Shared multi-tenant templates

The naive pattern — one permission contract per account, parameters in the constructor — gives a clean per-instance audit surface but is expensive in gas and bytecode. The **shared multi-tenant template** pattern shown here serves every account that registers it from one contract deployed once per chain, with per-account configuration stored in mappings keyed by `account`.

{% hint style="info" %}
**These templates are examples, not the protocol.** The `Shared*` templates and `BaseSharedPermission` are reference implementations that demonstrate how to implement the [`IPermission`](/protocol/permissions/ipermission.md) pattern across common DeFi primitives. They are illustrative, not a fixed part of the trusted core — anyone can deploy their own permission contracts, and the kernel registers and dispatches any contract implementing `IPermission`.

You are responsible for the correctness of any permission you register (see [permission correctness is the author's responsibility](/protocol/security/limitations.md)). Treat these templates as starting points to read, learn from, and adapt — not audited, drop-in production contracts. The seven shared templates are deployed against the current kernel (see [addresses](/protocol/reference/addresses.md)) and were included in the [Octane security review](/protocol/security/audits.md), but they remain reference implementations; verify and test before any production use.
{% endhint %}

## BaseSharedPermission

Shared templates inherit `BaseSharedPermission`, which provides the per-account configuration machinery so subclasses only implement their decode/check logic.

```solidity
abstract contract BaseSharedPermission is
    IConfigurablePermission, IAccountAgentIdentityResolver, EIP712, ReentrancyGuard
{
    bytes32 public constant CONFIGURE_TYPEHASH =
        keccak256("Configure(address account,bytes32 paramsHash,uint256 nonce,uint256 deadline)");

    mapping(address => uint256) public configNonces;
    mapping(address => bool)    public isConfigured;

    function _applyConfig(address account, bytes calldata params) internal virtual; // subclass hook
}
```

It exposes two ways to configure an account, both reading the authoritative `permissionSigner` from the kernel:

* `configure(account, params, deadline, sig)` — anyone may submit; authorization is the Permission Signer's EIP-712 signature over `Configure(account, keccak256(params), nonce, deadline)`. The per-account `configNonces` is incremented only **after** the signature verifies.
* `configureDirect(account, params)` — `msg.sender` must equal the account's `permissionSigner` (useful when the signer is an EOA submitting the tx itself).

A fresh `configure` clears the account's previous config and applies the new one atomically.

## The opaque params blob

`params` is an ABI-encoded blob whose structure each template defines. The kernel and the base contract treat it as opaque bytes; the subclass decodes it in `_applyConfig`. For `SharedBoundedSwapPermission`, for example:

```solidity
abi.encode(
    address[] routers,
    address[] tokensIn,
    address[] tokensOut,
    uint256   maxAmountPerTx,
    uint256   maxSlippageBps,
    address   priceOracle,
    uint256   maxPriceAgeSec
)
```

The template decodes this, validates it (e.g. an oracle requires a non-zero freshness bound, else `MissingPriceAge`), rebuilds its O(1) allowlist mappings for that account, and stores the slot.

## Starter catalog

A set of shared templates ships with the protocol as demonstrations of the pattern — **unaudited references**, not part of the trusted core. Each declares a capability id from `SailCapabilities`:

| Template                              | Gates                                                                                                                                                         | Capability           |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
| `SharedBoundedSwapPermission`         | AMM swaps: router + token allowlists, per-tx amount cap, optional oracle slippage check (Uniswap V3 `exactInputSingle` V1/V2, V2 `swapExactTokensForTokens`). | `bounded-swap.v1`    |
| `SharedBoundedBorrowPermission`       | Borrows on Aave V3 / Morpho / Compound with LTV enforcement.                                                                                                  | `bounded-borrow.v1`  |
| `SharedTransferTargetPermission`      | ERC-20 `transfer`/`transferFrom` to allowlisted recipients.                                                                                                   | `transfer-target.v1` |
| `SharedDeFiBundlePermission`          | Composite swap + borrow + transfer, selector-routed.                                                                                                          | `defi-bundle.v1`     |
| `SharedPendlePermission`              | Pendle V2 Router V4: liquidity, PT/YT swaps, mint/redeem, claim.                                                                                              | `pendle-yield.v1`    |
| `SharedAMMLiquidityPermission`        | Concentrated-liquidity ops on Uniswap V3 / Aerodrome.                                                                                                         | `amm-liquidity.v1`   |
| `SharedApproveAndCallBatchPermission` | Batch-only: the `approve → call → reset` pattern.                                                                                                             | `batch-dispatch.v1`  |

Anyone may deploy additional templates for any venue — the catalog above is a starting set, not a closed list.

## Standalone (clone) templates

Some templates are single-account and use `initialize(...)` instead of `configure(...)`. The `MandateFactory.deployAndAttach` flow clones such a logic contract (EIP-1167), initializes it, and registers the clone — one transaction, deterministic address. See [MandateFactory](/protocol/architecture/mandate-factory.md).

Configure one end to end in [Use a shared template](/protocol/guides/use-a-template.md).


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.sail.money/protocol/permissions/shared-templates.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
