Rules & judging
Everything below is the contract under which findings are accepted, ranked, and paid out. Severity is decided per the Impact × Likelihood matrix in the Severity section above.
Participation
- The number of contestants is capped at 50; CODESPECT selects the most relevant applicants. The selection criteria are noted on the registration form.
- KYC is mandatory for anyone who wins a bounty. It is arranged after the contest closes and only for winners.
- Non-disclosure: contestants must not disclose any project-related information publicly during the contest — this includes the protocol name, the codebase, the initial audit report shared at kickoff, contestants' findings, judging discussions, and any other material received through the contest channels. Public disclosure of any of the above results in a ban from this contest and from any future CODESPECT engagements.
- Findings are filed as GitHub issues in the per-contestant private repo provisioned at the start of the contest.
- Post-audit format: SpecSiege runs after CODESPECT has completed its initial audit. Contestants review the latest state of the codebase — the version the protocol team produced after applying fixes for the initial report.
- Initial audit report: at the start of the contest, CODESPECT shares its initial audit report with selected researchers. Findings already reported there — whether acknowledged and fixed by the protocol team, or explicitly marked won't-fix — are out of scope. The initial report sets the floor of what is considered already known.
- 0xSynthrax is the lead judge. Decisions on severity, duplicates, and validity are final.
- Communication channels: contestants interact only with the CODESPECT team and the lead judge 0xSynthrax. There is no direct contact with the protocol team. The contest Discord hosts a dedicated channel for contest-wide discussion (scope clarifications, general questions) plus a separate Lead Judge / Auditor thread inside that channel for finding-specific conversations (severity questions, duplicate appeals, ruling feedback).
- Output: a stand-alone contest report, published alongside the manual audit reports CODESPECT delivered to the protocol. Accepted contest findings are also included in CODESPECT's final audit report for the protocol, attributed inline as "Found by <handle> during the double-check contest."
Hierarchy of truth
When two sources disagree on whether a behavior is intended, judges resolve the conflict in this order (top wins):
- Public clarifications posted by the CODESPECT team or the lead judge 0xSynthrax in the dedicated contest Discord channel, up to 24 hours before the contest closes. These override the README and every later source when they disagree. The protocol team does not communicate with contestants directly.
- The README in the scope repository — source for intended behavior, invariants, and which roles are trusted, except where a public clarification supersedes it.
- Inline code comments — may be deemed outdated when they contradict a public clarification, the README, or the current implementation.
- These judging rules — fallback when none of the above settle the question.
When the README declares a property the contract must hold (e.g. an accounting invariant), breaking it is at least a Medium severity finding even without a fund-loss path, provided the breakage does not conflict with common sense.
What every report must show
Every report must demonstrate three things:
Root cause
The primary factor that produces the unwanted outcome. "The function reverts under condition X because Y" — not just "the function reverts."
Attack path
A concrete sequence of steps a malicious actor takes, or a passive failure mode that occurs under realistic conditions. Hand-waving "an attacker could" is not enough.
Impact
Who loses what, with rough magnitude. The Impact tier (High / Medium / Low) is determined from the magnitude per the matrix in the Severity section.
Final severity is Impact × Likelihood per the matrix. A High-impact bug that requires improbable preconditions can land at Medium; a Low-impact griefing vector that anyone can trigger can still be a Low finding rather than out of scope.
A proof-of-concept is strongly recommended for non-obvious bugs, including precision-loss issues, reentrancy variants, gas-induced reverts, and findings whose validity depends on subtle input constraints. Reports without a PoC are not automatically invalid, but a PoC dramatically reduces the chance of a downgrade or duplicate dispute. In some cases, the judge may also request a PoC to better assess or validate the finding.
Duplicates
Two findings are duplicates when they share the same root cause and at least Medium impact via a valid attack path. The bounty for that finding is split equally among duplicates; the highest severity within the group sets the payout tier.
- The same logic mistake repeated across multiple call sites (e.g. an unsafe numeric cast in three functions).
- The same conceptual flaw exposed through multiple entry points (e.g. an unchecked role assumption broken via several public functions).
Reentrancy variants are treated as distinct findings, not duplicates of each other: same-function, cross-function, cross-contract, read-only, and cross-chain reentrancy each count separately.
Escalation & feedback
There is no formal escalation period for this contest — the timeline is too tight to run one. Live judging fills the gap instead:
- The lead judge 0xSynthrax participates during the contest, not only after it closes.
- Ping 0xSynthrax in the dedicated Lead Judge / Auditor thread for additional context on a ruling, or to request a re-evaluation of a severity call or a duplicate decision.
- The judge will respond inside the contest window where time allows; this is best-effort, not guaranteed turnaround.
- Once the contest closes, decisions are final — there are no post-close appeals.
Out of scope
The following are not eligible findings on their own, regardless of where they appear in the code. Items here cannot be promoted to Critical / High / Medium / Low by adding more steps — they are out of scope:
- Front-running, sandwich attacks, and other MEV vectors that depend on observing pending transactions. EBSI is a permissioned chain — there is no public mempool, so this entire class of attacks predicated on mempool observation or transaction reordering is not applicable here. Findings whose attack path requires a public mempool are invalid for this contest.
- Gas optimizations.
- Event log values being wrong or missing, unless they directly feed a fund-affecting code path.
- Zero-address checks and other input validation whose only purpose is to prevent user mistakes.
- Admin call ordering (e.g. forgetting to call setX() before withdrawX()).
- Admins making bad parameter choices that harm users — admins are trusted by default.
- Centralization or admin-key risk in roles that the README marks as trusted.
- Front-running an initializer when the deployment is reversible and no permanent damage occurs.
- User-experience issues with no fund-loss path.
- A user blacklisting themselves on a token whose blacklist they consented to.
- Accidental token transfers to a contract by user error.
- Airdrops or external rewards not part of the protocol design.
- View-function return values being wrong, unless the function is consumed inside a fund-affecting code path.
- Chain re-orgs, sequencer downtime, RPC outages, and other network-level events — unless the protocol explicitly guarantees behavior under them.
- Items already in CODESPECT's initial audit report — whether acknowledged and fixed by the protocol team or explicitly marked won't-fix. The initial report is shared with all selected researchers at the start of the contest; re-discovering an item it already covers is not a finding.
- Future-integration issues for code not yet referenced in the README or scope.
- Non-standard token behaviors (rebasing, fee-on-transfer, double-entry-point) not called out in the README.
This contest has no Informational tier. Findings that would be Informational under the broader CODESPECT methodology are out of scope here.
Edge cases
Admin actions
Admins are trusted by default. An admin taking a bad-for-users action is not a finding. However, an admin unknowingly putting the protocol in a vulnerable state through a documented function — without doing anything overtly wrong themselves — is a valid finding.
Trusted roles
Internal protocol roles are trusted by default. A role becomes untrusted only if (a) the README explicitly says so, or (b) the report shows how an unauthorized user can obtain that role.
Library code
Vulnerabilities in libraries (in-repo or vendored) are valid findings only when they manifest through an in-scope contract.
Repeatable small attacks
A small loss per attack (e.g. 0.01% of TVL) that can be replayed without bound is scored on the cumulative loss it can inflict in the contest window, not the per-call loss.
Acknowledged risks
When the README explicitly acknowledges a risk and accepts it, reports of that exact behavior are not valid. Reports of a different consequence sharing the same root cause may still be valid.
Slippage logic vs. MEV
Missing or incorrect slippage protection in contract logic is still in scope — it is a code-level concern, independent of how transactions are propagated. However, attack scenarios that require observing pending transactions to execute (front-running, sandwich attacks, generalized MEV) are not applicable on EBSI’s permissioned chain and are invalid as findings; see Out of scope above.