Validator-Set Contracts


Validator Set contracts provide information on current validators and private functionality to add and remove validators.

Documentation and Source Code


For upgradeability purposes, the contracts are divided into 2 parts. See below Fig. 1.

RelaySet Contract

This contract implements the required reporting ValidatorSet interface expected by the engine and it is the contract defined in the chainspec seen by the engine. It relays most of the function calls to the RelayedSet contract, which holds the actual logic. The logic contract can be replaced (upgraded), so it is possible to change the behavior of validator management without conducting a hard fork.

RelayedSet Contract

This contract implements the logic and manages the validator list. The owner of the validator set interacts with this contract for managing the validators. This contract maintains two validator sets:

  1. The current validator set (the validators who are actively sealing)

  2. The migration validator set, which is the new set we migrate to in case of a change (validator addition or removal).

Validator States

Validators and potential validators have four states in these contracts:

  1. Active validator: Validator is in the active validator set, sealing new blocks

  2. Not a validator: The address nothing has to do with validation.

  3. Pending To Be Added Validator: Validator is already added by the owner and their acceptance is pending, but not active yet until it is finalized. This implies that the validator cannot report, be reported, or produce blocks yet.

  4. Pending To Be Removed Validator: Validator is pending to be removed (removed by the owner), but it is not finalized, and so is still active as a validator. This implies that as long as the removal is not finalized, the validator is actively producing blocks, can report and can be reported on.


The RelayedSet contract logs malicious or benign reports by emitting corresponding log events that can be seen by anyone. Reporting can only be on and about active sealing validators.

event ReportedMalicious(address indexed reporter, address indexed reported, uint indexed blocknum);
event ReportedBenign(address indexed reporter, address indexed reported, uint indexed blocknum);

The events contain the reporter- and reported address, and the block number which the validator was reported on.

Interaction with RelayedSet (logic) Contract






Callable functions




Returns true if there are ongoing changes to the active set, false otherwise. If true, implies that current validators list equals migration validators list.


Returns the state of an address, two integers: an integer representing the validator state, and an index value. The index is the position of the validator address in the currentValidators array. It is only relevant if the address is an active validator, should be ignored otherwise.

The validator state mappings are:

  • NonValidator: 0

  • Finalized: 1

  • PendingToBeAdded: 2

  • PendingToBeRemoved: 3


Returns currently active block producing validators


Returns the migration validator set. If there are no changes, it returns the same list as getValidators().


Returns the union of current and migration sets. Useful for tracking the statuses of all affected validators in case of an ongoing change


Returns the number of currently active validators


Returns true if address is pending to be added to the active list.


Returns true if address is pending to be removed from the active list.


Returns true if address is pending to be added or removed.


Returns true if address is an active validator, meaning it partakes in producing new blocks. Note that a validator who is pending to be removed is still active.


Returns true if address is a finalized validator, meaning it is active and NOT pending to be removed either.

Events you can listen to, in addition to report events:

event ChangeFinalized(address[] validatorSet);
event NewRelay(address indexed relay);

Interaction with Relay Contract

Callable functions

Function Name



Returns the system address


Same as RelayedSet getValidators()


Returns the address of the Relayed contract

Events you can listen to:

event NewRelayed(address indexed old, address indexed current);

Last updated