Skip to Content
Dial v1 live 🎉

Cardano Adapter

Status: prototype, last checked 2026-11-02. Source: cardano-invoicing dev at bbbe39b. Not audited, no mainnet deployment. main is behind dev and still has the older validator in placeholder.ak.

The prototype is a Plutus V3 spending validator written in Aiken , with TypeScript scripts for the preview testnet. It is not yet connected to SPORE or SPAWN.

Destinations are script addresses

Cardano has no CREATE2 and no deployment step. A script address comes from the hash of the compiled validator with its parameters applied, so the address is known as soon as the parameters are. Funds can be sent to it right away, and the script code is supplied when the funds are spent.

This has a few consequences:

  • Changing any parameter gives a new address. The expiry is a parameter, so changing the deadline does too.
  • Recompiling with a different compiler or dependency can change the hash. A commitment has to pin the compiled code as well as the source.
  • The payment credential comes from the script, and an address can also carry a stake credential. Agree on the full address, not only the script hash.

Binding a chain-neutral SPAWN commitment to this address is not designed yet. One candidate is deriving the invoice_id parameter from the commitment.

Parameters

ParameterTypePurpose
payerAddressGets the refund on cancel
expiryIntPOSIX time in milliseconds when cancel opens
recipientAddressGets the funds on complete
adminVerificationKeyHashMay use the rescue path
policyPolicyIdPolicy of the invoice asset
valueIntRequired quantity
asset_nameByteArrayName of the invoice asset
invoice_idByteArrayIdentifier checked on complete

The scripts attach an empty inline datum, and the validator ignores it. All state lives in the parameters.

Spend paths

RedeemerAllowed whenResult
Complete { invoiceId }Id matches, the input holds exactly value, every output goes to recipient, and no other assets leavePays the recipient
CancelAfter expiry, every output goes to payer, and no other assets leaveRefunds the payer
Rescueadmin signs and no output contains the invoice assetRecovers UTxOs without the invoice asset

Any other script purpose fails.

Known limits

Read these before calling the contract escrow. They come from reading the validator and have not been confirmed by a transaction on testnet.

  • Complete has no condition beyond the id. It needs no signature from the payer, and the id is visible once the script is. Anyone can send locked funds to the recipient at any time. That can’t divert funds, but it doesn’t support milestone or approval-based release either.
  • A wrong amount waits for expiry. A UTxO that doesn’t hold exactly value can’t complete. Its only exit is cancel after expiry.
  • Mixed UTxOs can get stuck. A UTxO holding the invoice asset plus an asset under another policy fails complete and cancel, and rescue requires that the invoice asset not appear in any output. With an asset nobody can burn, such as a real stablecoin, that UTxO has no way out. Wallets and payment links must not bundle other assets into the locking output.
  • Rescue trusts the admin for any UTxO at the address without the invoice asset, including its ADA.
  • All outputs must go to one address. Change from whoever submits the transaction goes to the recipient or payer as well, which complicates relayers and third-party fee payment.

Assets and fees

Every UTxO has to carry minimum ADA alongside native assets. The tests lock 2 ADA next to the invoice asset. The scripts use a one-signature test token, not a stablecoin, so real stablecoin behavior is untested. Execution units from the unit tests are recorded in the repo, though real transaction costs have not been published.

Testing

ItemState
Unit tests10 of 10 recorded as passing in benchmarks.json, not re-run for this page
Preview scriptssetup, lock, complete and cancel exist. Rescue is not covered
Recorded preview transactionsNone in the repo
Indexer, confirmation policy, receiptsNot built. The scripts use Blockfrost

Standards

There is no ratified Cardano invoice standard that we know of. The closest proposal, CIP-0157 Cardano URIs: Enhanced Payments , is an open, unmerged pull request about payment URIs rather than invoice metadata. Any invoice format Dial proposes would be a standards-alignment goal, and Dial makes no claim to an official Cardano standard. See interoperability.

Next: Cardano invoicing guide.

Explore invoicing: Programmable Invoicing and invoicing on Cardano

Last updated on