NotaRegistry
TheNotaRegistry contract (Solidity name NotareumNotaRegistry) is the on-chain source of truth for every .nota resource. It stores resource records, enforces unique resource IDs, maintains human-readable aliases, and records revocation state. Every other contract that reasons about resources (VerificationEngine, SlashingManager) consults this registry; every off-chain SDK consumer resolves resources through it.
Responsibilities
- Map
bytes32 resourceId→Resourcerecord. - Enforce uniqueness: one record per
(resourceType, chainId, identifier)triple. - Maintain alias →
resourceIdmappings. - Authorize updates and revocation to the resource owner.
- Emit the canonical events that indexers consume.
.nota payload lives off-chain; the registry only holds enough metadata to anchor trust decisions.
Resource record
notaHash rather than the full payload. Consumers pair the on-chain record with the off-chain .nota file and verify the hash matches. This keeps gas costs bounded regardless of payload size.
Resource ID computation
abi.encodePacked encoding is stable because uint8 and uint256 are fixed-width; bytes is appended without a length prefix (valid because it is the final argument).
Function surface
registerResource
- A record already exists for
(resourceType, chainId, identifier). - The alias is non-empty and already registered to a different resource.
- The caller has not paid the registration fee (see FeeManager).
ResourceRegistered(resourceId, owner, resourceType, chainId, notaHash) and, if aliased, AliasSet(resourceId, aliasHash).
updateResource
notaHash (pointer to the canonical .nota payload) and optionally sets a new alias. Preserves registeredAt, bumps updatedAt. Only the current owner can call. Emits ResourceUpdated and AliasSet.
revokeResource
ResourceRevoked(resourceId, reason).
getResource
owner == address(0); callers must check owner != 0 before trusting other fields.
resolveAlias
bytes32(0) if unbound.
ownerOf
transferOwnership(resourceId, newOwner) call (gated by the current owner).
Events
aliasName string is emitted unindexed for display; the indexed aliasHash supports efficient lookups.
Access control
NotaRegistry integrates with AccessManager for two administrative surfaces:
All resource-level writes (
registerResource, updateResource, revokeResource) are permissionless, gated only by ownership of the target resource and payment of the applicable fee.
Alias semantics
Aliases are human-readable pointers (“acme.eth”, “vitalik”, “meridian-collection”). The registry hashes the alias tobytes32 for storage, and stores a reverse aliasHash → resourceId mapping. Rules:
- First-come-first-served allocation.
- Case-folded and NFC-normalized at the contract boundary before hashing.
- An alias can be released (and reclaimed by others) only by the resource owner.
- Revoked resources release their alias automatically.
bob.eth as a Notareum alias, or use a Notareum-native alias (bob.nota) with no ENS registration.
Gas notes
registerResourceis dominated by two SSTOREs (the record and the alias entry). Without alias, expect ≈180k gas; with alias, ≈240k.updateResourcereuses the existing slots: ≈75k gas without alias change, ≈110k with alias change.revokeResourcetouches a single boolean and emits an event: ≈50k gas.getResourceis a view and free for off-chain callers.
identifier field is bytes, which costs one storage slot per 32 bytes plus a length slot. Typical EVM addresses (20 bytes) fit in one slot; long identifiers (IPFS CIDs, Cosmos bech32 strings) can span two slots.
SDK usage
Indexer-friendly queries
Subgraph entities derived from events:contracts/subgraph/notareum is the reference implementation consumed by the dApp and SDK explorer helpers.
Invariants
- For every resource,
resourceId == keccak256(abi.encodePacked(type, chainId, identifier)). - At most one resource per
(type, chainId, identifier)triple; subsequent writes replace-only after revocation. - Every alias maps to at most one non-revoked resource; revoked resources release alias on the next registration touching it.
registeredAtis immutable once set.

