Governor Contracts
Governor contracts are the backbone of secure, flexible, and upgradeable governance for Euler Vault Kit (EVK) vaults and oracle routers. They enable fine-grained control over vault operations, risk parameters, and emergency responses — balancing the need for rapid intervention with robust user protection.
The Role of Governor Contracts
In Euler V2, every EVK vault and the oracle router can be assigned a governor address. The governor acts as an admin, controlling upgrades, parameter changes, and access to sensitive functions. This modular approach allows vault creators and curators to choose the governance model that best fits their risk profile and operational needs.
Roles and Configuration
Governor contracts use a robust role-based access control system, often selector-based, to manage permissions:
- DEFAULT_ADMIN_ROLE: The most powerful role, able to grant/revoke other roles and perform admin actions. Should be held by a highly trusted multisig or DAO.
- WILD_CARD: Grants access to all function selectors, typically held by a timelock for day-to-day governance.
- Function Selector Roles: Grant access to specific functions, allowing granular permissioning.
- GUARDIAN_ROLE: Allows pausing/unpausing of vaults.
- Emergency Roles: Special roles for rapid response, such as
LTV_EMERGENCY_ROLE
,HOOK_EMERGENCY_ROLE
, andCAPS_EMERGENCY_ROLE
.
Careful assignment and monitoring of these roles is critical for security.
Types of Governor Contracts
Euler provides several specialized governor contracts, each with unique features:
GovernorGuardian
GovernorGuardian
is a simple, proxy-like governor for vaults. Default admins can call any function, while guardians can pause or unpause the vault. It includes a cooldown to prevent repeated pausing and allows selective re-enabling of methods (e.g., only allow withdrawals/repays). This is a good choice for vaults that want straightforward pause/unpause controls with minimal complexity.
GovernorAccessControl
GovernorAccessControl
provides selector-based access control: permissions are granted per function selector, or globally via the WILD_CARD
role. Whitelisted callers can invoke specific functions on target contracts, with authentication and forwarding handled by the governor. It can be used standalone or as part of a timelock-enabled governance suite. This is the most flexible and granular governor type.
GovernorAccessControlEmergency
This contract inherits from GovernorAccessControl
and adds emergency roles for rapid response. Emergency guardians can instantly lower borrow LTV, pause all vault operations, or lower supply/borrow caps. These actions can be executed rapidly, providing a circuit breaker for risk events. Recovery from emergency states (e.g., unpausing) requires going through the timelock process (if timelock installed), ensuring careful review.
CapRiskSteward
CapRiskSteward
is a specialized risk management contract that works alongside selector-based governors. It allows authorized users to adjust supply and borrow caps within predefined safety limits and cooldowns, and to update interest rate models (IRM) only to those deployed by a recognized factory. This contract is ideal for delegating limited, controlled risk parameter management to trusted stewards, while keeping ultimate control with the governor and timelock.
Timelock Integration: Dual Timelock Model
The recommended deployment uses the GovernorAccessControlEmergencyFactory
, which sets up:
- Admin Timelock: Holds the
DEFAULT_ADMIN_ROLE
, controls governance of the governor contract itself (break-glass, rarely used). - Wildcard Timelock: Holds the
WILD_CARD
role, used for day-to-day governance (parameter changes, etc.).
This dual timelock model provides transparency (all changes are queued and visible before execution), user protection (users have time to react to pending changes), and operational flexibility (emergency guardians can act instantly, but recovery is time-delayed).
How to call the GovernorAccessControl
contract
To call a function on a vault via GovernorAccessControl
, you must append the target vault address to the calldata. This allows the governor to authenticate the call and forward it to the correct vault. Here's a simple example in Solidity:
// Assume you want to call setCaps(uint16,uint16) on a vault via the governor
address vault = VAULT_ADDRESS;
uint16 supplyCap = 1000;
uint16 borrowCap = 500;
// Fetch the governor address from the vault contract
address governor = IVault(vault).governorAdmin();
// Encode the function selector and arguments
bytes memory encodedCall = abi.encodeWithSelector(
IEVault.setCaps.selector,
supplyCap,
borrowCap
);
// Append the vault address (20 bytes) to the calldata using abi.encodePacked
bytes memory encodedCallWithTarget = abi.encodePacked(encodedCall, vault);
// Call the governor contract
(bool success, bytes memory result) = governor.call(encodedCallWithTarget);
require(success, "Governor call failed");
This pattern is also used for GovernorAccessControlEmergency
and CapRiskSteward
contracts. The governor contract extracts the trailing address and forwards the call to the vault, authenticating the caller's permissions for the function selector.