Ora ABI v0.1 — Compiler-facing appendix
This appendix defines rules needed to implement stable IDs, validation, and emission.
A1. Canonical JSON rules (for hashing)
To compute typeId (and optionally callable IDs):
- Serialize JSON with:
- UTF-8
- object keys sorted lexicographically
- no insignificant whitespace
- Exclude the
typeIdfield from the hashed payload. - Prefer numbers as strings when precision matters (e.g.
u256constants) to avoid JSON number limits.
Why “string numbers” for big ints?
JSON number handling differs across parsers; representing big values as strings avoids precision loss.
A2. Type graph validation
A conforming compiler/emitter MUST validate:
- All referenced
typeIdexist. - No recursive value types (cycle detection across
fields,components,elementType,base). enum.repr.typeIdresolves to an integer primitive.refinement.baseresolves to a concrete encodable base type.- Field names in
struct.fields[]are unique. - Tuple component ordering is stable (source order).
A3. Callable validation
idMUST be unique across all callables.- For
functionanderror:signatureMUST be canonical under the selected wire profile.wire.<profile>.selectorMUST match the profile’s selector derivation rules.
- For
event:inputs[].indexedmust be boolean; absence impliesfalse.
A3.1 Effects and mutability projection (evm-default)
Ora effects are the authoritative source. When emitting Solidity-compatible JSON ABI:
readsonly →stateMutability: "view"- no reads/writes/calls/value →
stateMutability: "pure" valuepresent →stateMutability: "payable"- otherwise →
stateMutability: "nonpayable"
If a compiler cannot prove purity, it should default to nonpayable.
A4. Callable ID scheme (recommended)
id = "c:" + canonical_signature
Where canonical_signature is:
name(type1,type2,...)forfunctionanderrorName(type1,type2,...)forevent
Alternative: content-hash callable nodes like types. Either is fine; v0.1 only requires stability + uniqueness.
A5. Canonical type spelling (profile-dependent)
Each wire profile defines how to spell types in signatures and how to map types[] to wire types.
Implementation recommendation:
- Keep a single internal “canonical type string” per profile.
- Enforce it both in:
callables[].signaturetypes[].wire[profile]
A6. Refinement predicate language (v0.1)
The predicate object MUST be a small AST with:
op: one of== != < <= > >= && || ! + - * / %(you can restrict in v0.1)- terminals:
{ "var": "x" }{ "const": "<string-int>" }
- optional:
{ "constBool": true/false }
Tooling requirement:
- A consumer MAY ignore
predicatefor execution, but SHOULD use it for validation/UI hints.
A7. Emission pipeline (recommended)
- Build internal type table.
- Emit all
typesfirst (deduplicate; assigntypeId). - Emit
callablesreferencing typeIds. - Add
wireProfiles. - (Optional) emit
ora.abi.schema.extras.jsonfor heavy annotations.
A8. Versioning rules
schemaVersionis semver-like but stringly typed for now.- v0.1 consumers:
- MUST reject unknown major versions.
- SHOULD ignore unknown fields (forward compatibility).
A9. JSON Schema (optional, recommended)
Provide a ora-abi-0.1.schema.json for:
- editor tooling
- CI validation
- third-party consumers
The compiler SHOULD be able to emit it or bundle it with releases.