CGM Architecture
There are currently two Chain Fusion Governance Module (CGM) archetypes, the ICP Treasury, which is deployed on Q and ICP and can hold tokens natively on ICP; and the Chain Fusion Treasury Hub, which utilizes ICP to govern assets on one or multiple foreign chains.
Each deployed instance, the CGM consists of multiple components, deployed on the chains that are involved. Depending on the archetype and individual use case, these are:
- DAO and DAO Module Smart Contracts on the Q Blockchain
- Backend Canisters on the Internet Computer Protocol (ICP)
- One or multiple Treasury contracts on the foreign-chains (e.g. an EVM L2)
To better understand the components, an overview of all component functions is given below.
ICP Treasury
Contract/ Canister | Network | Explanation | Source Code |
---|---|---|---|
ICP Treasury Module | Q | Can be used by Chain Fusion DAO to govern a treasury on ICP. Specifically for transferring native ICP or other ICRC tokens. | DAO Module Smart Contract |
ICP Treasury | ICP | Reads the state on the ICP Treasury Module on Q and executes token transfers on ICP. It is configured to only work in combination with one dedicated ICP Treasury Module on Q and initialized with its address. Transfers can only be executed on ICP once for any relevant and successfully executed proposal on Q. | Canister Elements |
Chain Fusion Treasury Hub
Contract/ Canister | Network | Explanation | Source Code |
---|---|---|---|
Chain Fusion Treasury Hub Module | Q | Can be used by Chain Fusion DAO to govern one or multiple treasuries on any EVM chain. Specifically, for transferring the destination-chain’s native token or ERC20 tokens. | DAO Module Smart Contract |
Chain Fusion Treasury Hub | ICP | Reads the state on the Chain Fusion Treasury Hub Module on Q and relays a transfer transation to a dedicated treasury contract on the destination-chain. It is configured to only work in combination with one dedicated Chain Fusion Treasury Hub Module on Q and initialized with its address. However, multiple treasuries on foreign chains can be configured to be called by this canister. Therefore, this canister has a dedicated EVM address in addition to its identifier on ICP. Foreign-chain transfers can only be executed once for any relevant and successfully executed proposal on Q. | Canister Elements |
Foreign-Chain Treasury | [Any EVM based chain] | A treasury smart contract to be deployed on any foreign EVM chain. It can hold the chain’s native token, as well as other ERC20 tokens. It is configured to only allow transfers if called by the respective Chain Fusion Treasury Hub canister’s EVM address and thereby can only be used by the DAO on Q through oRicial proposals. | Smart Contract |
Component Functions
The following sections dive deeper into the components introduced above and explain the most important functions of each component.
DAO Module Smart Contracts
Depending on whether a DAO wants to use the ICP Treasury or the Chain Fusion Hub, a respective DAO module contract needs to be deployed on Q and added to the DAO. Since the focus of this section of the documentation lays in explaining the integration between Chain Fusion and Q, the functions crucial for achieving the respective use case are discussed in the tables below. Other internal functions (i.e. for configuring the module) can be found in the source code provided above.
ICP Treasury Module (Q DAO Side)
Function | Input | Called by | Explanation |
---|---|---|---|
sendICRCTokens | string (token); string (recipient); uint (amount) | DAOVoting Contract | Provides all relevant information for calling the ‘icrc1_transfer’ function of the provided token to be executed by the ICP Treasury canister. This function can only be called by the DAO after a successful proposal. |
sendICPTokens | string (recipient); uint (amount) | DAOVoting Contract | Analogous to the sendICRCTokens function described above, but the ICP token address is pre-configured, so this function can only be used to transfer the native ICP token. This function can only be called by the DAO after a successful proposal. |
getICPMessage | uint256 (messageId_) | ICP Treasury (canister) | Provides a message that was approved through a sucessfully executed DAO proposal and that contains the details of a token transfer (either ICRC or ICP) to be executed by the ICP Treasury canister. |
getNextICPMessageId | none | it depends | Returns the number of messages approved through sucessfully executed DAO proposals. This functiton is used internally by the module, but also by the Chain Fusion Treasury Hub canister when calling ‘icp_execute_last_message’ |
[internal functions] | it depends | it depends | Various functions used for configuring and utilizing the module by the DAO. |
Chain Fusion Treasury Hub Module (Q DAO Side)
Function | Input | Called by | Explanation |
---|---|---|---|
setDestinationChainData | string (chain); address (treasury contract) | DAOVoting Contract | Configures the DAO module to utilize the treasury contract address for a specific foreign chain as provided. It also provides the information for setting up the Chain Fusion Treasury Hub canister on ICP. The function only needs to be called once for every foreign-chain treasury during configuration. It can only be called by the DAO after a successful proposal. |
sendNativeEVM | address (recipient); unit (amount); string (chain) | DAOVoting Contract | Provides all relevant information for building a transaction to call the foreign-chain treasury from the Chain Fusion Treasury Hub canister and transfer the foreign-chain’s native token from the foreign-chain treasury. Hence this function takes the address of the recipient on the foreign- chain, the amount to be sent and the identifier of the destination chain used when calling ‘setDestinationChainAddress’. When defining the amount, pay attention to the native token’s decimals (18 for ETH) and add sufficient trailing zeros. This function can only be called by the DAO after a successful proposal. |
sendERC20EVM | Address (token); address (recipient); unit (amount); string (chain) | DAOVoting Contract | Provides all relevant information for building a transaction to call the foreign-chain treasury from the Chain Fusion Treasury Hub canister and transfer a specific ERC20 token from the foreign-chain treasury. Hence this function takes the addresses of the desired token and of the recipient on the foreign-chain, the amount to be sent and the identifier of the destination chain used when calling ‘setDestinationChainAddress’. When defining the amount, pay attention to the native token’s decimals (18 for ETH) and add sufficient trailing zeros. This function can only be called by the DAO after a successful proposal. |
getEVMMessage | uint256 (messageId_) | Chain Fusion Treasury Hub (canister) | Provides a message that was approved through a sucessfully executed DAO proposal and that contains the details of a transaction to be executed by the Chain Fusion Treasury Hub canister for transferring funds from the foreign-chain treasury. |
getNextEVMMessageId | none | it depends | Returns the number of messages approved by the DAO. It is used internally by the module, but also by the Chain Fusion Treasury Hub canister when calling ‘evm_execute_last_message’ |
[internal functions] | it depends | it depends | Various functions used for configuring and utilizing the module by the DAO. |
Backend Canisters
As mentioned above, this documentation introduces two Archetypes, the ICP Treasury and the Chain Fusion Treasury Hub . For improved readability, the tables below are structured to first discuss the functions which are unique to the respective canister. A table of functions that are implemented on both canisters is provided at the end of this section.
Unique to ICP Treasury
Function | Input | Called By | Explanation |
---|---|---|---|
icp_execute_last_message | none | anyone | Retrieves the last message that was approved by the DAO through an ICP Treasury Module Vote and executes it on ICP according to the details provided. Depending on the function called by the module and its input, the execution triggers a transfer of the defined amount of ICP tokens or another ICRC token held by the ICP Treasury canister to the recipient provided. It is also used when (re-)configuring the canister through the DAO. |
icp_execute_message | nat | anyone | Executes the same type of message, but instead of retrieving the last message, it executes a dedicated message, as provided by the input parameter. This is relevant, when multiple ICP Treasury Module Vote proposals have been passed and executed simultaneously on Q, but have not yet been executed on ICP. |
|
Unique to Chain Fusion Treasury Hub canister
Function | Input | Called By | Explanation |
---|---|---|---|
evm_execute_last_message | none | anyone | Retrieves the last message that was approved by the DAO through a Chain Fusion Treasury Hub Module Vote and executes it on the foreign-chain according to the details provided. Depending on the function called by the module and its input, the execution triggers the foreign-chain treasury to transfer of the defined amount of native tokens or of the defined ERC20 token held by the foreign-chain treasury to the recipient provided. t is also used when (re-)configuring the canister through the DAO. |
evm_execute_message | nat | anyone | Executes the same type of message as above, but instead of retrieving the last message, it executes a dedicated message, as provided by the input parameter. This is relevant, when multiple Chain Fusion Treasury Hub Module Vote proposals have been passed and executed simultaneously. |
eth_address | none | anyone | Returns the canister’s EVM address. It is used to call the transfer function on the foreign-chain treasury. The user needs to know this address to set up the foreign-chain treasury and to fund it with gas tokens for transaction fees on the foreign-chain. |
sync_foreign_chain_data | Text (chain) | anyone | Configures the canister to add a foreign-chain treasury, as identified by the chain name provided. New treasuries can only be added after a sucessful proposal in the DAO, which calls ‘setDestinationChainData’ on Q. In the DAO proposal, the corresponding RPC of the foreign-chain and the address of the treasury contract are provided. |
get_foreign_chain_id_data | text | anyone | Returns the numeric chainID linked to a specific chain name as set when calling ‘set_foreign_chain_data'. |
get_foreign_rpc_data | text | anyone | Returns the RPC URL linked to a specific chain name as set when calling ‘set_foreign_chain_data'. |
is_evm_message_executed | nat | anyone | Utility function that is used to check if a message with a specific ID has already been executed. |
Common functions for both canisters
- [!] Note: the functions callable by the 'canister owner' are available to set up the canister. Ownership should be revoked after setup.
Function | Input | Called By | Explanation |
---|---|---|---|
get_canister_rpcs | none | anyone | Returns a list of the RPCs used to verify messages from the DAO module to the respective canister. |
remove_existing_rpc | text | only canister owner | Allows removing individual RPCs. |
get_current_module_address | none | anyone | Returns the address of the DAO Module on Q that the respective canister is configured with. |
get_canister_owners | none | anyone | Returns a list of principals which are privileged to configure the canister. |
add_new_owner | principal | only canister owner | Allows adding new principals, privileged to configure the canister (to be revoked after configuration phase). |
remove_existing_owner | principal | only canister owner | Allows removing principals from being privileged to configure the canister. |
get_account_identifier_from_principal | principal | anyone | Utility function which returns the account identifier to a given principal. |
get_canister_principal | none | anyone | Utility function which returns the canisters principal identifier. |
get_canister_identifier | none | anyone | Utility function which returns the canisters identifier. |
update_current_module_address | none | anyone | Updates the address of which DAO module can control the canister. This enables a migration of the Treasury or Hub from one DAO module to another, or even to a completely new DAO. This function can only be sucessfully after a successful DAO Proposal on the existing DAO module (Calling the setDestinationChainData funciton on Q) |
Treasury contracts on the foreign-chains
The contract on the foreign chain is configured to only handle and execute the transactions provided by the DAO through the Chain Fusion Treasury Hub. In the Treasury case, this is limited to the transfer of funds, either in the foreign-chain's native token, or ERC-20 tokens.
Other user Facing DAO Functions of (on Q)
Besides the components unique to the CGM, this documentation would be incomplete without addressing the role of a DAO's system smart contracts. Below is a selected list of functions which are called directly by the end-user (DAO member) when using the CGM through their DAO:
Function | Input | Explanation | Applicable Smart Contract |
---|---|---|---|
approve | address (_spender); uint256 (_value) | Approve a transfer of DAO Tokens to the DAO Vault. | DAO Token |
depositERC20/ [or depositNFT] | address (tokenAddress_); uint256 (amount_)/ [or uint256 tokenId_] | Transfer DAO Tokens to the DAO Vault. This gives the voting power within the DAO to the user and allows them to create and vote on proposals. | DAO Vault |
createProposal | string (situation_), string (remark_), bytes (callData_) | In this case this will be creating an "ICP Treasury Module Voting" or “Chain Fusion Treasury Hub Module Voting “(situation_), with a description for DAO Members to understand the proposal (remark_) and the necessary call data to call the respective transfer function with the correct input (callData_). The call data contains the information which function to call, and the input parameters like token identifier, recipient address and the amount to transfer. | DAOVoting Contract |
voteFor (or voteAgainst) | uint256 (_proposalId) | Vote on a specific proposal. In this case the ICP Treasury Module Voting or Chain Fusion Treasury Hub Module Voting. | DAOVoting Contract |
executeProposal | uint256 (_proposalId) | Execute the Proposal (if successful) and call the ICP Treasury Module or Chain Fusion Treasury Hub Module (via the Voting Contract). | DAOVoting Contract |