warda_grant.sil · v4 · fingerprint b3e5eeefacf2021f

Covenant audit

Every verdict below comes from TxScriptEngine, the same script engine a Kaspa node validates a transaction with. Nothing here is inferred from reading the source.

38 of 39 published claims were exercised against the engine, 13 of them at a measured boundary. Nothing the guarantees forbid was accepted, and nothing they permit was refused.

118 transactions built and executed. This is a conformance result, not a safety one — what that distinction costs is two sections down.

This is not a statement that the covenant is secure. It reports the properties that were tested, where the bytecode and GUARANTEES.md disagree, and which claims no constructed transaction could reach. The last of those is a section, not an omission.
Cases
118
transactions executed
Claims covered
38 / 39
13 rules at a measured boundary
Violations
0
forbidden, yet accepted
Over-refusals
0
permitted, yet refused
Baseline
accepted
every flip depends on it

Where this audit is strong, and where it is thin

One bar per entrypoint, on one scale: a longer bar is more published claims. Boundary means a numeric pair was measured on the claim's own axis, one unit apart. Flip means only the refusal was executed, attributable because the case is a single field from an accepted baseline — a Merkle root has no number line, so its claims can only ever be flip grade. Neither is better; they are different evidence.

auth_spend
12 claims
delegate
7 claims
revoke
3 claims
reclaim
4 claims
reabsorb
8 claims
settle
5 claims · 1 uncovered
Boundary Flip Not covered

Why a rejection here means something

The engine collapses every failed require into one opaque VerifyError. It never says which rule rejected, so asserting that something was refused proves nothing on its own — a malformed signature script looks exactly like a working spending cap.

Every case is a single field changed from a baseline this run proved the engine accepts. A rejection can therefore only be caused by the field that moved. Numeric rules are exercised one unit either side of their boundary, so a rule that is present but in the wrong place shows up as a disagreement rather than as a pass.

Where each boundary actually is

The filled mark is the tightest value the engine accepted. The barred mark is the loosest it refused. Both were executed; neither is inferred.

amount, against the per-spend capper-spend cap · sompi
accepted
200,000,000
refused
200,000,001
1 sompi apart
amount, against an unreserved budgetbudget · sompi
accepted
150,000,000
refused
150,000,001
1 sompi apart
amount, with 1.5 KAS reservedbudget · sompi
accepted
150,000,000
refused
150,000,001
1 sompi apart
amount, against this epoch's allowanceepoch limit · sompi
accepted
150,000,000
refused
150,000,001
1 sompi apart
transaction locktimecltv · DAA
accepted
1,000,500
refused
1,000,499
1 DAA apart
claimed DAA, at the window's startwindow opens · DAA
accepted
1,000,000
refused
999,999
1 DAA apart
claimed DAA, at the window's endwindow closes · DAA
accepted
1,006,999
refused
1,007,000
1 DAA apart
fee taken from the grantcontinuation value · sompi
accepted
100,000
refused
100,001
1 sompi apart
child maxPerSpenddelegation attenuation · sompi
accepted
200,000,000
refused
200,000,001
1 sompi apart
child epochLimitdelegation attenuation · sompi
accepted
1,000,000,000
refused
1,000,000,001
1 sompi apart
child notBeforedelegation attenuation · DAA
accepted
1,000,000
refused
999,999
1 DAA apart
child expiresAtdelegation attenuation · DAA
accepted
1,007,000
refused
1,007,001
1 DAA apart
child delegationDepthdelegation attenuation · levels
accepted
1
refused
2
1 level apart
child budgetTotaldelegation budget · sompi
accepted
2,500,000,000
refused
2,500,000,001
1 sompi apart
revoke feerevoke conservation · sompi
accepted
100,000
refused
100,001
1 sompi apart
reclaim locktimereclaim term · DAA
accepted
1,007,000
refused
1,006,999
1 DAA apart
reclaim feereclaim conservation · sompi
accepted
100,000
refused
100,001
1 sompi apart
settlement feesettle conservation · sompi
accepted
100,000
refused
100,001
1 sompi apart

