Architecture
Last updated
Last updated
TODO:
Migrate references to ZNM
Update links to stale documentation + old monorepo
This document describes a governable system for executing permissioned actions across chains.
We aim to clearly describe
what contracts comprise the system for calling permissioned functions across chains
which functions will be delegated to this system at launch, and
(directionally) who will have permission to call these functions at launch and in the future
This document does NOT describe a system for how governance actions will be proposed, voted on, and/or approved before being executed.
It does not describe how contract upgrades will be written, reviewed, verified.
We define a role, governor
, with the power to perform permissioned actions across chains. In order to empower the governor
, we deploy a cross-chain application comprised of a GovernanceRouter
contract on each chain.
Each GovernanceRouter
can be delegated control over an arbitrary set of permissioned functions on its local chain. The only way to access the permissioned functionality is to call the function via the GovernanceRouter
contract.
Each GovernanceRouter
is programmed to accept messages only from the governor
, which is deployed on only one chain. The governor
may call the contract locally (if it is deployed on the same chain), or it may send it messages remotely via Nomad. Because of its exclusive power over the GovernanceRouter
contracts, the governor
has exclusive rights to perform all of the permissioned roles that are delegated to the GovernanceRouter
on each chain.
The system receives orders from the governor
and carries out their effects across chains; it is agnostic to how the governor
chooses to operate. This maintains flexibility to design the governance proposal process in the future.
At launch, the governor
will be a multisig of trusted team and community members. In the near future, the governor
role will most likely be transferred to a more fully-featured set of contracts capable of accepting proposals, tallying votes, and executing successful proposals.
governor
sends message to its local GovernanceRouter
GovernanceRouter
dispatches the message...
if the recipient is local, to the recipient directly (→ process finished)
if the recipient is remote, via Nomad to the local Home contract (→ continue to 3)
Message is relayed from local Home
to remote Replica
via Nomad
Replica
dispatches message to the remote GovernanceRouter
GovernanceRouter
dispatched the message directly to the local recipient
Note on message recipient:
the recipient may be a Replica
or Home
contract
it may be an UpgradeBeacon
that controls the implementation of Replica
or Home
it may be any other app
For simplicity & clarity to show the message flow, this diagram represents the recipient as a generic "App"
xApp - Cross-Chain Application
role —
an address stored in a smart contract's state that specifies an entity with special permissions on the contract
permission to call certain functions is usually implemented using a function modifier that requires that the caller of the function is one of the roles with permission to call it; all contract calls sent from callers that do not have valid permission will revert
permissioned function —
any smart contract function that restricts callers of the function to a certain role or roles
permissioned call — a call to a permissioned function
governor chain —
the chain on which the governor
is deployed
the chain whose GovernanceRouter
is also the special GovernorRouter
which can send messages; all GovernanceRouters
on other chains can only receive governance messages
GovernanceRouter
xApp designed to perform permissioned roles on core Nomad contracts on all chains
State Variables
governor state variable
if the governor
is local, governor
will be set to the EVM address of the governor
if the governor
is remote, governor
will be address(0)
governorDomain state variable
the Nomad domain of the governor chain
stored as a state variable on all GovernanceRouters
; should be the same on all GovernanceRouters
; always non-zero
if the governor
is local, governorDomain
is equal to the originDomain
of the local Home
contract
if the governor
is remote, governorDomain
is equal to the originDomain
of the remote Home
contract
equal to the originDomain
of the local Home
contract on the chain of the GovernorRouter
used by all GovernanceRouters
to determine whether an incoming Nomad message was sent from the GovernorRouter
if the message is from the GovernorRouter
, the GovernanceRouter
will handle the incoming message
if not, it will revert
routers state variable
a mapping of domain → address of the remote GovernanceRouter
on every other chain
domains state variable
an array of all domains that are registered in routers
used to loop through and message all other chains when taking governance actions
there is the possibility that some domains in the array are null (if a chain has been de-registered)
GovernorRouter
the special GovernanceRouter
that has permission to send governance messages to all other GovernanceRouters
the GovernanceRouter
on the governor chain
Governor
via the GovernanceRouter
system, it has the unique ability to call permissioned functions on any contract on any chain that transfers permission to the local GovernanceRouter
the role with permission to send messages to the GovernorRouter
the GovernorRouter
has exclusive permission to send messages via Nomad to all other GovernanceRouters
the GovernanceRouters
can have arbitrary permissions delegated to them by any contract on their local chain
therefore, the governor
is the entity with the power to call any permissioned function delegated to any GovernanceRouter
on any chain
there is only one governor
throughout the Nomad system; it can be deployed on any chain
the governor
role can always be transferred to another contract, on the same chain or a different remote chain
stored as a state variable on GovernanceRouters
; set to zero on all GovernanceRouters
except on the governor chain
Any contract on any chain that wishes for this governance system to have discretion to call a set of its functions can create a role & a function modifier giving exclusive permission to that role to call the function(s) (similar pattern to Ownable). The contract must then set the local GovernanceRouter
to the permissioned role, which — by extension — gives the governor
exclusive permission to call those functions (regardless of whether the governor
is remote or local)
If there is fraud on the Nomad Home
contract on the governor chain, this is currently a "catastrophic failure state" — no further governance actions can be rolled out to remote chains; we must create a plan to recover the system in this case.
for each chain, the governor
constructs the array of (to, data)
calls to the permissioned functions on the contracts that will perform the upgrades on that chain
the governor
sends a transaction to the GovernanceRouter.callRemote
function on its local the , passing in the domain
of the remote chain and the array of (to, data)
calls of transactions to execute on that chain
the local GovernanceRouter
constructs an Nomad-compatible message from the array of calls, addresses the message to the remote GovernanceRouter
, and sends the message to the local Home
contract
the message is relayed from the local Home
to the remote Replica
contract on the specified domain
the Replica
dispatches the message to the specified recipient, which is the local GovernanceRouter
the GovernanceRouter
parses the message to decode the array of (to, data)
calls
the GovernanceRouter
uses low-level call to execute each of the transactions in the array within the local chain
Possible State Transitions
called by the local owner to transfer ownership to another local owner (domain
does not change, owner
changes to a new bytes32
address)
called by the local owner to transfer ownership to a remote owner (domain
changes to the remote, owner
changes from a non-zero bytes32
to bytes32(0)
)
called by a remote owner to transfer ownership to a local owner (domain
changes to the local domain, owner
changes from bytes32(0)
to a non-zero bytes32
)
called by a remote owner to transfer ownership to another remote owner (domain
changes to the new remote owner, owner
remains bytes32(0)
)
used when a new chain is added to Nomad after we've already set up the system and transferred governorship
add a new domain → address mapping to the routers
mapping on every other GovernanceRouter
At launch, the GovernanceRouter
system will have the following permissions:
upgrade the implementation of Home
(via UpgradeBeacon
pattern)
upgrade the implementation of all Replicas
(via 1-to-N UpgradeBeacon
pattern)
upgrade the implementation of itself (via UpgradeBeacon
pattern)
The GovernanceRouter
will NOT have permission to:
un-enroll a Replica
from the UsingNomad
contract, which will require a specialized role that can act quickly
The flexibility of this system will support a move to progressive decentralization.
Initially, the governor
will most likely be a multisig controlled by trusted team and community members
Later, the governor
role will most likely be transferred to a decentralized governance contract
At launch, the core functionality that will be delegated to the GovernanceRouter
on each chain is the power to upgrade the implementation of the Home
and Replica
contracts. This way, the governor
will have the power to conduct upgrades of the Nomad system on every chain. More details on the upgradability system can be found .
example: owner
is the role set on all contracts upon deployment; the owner
role has exclusive permission to call functions with the onlyOwner
modifier
example: functions using the onlyOwner
modifier on contracts