Bor consensus is inspired by Clique consensus: Clique works with multiple pre-defined producers. All producers vote on new producers using Clique APIs. They take a turn creating blocks.

Bor fetches new producers through span and sprint management mechanism.


Matic is a Proof-of-stake system. Anyone can stake their Matic token on Ethereum smart-contract, "staking contract", and become a validator for the system.

function stake(
	uint256 amount,
	uint256 heimdallFee,
	address signer,
	bool acceptDelegation
) external;

Once validators are active on Heimdall they get selected as producers through bor module.

Check Bor overview to understand span management more in details:

Bor Overview


A logically defined set of blocks for which a set of validators is chosen from among all the available validators.

Heimdall provides span details through span-details APIs.

// HeimdallSpan represents span from heimdall APIs
type HeimdallSpan struct {
	ValidatorSet      ValidatorSet `json:"validator_set" yaml:"validator_set"`
	SelectedProducers []Validator  `json:"selected_producers" yaml:"selected_producers"`
	ChainID           string       `json:"bor_chain_id" yaml:"bor_chain_id"`

// Span represents a current bor span
type Span struct {
	ID         uint64 `json:"span_id" yaml:"span_id"`
	StartBlock uint64 `json:"start_block" yaml:"start_block"`
	EndBlock   uint64 `json:"end_block" yaml:"end_block"`

// Validator represents a volatile state for each Validator
type Validator struct {
	ID               uint64         `json:"ID"`
	Address          common.Address `json:"signer"`
	VotingPower      int64          `json:"power"`
	ProposerPriority int64          `json:"accum"`

Geth (In this case, Bor) uses block snapshot to store state data for each block, including consensus related data.

Each validator in span contains voting power. Based on their power, they get selected as block producers. Higher power, a higher probability of becoming block producers. Bor uses Tendermint's algorithm for the same. Source:


A set of blocks within a span for which only a single block producer is chosen to produce blocks. The sprint size is a factor of span size.

Bor uses validatorSet to get current proposer/producer for current sprint.

currentProposerForSprint := snap.ValidatorSet().Proposer