Skip to main content

CCIPTokenPoolConfigProposal

Git Source

Inherits: GovernorBravoProposal

OCG proposal that re-activates OHM bridging through Chainlink CCIP: it opens the mainnet routes to Arbitrum, Optimism, Base, Berachain and Robinhood Chain on the OHM token pool, and moves the pool under the CCIPTokenPoolConfig policy and its CCIPTokenPoolConfigTimelock and the OHM administrator position in the Chainlink TokenAdminRegistry under the OCG timelock.

The first action calls the deployed CCIPTokenPoolConfigProposalChecker, a read-only contract that asserts at execution time what the build read: the precondition of each handover action the proposal includes, the end state of each handover action the live state already satisfies, the absence of the five routes from the pool and the minimum backing of the pool. Every handover action is conditional on the live state, so the proposal is idempotent with respect to steps that had already happened when it was built; a step that happens between the build and the execution fails the first action instead. The actions read, in order: check the preconditions, accept the OHM administrator role, grant bridge_admin to the DAO MS, enable the config policy, accept the pool ownership, set the config timelock as config operator, set the OCG timelock as rebalancer, clear the native rate limit admin, enable the config timelock, and add the five routes through CCIPTokenPoolConfig.addChain. At most fourteen actions, so no activator contract is needed.

The route actions come after the handover actions because addChain requires the config policy to be enabled and to own the pool, both of which happen earlier in the same execution. The gap between submission and execution is covered by the checker: until execution the only party able to change the pool, the registry entry or the routes is the DAO MS (the pool owner, the pool rebalancer and the OHM administrator until the proposal accepts both transfers), and a change that invalidates an action or lowers the backing below the minimum makes the first action revert with a named error, so no handover action runs. The one change the checker cannot see is a repointed pending pool owner, since the pool exposes no read of it; that case reverts at the acceptance action with MustBeProposedOwner. If a route is added directly before submission, the build-time check of the missing set fails closed: investigate, rebuild and resubmit.

Assumes:

  • CCIPTokenPoolConfig, CCIPTokenPoolConfigTimelock and CCIPTokenPoolConfigProposalChecker have been deployed on Ethereum mainnet and recorded in src/proposals/addresses.json and src/scripts/env.json.
  • The DAO MS has run CCIPTokenPoolConfigBatch.prepareHandover: both policies are active in the Kernel, CCIPTokenPoolConfig is the pending owner of the pool and the OCG timelock is the pending OHM administrator in the TokenAdminRegistry.
  • The OCG timelock holds the admin role.
  • The live Solana route of the pool matches olympus.config.CCIP.routes in src/scripts/env.json; the exact five routes to Arbitrum, Optimism, Base, Berachain and Robinhood Chain are declared there and missing from the pool.
  • The burn/mint pools of those five chains are deployed and recorded in src/scripts/env.json (olympus.policies.CCIPBurnMintTokenPool), since each route resolves its accepted remote pool from there unless it declares an explicit remotePools override; so is the OHM of Robinhood Chain (olympus.legacy.OHM), the default remote token of its route, which the tracked file records as the zero address until it is deployed.
  • The pool holds at least olympus.config.CCIP.minimumPoolBacking OHM (the supply outstanding on the burn/mint chains; CCIPTokenPoolBatch.fundPool).
  • Every mainnet lane toward the five chains carries an enabled OHM fee entry with a delivery gas budget of at least 175000, obtained from Chainlink.

Constants​

_ENV_PATH​

string internal constant _ENV_PATH = "./src/scripts/env.json";

_EXPECTED_ROUTE_COUNT​

The chain selectors of the five routes this proposal opens. The build fails closed unless the set of desired routes missing from the pool equals exactly this set.

uint256 internal constant _EXPECTED_ROUTE_COUNT = 5;

_ARBITRUM_SELECTOR​

uint64 internal constant _ARBITRUM_SELECTOR = 4949039107694359620;

_OPTIMISM_SELECTOR​

uint64 internal constant _OPTIMISM_SELECTOR = 3734403246176062136;

_BASE_SELECTOR​

uint64 internal constant _BASE_SELECTOR = 15971525489660198786;

_BERACHAIN_SELECTOR​

uint64 internal constant _BERACHAIN_SELECTOR = 1294465214383781161;

_ROBINHOOD_SELECTOR​

uint64 internal constant _ROBINHOOD_SELECTOR = 6180753054346818345;

State Variables​

_kernel​

