PirexEthValidators.sol

General Overview

The PirexEthValidators.sol contract is a central component in managing Ethereum validators for the Beacon Chain deposit contract. It facilitates a wide range of functions including setting contract addresses, managing validator queues, initiating deposits, and handling rewards and slashing operations. The contract also allows for validator management through various queues with capabilities to add, swap, remove, or clear validators.

Additionally, it addresses the redemption and rewarding of validators with upxEth tokens. The roles defined within the contract, such as GOVERNANCE_ROLE, KEEPER_ROLE, and DEFAULT_ADMIN_ROLE, are important for these activities, ensuring a seamless and secure operation of validators within the protocol.

  • GOVERNANCE_ROLE - manages the validator queue, sets fee parameters, and controls the pausing of deposits to the Beacon Chain deposit contract.
  • KEEPER_ROLE - responsible for harvesting rewards, updating the status of validators when they are slashed, and topping up the validator's stake if the active balance falls below the effective balance.
  • DEFAULT_ADMIN_ROLE - sets external contract addresses.

Technical Overview

Inherits: ReentrancyGuard, AccessControlDefaultAdminRules, IPirexEth

Author: redactedcartel.finance

State Variables

DENOMINATOR

uint256 public constant DENOMINATOR = 1_000_000;

KEEPER_ROLE

bytes32 public constant KEEPER_ROLE = keccak256("KEEPER_ROLE");

GOVERNANCE_ROLE

bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");

_NOT_PAUSED

uint256 internal constant _NOT_PAUSED = 1;

_PAUSED

uint256 internal constant _PAUSED = 2;

beaconChainDepositContract

address public immutable beaconChainDepositContract;

preDepositAmount

uint256 public immutable preDepositAmount;

DEPOSIT_SIZE

uint256 public immutable DEPOSIT_SIZE;

withdrawalCredentials

bytes public withdrawalCredentials;

buffer

uint256 public buffer;

maxBufferSize

uint256 public maxBufferSize;

maxBufferSizePct

uint256 public maxBufferSizePct;

maxProcessedValidatorCount

uint256 public maxProcessedValidatorCount = 20;

upxEth

ERC1155Solmate public upxEth;

pxEth

PxEth public pxEth;

autoPxEth

AutoPxEth public autoPxEth;

oracleAdapter

IOracleAdapter public oracleAdapter;

rewardRecipient

address public rewardRecipient;

depositEtherPaused

uint256 public depositEtherPaused;

pendingDeposit

uint256 public pendingDeposit;

_initializedValidators

DataTypes.ValidatorDeque internal _initializedValidators;

_stakingValidators

DataTypes.ValidatorDeque internal _stakingValidators;

pendingWithdrawal

uint256 public pendingWithdrawal;

outstandingRedemptions

uint256 public outstandingRedemptions;

batchId

uint256 public batchId;

endBlock

uint256 public endBlock;

status

mapping(bytes => DataTypes.ValidatorStatus) public status;

batchIdToValidator

mapping(uint256 => bytes) public batchIdToValidator;

burnerAccounts

mapping(address => bool) public burnerAccounts;

Functions

onlyRewardRecipient

modifier onlyRewardRecipient();

onlyWhenDepositEtherPaused

modifier onlyWhenDepositEtherPaused();

constructor

constructor(
    address _pxEth,
    address _admin,
    address _beaconChainDepositContract,
    address _upxEth,
    uint256 _depositSize,
    uint256 _preDepositAmount,
    uint48 _initialDelay
) AccessControlDefaultAdminRules(_initialDelay, _admin);

Parameters

NameTypeDescription
_pxEthaddressPxETH contract address
_adminaddressAdmin address
_beaconChainDepositContractaddressThe address of the deposit precompile
_upxEthaddressUpxETH address
_depositSizeuint256Amount of ETH to stake
_preDepositAmountuint256Amount of ETH for pre-deposit
_initialDelayuint48Delay required to schedule the acceptance of a access control transfer started

