Skip to main content

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, and CAPS_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.