Findings

No violations — nothing the guarantees forbid was accepted. No over-refusals — nothing they permit was refused.

Every claim the guarantees make

This is the report's denominator: each enforcement claim GUARANTEES.md makes, and each require in the two exits, against what this run executed. A claim nothing covers is listed here as uncovered rather than left out of the count.

Boundary — a numeric pair was measured on the claim's own axis, one unit apart. Flip — only the refusal was executed, and it is attributable because the case is a single field away from an accepted baseline. A Merkle root has no number line, so its claims can only ever be flip grade.

EntryClaimGrade
auth_spendthe payee is on the allowlistflip
the amount is within the per-spend capboundary
total spending stays within budgetboundary
per-epoch spending stays within the epoch capboundary
epochs are consumed once, in orderflip
the claimed time has actually arrivedboundary
the window has openedboundary
the window has not closedboundary
authority is unchanged in the successorflip
the successor state is exactly rightflip
the continuation keeps the remainderboundary
the agent signed itflip
delegatethe child cannot exceed the parent's uncommitted budgetboundary
every attenuable field only narrowsboundary
the allowlist is inherited exactlyflip
the child starts cleanflip
the parent changes in exactly one wayflip
coin follows authorityflip
exactly one childflip
revokesigned by the revocation keyflip
the output is P2PK(principalKey)flip
the output keeps the balance, less maxFeeboundary
reclaimthe term is over — tx.daa >= expiresAtboundary
signed by the principal keyflip
the output is P2PK(principalKey)flip
the output keeps the balance, less maxFeeboundary
reabsorbthe child is a real input, and not the parent itselfflip
the pop is proven — the parent carried exactly this childflip
the child has no outstanding children of its ownflip
reserve is released by exactly the child's budgetflip
the child's spending becomes the parent'sflip
everything else about the parent stands stillflip
the parent's agent signed itflip
one continuation, and the coin from both inputs lands in itboundary
settlesigned by the revocation keyflip
the co-input is a grant of this templateflip
exactly two inputsflip
output 0 is that grant's single authorised continuationnot covered
the output keeps both inputs' coin, less maxFeeboundary

Every case

