Execution security for FAssets agents

Only the XRP payment FAssets asked for.

Signet reads the redemption obligation from Flare, derives the payment instead of accepting caller-supplied fields, checks XRPL for a prior payment, and returns execution evidence through FDC.

Network
Coston2 · live
FCC extension
66248 · registered
Execution
Simulated FCC
XRPL
Testnet · live
FDC
Proof on chain
Several redemption obligations converge into a single constrained gate, one exact XRP payment leaves it, and a proof path returns from the payment back to the gate.
How it works

One request in. One exact payment out.

Each step opens. Nothing here needs reading in order.

01 FAssets obligation The protocol states what is owed

Destination, amount, reference, destination tag and the payment window all come from FAssets protocol state, read on chain. Nobody types them.

02 Signet derives and observes The caller supplies a request id

authorizeRedemption(uint256,uint32) has no parameter for a payment field. Signet also observes the XRP ledger itself, across independent endpoints that must agree, before it will authorize anything.

03 Exact XRP payment One obligation, at most one payment

The signed transaction is persisted before submission, and the chain records at most one instruction dispatch per request and generation.

04 FDC proves the outcome Independently checkable on Flare

An XRPPayment attestation carries the memo and destination tag a generic payment proof would not, and FdcVerification accepted it on Coston2.

Why all four are load-bearing
  • Remove FAssets and there is no authoritative obligation. Signet degrades into enforcing a policy someone typed, which is a generic policy signer.
  • Remove FCC and a compromised host can sign arbitrary XRP.
  • Remove the XRPL observation and a payment already made by another party is invisible. That is incident 44928272, not a hypothetical.
  • Remove FDC and completion cannot be independently established on Flare. The operator's word becomes the evidence.
Try it · deterministic demo

Try to break it

A representative obligation, and every way a caller might try to bend it. This runs from a committed fixture and makes no network call, so it is labelled a deterministic demo rather than live. The reason codes are the real ones the policy returns.

FAssetsDeterministic demo

The request

This is all a caller supplies.

requestId
45430134
generation
0

Derived by the contract, from FAssets

Read-only. There is no parameter through which these could be supplied.

destination
rpa8bBa8GS1Zit6y9PcpQbahkqFahpWMyb
amount
9950000 drops
agent vault
0x165c62b4…e4e028
window
19895402 → 19895947
Signet policy

Attack it

Pick a move. The outcome is what the deployed contract and the policy actually do.

Impossible through the deployed API

The entry point is authorizeRedemption(uint256 requestId, uint32 generation). There is no destination parameter to change. A 256-run fuzz over caller addresses asserts one request id yields one payload for every caller.

Impossible through the deployed API

Same reason. The amount is read from the FAssets obligation by the contract, so a caller has nothing to alter.

Impossible through the deployed API

The reference is the obligation's identity on the ledger and is resolved on chain, not accepted from a caller.

Refused · S021_PAYMENT_ALREADY_OBSERVED

This is not hypothetical. It happened on live Coston2 with request 44928272, and it is why schema V2 requires the signing boundary's own XRP ledger observation.

Refused · S022_UNDERLYING_STATE_UNAVAILABLE

Refusing is the default. There is no input that authorizes without an observation, and too few agreeing sources counts as no observation.

Refused · S023_UNDERLYING_STATE_DISAGREEMENT

Endpoints that disagree fail closed, and this one is deliberately never retried automatically.

Refused · S024_UNDERLYING_OBSERVATION_STALE

An observation too old to rely on is refused rather than accepted with a warning.

Refused by the XRP ledger itself

The identical signed blob resubmitted returns tefPAST_SEQ: the account sequence is already consumed. Signet does not have to be trusted for this one.

Reason codes: S021_PAYMENT_ALREADY_OBSERVED, S022_UNDERLYING_STATE_UNAVAILABLE, S023_UNDERLYING_STATE_DISAGREEMENT, S024_UNDERLYING_OBSERVATION_STALE. What each one means.

Operator

For agent operators who keep their own underlying account

The job: fulfil redemption obligations without leaving an unrestricted XRPL spending key available to a compromised operator host. Before Signet, a hot signer can authorize arbitrary XRP. With Signet, a request id goes in and a protocol-derived obligation comes out as the only admissible payment.

Connect or continue read-only

A wallet is optional and never implies agent status.

Inspect a redemption

Read the canonical obligation from Coston2 by request id.

Observe XRPL

Independent endpoints must agree before a decision is possible.

Preview the decision

Authorization or a typed refusal, with the reason code.

Open operator
Live incident · Coston2

The tests passed. The ledger proved us wrong.

A live redemption was still ACTIVE on Flare after the assigned agent had already paid it on XRPL. Signet read ACTIVE as unpaid and sent the same obligation again.

Before

ACTIVE meant authorize

Three duplicate-payment guards, all watching Flare.

Ledger 19825006

The agent had paid

From its own underlying address, on XRPL.

Ledger 19825042

Signet paid again

36 ledgers later. No third party lost funds, which is luck about the test setup.

Now

S021_PAYMENT_ALREADY_OBSERVED

V2 requires the signing boundary's own XRPL observation, bound into the commitment.

Read the full incident
Proof

What holds up, and what does not

Six of 34 claims. Each one links to its evidence and to everything it does not prove.

Verified testXRP

The exact XRP payment executed

A transaction template produced by the Signet reference model was signed by a rotatable RegularKey and reached validated success on XRPL Testnet, unmodified, carrying the FAssets payment …

View evidence
Verified coston2xrpl-testnet

FDC proof accepted on chain

An XRPL Testnet payment made by Signet was attested by the Flare Data Connector end to end: the request was paid for and submitted to FdcHub, the voting round finalized, the Merkle proof …

View evidence
Verified xrpl-testnetcoston2

Anyone can re-check a receipt

An independent verifier runs from a fresh clone with no credentials and checks a Signet receipt against sources this repository does not control: it asks every XRPL endpoint and requires …

View evidence
All 34 claims
Current deployment boundary

What this deployment is not

Five FCC states, tracked separately, because collapsing any two of them is how a project ends up implying attestation it does not have.

Extension Registered
Extension 66248 is registered on the live Coston2 FlareTeeManager, and the registry routes it to Signet's own instruction sender.
Machine Unavailable
No TEE machine is registered. Registration was attempted on the live chain and reverted OwnerNotAllowed: MachineManager is gated on an owner allowlist Flare maintains.
Production No
Promotion needs a registered machine, which the owner allowlist blocks, and real attestation, which this deployment does not have. Tracked separately from machine registration on purpose.
Simulated execution Available
The decision runs through the FCC extension contract as an ordinary local process. Accepted for hackathon judging when disclosed as simulated, which it is, everywhere.
Hardware attestation No
Nothing is hardware-attested. A running node reported platform TEST_PLATFORM and attestation magic_pass, which the pinned deployment docs name as rejection conditions.

Check it yourself

No wallet, no funds, no Docker, no GCP, no secrets. One command from a fresh clone.

make judge
→ 13 PASS · 0 FAIL · 2 UNVERIFIABLE