|
| 1 | +## Delegation |
| 2 | + |
| 3 | +Delegation allows separating protocol permissions from oracle hot keys. Instead of granting permissions directly to the oracle account, they are granted to a [DelegationContract](https://github.com/lidofinance/delegation-execution-authority), and the oracle executes calls through it. |
| 4 | + |
| 5 | +This enables instant hot key rotation by the contract admin without governance voting. |
| 6 | + |
| 7 | +### How it works |
| 8 | + |
| 9 | +``` |
| 10 | +Oracle (hot key) |
| 11 | + │ |
| 12 | + │ calls execute(target, calldata) |
| 13 | + ▼ |
| 14 | +DelegationContract (holds protocol permissions) |
| 15 | + │ |
| 16 | + │ forwards call as msg.sender |
| 17 | + ▼ |
| 18 | +Target contract (HashConsensus, AccountingOracle, ExitBusOracle, CSFeeOracle) |
| 19 | +``` |
| 20 | + |
| 21 | +When delegation is enabled, the following calls are affected: |
| 22 | + |
| 23 | +| Target contract | Method | Module | |
| 24 | +|--------------------------------------------------------------------------------------------|-------------------------------|--------------------| |
| 25 | +| [HashConsensus](https://docs.lido.fi/contracts/hash-consensus) | `submitReport` | All | |
| 26 | +| [AccountingOracle](https://docs.lido.fi/contracts/accounting-oracle) | `submitReportData` | Accounting | |
| 27 | +| [AccountingOracle](https://docs.lido.fi/contracts/accounting-oracle) | `submitReportExtraDataList` | Accounting | |
| 28 | +| [AccountingOracle](https://docs.lido.fi/contracts/accounting-oracle) | `submitReportExtraDataEmpty` | Accounting | |
| 29 | +| [ValidatorsExitBusOracle](https://docs.lido.fi/contracts/validators-exit-bus-oracle) | `submitReportData` | Ejector | |
| 30 | +| CSFeeOracle | `submitReportData` | Staking Module | |
| 31 | + |
| 32 | +The target contract sees `DelegationContract` as `msg.sender`, so all permissions must be granted to the delegation contract address, not to the oracle account. |
| 33 | + |
| 34 | +### Setup |
| 35 | + |
| 36 | +#### 1. Deploy delegation contract |
| 37 | + |
| 38 | +The contract admin deploys a `DelegationContract` instance via `DelegationFactory` from the [delegation-execution-authority](https://github.com/lidofinance/delegation-execution-authority) repository. |
| 39 | + |
| 40 | +#### 2. Grant protocol permissions |
| 41 | + |
| 42 | +Governance grants oracle member permissions to the deployed `DelegationContract` address (not to the oracle hot key). |
| 43 | + |
| 44 | +#### 3. Assign oracle as delegatee |
| 45 | + |
| 46 | +The contract admin calls `assignDelegate(oracleAddress)` on the delegation contract, where `oracleAddress` is the oracle operator's account address. |
| 47 | + |
| 48 | +#### 4. Configure the oracle |
| 49 | + |
| 50 | +Set the environment variable: |
| 51 | + |
| 52 | +```bash |
| 53 | +DELEGATION_CONTRACT_ADDRESS=0x... # deployed DelegationContract address |
| 54 | +``` |
| 55 | + |
| 56 | +### Startup validation |
| 57 | + |
| 58 | +On startup the oracle validates the delegation setup: |
| 59 | + |
| 60 | +- If `DELEGATION_CONTRACT_ADDRESS` is not set, delegation is disabled and the oracle sends transactions directly. |
| 61 | +- If set but `MEMBER_PRIV_KEY` is not configured (dry mode), validation is skipped. |
| 62 | +- If the contract has no delegatee (`address(0)`), the oracle fails with `NotConfiguredError`. |
| 63 | +- If the contract's delegatee does not match the oracle account, the oracle fails with `DelegateMismatchError`. |
| 64 | + |
| 65 | +### Key rotation |
| 66 | + |
| 67 | +To rotate the oracle hot key: |
| 68 | + |
| 69 | +1. Admin calls `assignDelegate(newOracleAddress)` on the delegation contract. |
| 70 | +2. Update `MEMBER_PRIV_KEY` in the oracle config to the new key. |
| 71 | +3. Restart the oracle. |
| 72 | + |
| 73 | +No governance vote is required. |
0 commit comments