The protocol provides a number of settings controllable by the DAO. Modifying each of them requires
the caller to have a specific permission. After deploying the DAO, all permissions belong to the DAO
Voting
app, which can also manage them. This means that, initially, levers can only be changed by
the DAO voting, and other entities can be allowed to do the same only as a result of the voting.
All existing levers are listed below, grouped by the contract.
The following contracts are upgradeable by the DAO voting:
contracts/0.4.24/Lido.sol
contracts/0.4.24/NodeOperatorsRegistry.sol
contracts/0.4.24/LidoOracle.sol
Upgradeability is implemented by the Aragon kernel and base contracts. To upgrade an app, one needs
the dao.APP_MANAGER_ROLE
permission provided by Aragon. All upgradeable contracts use the
Unstructured Storage pattern in order to provide stable storage structure accross upgrades.
The following contracts are not upgradeable and don't depend on the Aragon code:
contracts/0.6.12/CstETH.sol
- Mutator:
burnShares(address _account, uint256 _sharesAmount)
- Permission required:
BURN_ROLE
- Permission required:
DAO members can burn token shares via DAO voting to offset slashings using insurance funds. E.g. protocol was slashed by 5 Ether; by burning the amount of shares corresponding to 5 stETH the stakers can be made whole.
The address of the oracle contract.
- Mutator:
setOracle(address)
- Permission required:
SET_ORACLE
- Permission required:
- Accessor:
getOracle() returns (address)
This contract serves as a bridge between ETH 2.0 -> ETH oracle committee members and the rest of the protocol, implementing quorum between the members. The oracle committee members report balances controlled by the DAO on the ETH 2.0 side, which can go up because of reward accumulation and can go down due to slashing.
The total fee, in basis points (10000
corresponding to 100%
).
- Mutator:
setFee(uint16)
- Permission required:
MANAGE_FEE
- Permission required:
- Accessor:
getFee() returns (uint16)
The fee is taken on staking rewards and distributed between the treasury, the insurance fund, and node operators.
Controls how the fee is distributed between the treasury, the insurance fund, and node operators.
Each fee component is in basis points; the sum of all components must add up to 1 (10000
basis points).
- Mutator:
setFeeDistribution(uint16 treasury, uint16 insurance, uint16 operators)
- Permission required:
MANAGE_FEE
- Permission required:
- Accessor:
getFeeDistribution() returns (uint16 treasury, uint16 insurance, uint16 operators)
Credentials to withdraw ETH on ETH 2.0 side after phase 2 is launched.
- Mutator:
setWithdrawalCredentials(bytes)
- Permission required:
MANAGE_WITHDRAWAL_KEY
- Permission required:
- Accessor:
getWithdrawalCredentials() returns (bytes)
The protocol uses these credentials to register new ETH 2.0 validators.
Controls how many ETH 2.0 deposits can be made in a single transaction.
- A parameter of the
depositBufferedEther(uint256)
funciton - Default value:
16
- Scenario test
When someone calls depositBufferedEther
, Lido
tries to register as many ETH 2.0 validators
as it can given the buffered Ether amount. The limit is passed as an argument to this function and
is needed to prevent the transaction from failing due to the block gas limit, which is possible
if the amount of the buffered Ether becomes sufficiently large.
- Mutators:
stop()
,resume()
- Permission required:
PAUSE_ROLE
- Permission required:
- Accessor:
isStopped() returns (bool)
When paused, Lido
doesn't accept user submissions, doesn't allow user withdrawals and oracle
report submissions. No token actions (burning, transferring, approving transfers and changing
allowances) are allowed. The following transactions revert:
- Plain Ether transfers;
- calls to
submit(address)
; - calls to
depositBufferedEther(uint256)
; - calls to
withdraw(uint256, bytes32)
(withdrawals are not implemented yet). - calls to
pushBeacon(uint256, uint256)
; - calls to
burnShares(address, uint256)
- calls to
transfer(address, uint256)
- calls to
transferFrom(address, address, uint256)
- calls to
approve(address, uint256)
- calls to
increaseAllowance(address, uint)
- calls to
decreaseAllowance(address, uint)
- Treasury (
getTreasury() returns (address)
; mutator?) - Insurance fund (
getInsuranceFund() returns (address)
; mutator?) - Transfer to vault (
transferToVault()
)
- Mutator:
addNodeOperator(string _name, address _rewardAddress, uint64 _stakingLimit)
- Permission required:
ADD_NODE_OPERATOR_ROLE
- Permission required:
- Mutator:
setNodeOperatorName(uint256 _id, string _name)
- Permission required:
SET_NODE_OPERATOR_NAME_ROLE
- Permission required:
- Mutator:
setNodeOperatorRewardAddress(uint256 _id, address _rewardAddress)
- Permission required:
SET_NODE_OPERATOR_ADDRESS_ROLE
- Permission required:
- Mutator:
setNodeOperatorStakingLimit(uint256 _id, uint64 _stakingLimit)
- Permission required:
SET_NODE_OPERATOR_LIMIT_ROLE
- Permission required:
Node Operators act as validators on the Beacon chain for the benefit of the protocol. Each
node operator submits no more than _stakingLimit
signing keys that will be used later
by the protocol for registering the corresponding ETH 2.0 validators. As oracle committee
reports rewards on the ETH 2.0 side, the fee is taken on these rewards, and part of that fee
is sent to node operators’ reward addresses (_rewardAddress
).
- Mutator:
setNodeOperatorActive(uint256 _id, bool _active)
- Permission required:
SET_NODE_OPERATOR_ACTIVE_ROLE
- Permission required:
Misbehaving node operators can be deactivated by calling this function. The protocol skips deactivated operators during validator registration; also, deactivated operators don’t take part in fee distribution.
- Mutator:
addSigningKeys(uint256 _operator_id, uint256 _quantity, bytes _pubkeys, bytes _signatures)
- Permission required:
MANAGE_SIGNING_KEYS
- Permission required:
- Mutator:
removeSigningKey(uint256 _operator_id, uint256 _index)
- Permission required:
MANAGE_SIGNING_KEYS
- Permission required:
Allow to manage signing keys for the given node operator.
Signing keys can also be managed by the reward address of a signing provier by calling the equivalent functions with the
OperatorBH
suffix:addSigningKeysOperatorBH
,removeSigningKeyOperatorBH
.
- Mutator:
reportStoppedValidators(uint256 _id, uint64 _stoppedIncrement)
- Permission required:
REPORT_STOPPED_VALIDATORS_ROLE
- Permission required:
Allows to report that _stoppedIncrement
more validators of a node operator have become stopped.
Address of the Lido contract.
- Accessor:
getLido() returns (address)
The list of oracle committee members.
- Mutators:
addOracleMember(address)
,removeOracleMember(address)
- Permission required:
MANAGE_MEMBERS
- Permission required:
- Accessor:
getOracleMembers() returns (address[])
The number of oracle committee members required to form a data point.
- Mutator:
setQuorum(uint256)
- Permission required:
MANAGE_QUORUM
- Permission required:
- Accessor:
getQuorum() returns (uint256)
The data point for a given report interval is formed when:
- No less than
quorum
oracle committee members have reported their value for the given report interval; - Among these values, there is some value that occurs more frequently than the others, i.e. the set of reported values is unimodal. This value is then used for the resulting data point.