RuleTransactionGuaranteeEngine
baseline0.5 KAS to an allowlisted payee, in the window, within every cappermitsaccepted
per-spend capexactly the cappermitsaccepted
per-spend capone sompi under the cappermitsaccepted
per-spend capone sompi over the capforbidsrefused
per-spend capa hundred times the capforbidsrefused
per-spend capone sompipermitsaccepted
per-spend capnothing at allforbidsrefused
per-spend capa negative amountforbidsrefused
budgetexactly the uncommitted budgetpermitsaccepted
budgetone sompi past the uncommitted budgetforbidsrefused
budgetexactly what is left once reserve is countedpermitsaccepted
budgetone sompi into the reserveforbidsrefused
epoch limitexactly this epoch's remaining allowancepermitsaccepted
epoch limitone sompi past this epoch's allowanceforbidsrefused
epoch ratcheta later epoch, with its own fresh allowancepermitsaccepted
epoch ratchetthe recorded epoch, which is already exhaustedforbidsrefused
epoch ratchetan EARLIER epoch — the v1 allowance resetforbidsrefused
epoch ratchetthe first epoch, long pastforbidsrefused
cltvlocktime exactly the claimed DAApermitsaccepted
cltvlocktime one DAA below the claimforbidsrefused
window opensthe first DAA of the windowpermitsaccepted
window opensone DAA before the window opensforbidsrefused
window closesthe last DAA of the windowpermitsaccepted
window closesthe first DAA after expiryforbidsrefused
window closeswell past expiryforbidsrefused
authority immutablebudgetTotal raised by one in the successorforbidsrefused
authority immutablebudgetTotal lowered by one in the successorforbidsrefused
authority immutablemaxPerSpend raised by one in the successorforbidsrefused
authority immutablemaxPerSpend lowered by one in the successorforbidsrefused
authority immutableepochLimit raised by one in the successorforbidsrefused
authority immutableepochLimit lowered by one in the successorforbidsrefused
authority immutableepochLength raised by one in the successorforbidsrefused
authority immutableepochLength lowered by one in the successorforbidsrefused
authority immutablenotBefore raised by one in the successorforbidsrefused
authority immutablenotBefore lowered by one in the successorforbidsrefused
authority immutableexpiresAt raised by one in the successorforbidsrefused
authority immutableexpiresAt lowered by one in the successorforbidsrefused
authority immutabledelegationDepth raised by one in the successorforbidsrefused
authority immutabledelegationDepth lowered by one in the successorforbidsrefused
authority immutableagentKey swapped in the successorforbidsrefused
authority immutablerecipientsRoot swapped in the successorforbidsrefused
authority immutabletemplateId swapped in the successorforbidsrefused
successor accountingspend the money, record nothingforbidsrefused
successor accountingspentTotal short by oneforbidsrefused
successor accountingspentTotal over by oneforbidsrefused
successor accountingreserved raised by oneforbidsrefused
successor accountingreserved lowered by oneforbidsrefused
successor accountingepochSpent short by oneforbidsrefused
successor accountingepochSpent over by oneforbidsrefused
successor accountingepochIndex pushed forwardforbidsrefused
successor accountingepochIndex pushed backwardforbidsrefused
continuation valuea fee of exactly maxFeepermitsaccepted
continuation valuea fee one sompi over maxFeeforbidsrefused
continuation valuethe whole remainder taken as feeforbidsrefused
signaturesigned by a key that is not the agent'sforbidsrefused
allowlistmember 0xa1 of the allowlistpermitsaccepted
allowlistmember 0xa2 of the allowlistpermitsaccepted
allowlistmember 0xa3 of the allowlistpermitsaccepted
allowlistmember 0xa4 of the allowlistpermitsaccepted
allowlista payee absent from the allowlistforbidsrefused
allowlista proof naming an allowlisted payee, money going elsewhereforbidsrefused
delegation baselinea child narrower on every axispermitsaccepted
delegation attenuationchild maxPerSpend exactly equal to the parent'spermitsaccepted
delegation attenuationchild maxPerSpend one step wider than the parent'sforbidsrefused
delegation attenuationchild epochLimit exactly equal to the parent'spermitsaccepted
delegation attenuationchild epochLimit one step wider than the parent'sforbidsrefused
delegation attenuationchild notBefore exactly equal to the parent'spermitsaccepted
delegation attenuationchild notBefore one step wider than the parent'sforbidsrefused
delegation attenuationchild expiresAt exactly equal to the parent'spermitsaccepted
delegation attenuationchild expiresAt one step wider than the parent'sforbidsrefused
delegation attenuationchild delegationDepth one below the parent'spermitsaccepted
delegation attenuationchild delegationDepth exactly equal to the parent'sforbidsrefused
delegation starta child born already having spent one sompiforbidsrefused
delegation reserveno reserve takenforbidsrefused
delegation reservereserve one KAS shortforbidsrefused
delegation reservereserve one KAS overforbidsrefused
delegation budgeta child taking exactly the parent's uncommitted budgetpermitsaccepted
delegation budgetone sompi more than the parent has leftforbidsrefused
delegation allowlista child claiming a different allowlist with an empty witnessforbidsrefused
delegation cointhe child's coin exactly its budgetpermitsaccepted
delegation cointhe child's coin one sompi short of its budgetforbidsrefused
delegation coinone sompi overforbidsrefused
delegation fanoutone childpermitsaccepted
delegation fanouttwo children in one delegationforbidsrefused
revoke signaturethe revocation keypermitsaccepted
revoke signaturethe agent's key, not the revocation keyforbidsrefused
revoke signaturethe principal's key, not the revocation keyforbidsrefused
revoke destinationpaying anybody but the principalforbidsrefused
revoke conservationa fee of exactly maxFeepermitsaccepted
revoke conservationone sompi more than maxFee burnedforbidsrefused
reclaim signaturethe principal's keypermitsaccepted
reclaim signaturethe agent's key, not the principal'sforbidsrefused
reclaim signaturethe revocation key, not the principal'sforbidsrefused
reclaim destinationsweeping to anybody but the principalforbidsrefused
reclaim termthe first DAA the term allowspermitsaccepted
reclaim termone DAA before the term is overforbidsrefused
reclaim conservationa fee of exactly maxFeepermitsaccepted
reclaim conservationone sompi more than maxFee burnedforbidsrefused
settle baselinea child settled home, its spending charged and its reserve releasedpermitsaccepted
settle child indexthe child claimed at the parent's own indexforbidsrefused
settle child indexthe child claimed at an input that does not existforbidsrefused
settle child indexthe child claimed at a negative indexforbidsrefused
settle popa previous reserve root the parent never carriedforbidsrefused
settle leaves firsta child that still has coin committed to a grandchildforbidsrefused
settle reservethe reserve not releasedforbidsrefused
settle reservemore reserve released than was heldforbidsrefused
settle chargethe child's spending never charged to the parentforbidsrefused
settle chargeone sompi less charged than the child spentforbidsrefused
settle parent stillthe parent raising its own per-payment capforbidsrefused
settle parent stillthe parent extending its own expiryforbidsrefused
settle parent stillthe parent inflating its own budgetforbidsrefused
settle parent signaturethe parent's half signed by the revocation keyforbidsrefused
settle child signaturethe revocation keypermitsaccepted
settle child signaturethe child's half signed by the agent's keyforbidsrefused
settle child signaturethe child's half signed by the principal's keyforbidsrefused
settle co-inputthe revocation key settling a child against its own dustforbidsrefused
settle conservationa fee of exactly maxFee across both inputspermitsaccepted
settle conservationone sompi more than maxFeeforbidsrefused

