← Back
blueshift-gg

blueshift-gg/solana-intent-system

An intent system for Solana: sign what may leave and what must arrive, anyone fills it, the program enforces the outcome

View on GitHub ↗
Stars
4
Forks
0
Watchers
4
Open issues
0
Contributors
1
Language
Rust
License
MIT License
Default branch
main
Created Oct 1, 2026Updated Oct 1, 2026

Star growth

Today—
This week—
This month—

Star history will appear here once this repo has been tracked for a couple of days.

README

Solana Intent System

A Solana program that enforces signed intents over SPL token accounts.

An intent states what may leave one token account and what must arrive in another. The owner signs it as text. Anyone can execute it. The program checks the balances afterwards and fails the transaction if they are wrong.

Open  →  any instructions  →  Close

Open verifies the signature, pulls up to the signed limit as the account's SPL delegate and snapshots every balance the intent names. Close compares them to the snapshots. Funds stay in the owner's wallet until Open, and nothing in between is trusted.

What is signed

Solana Mandate v1
cluster: localnet
engine: Mand89p7P6okjEKQx2SpwDX6mdb5zAcdpshRafFtv7A
authority: A9XwnWUxXn1HH1MPzxe5MqfYaKvEHtdQMCoDd72QjPLN
[0] MAY TAKE: at most 8.000000 of mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v from 6NSx1jcpyqzHDFHwC7RXm4LZy53gNsMZWpV3P8vr8k4M at a time
[1] REQUIRES: FAUD3SfhKYyynnZsS8pKVgZ9ea5VQohFqpaxKpAwzEGA (mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v, owner GNxM82DJMja5ux5extFCEjbQ5C88hvcG7fvsiSCQumgs) gains at least 1.000000 for every 1.000000 taken by [0]
EXECUTOR: anyone
VALID: from 2026-10-01T08:16:00Z until 2027-10-01T08:16:00Z
REPLAY: refills over 30d
EPOCH: 0

This is a subscription: 8 USDC, refilling over 30 days, payable only to one account, for a year. The text is an Offchain Message v1. The transaction carries the terms as 289 bytes of binary; the program renders them back to this text and verifies Ed25519 over it in-program. The text is the only thing a wallet has to show, and a byte of the terms cannot change without changing it (every_byte_of_the_terms_is_visible_in_the_text).

Terms

Terms  { authority, executor: any | key, not_before, not_after, replay, epoch, asserts }
Replay = once | fill | rate(period)
Assert { target, mint, owner, bound }
Bound  = const | linear(t0, v0, t1, v1) | ratio(of, num, den)

An assert is a lower bound on how much a token account's balance changes between Open and Close. A negative constant on the authority's own account is a spending limit, and is the only thing that permits a pull. Anything else is an amount that must arrive.

Replay Limit applies
once to a single execution
fill in total, across partial fills
rate to a budget that refills linearly over period seconds

Bounds are summed per account across every intent in the transaction, so one deposit cannot satisfy two intents and two intents can settle against each other.

Instructions

# Instruction Signer
0 CreateMandate authority store terms on chain instead of signing them
1 CloseMandate authority delete stored terms
2 BumpEpoch authority revoke every signed intent
3 RevokeSigned authority revoke one signed intent
20 Open executor authenticate, pull, snapshot
21 Close executor check, end the session
22 CloseState anyone return the rent of an expired or revoked intent's state

Open and Close must be top-level. The first Open reads the instructions sysvar and requires exactly one Close after it.

Replay state lives in one PDA per signed intent, created by the executor on first use. It can be closed only once the intent can never verify again, so it cannot be deleted and replayed.

Cost

LiteSVM, whole transaction:

CU
Stored intent, Open + Close 10k
Signed intent, Open + Close 81k to 95k
Signed swap with the solver's transfer 103k to 110k

The signed path pays for SHA-512 and Ed25519 in-program. The spread is PDA bump search.

Limits

  • Not audited. The invariants in SPEC.md §9 are not model-checked.
  • The program is upgradeable and is the delegate of every account that enables it.
  • A token account has one delegate. Any other Approve on it disables its intents.
  • Token accounts only. Native SOL has to be wrapped.
  • Enabling a token account is an SPL Approve, which is a transaction.
  • Token-2022 transfer hooks are not forwarded.
  • No wallet implements solana:signMandate. Signing falls back to an offchain message.

Build

cargo build-sbf --manifest-path program/Cargo.toml --features localnet
cargo test --workspace

npm install
npm run dev                  # examples/agents on a Surfpool mainnet fork
npm run dev:subscriptions    # examples/subscriptions

Layout

Path Holds
program The engine
packages/mandate-core Terms, validity rules, the canonical text and account layouts, shared by the program and every client
packages/sdk @solana/kit builders plus mandate-core compiled to WebAssembly
packages/wallet-standard solana:signMandate, the one feature a wallet adds
examples The agent demo and the subscription site
tests LiteSVM flows and the canonical-text tests

SPEC.md is the standard. The code calls an intent a mandate.