Create and register a Schema

Before you can issue attestations into the registry, you will need a Schema upon which to base those attestations.

Schema creation takes 4 parameters, defined as follows:

ParameterDescription

name

An on-chain descriptive name for the schema.

description

The location of documentation for the schema (can be a URL, an IPFS hash, etc.), which describes its intended use and any relationships.

context

A link to a description of the schema's fields. You have two options: a URL linking to some shared ontology, or the attestation ID of a custom context.

schemaString

The actual schema string that describes the data structure of the attestations.

Manually calling the SchemaRegistry smart contract

To create a Schema, you must call the createSchema function on the SchemaRegistry contract:

function createSchema(
    string memory name,
    string memory description,
    string memory context,
    string memory schemaString
)

Then you need to get the logs from the transaction, and catch the Schema ID from there.

Using a blockchain explorer

Instead of crafting the smart contract call by hand, you can benefit from a chain explorer interface. Let's use the Linea Sepolia explorer, Lineascan.

  1. Retrieve the SchemaRegistry contract address from the project README

  2. Access the SchemaRegistry contract on Lineascan

  3. Go to the "Contract" tab

  4. Connect your allow-listed wallet and fill the createSchema form with the parameters described above

  5. Send the transaction and watch the details of this transaction

  6. Go to the "Logs" tab and grab the Schema ID

  7. In the example, it's 0xa288e257097a4bed4166c002cb6911713edacc88e30b6cb2b0104df9c365327d

Using the official Verax SDK

We have seen rather manual ways to create a Schema, now let's focus on the easiest way: via the Verax SDK.

Check this page to discover how to instantiate the Verax SDK.

Once you have an SDK instance, you can create a Schema like this:

await veraxSdk.schema.create(
    "Example Schema",
    "This Schema is used as an example",
    "https://docs.ver.ax",
    "(bool isExample, bool isWorking)",
);

The Schema String Syntax

A schema string is a comma separated list of data type + field name tuples, for example:

(string firstName, string lastName)

The schema should be wrapped in outer round brackets. It is best practice as it will make it easier for different clients to parse the schema, but also for you to use it from the SDK.

The data types can be any valid Solidity datatype:

  1. Boolean: Identified by the bool keyword. Represents a boolean value: true or false.

  2. Integer: Represents signed integers of various sizes. Examples include int8, int16, int256, etc.

  3. Unsigned Integer: Represents unsigned integers of various sizes. Examples include uint8, uint16, uint256, etc.

  4. Address: Represents a 20-byte Ethereum address. It is used to store addresses of EOAs and smart contracts. Identified by the keyword address.

  5. Bytes: Represents a fixed-size array of bytes. For example, bytes32 represents a 32-byte array, and bytes represents a dynamic-sized byte array.

  6. String: Represents a sequence of characters, like strings in other programming languages. Identified by the keyword string.

  7. Array: Represents a fixed-size or dynamic-size array containing elements that share the same type, e.g. string[].

  8. Struct: Represents a user-defined data structure that can hold multiple variables of different types. To define a struct, include the field name, followed by the struct definition in curly braces, see below for an example.

The only Solidity data types that aren't supported are mapping and enum. If you want to store a mapping, you can instead choose to store an array of key <> value pairs, e.g. mapping(address => uint32) points becomes (address user, uint32 score)[] points`

Defining a struct in a schema string is done using round braces. For example, defining a struct that contains Street and City properties can be done like so:

(string firstName, string lastName, (string Street, string City) isResidentAt)

Note that the name of the field in the attestation is isResidentAt but the name of the actual struct isn't defined in the schema string.

Arrays of structs can be defined using square brackets, e.g.:

(string firstName, string lastName, (string Street, string City)[] homeAddress)

Getting a schema ID from a schema string

To deterministically calculate what the schema ID is, you can call the function getIdFromSchemaString function on the SchemaRegistry smart contract.

This function is as follows:

function getIdFromSchemaString(string memory schema) public pure returns (bytes32) {
    return keccak256(abi.encodePacked(schema));
}

To understand more about the schema creation process, you can view the SchemaRegistry smart contract source code.

Once you've created one or more schemas, you can optionally create a module to enforce any constraints or business logic that are associated with those schemas.

Last updated