Pharos employs a Proof-of-Stake (PoS) mechanism for node admission and currently does not support delegation. Its consensus process follows a leaderless model, i.e. Multiple Concurrent Proposers approach, allowing multiple validators to propose transactions simultaneously. Voting power is weighted proportionally to each validator’s staked amount.
Pharos manages the validator set via a system contract located at 0x4100000000000000000000000000000000000000. During epoch transitions, updates to the validator set are executed and block rewards are distributed. Block rewards comprise both PoS rewards and transaction fees, with PoS rewards allocated proportionally according to each validator’s stake.
Note: The contract is currently under audit, and its interfaces may be subject to change.
abstract contract StakingStorageV1 is IStaking {
mapping(bytes32 => Validator) public validators;
bytes32[] public activePoolIds;
bytes32[] public pendingAddPoolIds;
bytes32[] public pendingUpdatePoolIds;
bytes32[] public pendingExitPoolIds;
uint256 public constant MIN_DELEGATOR_STAKE = 1 ether; // default value
uint256 public constant MIN_POOL_STAKE = 10000000 ether; // default value
uint256 public constant MAX_POOL_STAKE = 50000000 ether; // default value
uint256 public currentEpoch;
uint256 public totalStake;
IChainConfig public cfg;
mapping(address => uint256) public pendingWithdrawStakes;
}
struct Validator {
string description;
string publicKey;
string publicKeyPop;
string blsPublicKey;
string blsPublicKeyPop;
string endpoint;
uint8 status;
bytes32 poolId;
uint256 totalStake;
address owner;
uint256 stakeSnapshot;
uint256 pendingWithdrawStake;
uint8 pendingWithdrawWindow;
}
activePoolIds: List of active validator ids for the current epoch.validators: Mapping of validators, keyed by validator id.function registerValidator(
string memory _description,
string memory _publicKey,
string memory _publicKeyPop,
string memory _blsPublicKey,
string memory _blsPublicKeyPop,
string memory _endpoint
) external payable returns (bytes32);
When registering a node, this interface is called with the node’s public key, endpoint infors, and other details. The staking amount is provided via msg.value during registration and must satisfy min_validator_stake <= msg.value <= max_validator_stake, where min_validator_stake and max_validator_stake are system-configured parameters.
The msg.sender calling this method is considered the node’s owner, who has the authority to update or exit the node. Block rewards are also distributed to the owner’s address during epoch transitions.
function addStake(bytes32 _poolId) external payable;
This interface allows additional stake to be added to a validator. In addition to validating the validator’s status, it checks whether the provided stake meets the minimum delegation requirement and ensures that the validator’s total stake after the increase does not exceed max_validator_stake. However, the contract does not record the account that added the stake.