Kernel internal _kernel;

Functions​

id​

function id() public pure override returns (uint256);

Returns

NameTypeDescription
<none>uint256

name​

function name() public pure override returns (string memory);

Returns

NameTypeDescription
<none>string

description​

function description() public pure override returns (string memory);

Returns

NameTypeDescription
<none>string

_descriptionPreamble​

function _descriptionPreamble() private pure returns (string memory);

Returns

NameTypeDescription
<none>string

_descriptionSteps​

function _descriptionSteps() private pure returns (string memory);

Returns

NameTypeDescription
<none>string

_deploy​

function _deploy(Addresses addresses, address) internal override;

Parameters

NameTypeDescription
addressesAddresses
_address

_build​

function _build(Addresses addresses) internal override;

Parameters

NameTypeDescription
addressesAddresses

_expectations​

Reads the live state that decides each conditional handover action and records the decisions as the expectations of the checker: for each action, whether it is included, which the checker turns into the precondition the action needs or the end state the action would have left.

Reverts with PendingMismatch when a two-step transfer is neither completed nor pending to the right party, and with AddressMismatch when the registry does not register the pool, when the pool ownership is to be accepted but the DAO MS does not own the pool, or when the grant of bridge_admin is needed but the OCG timelock does not administer RolesAdmin. The route selectors are filled by the caller from _missingRoutes.

function _expectations(
Contracts memory c,
CCIPConfigLib.DesiredConfig memory desired,
uint256 minBacking_
) internal view returns (ICCIPTokenPoolConfigProposalChecker.Expectations memory e);

Parameters

NameTypeDescription
cContracts
desiredCCIPConfigLib.DesiredConfig
minBacking_uint256

Returns

NameTypeDescription
eICCIPTokenPoolConfigProposalChecker.Expectations

_pushAuthorityActions​

Adds the registry and role actions the expectations include: accept the OHM administrator role and grant bridge_admin to the DAO MS.

function _pushAuthorityActions(
Contracts memory c,
ICCIPTokenPoolConfigProposalChecker.Expectations memory e
) internal;

Parameters

NameTypeDescription
cContracts
eICCIPTokenPoolConfigProposalChecker.Expectations

_pushConfigActions​

Adds the config policy and timelock actions the expectations include: enable the config policy, accept the pool ownership, set the config operator, the rebalancer and the rate limit admin, and enable the timelock.

function _pushConfigActions(
Contracts memory c,
ICCIPTokenPoolConfigProposalChecker.Expectations memory e
) internal;

Parameters

NameTypeDescription
cContracts
eICCIPTokenPoolConfigProposalChecker.Expectations

_missingRoutes​

Returns one addChain update per desired route missing from the pool, in remote chain name order with the remote chain names alongside, and requires the missing set to be exactly the five expected chains (Arbitrum, Optimism, Base, Berachain, Robinhood Chain). Each update passes the config policy's own validation.

Fails closed on any drift: a missing route outside the expected set (an undeclared selector cannot appear here since the routes come from env.json, so this means the declaration changed), or an expected route that is already configured (someone added it directly while the DAO MS still owned the pool). Both need investigation and a rebuild rather than a silently smaller proposal.

function _missingRoutes(
Contracts memory c
)
internal
view
returns (ICCIPTokenPoolAdmin.ChainUpdate[] memory updates, string[] memory names);

Parameters

NameTypeDescription
cContracts

Returns

NameTypeDescription
updatesICCIPTokenPoolAdmin.ChainUpdate[]
namesstring[]

_pushRouteActions​

Adds one addChain action per route update, in the order given.

function _pushRouteActions(
Contracts memory c,
ICCIPTokenPoolAdmin.ChainUpdate[] memory updates,
string[] memory names
) internal;

Parameters

NameTypeDescription
cContracts
updatesICCIPTokenPoolAdmin.ChainUpdate[]
namesstring[]

_selectorsOf​

The chain selectors of the route updates, in the same order.

function _selectorsOf(
ICCIPTokenPoolAdmin.ChainUpdate[] memory updates
) internal pure returns (uint64[] memory selectors);

Parameters

NameTypeDescription
updatesICCIPTokenPoolAdmin.ChainUpdate[]

Returns

NameTypeDescription
selectorsuint64[]

_endStateExpectations​

The expectations of the end state the proposal leaves: no handover action included, no route to add, the declared rebalancer, rate limit admin and minimum backing.

