
Code on an escrow
4 minDifficulty Checked 2026-11-10- A Smart Escrow is a normal escrow with a small WebAssembly program attached.
- The program runs only when someone tries to finish that escrow.
- It is a draft, XLS-100. It is not live on the XRP Ledger.
An escrow is a locked box on the ledger. Someone puts funds in. The box opens for the receiver when a rule is met.
Today the ledger knows two kinds of rule:
- A clock. The box can open after a set time.
- A password. The box opens for whoever presents the matching secret.
That covers a lot, but not everything. What if the box should open only when a named notary says so? Or only when the receiver holds a certain credential?
Smart Escrows are a proposal to allow a third kind of rule: a small program. The program sits on the escrow. When someone tries to open the box, the ledger runs the program. The program answers one question, yes or no: can this escrow finish?
The program cannot do anything else. It cannot move funds somewhere new. It cannot send transactions. It can only say yes or no for the one escrow it lives on.
The draft lists uses such as:
- A notary escrow that only one account can release.
- A hold that releases once the receiver has a credential.
- Token vesting on milestones.
- A release that depends on a price from an oracle.
All of this is a draft. It is not on the XRP Ledger today, and validators are not voting on it. The last lesson of this module covers its status.
XLS-100 is a Draft in the Amendment category, created on 2025-02-25. It would need an amendment that the draft names SmartEscrow.
Two new fields on Escrow and EscrowCreate:
| Field | Type | Purpose |
|---|---|---|
Bytecode | Blob | Compiled WebAssembly (WASM) that must approve the finish |
Data | Blob | Extra data the code can read and update |
The entry point. The WASM must export a function named escrow_finish. It takes no parameters and returns a signed 32-bit integer. A value greater than 0 means the escrow can finish. Zero or a negative value means it cannot.
The draft's notary example, in Rust:
pub extern "C" fn escrow_finish() -> i32 {
let escrow_finish = escrow_finish::get_current_escrow_finish();
let tx_account = match escrow_finish.get_account() {
Ok(v) => v,
Err(e) => { return e.code(); }
};
(tx_account.0 == NOTARY_ACCOUNT) as i32
}It returns 1 only when the sender of the EscrowFinish is the notary.
Combining conditions. An EscrowCreate must have at least one of CancelAfter, FinishAfter or Bytecode. A Condition may be added. When several finish conditions are present, all must be true. The draft adds four allowed combinations, each with Bytecode and CancelAfter:
- Function with expiration.
- Timed function with expiration.
- Conditional function with expiration.
- Timed conditional function with expiration.
CancelAfter is mandatory when Bytecode is present. Without it, EscrowCreate fails with temBAD_EXPIRATION. The reason given: funds must not be stuck forever if the code has a bug.
Finishing. EscrowFinish gains a Gas field, required when the escrow has Bytecode. If the code does not approve, the run traps, or the gas runs out, the result is tecBYTECODE_REJECTED. Metadata would record GasUsed and VMReturnCode.
The draft describes Smart Escrows as an extension of crypto-conditions and a first step toward wider XRPL programmability.
Related: Escrow and Token Escrow, Limits, gas and data.
- XLS-100 Smart EscrowsRead 2026-11-10
- Known AmendmentsRead 2026-11-10
