Skip to main content
Version: v4 (next)

Create a Root Participant

A Credential Schema always requires at least one root participant (role: ECOSYSTEM). After creating a credential schema, the Ecosystem controller (the Corporation that owns the schema's Ecosystem) must create a root participant for that schema (MOD-PP-MSG-7, MsgCreateRootParticipant).

Why it matters

  • It anchors the participant hierarchy for the schema (enables Grantors, Issuers, Verifiers).
  • It defines the default trust fees (validation, issuance, verification) used by the ecosystem.
  • Without an active root participant:
    • Candidates cannot run an onboarding process with the Ecosystem controller.
    • Even in OPEN mode, candidates cannot self-create ISSUER/VERIFIER participants — a root must exist as the validator of last resort.

Overlaps & rotation

  • Multiple root participants can co-exist only if their effective periods do not overlap.
  • If an existing root participant has no effective_until, set an end date before creating a new one.
Prerequisites

This is a delegable transaction executed on behalf of a Corporation. Before running it you need:

  1. A Corporation (policy_address) that controls the schema's Ecosystem — see Create a Corporation.
  2. The policy funded with uvna for fees.
  3. An operator granted authorization for /verana.pp.v1.MsgCreateRootParticipant via Grant Operator Authorization.
  4. An existing credential schema — see Create a Credential Schema.

Sign with --from <operator> and pass the corporation with --corporation <policy_address>.

Message Parameters

NameDescriptionMandatory
schema-idID of the credential schema.yes
didDID of the Verifiable Service that will hold the root participant.yes
validation-feesFee (trust units) charged for each onboarding process under this schema.yes
issuance-feesFee (trust units) applied to each issuance under this schema.yes
verification-feesFee (trust units) applied to each verification under this schema.yes
--corporationpolicy_address of the owning Corporation.yes
--effective-fromRFC3339 timestamp from which the participant is effective (must be in the future).yes
--effective-untilOptional RFC3339 timestamp until which the participant is effective.no

Trust fees are priced in the ecosystem's trust unit; gas/tx fees are paid in chain tokens (uvna).

Post the Message

Usage

veranad tx pp create-root-participant [schema-id] [did] [validation-fees] [issuance-fees] [verification-fees] \
--corporation <policy_address> \
--effective-from <RFC3339> [--effective-until <RFC3339>] \
--from <operator> --chain-id <chain-id> --keyring-backend test --fees 750000uvna --gas auto --node $NODE_RPC

Example

Set your environment first (values below are from a real testnet run):

SCHEMA_ID=3
ROOT_DID=did:example:18c0df1833f9f2002c4395780e84af3b
CORPORATION=verana1n64en27u7qckklkk4twkkun5h6v5dsur7g6l4pfmfhydvfru9upq5w4nlu
OPERATOR=verana1aesnnc4fvar4wyaryvj9y4sty9vsw69hgymw7q
CHAIN_ID="vna-testnet-1"
NODE_RPC=https://rpc.testnet.verana.network

Create the root participant with fees 100/50/25:

veranad tx pp create-root-participant $SCHEMA_ID $ROOT_DID 100 50 25 \
--corporation $CORPORATION \
--effective-from 2026-07-10T08:06:20Z \
--from $OPERATOR --chain-id $CHAIN_ID --keyring-backend test --fees 750000uvna --gas auto --node $NODE_RPC --yes

Real result

The transaction succeeds with code: 0 and emits a create_root_participant event (txhash 0D410489E466B0B7E798FA6F60DD7A5034D5AA62A80867692E8BA4939A6DF4ED):

- type: message
attributes:
- key: action
value: /verana.pp.v1.MsgCreateRootParticipant
- key: module
value: pp
- type: create_root_participant
attributes:
- key: root_participant_id
value: "3"
- key: schema_id
value: "3"
- key: corporation
value: verana1n64en27u7qckklkk4twkkun5h6v5dsur7g6l4pfmfhydvfru9upq5w4nlu
- key: corporation_id
value: "6"
- key: operator
value: verana1aesnnc4fvar4wyaryvj9y4sty9vsw69hgymw7q
- key: validation_fees
value: "100"
- key: issuance_fees
value: "50"
- key: verification_fees
value: "25"

Verify

Query the new participant by its ID:

veranad query pp get-participant 3 --node $NODE_RPC --output json
{
"participant": {
"id": "3",
"schema_id": "3",
"role": "ECOSYSTEM",
"did": "did:example:18c0df1833f9f2002c4395780e84af3b",
"created": "2026-07-10T08:06:09.158617Z",
"effective_from": "2026-07-10T08:06:20.510395Z",
"effective_until": "2027-07-05T08:06:20.510395Z",
"modified": "2026-07-10T08:06:09.158617Z",
"validation_fees": "100",
"issuance_fees": "50",
"verification_fees": "25",
"op_state": "VALIDATED",
"op_last_state_change": "2026-07-10T08:06:09.158617Z",
"corporation_id": "6"
}
}

You should see a participant with role: "ECOSYSTEM", your did, the fees you set, and op_state: "VALIDATED".

Common errors

  • Unauthorized operatorauthorization check failed: operator authorization not found for this corporation/operator pair. Grant the operator /verana.pp.v1.MsgCreateRootParticipant first.
  • effective-from not in the future → set it a few seconds ahead so it is still in the future when the block is produced.

See also