For the complete documentation index, see llms.txt. This page is also available as Markdown.

Account Delegation

Delegation is what makes a Solana account writable inside a NorthStar session. Without it, the ER can read the account (inherited from L1) but cannot mutate it. With it, the ER has exclusive write authority for the session's lifespan, and L1 cannot modify the account until the session closes.

The two-sided rule

Every delegated account has the same two properties for the session's duration:

On L1
On ER

Read

Yes

Yes

Write

No — locked by Portal

Yes

This is the core property the Portal program enforces. No L1 transaction signed by anyone — including the original owner — can mutate a delegated account. The ER is the single source of writes.

What can be delegated

Account type
Delegated?
Notes

PDAs your program owns

Yes

Pool PDA, vault PDA, custom state. Requires a delegate_to_portal hook in the owning program.

Keypair-owned signer accounts

Yes

E.g. an agent keypair that signs place_intent ixs inside the ER. Delegated via the Portal's Delegate instruction.

SPL token accounts

Yes

Each token account gets its own delegation.

SPL token mints

No

Mints are not delegated — inherited as read-only into the ER on first reference.

The owner keypair itself

No

Owner stays system-owned on L1 so it can sign close/undelegate ixs.

How delegation lands on chain

Three coordinated state changes per delegation:

  1. Account ownership — the account's owner field is reassigned from the original program (or SystemProgram) to the Portal program. This is what locks it on L1.

  2. A delegation record — a Portal-owned PDA at delegationRecordPda(portal, account) is created with (grid_id, owner_program, bump). This is the on-chain proof of delegation.

  3. A buffer account — a transient account holding rent for the buffer-dance pattern that survives the ownership transfer.

Undelegation

When the session closes (explicit CloseSession or TTL expiry), each delegated account undergoes the reverse:

  1. Final state from the ER is committed to the L1 account.

  2. Ownership is restored to the original program.

  3. The delegation record is closed; rent goes back to the owner.

If the session expires without explicit close, the Portal allows forced undelegation by the owner — see security model for the formal guarantees.

Common patterns

  • Pool + vault delegation — for an AMM running inside a session, both the pool PDA and the vault PDA delegate to the same grid_id. The agent keypair that signs place_intent also delegates so it can sign on the ER.

  • Token account delegation — every SPL token account that holds delegated funds also delegates. The mints stay on L1.

  • Per-user delegation (Phase 5) — a per-user session opens and delegates only that user's accounts; isolation between users is enforced at the session boundary.

Constraints

  • Programs need a delegate_to_portal hook. Portal's Delegate instruction only accepts accounts owned by the calling program. Third-party programs (Jupiter, Raydium) without this hook can't be delegated. Workaround: separate agent reasoning (in the ER) from external execution (on L1) — see the Mach Sandbox architecture.

  • Re-delegation requires undelegate first. An account already delegated to grid 1 cannot be re-delegated to grid 2 directly; close + reopen.

See also

Last updated