getInitializedValidatorCount

Get the number of initialized validators

function getInitializedValidatorCount() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256Number of initialised validators

getStakingValidatorCount

Get the number of staking validators

function getStakingValidatorCount() public view returns (uint256);

Returns

NameTypeDescription
<none>uint256Number of staking validators

getInitializedValidatorAt

Get the initialized validator info at the specified index

function getInitializedValidatorAt(uint256 _i)
    external
    view
    returns (bytes memory, bytes memory, bytes memory, bytes32, address);

Parameters

NameTypeDescription
_iuint256Index

Returns

NameTypeDescription
<none>bytesPublic key
<none>bytesWithdrawal credentials
<none>bytesSignature
<none>bytes32Deposit data root hash
<none>addresspxETH receiver

getStakingValidatorAt

Get the staking validator info at the specified index

function getStakingValidatorAt(uint256 _i)
    external
    view
    returns (bytes memory, bytes memory, bytes memory, bytes32, address);

Parameters

NameTypeDescription
_iuint256Index

Returns

NameTypeDescription
<none>bytesPublic key
<none>bytesWithdrawal credentials
<none>bytesSignature
<none>bytes32Deposit data root hash
<none>addresspxETH receiver

setContract

Set a contract address

function setContract(DataTypes.Contract c, address contractAddress) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
cDataTypes.ContractContract
contractAddressaddressContract address

setMaxBufferSizePct

Set the percentage that will be applied to total supply of pxEth to determine maxBufferSize

function setMaxBufferSizePct(uint256 _pct) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_pctuint256Max buffer size percentage

setMaxProcessedValidatorCount

Set maximum count of processed validator in a _deposit call

function setMaxProcessedValidatorCount(uint256 _count) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_countuint256Max processed count

togglePauseDepositEther

Toggle allowing depositing ETH to validators

function togglePauseDepositEther() external onlyRole(GOVERNANCE_ROLE);

toggleBurnerAccounts

Approve/revoke addresses as burner accounts

function toggleBurnerAccounts(address[] calldata _accounts, bool _state) external onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_accountsaddress[]Addresses
_stateboolBurner acount state

dissolveValidator

Update validator to Dissolve once Oracle updates on ETH being released

function dissolveValidator(bytes calldata _pubKey) external payable override onlyRewardRecipient;

Parameters

NameTypeDescription
_pubKeybytesPublic key of the validator

slashValidator

Update validator state to be slashed

function slashValidator(
    bytes calldata _pubKey,
    uint256 _removeIndex,
    uint256 _amount,
    bool _unordered,
    bool _useBuffer,
    DataTypes.BurnerAccount[] calldata _burnerAccounts
) external payable override onlyRewardRecipient;

Parameters

NameTypeDescription
_pubKeybytesPublic key of the validator
_removeIndexuint256Index of validator to be slashed
_amountuint256ETH amount released from Beacon chain
_unorderedboolWhether remove from staking validator queue in order or not
_useBufferboolwhether to use buffer to compensate the loss
_burnerAccountsDataTypes.BurnerAccount[]Burner accounts

addInitializedValidators

Add multiple synced validators in the queue to be ready for staking

function addInitializedValidators(DataTypes.Validator[] memory _validators)
    external
    onlyWhenDepositEtherPaused
    onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_validatorsDataTypes.Validator[]Validators details

swapInitializedValidator

Swap initialized validators specified by the indexes

function swapInitializedValidator(uint256 _fromIndex, uint256 _toIndex)
    external
    onlyWhenDepositEtherPaused
    onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_fromIndexuint256From index
_toIndexuint256To index

popInitializedValidator

Pop initialized validators

function popInitializedValidator(uint256 _times) external onlyWhenDepositEtherPaused onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_timesuint256Count of pop operations

removeInitializedValidator

Remove initialized validators

function removeInitializedValidator(bytes calldata _pubKey, uint256 _removeIndex, bool _unordered)
    external
    onlyWhenDepositEtherPaused
    onlyRole(GOVERNANCE_ROLE);

