> ## Documentation Index
> Fetch the complete documentation index at: https://docs.notareum.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Nota registry

# NotaRegistry

The `NotaRegistry` 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` → `Resource` record.
* Enforce uniqueness: one record per `(resourceType, chainId, identifier)` triple.
* Maintain alias → `resourceId` mappings.
* Authorize updates and revocation to the resource owner.
* Emit the canonical events that indexers consume.

The registry stores no signatures or attestation content. The signed `.nota` payload lives off-chain; the registry only holds enough metadata to anchor trust decisions.

## Resource record

```solidity theme={"system"}
enum ResourceType {
    Address,          // 0: wallet address
    Contract,         // 1: deployed contract
    Transaction,      // 2: tx hash
    NftCollection,    // 3: NFT contract
    Nft,              // 4: specific (contract, tokenId)
    IpfsCid,          // 5: IPFS content identifier
    Attestation       // 6: generic signed attestation
}

struct Resource {
    address owner;              // on-chain owner (has update/revoke rights)
    bytes32 notaHash;           // keccak256 of canonical .nota payload
    uint8 resourceType;
    uint256 chainId;
    bytes identifier;           // UTF-8 bytes of resource identifier
    bytes32 alias_;             // hashed alias (0 if none)
    uint64 registeredAt;
    uint64 updatedAt;
    bool isRevoked;
}
```

The registry intentionally stores `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

```solidity theme={"system"}
function computeResourceId(
    uint8 resourceType,
    uint256 chainId,
    bytes calldata identifier
) public pure returns (bytes32) {
    return keccak256(abi.encodePacked(resourceType, chainId, identifier));
}
```

This exact formula is replicated byte-for-byte in all three SDKs. The `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`

```solidity theme={"system"}
function registerResource(
    uint8 resourceType,
    uint256 chainId,
    bytes calldata identifier,
    bytes32 notaHash,
    string calldata aliasName
) external payable returns (bytes32 resourceId);
```

Creates a new resource record. Reverts if:

* 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](fee-manager.md)).

Emits `ResourceRegistered(resourceId, owner, resourceType, chainId, notaHash)` and, if aliased, `AliasSet(resourceId, aliasHash)`.

### `updateResource`

```solidity theme={"system"}
function updateResource(
    bytes32 resourceId,
    bytes32 newNotaHash,
    string calldata newAlias
) external payable;
```

Replaces the `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`

```solidity theme={"system"}
function revokeResource(bytes32 resourceId, string calldata reason) external;
```

Marks a resource as revoked. Irreversible at the record level; revocation can only be reversed by registering a fresh resource (which computes a new ID only if the identifier changes). Reason string is emitted on-chain for indexers. Emits `ResourceRevoked(resourceId, reason)`.

### `getResource`

```solidity theme={"system"}
function getResource(bytes32 resourceId)
    external
    view
    returns (
        address owner,
        bytes32 notaHash,
        uint8 resourceType,
        uint256 chainId,
        bytes memory identifier,
        bytes32 aliasHash,
        uint64 registeredAt,
        uint64 updatedAt,
        bool isRevoked
    );
```

Returns the full record. For non-existent IDs, returns the zero record with `owner == address(0)`; callers must check `owner != 0` before trusting other fields.

### `resolveAlias`

```solidity theme={"system"}
function resolveAlias(string calldata aliasName) external view returns (bytes32 resourceId);
```

Returns the resource ID bound to the alias, or `bytes32(0)` if unbound.

### `ownerOf`

```solidity theme={"system"}
function ownerOf(bytes32 resourceId) external view returns (address);
```

Returns the current owner. Zero for non-existent resources. Ownership can be transferred via a dedicated `transferOwnership(resourceId, newOwner)` call (gated by the current owner).

## Events

```solidity theme={"system"}
event ResourceRegistered(
    bytes32 indexed resourceId,
    address indexed owner,
    uint8 resourceType,
    uint256 chainId,
    bytes32 notaHash
);
event ResourceUpdated(
    bytes32 indexed resourceId,
    bytes32 newNotaHash,
    uint64 updatedAt
);
event ResourceRevoked(
    bytes32 indexed resourceId,
    address indexed by,
    string reason
);
event AliasSet(
    bytes32 indexed resourceId,
    bytes32 indexed aliasHash,
    string aliasName
);
```

The `aliasName` string is emitted unindexed for display; the indexed `aliasHash` supports efficient lookups.

## Access control

`NotaRegistry` integrates with `AccessManager` for two administrative surfaces:

| Action                 | Role             | Delay         |
| ---------------------- | ---------------- | ------------- |
| Pause registrations    | `PROTOCOL_ADMIN` | 0 (emergency) |
| Unpause                | `PROTOCOL_ADMIN` | 24h           |
| Set FeeManager         | `PROTOCOL_ADMIN` | 7 days        |
| Upgrade implementation | `UPGRADER`       | 7 days        |

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 to `bytes32` for storage, and stores a reverse `aliasHash → resourceId` mapping. Rules:

1. First-come-first-served allocation.
2. Case-folded and NFC-normalized at the contract boundary before hashing.
3. An alias can be released (and reclaimed by others) only by the resource owner.
4. Revoked resources release their alias automatically.

ENS interoperability is intentional but not required. You can register `bob.eth` as a Notareum alias, or use a Notareum-native alias (`bob.nota`) with no ENS registration.

## Gas notes

* `registerResource` is dominated by two SSTOREs (the record and the alias entry). Without alias, expect ≈180k gas; with alias, ≈240k.
* `updateResource` reuses the existing slots: ≈75k gas without alias change, ≈110k with alias change.
* `revokeResource` touches a single boolean and emits an event: ≈50k gas.
* `getResource` is a view and free for off-chain callers.

The `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

```typescript theme={"system"}
import { Notareum } from "@notareum/sdk";

const ntm = Notareum({ provider, signer, contracts });

// Deterministic ID
const id = ntm.registry.computeResourceId({
  type: "address",
  chainId: 1,
  identifier: "0xabc...",
});

// On-chain register (signed .nota hashed off-chain first)
const nota = await ntm.nota.create({ /* ... */ }).sign(signer);
const tx = await ntm.registry.registerResource(nota, { alias: "bob.eth" });
await tx.wait();

// Resolve an alias
const resId = await ntm.registry.resolveAlias("bob.eth");
const record = await ntm.registry.getResource(resId);
```

## Indexer-friendly queries

Subgraph entities derived from events:

```graphql theme={"system"}
type Resource @entity {
  id: ID!                 # resourceId
  owner: Bytes!
  notaHash: Bytes!
  resourceType: Int!
  chainId: BigInt!
  identifier: Bytes!
  alias: String
  isRevoked: Boolean!
  registeredAt: BigInt!
  updatedAt: BigInt!
  verification: Verification  @derivedFrom(field: "resource")
}
```

The subgraph deployment in `contracts/subgraph/notareum` is the reference implementation consumed by the dApp and SDK explorer helpers.

## Invariants

1. For every resource, `resourceId == keccak256(abi.encodePacked(type, chainId, identifier))`.
2. At most one resource per `(type, chainId, identifier)` triple; subsequent writes replace-only after revocation.
3. Every alias maps to at most one non-revoked resource; revoked resources release alias on the next registration touching it.
4. `registeredAt` is immutable once set.

## Related pages

* [Smart Contracts Overview](overview.md)
* [VerificationEngine](verification-engine.md)
* [FeeManager](fee-manager.md)
* [Resource Registry protocol doc](../protocol/resource-registry.md)
