Build & register a mandate
A mandate is the set of permissions registered on your SMA. With Sailor you author them in a Foundry workspace, prove them off-chain, then register them — every authorizing signature comes from the owner / permission signer in the browser.
1. Author a permission
Section titled “1. Author a permission”The scaffold includes a Foundry workspace with @sail/interfaces/IPermission.sol vendored under .sail/contracts/. Write a contract implementing IPermission that encodes your bounds (tokens, amounts, venues, recipients), then build:
forge buildSee the Protocol’s Write your first permission for the contract pattern, and Configure a shared template to use an example instead of writing from scratch.
2. Simulate before authorizing
Section titled “2. Simulate before authorizing”Never register a permission you haven’t proven. Probe it off-chain (no gas):
sailor mandate simulate --address MyPermission --sma 0xYourSMA \ --target 0xRouter --calldata 0x... --expect passThis eth_calls the permission’s evaluate with a constructed Context and reports PASS / FAIL / REVERT. See Simulate before going live for the batch (--calls) form and the full option set.
3. Deploy and register
Section titled “3. Deploy and register”# deploy a compiled permission and register it in one flow (owner signs in the browser):sailor mandate deploy --contract MyPermission --attach --sma 0xYourSMA \ --args '["0xPermissionSigner", ["0xTarget"]]'
# or register an already-deployed permission:sailor mandate register --address 0xPermission --sma 0xYourSMAdeploy emits a contract-creation signing request (the owner signs it), reads the deployed address from the receipt, and tracks it in .sail/state/mandates.json. attach reads the signer nonce, has the owner sign a RegisterPermission EIP-712 message, then submits kernel.registerPermission with the exact registration fee. Both take --json for headless use.
4. Confirm and sign the mandate
Section titled “4. Confirm and sign the mandate”sailor mandate prepare # prepare a mandate draft for review/signing in the UIsailor mandate sign # review and confirm the permissions authorized for your SMA (--yes to skip the prompt)sign reconciles against the live on-chain getPermissions() before building the payload — permissions revoked on-chain are excluded even if they remain in the local append-only .sail/state/mandates.json. The signed result lands in .sail/mandate.json, which the runner executes against.
Critical: ERC-20 approvals need explicit coverage
Section titled “Critical: ERC-20 approvals need explicit coverage”An ERC-20 approve() is not covered by a swap, supply, or deposit permission — it is a distinct call and needs its own authorization. There are two non-mixable models:
- Per-call (default): separate single dispatches, each gated by its own
IPermission— one for theapprove, one for the action. - Atomic batch: one
IBatchPermissionauthorizing the whole[approve, action, reset]sequence as a unit. A normalIPermissioncannot authorize a batch.
Choose deliberately; a swap permission alone will not let your agent approve the router.
Changing the mandate later
Section titled “Changing the mandate later”sailor mandate revoke --address 0xPermission --sma 0xYourSMA # or --allsailor mandate update --address MyName --name NewName # tracking metadata onlysailor mandate list # permissions deployed from this projectRevocation is owner-authorized (RevokePermissions) and takes effect in a single block, invalidating the manager’s outstanding pre-signed dispatches. See the Protocol’s permission lifecycle.