The check that reads no specification

Everything above compares the bytecode to a written claim, which is why it cannot notice a rule that should exist and does not. A second pass asks a question nobody had to write down first: it generates spend attempts structurally, discards everything the engine refused, and asserts one property of what is left — an accepted spend must not leave the agent able to do more than it could before, minus what it just paid.

CovenantGeneratedEngine acceptedAuthority grew
warda_grant.sil v4, as written768610
the same, with the epoch ratchet removed768698

The second row is the self-check, and it is not decoration. An oracle that has never fired is indistinguishable from one that cannot, so the run ends by deleting require(currentEpoch >= prevState.epochIndex) from the covenant — and requiring the same oracle to catch it. It does: an agent whose epoch allowance is exhausted claims an earlier epoch, and the whole allowance comes back.

That is the one line in this report that says a clean run above is worth something. The oracle can fire, it fires on a covenant this one used to be, and it is silent on the covenant as written.

What this run did not test

What a clean run does not mean

This instrument checks the bytecode against a written claim. It cannot notice a rule that should exist and does not, because the document it takes its claims from is the same document that would have omitted it.

That is not a hypothetical. Of the five vulnerabilities this covenant has had, none would have been caught by the claims suite. The epoch cap that limited nothing and the missing expiry check were both absent from the guarantees at the time. The template-id defect is not engine-visible. The fifth was in settle, The fifth is now covered — but only because it has already been found: the claim it violates was written as part of its fix, and a suite whose oracle is the documentation learns about a hole the day somebody else closes it. Every one of the five was found the same way, and it was not this way: a person asked what an adversary supplies at each input, built it, and watched the engine accept it.

The section above it is the answer to that, and the only one this tool has: an oracle that consults no document, and a covenant with a known hole in it to prove the oracle can fire.