Skip to main content

Verify an ASP root on-chain

What this lets you do

Confirm that a specific ASP-attested root is published to the on-chain ASPRegistry contract. Roots are the ASP's batched attestation of "these deposit labels are approved", and the on-chain registry is what makes those attestations binding to the protocol's spending rules.

Spending a note requires proving membership of its deposit label in the current latest ASP root: PoolVault.transact enforces associationSetRoot == ASPRegistry.latestASPRoot(), so a proof built against a stale root reverts with PoolVault_InvalidASPRoot. If you're skeptical of an ASP service's claims, verify their roots are actually on-chain before trusting them.

Constraints & limits

  • The root must be on-chain. An ASP saying "this root is canonical" off-chain doesn't bind anything. Only roots that have been published to ASPRegistry by a holder of POSTMAN_ROLE are valid.
  • Roots are append-only history, but only the head is spendable. The registry keeps an append-only list, yet transact only accepts the current latestASPRoot(). An older root is fine for auditing what was once published, but a spend proof must target the latest root. Walking the history tells you whether a root was ever published, not whether it is currently spendable.
  • Doesn't tell you which labels are in the root. The root is a Merkle root, so verifying inclusion of a specific label requires the merkle proof (which the ASP provides). This capability just checks "does this root exist on-chain at all."

What it unlocks next

  • Check a single note's attestation: once the root is on-chain, verify your specific deposit is in it.
  • Compliance-audit workflows: prove to a regulator that an ASP's claimed attestations are actually on-chain.

How to use it

const aspRoot = await fetch(`${aspUrl}/association-set/root?chainId=${chainId}&entrypoint=${entrypointAddress}`).then(r => r.json());
const claimedRoot = aspRoot.root;

const onChainLatest = await publicClient.readContract({
address: aspRegistryAddress,
abi: ASP_REGISTRY_ABI,
functionName: "latestASPRoot",
});

if (BigInt(claimedRoot) === onChainLatest) {
console.log("Claimed root matches the latest on-chain root.");
} else {
throw new Error("ASP's claimed root is not the latest; walk associationSets to verify.");
}

Behind the scenes

Contract methods ASPRegistry.latestASPRoot() (returns uint256) for the head root, and ASPRegistry.associationSets(uint256 _index) (returns AssociationSetData) to walk history. There is no isRootKnown method.
SDK service ASPRegistryInteractor.getLatestASPRoot() and getLatestAssociationSetData(). No isRootKnown wrapper exists. Build the membership check yourself by comparing against the head or walking the array.
Publishing flow The ASP service generates a root from approved labels, then POSTMAN_ROLE calls ASPRegistry.updateASPRoot(root, ipfsCID), and the root is appended to history