Depth of Attestcoin Protocol use is the one scoring criterion the organisers have published. So this is the full surface, with a reason next to every line that is not in use. An unused surface without a reason is an oversight, not a decision.
Everything below was confirmed by calling CC3 testnet directly, or by reading a contract's own ABI off Blockscout. That is deliberate rather than fussy: the docs page that lists precompiles omits BlockProver and ChainInfo entirely, and research into this that leaned on repository paths turned out to be citing files nobody had opened. Where a figure below has no call behind it, it is not here.
A note on how the set was probed, because the obvious way is wrong here.
eth_getCode returns 0x for every address in this document, including the
three this project calls in production. These are Substrate precompiles, not
deployed contracts, and they have no EVM bytecode to return. An earlier version
of this page said the six carry code, which was a claim eth_getCode cannot
support and which the chain contradicts. What separates them is behaviour: the
six answer an unknown selector with revert Unknown selector, while 0x0FD5
and 0x13BB return empty for any input at all, which is what the EVM answers
for an address where nothing is registered. So the set does not simply continue,
but the evidence is the refusal, not the code. Whether anything else is
registered at an address not probed here is not claimed either way.
| Surface | Address | How it is used |
|---|---|---|
| BlockProver | 0x0FD2 |
Both forms of verify in view: one transaction for a single pledge, an array against one shared continuity proof for a batch. Plus calculateTxIndex for the replay nullifier |
| ChainInfo | 0x0fD3 |
get_latest_attestation_height_and_hash on chain for the finality guard, get_supported_chains off chain to resolve a chain key from a chain id |
| AttestorStash | 0x0FD4 |
getAttestorsCount and getMinBondRequirement read inside the transaction that accepts a proof. Both numbers are stored with the lien and with every refusal, and a chain whose set has fallen below a stated floor stops producing records |
| EvmV1Decoder | 0x731c345d79Fb8BbDC541f9DF3b6317585F849F9f |
Receipt and log decoding, as a linked library rather than a copy |
@gluwa/usc-sdk 0.18.0 |
ProofBuilder.getProof in the relay |
|
| Attested source chains | keys 1 and 3 | Sepolia and Ethereum mainnet, which get_supported_chains reports as the whole list |
The last row is worth stating precisely, because it sounds smaller than it is. Creditcoin attests exactly two chains on CC3 testnet and one on mainnet. Both of the two are read here, six proofs against each. This is not a subset.
One thing about the batch form that is in no document, because it was found by calling the precompile rather than by reading. The shared continuity proof is anchored at the lowest header the prover built it from, so a batch that does not contain a transaction at that header is refused outright with a continuity mismatch. And the batch does check every member: a corrupted transaction, a forged merkle root or a misstated height inside an otherwise honest batch each revert it. Both were established by deliberately breaking a real batch against CC3, which is the only way to know that a verification verifies.
Two requirements the documentation puts in a danger block, both met:
- BlockProver does not check whether the source transaction succeeded. The
registry checks
receiptStatus == 1itself, andtest_revertedSourceTransactionIsRejectedintest/SingletonRegistry.t.solfails the build if that check is removed. - Replay protection. A nullifier per operation domain, keyed by chain, height, transaction index and log index, so the same proof cannot be spent twice and reporting a collision does not consume the proof that would register the same lien legitimately later.
| Surface | Address | Why not |
|---|---|---|
| SubstrateTransfer | 0x0FD1 |
Moves CTC from the EVM ledger to a Substrate account, one way. A register holds no funds and moves none. |
| Sr25519Verifier | 0x13B9 |
Substrate-keyed signatures. Nothing here is signed by a borrower; the evidence is an inclusion proof. |
| Ed25519Verifier | 0x13BA |
Same. |
| CTC staking, nomination pools | Not reachable from Solidity at all. There is no staking precompile; this is a property of the chain, not a choice. | |
| The legacy Creditcoin loan pallets | Not in the CC3 runtime. They run on a separate Substrate chain with no EVM and no attestation registration, so no contract can reach them. | |
| Attestcoin writability, the outbound direction | Not shipped. The docs say it is in third party testing. A register only needs to read. | |
| Ecosystem tooling: the DEX, the bridge, the wallet | This hackathon has no sponsor bounties. Touching any of them would be decoration, and a register that swapped tokens would be a worse register. | |
QueryBuilder byte offsets |
An alternative to structural decoding, cheaper in gas. The deployed decoder already does the job, and using both would be two ways of reading the same bytes. | |
PrecompileBlockProver, PrecompileChainInfoProvider |
Typed off-chain wrappers. Verification happens inside the contract here, which is the stronger position; verifying off chain and trusting the result is the thing this project exists to avoid. |
A cross chain record inherits the security of the set that attested the block it was read from. That set is not a constant, which is a measurement here and not a turn of phrase: read at historical heights, Sepolia went 0 to 1 to 6 to 7 between 2026-05-01 and 2026-07-09, and Ethereum went 0 to 1 to 3 to 4 between 2026-05-01 and 2026-07-16. Creditcoin bonds seven and four respectively as this is written, a hundred CTC each, and any contract on the chain can read both.
Ethereum also appeared on get_supported_chains before a single attestor was
bonded for it. Being on the supported list is not the same as being backed, and
this project uses that list everywhere to decide what is readable.
One thing this records precisely, because it was got wrong in the first writing
of it. The number kept with a lien is the set bonded when the lien was filed,
not the set that stood behind the original attestation of the source block. Those
differ, and getAttestorsCount takes no height, so the second is not reachable
from inside a transaction. Caveat 11 in CAVEATS.md carries the
worked case and the way to read the other number from outside.
Nothing that consumes an attestation writes them down. A record made while seven
attestors stood behind it and a record made while two did are stored identically
by every bridge, oracle and message layer, so the question "how much was standing
behind this when it was written" has no answer after the fact. The registry
answers it: Record.security and Collision.security carry the count, the bond
and the attested tip that were true at the moment the proof was accepted, and
AttestationWitnessed puts the same three numbers in the log, which survives the
lien being released and its record deleted.
The floor is the enforcing half. setMinAttestors states the smallest set a
chain may have before this registry will create a record from anything read out
of it, and zero is refused for the same reason a confirmation depth of zero is.
Three is used on both live chains: below three, a single attestor is a majority
of the set. The floor gates entry only. A settlement or a release still goes
through under a collapsed set, because trapping a borrower's asset over an
attestor rotation they had no part in would be a worse failure than the one the
floor exists to prevent.
An unattested chain key answers zero attestors rather than reverting, verified live, so the floor doubles as the refusal to read a chain Creditcoin does not attest at all.
is_height_attested. It exists and it works. It is also, on both live
chains, exactly the comparison the finality guard already makes. Measured at CC3
block 5343128 against chain key 1, attested tip 11529470: true at 11529469 and
at 11529470, false at 11529471 and above, and true at every height sampled below
it down to zero, with no gaps. get_attestation_genesis_height returns 0 for
both chains, so there is no lower bound to fall outside of either. Calling it
would spend a staticcall to be told what height <= tip already says. It is
listed here rather than in the table above because the reason it is unused is a
measurement, not an assumption.
There is no get_attestation_bounds. An earlier draft of this document named
one; the selector returns "Unknown selector" on CC3 testnet, and the claim has
been removed rather than softened.
get_latest_checkpoint_height_and_hash. A separate marker that trails the
attested tip: at CC3 block 5343190, chain key 1 reported an attestation at
11529540 and a checkpoint at 11529400, chain key 3 an attestation at 25796830
and a checkpoint at 25796700. Both checkpoint results carry isAttestation
false. The registry gates on the attested tip because a height it accepts has to
be one the attestor set stood behind, and that is the flag the checkpoint result
clears.