function _endStateExpectations(
CCIPConfigLib.DesiredConfig memory desired,
uint256 minBacking_
) internal pure returns (ICCIPTokenPoolConfigProposalChecker.Expectations memory e);

Parameters

NameTypeDescription
desiredCCIPConfigLib.DesiredConfig
minBacking_uint256

Returns

NameTypeDescription
eICCIPTokenPoolConfigProposalChecker.Expectations

_minimumPoolBacking​

Reads olympus.config.CCIP.minimumPoolBacking of the chain.

function _minimumPoolBacking() internal view returns (uint256 minBacking);

Returns

NameTypeDescription
minBackinguint256

_requireBackingAndFeeBudgets​

Reverts unless the pool holds the minimum backing and every mainnet lane toward a burn/mint destination carries the raised OHM delivery gas budget. Checked at build time and re-checked by _validate.

function _requireBackingAndFeeBudgets(Contracts memory c, uint256 minBacking_) internal view;

Parameters

NameTypeDescription
cContracts
minBacking_uint256

_run​

function _run(Addresses addresses, address) internal override;

Parameters

NameTypeDescription
addressesAddresses
_address

_validate​

function _validate(Addresses addresses, address) internal view override;

Parameters

NameTypeDescription
addressesAddresses
_address

_validateLifecycle​

function _validateLifecycle(Contracts memory c) internal view;

Parameters

NameTypeDescription
cContracts

_validatePoolAuthority​

function _validatePoolAuthority(
Contracts memory c,
CCIPConfigLib.DesiredConfig memory desired
) internal view;

Parameters

NameTypeDescription
cContracts
desiredCCIPConfigLib.DesiredConfig

_validateRegistry​

function _validateRegistry(Contracts memory c) internal view;

Parameters

NameTypeDescription
cContracts

_validateRoles​

function _validateRoles(Contracts memory c, address proposer) internal view;

Parameters

NameTypeDescription
cContracts
proposeraddress

_validateParameters​

function _validateParameters(
Contracts memory c,
CCIPConfigLib.DesiredConfig memory desired
) internal view;

Parameters

NameTypeDescription
cContracts
desiredCCIPConfigLib.DesiredConfig

_requireDeployment​

Reverts unless the config policy, the timelock and the pool are bound together, the pool serves OHM and the checker is bound to the same contracts and accounts.

function _requireDeployment(Contracts memory c) internal view;

Parameters

NameTypeDescription
cContracts

_requireCheckerBindings​

Reverts unless the checker reports the contracts and accounts this proposal acts on as its bindings.

function _requireCheckerBindings(Contracts memory c) internal view;

Parameters

NameTypeDescription
cContracts

_requireVersion​

Reverts unless the policy reports version 1.0.

function _requireVersion(address policy_) internal view;

Parameters

NameTypeDescription
policy_address

_requireActive​

Reverts unless the policy is active in the Kernel.

function _requireActive(address policy_) internal view;

Parameters

NameTypeDescription
policy_address

_requireEnabled​

Reverts unless the policy is enabled.

function _requireEnabled(address policy_) internal view;

Parameters

NameTypeDescription
policy_address

_requireRole​

Reverts unless the account holds the role.

function _requireRole(ROLESv1 roles_, bytes32 role_, address account_) internal view;

Parameters

NameTypeDescription
roles_ROLESv1
role_bytes32
account_address

_requireAddress​

Reverts unless the read address equals the expected one.

function _requireAddress(
string memory field_,
address actual_,
address expected_
) internal pure;

Parameters

NameTypeDescription
field_string
actual_address
expected_address

_requireParameter​

Reverts unless the read parameter equals the declared one.

function _requireParameter(
string memory name_,
uint256 actual_,
uint256 expected_
) internal pure;

Parameters

NameTypeDescription
name_string
actual_uint256
expected_uint256

_requireRoutesMatchEnv​

Reverts unless every route declared in env.json matches the pool field by field (existence, remote token, accepted remote pools and both rate limits), every live route of the pool is declared as enabled in env.json with both limiters enabled, and every route declared with enabled: false (the removal marker) is absent from the pool.

function _requireRoutesMatchEnv(
ICCIPTokenPoolAdmin pool_,
bool requireDesiredLive_
) internal view;

Parameters

NameTypeDescription
pool_ICCIPTokenPoolAdmin
requireDesiredLive_boolWhether a desired enabled route missing from the pool reverts.
The build passes false and requires the missing set to equal the five expected
chains instead; the post-execution validation passes true.

