- Born, live, and die entirely on the ER
- Owned by the calling program (inferred from CPI context)
- Funded by a sponsor account’s lamports
- Can be created, resized, and closed
The #[ephemeral_accounts] Macro
This proc-macro attribute goes on an Anchor Accounts struct. It recognizes two custom markers inside #[account(...)]:
| Marker | Purpose |
|---|---|
sponsor | Marks the account that pays rent for ephemeral accounts |
eph | Marks an account as ephemeral (ER-only) |
Validation Rules
- At least one
sponsoris required if anyephfields exist - Only one
sponsoris allowed per struct ephcannot be combined withinitorinit_if_needed(use the generated methods instead)- If the sponsor is a PDA (not a
Signer), it must haveseedsfor PDA signing
Generated Methods
For a field namedconversation, the macro generates:
| Method | Signature | Description |
|---|---|---|
create_ephemeral_conversation | (data_len: u32) -> Result<()> | Creates the ephemeral account |
init_if_needed_ephemeral_conversation | (data_len: u32) -> Result<()> | Creates only if data_len == 0 |
resize_ephemeral_conversation | (new_data_len: u32) -> Result<()> | Grows or shrinks the account |
close_ephemeral_conversation | () -> Result<()> | Closes account, refunds rent to sponsor |
Signing Requirements
- Sponsor: Must be a signer for all operations (create, resize, close)
- Ephemeral: Must be a signer only on create (prevents pubkey squatting). Not required for resize or close.
- For PDA accounts, the macro auto-derives signer seeds via
find_program_address
Rent Model
- Growing: sponsor pays additional rent to vault
- Shrinking: vault refunds excess rent to sponsor
- Close: all rent refunded from vault to sponsor
Create an Ephemeral Account
Resize an Ephemeral Account
Close an Ephemeral Account
Using a Wallet as Sponsor
ASigner can be used directly as the sponsor instead of a PDA:
TypeScript Client Usage
All ephemeral account operations are sent to the ER connection, not the base layer:Common Gotchas
eph fields must use AccountInfo, not Account
eph fields must use AccountInfo, not Account
eph fields must use AccountInfo<'info>, not Account<'info, T>. The account doesn’t exist yet at validation time, so Anchor cannot deserialize it.Manual serialization is required after create
Manual serialization is required after create
After calling
create_ephemeral_*, you must serialize your data struct into the raw account data yourself. The macro allocates space but does not write any data.Cannot combine eph with init
Cannot combine eph with init
The macro enforces this at compile time. Use the generated
create_ephemeral_* method instead of Anchor’s init constraint.Sponsor must be delegated first
Sponsor must be delegated first
The sponsor account needs lamports on the ER to pay ephemeral rent. It must be delegated before creating ephemeral accounts.
Top up the sponsor before delegation
Top up the sponsor before delegation
Transfer extra SOL to the sponsor account before delegating it, so it has enough lamports to fund ephemeral accounts on the ER.
vault and magic_program are auto-injected
vault and magic_program are auto-injected
You don’t need to declare them in your struct, but they appear in the IDL and must be passed from the client. Anchor resolves them automatically if named correctly.
Learn More
Ephemeral Accounts Demo
Full example program on GitHub
Delegation & Undelegation
How delegation and state synchronization work
Quickstart
Build your first program with Ephemeral Rollups