Parameters

NameTypeDescription
_pubKeybytes
_removeIndexuint256Remove index
_unorderedboolWhether unordered or ordered

clearInitializedValidator

Clear initialized validators

function clearInitializedValidator() external onlyWhenDepositEtherPaused onlyRole(GOVERNANCE_ROLE);

depositPrivileged

Trigger deposit to the ETH 2.0 deposit contract when allowed

function depositPrivileged() external nonReentrant onlyRole(KEEPER_ROLE);

topUpStake

Topup ETH to the validator if current balance drops below effective balance

function topUpStake(
    bytes calldata _pubKey,
    bytes calldata _signature,
    bytes32 _depositDataRoot,
    uint256 _topUpAmount,
    bool _useBuffer,
    DataTypes.BurnerAccount[] calldata _burnerAccounts
) external payable nonReentrant onlyRole(KEEPER_ROLE);

Parameters

NameTypeDescription
_pubKeybytesValidator public key
_signaturebytesA BLS12-381 signature
_depositDataRootbytes32The SHA-256 hash of the SSZ-encoded DepositData object.
_topUpAmountuint256Top-up amount
_useBufferboolWhether to use buffer
_burnerAccountsDataTypes.BurnerAccount[]Burner accounts

harvest

Harvest and mint staking rewards when available

function harvest(uint256 _endBlock) external payable override onlyRewardRecipient;

Parameters

NameTypeDescription
_endBlockuint256Block until which ETH rewards is computed

_mintPxEth

Internal method for minting pxETH

function _mintPxEth(address _account, uint256 _amount) internal;

Parameters

NameTypeDescription
_accountaddressAccount
_amountuint256Amount

_burnPxEth

Internal method for burning pxETH

function _burnPxEth(address _account, uint256 _amount) internal;

Parameters

NameTypeDescription
_accountaddressAccount
_amountuint256Amount

_deposit

Spin up validator if sufficient ETH is available

function _deposit() internal;

_addPendingDeposit

Add pending deposit and spin up validator if required ETH available

function _addPendingDeposit(uint256 _amount) internal virtual;

Parameters

NameTypeDescription
_amountuint256ETH asset amount

_initiateRedemption

Internal handler for validator related logic on redemption

function _initiateRedemption(uint256 _pxEthAmount, address _receiver, bool _shouldTriggerValidatorExit) internal;

Parameters

NameTypeDescription
_pxEthAmountuint256Amount of pxETH
_receiveraddressReceiver for upxETH
_shouldTriggerValidatorExitboolWhether initiate partial redemption with validator exit or not

_updateBuffer

function _updateBuffer(uint256 _amount, DataTypes.BurnerAccount[] calldata _burnerAccounts) private;

Events

ValidatorDeposit

event ValidatorDeposit(bytes pubKey);

SetContract

event SetContract(DataTypes.Contract indexed c, address contractAddress);

DepositEtherPaused

event DepositEtherPaused(uint256 newStatus);

Harvest

event Harvest(uint256 amount, uint256 endBlock);

SetMaxBufferSizePct

event SetMaxBufferSizePct(uint256 pct);

ApproveBurnerAccount

event ApproveBurnerAccount(address indexed account);

RevokeBurnerAccount

event RevokeBurnerAccount(address indexed account);

DissolveValidator

event DissolveValidator(bytes pubKey);

SlashValidator

event SlashValidator(bytes pubKey, bool useBuffer, uint256 releasedAmount, uint256 penalty);

TopUp

event TopUp(bytes pubKey, bool useBuffer, uint256 topUpAmount);

SetMaxProcessedValidatorCount

event SetMaxProcessedValidatorCount(uint256 count);

UpdateMaxBufferSize

event UpdateMaxBufferSize(uint256 maxBufferSize);

SetWithdrawCredentials

event SetWithdrawCredentials(bytes withdrawalCredentials);