_requireLiveRoutesDeclared​

Reverts unless every live route of the pool is declared as enabled in env.json with both limiters enabled.

function _requireLiveRoutesDeclared(
ICCIPTokenPoolAdmin pool_,
CCIPConfigLib.DesiredRoute[] memory desired
) internal view;

Parameters

NameTypeDescription
pool_ICCIPTokenPoolAdmin
desiredCCIPConfigLib.DesiredRoute[]

_requireDesiredRoutesConverged​

Reverts unless every desired route matches the pool: a route declared with enabled: false is absent, an enabled route is present (when required) and matches field by field.

function _requireDesiredRoutesConverged(
ICCIPTokenPoolAdmin pool_,
CCIPConfigLib.DesiredRoute[] memory desired,
bool requireDesiredLive_
) internal view;

Parameters

NameTypeDescription
pool_ICCIPTokenPoolAdmin
desiredCCIPConfigLib.DesiredRoute[]
requireDesiredLive_bool

_contracts​

function _contracts(Addresses addresses) internal view returns (Contracts memory c);

Parameters

NameTypeDescription
addressesAddresses

Returns

NameTypeDescription
cContracts

_pendingOwner​

function _pendingOwner(address pool_) internal view returns (address pending);

Parameters

NameTypeDescription
pool_address

Returns

NameTypeDescription
pendingaddress

_readEnv​

Reads env.json, the desired-state source that the proposal validates the deployment and the routes against.

Read from disk on every use rather than cached in storage: run executes as one isolated transaction under the block gas limit, and storing the file would spend most of it.

function _readEnv() internal view virtual returns (string memory env);

Returns

NameTypeDescription
envstring

_chain​

function _chain() internal view returns (string memory chain);

Returns

NameTypeDescription
chainstring

Errors​

CCIPTokenPoolConfigProposal_AddressMismatch​

Thrown when an address read from the chain or from env.json differs from the expected one.

error CCIPTokenPoolConfigProposal_AddressMismatch(
string field,
address actual,
address expected
);

Parameters

NameTypeDescription
fieldstringThe name of the compared field.
actualaddressThe value read.
expectedaddressThe expected value.

CCIPTokenPoolConfigProposal_PendingMismatch​

Thrown when a two-step transfer is not in the expected state: at build time the expected value is the party that must accept (run CCIPTokenPoolConfigBatch.prepareHandover first), after execution it is the zero address.

error CCIPTokenPoolConfigProposal_PendingMismatch(
string field,
address pending,
address expected
);

Parameters

NameTypeDescription
fieldstringThe name of the transferred authority.
pendingaddressThe pending value read.
expectedaddressThe expected pending value.

CCIPTokenPoolConfigProposal_MissingRole​

Thrown when an account does not hold a required role.

error CCIPTokenPoolConfigProposal_MissingRole(bytes32 role, address account);

Parameters

NameTypeDescription
rolebytes32The role.
accountaddressThe account.

CCIPTokenPoolConfigProposal_RoleNotUnassigned​

Thrown when an account holds a role that must be unassigned at launch.

error CCIPTokenPoolConfigProposal_RoleNotUnassigned(bytes32 role, address account);

Parameters

NameTypeDescription
rolebytes32The role.
accountaddressThe account.

CCIPTokenPoolConfigProposal_PolicyNotActive​

Thrown when a policy is not active in the Kernel (run CCIPTokenPoolConfigBatch.prepareHandover first).

error CCIPTokenPoolConfigProposal_PolicyNotActive(address policy);

Parameters

NameTypeDescription
policyaddressThe policy.

CCIPTokenPoolConfigProposal_PolicyNotEnabled​

Thrown when a policy is not enabled.

error CCIPTokenPoolConfigProposal_PolicyNotEnabled(address policy);

Parameters

NameTypeDescription
policyaddressThe policy.

CCIPTokenPoolConfigProposal_NotLiquidityContainer​

Thrown when the pool does not advertise the liquidity container interface.

error CCIPTokenPoolConfigProposal_NotLiquidityContainer(address pool);

Parameters

NameTypeDescription
pooladdressThe pool.

CCIPTokenPoolConfigProposal_VersionMismatch​

Thrown when a policy does not report version 1.0.

error CCIPTokenPoolConfigProposal_VersionMismatch(address policy, uint8 major, uint8 minor);

Parameters

NameTypeDescription
policyaddressThe policy.
majoruint8The reported major version.
minoruint8The reported minor version.

CCIPTokenPoolConfigProposal_ParameterMismatch​

Thrown when a numeric parameter differs from the value declared in env.json.

error CCIPTokenPoolConfigProposal_ParameterMismatch(
string name,
uint256 actual,
uint256 expected
);

Parameters

NameTypeDescription
namestringThe parameter name.
actualuint256The value read.
expecteduint256The declared value.

CCIPTokenPoolConfigProposal_NoRoutesDeclared​

Thrown when env.json declares no CCIP route for the chain.

error CCIPTokenPoolConfigProposal_NoRoutesDeclared();

CCIPTokenPoolConfigProposal_RouteUndeclared​

Thrown when a live route of the pool is not declared as enabled in env.json.

error CCIPTokenPoolConfigProposal_RouteUndeclared(uint64 chainSelector);

Parameters

NameTypeDescription
chainSelectoruint64The chain selector of the route.

CCIPTokenPoolConfigProposal_RouteLimiterDisabled​

Thrown when a live route carries a disabled rate limiter.

error CCIPTokenPoolConfigProposal_RouteLimiterDisabled(uint64 chainSelector);

Parameters

NameTypeDescription
chainSelectoruint64The chain selector of the route.

CCIPTokenPoolConfigProposal_RouteNotRemoved​

Thrown when a route declared with enabled: false is still configured on the pool (remove it through CCIPRouteReconcileBatch before the proposal).

error CCIPTokenPoolConfigProposal_RouteNotRemoved(string remoteChain);

Parameters

NameTypeDescription
remoteChainstringThe remote chain name.

CCIPTokenPoolConfigProposal_RouteMissing​

Thrown when an enabled desired route is not configured on the pool after execution.

error CCIPTokenPoolConfigProposal_RouteMissing(string remoteChain);

Parameters

NameTypeDescription
remoteChainstringThe remote chain name.

CCIPTokenPoolConfigProposal_RouteDrift​

Thrown when a live route differs from its env.json declaration (reconcile it before the proposal: direct pool owner batch before the handover, config timelock afterwards).

error CCIPTokenPoolConfigProposal_RouteDrift(string remoteChain);

Parameters

NameTypeDescription
remoteChainstringThe remote chain name.

CCIPTokenPoolConfigProposal_UnexpectedMissingRoute​

Thrown when a desired route missing from the pool is not one of the five chains this proposal opens.

error CCIPTokenPoolConfigProposal_UnexpectedMissingRoute(string remoteChain);

Parameters

NameTypeDescription
remoteChainstringThe remote chain name.

CCIPTokenPoolConfigProposal_MissingRouteSetMismatch​

Thrown when the set of desired routes missing from the pool is not exactly the five chains this proposal opens (investigate, rebuild and resubmit).

error CCIPTokenPoolConfigProposal_MissingRouteSetMismatch(
uint256 missingCount,
uint256 expectedCount
);

Parameters

NameTypeDescription
missingCountuint256The number of missing routes among the expected chains.
expectedCountuint256The number of expected chains.

CCIPTokenPoolConfigProposal_BackingTooLow​

Thrown when the pool holds less OHM than olympus.config.CCIP.minimumPoolBacking (re-read shell/calc_bridged_supply.sh and run CCIPTokenPoolBatch.fundPool first).

error CCIPTokenPoolConfigProposal_BackingTooLow(uint256 balance, uint256 minimum);

Parameters

NameTypeDescription
balanceuint256The OHM balance of the pool.
minimumuint256The required minimum.

Structs​

Contracts​

The contracts and accounts the proposal acts on, resolved from the address registry.

struct Contracts {
ICCIPTokenPoolConfig config;
ICCIPTokenPoolConfigTimelock configTimelock;
CCIPTokenPoolConfigProposalChecker checker;
ICCIPTokenPoolAdmin pool;
ICCIPTokenAdminRegistry registry;
ROLESv1 roles;
address rolesAdmin;
address ohm;
address daoMS;
address emergencyMS;
address ocgTimelock;
address bridge;
}

Properties

NameTypeDescription
configICCIPTokenPoolConfig
configTimelockICCIPTokenPoolConfigTimelock
checkerCCIPTokenPoolConfigProposalChecker
poolICCIPTokenPoolAdmin
registryICCIPTokenAdminRegistry
rolesROLESv1
rolesAdminaddress
ohmaddress
daoMSaddress
emergencyMSaddress
ocgTimelockaddress
bridgeaddress