Integrating a New Chain Family
This guide provides a comprehensive overview for engineers adding MCMS (Many Chain Multi-Sig) support to a new blockchain family.
Introduction
What is MCMS?
MCMS is a cross-chain governance system that allows for secure execution of operations across multiple blockchain families. The chain family SDK provides the necessary abstractions to integrate MCMS with different blockchain ecosystems.
Integration Overview
Adding support for a new chain family involves:
- Implementing core SDK interfaces for contract interaction
- Creating chain-specific encoders and decoders
- Writing comprehensive unit and end-to-end tests
- Optionally implementing simulation and timelock functionality
Prerequisites
Before starting, you should have:
- Strong understanding of Go programming
- Deep knowledge of the target blockchain's architecture, transaction format, and smart contract capabilities
- Familiarity with MCMS core concepts (see Key Concepts)
- Understanding of the target chain's RPC interfaces and client libraries
SDK Interfaces Overview
All chain family integrations must implement interfaces defined in the /sdk folder. Here's a complete overview:
| Interface | Status | Purpose | Definition |
|---|---|---|---|
Executor | Required | Execute MCMS operations on-chain | executor.go |
Inspector | Required | Query MCMS contract state | inspector.go |
Encoder | Required | Hash operations and metadata | encoder.go |
ConfigTransformer | Required | Convert between chain-agnostic and chain-specific configs | config_transformer.go |
Configurer | Required | Update MCMS contract configuration | configurer.go |
Decoder | Optional | Decode transaction data for human readability | decoder.go |
Simulator | Optional | Simulate transactions before execution | simulator.go |
TimelockExecutor | Required | Execute timelock operations | timelock_executor.go |
TimelockInspector | Required | Query timelock contract state | timelock_inspector.go |
TimelockConverter | Required | Convert batch operations to timelock operations | timelock_converter.go |
Required Interfaces
Executor Interface
The Executor is the primary interface for executing MCMS operations on your chain. It embeds both Inspector and Encoder interfaces.
Interface Definition: sdk/executor.go
Key Methods:
ExecuteOperation(ctx, metadata, nonce, proof, op)- Executes a single MCMS operationSetRoot(ctx, metadata, proof, root, validUntil, signatures)- Sets a new Merkle root with signatures
Implementation Examples:
- EVM Executor - Uses go-ethereum bindings
- Solana Executor - Uses Solana program instructions
- Aptos Executor - Uses Move entry functions
- Sui Executor - Uses Sui Move transactions
Key Considerations:
- Return
types.TransactionResultwith transaction hash and chain family - Handle chain-specific transaction signing and submission
- Properly format proofs and signatures for your chain
Inspector Interface
The Inspector queries on-chain state of MCMS contracts.
Interface Definition: sdk/inspector.go
Key Methods:
GetConfig(ctx, mcmAddr)- Retrieves current MCMS configurationGetOpCount(ctx, mcmAddr)- Gets the current operation countGetRoot(ctx, mcmAddr)- Returns the current Merkle root and valid until timestampGetRootMetadata(ctx, mcmAddr)- Gets metadata for the current root
Implementation Examples:
Key Considerations:
- Use chain-specific RPC clients to query contract state
- Parse chain-specific data structures into common
types.Configformat - Handle chain-specific address formats
Encoder Interface
The Encoder creates chain-specific hashes for operations and metadata.
Interface Definition: sdk/encoder.go
Key Methods:
HashOperation(opCount, metadata, op)- Creates a hash of an operationHashMetadata(metadata)- Creates a hash of chain metadata
Implementation Examples:
- EVM Encoder - Uses Solidity keccak256 encoding
- Solana Encoder - Uses Borsh serialization + SHA256
- Aptos Encoder - Uses BCS serialization + SHA3-256
- Sui Encoder - Uses BCS serialization + Blake2b
Key Considerations:
- Match the exact hashing algorithm used by your on-chain contract
- Ensure byte-level encoding matches contract expectations
- Test hash compatibility with contract thoroughly
ConfigTransformer Interface
The ConfigTransformer converts between chain-agnostic types.Config and chain-specific configuration structures.
Interface Definition: sdk/config_transformer.go
Key Methods:
ToChainConfig(cfg, chainSpecificConfig)- Converts to chain-specific formatToConfig(onchainConfig)- Converts from chain-specific format to common format
Implementation Examples:
Key Considerations:
- Handle address format conversions between chain-specific and common formats
- Preserve all configuration fields during round-trip conversion
- Support chain-specific configuration parameters via the generic
Ctype parameter
Configurer Interface
The Configurer updates MCMS contract configuration on-chain.
Interface Definition: sdk/configurer.go
Key Methods:
SetConfig(ctx, mcmAddr, cfg, clearRoot)- Updates the MCMS configuration
Implementation Examples:
Key Considerations:
- Requires administrative/owner privileges on the MCMS contract
- Handle the
clearRootparameter to optionally clear the current root - Return transaction result with hash and status
Optional Interfaces
Decoder Interface
Implement Decoder if your chain supports decoding transaction calldata into human-readable format.
Interface Definition: sdk/decoder.go
Key Methods:
Decode(op, contractInterfaces)- Decodes transaction data using contract interfaces
Return Type: sdk/decoded_operation.go
Implementations:
- EVM Decoder - Uses ABI parsing
- Aptos Decoder - Uses Move ABI
- Sui Decoder - Uses Move ABI
- Note: Solana does not implement decoding
When to Implement:
- Your chain has a standardized interface definition language (like ABI)
- Transaction calldata can be parsed into method names and arguments
- Useful for debugging and operation visualization
Simulator Interface
Implement Simulator if your chain supports transaction simulation/dry-run before execution.
Interface Definition: sdk/simulator.go
Key Methods:
SimulateSetRoot(ctx, originCaller, metadata, proof, root, validUntil, signatures)- Simulates setting a rootSimulateOperation(ctx, metadata, operation)- Simulates executing an operation
Implementations:
- EVM Simulator - Uses
eth_call - Solana Simulator - Uses
simulateTransactionRPC - Sui Simulator - Uses
devInspectTransactionBlock - Note: Aptos does not currently implement simulation
When to Implement:
- Your chain's RPC supports simulation/dry-run capabilities
- Allows validation before actual on-chain execution
- Helps detect errors early without spending gas
Timelock Interfaces
If your chain supports timelock functionality (scheduled/delayed execution), implement these interfaces:
TimelockExecutor Interface
Interface Definition: sdk/timelock_executor.go
Embeds TimelockInspector and adds the Execute method for executing scheduled operations.
Implementations:
TimelockInspector Interface
Interface Definition: sdk/timelock_inspector.go
Queries timelock contract state including roles, operation status, and minimum delay.
Key Methods:
GetProposers,GetExecutors,GetBypassers,GetCancellers- Query role membersIsOperation,IsOperationPending,IsOperationReady,IsOperationDone- Check operation statusGetMinDelay- Get minimum timelock delay
Implementations:
TimelockConverter Interface
Interface Definition: sdk/timelock_converter.go
Converts batch operations into chain-specific timelock operations.
Key Methods:
ConvertBatchToChainOperations- Converts batch to chain operations with timelock scheduling
Implementations:
Implementation Guidelines
Package Structure
Create a new package under /sdk/<chain-family>/ with the following typical structure:
sdk/
└── <chain-family>/
├── encoder.go # Encoder implementation
├── encoder_test.go # Encoder tests
├── executor.go # Executor implementation
├── executor_test.go # Executor tests
├── inspector.go # Inspector implementation
├── inspector_test.go # Inspector tests
├── configurer.go # Configurer implementation
├── configurer_test.go # Configurer tests
├── config_transformer.go # ConfigTransformer implementation
├── config_transformer_test.go # ConfigTransformer tests
├── decoder.go # Decoder implementation (optional)
├── decoder_test.go # Decoder tests
├── simulator.go # Simulator implementation (optional)
├── simulator_test.go # Simulator tests
├── timelock_executor.go # TimelockExecutor (if supported)
├── timelock_executor_test.go
├── timelock_inspector.go # TimelockInspector (if supported)
├── timelock_inspector_test.go
├── timelock_converter.go # TimelockConverter (if supported)
├── timelock_converter_test.go
├── transaction.go # Transaction utilities
├── transaction_test.go
├── utils.go # Chain-specific helpers
├── utils_test.go
└── mocks/ # Generated mocks for testing
└── ...
Reference: See sdk/evm/ for a complete example.
Chain-Specific Considerations
Transaction Formatting
- Each chain has unique transaction structures (e.g., EVM calldata, Solana instructions, Move entry functions)
- Ensure your implementation correctly formats transactions for contract calls
- Handle nonce/sequence numbers according to chain requirements
Address Encoding
- Implement conversion between chain-specific address formats (hex, base58, bech32, etc.) and common representations
- Store addresses in a consistent format within
types.Config - See types/chain_metadata.go for metadata requirements
Signature Handling
- Different chains use different signature schemes (ECDSA, EdDSA, etc.)
- Ensure signature verification matches on-chain expectations
- Handle signature serialization correctly (r,s,v format vs compact format, etc.)
Chain Metadata Requirements
- Define required metadata fields in
types.ChainMetadata - Include MCMS contract address and chain selector
- Add chain-specific parameters as needed
Additional Fields in Operations
- Use
types.Transaction.AdditionalFields(JSON) for chain-specific data - Examples: Solana account lists, Aptos type arguments, Sui object references
- Document expected structure for your chain
Error Handling
Use the /sdk/errors/ package for standardized error handling:
Reference: sdk/errors/errors.go
Common Error Patterns:
- Wrap errors with context using
fmt.Errorf("operation failed: %w", err) - Return specific errors for common failure cases (insufficient signatures, invalid proof, etc.)
- Use typed errors for cases that callers may need to handle specifically
Testing Requirements
Unit Tests
Each interface implementation needs a corresponding _test.go file with comprehensive coverage (>80%). Test all public methods with both success and failure cases using table-driven tests. Mock external dependencies (RPC clients, contracts) in sdk/<chain>/mocks/.
Test Examples:
E2E Tests
Create test suite under /e2e/tests/<chain-family>/ covering:
| Test Category | Example | Key Coverage |
|---|---|---|
| Config Management | solana/set_config.go | Set/update config, retrieve and verify, clearRoot flag |
| Root Operations | solana/set_root.go | Set root with signatures, quorum requirements, expiration |
| Operation Execution | solana/execute.go | Execute with valid proof, verify effects, test invalid proofs |
| Contract Inspection | solana/inspection.go | Query config, op count, root, metadata |
| Simulation (optional) | solana/simulator.go | Simulate valid/invalid ops, verify no state changes |
| Timelock Conversion (optional) | solana/timelock_converter.go | Convert batch to timelock ops, verify IDs and actions |
| Timelock Execution (optional) | solana/timelock_execution.go | Schedule with delay, execute after delay, predecessors |
| Timelock Inspection (optional) | solana/timelock_inspection.go | Query roles, operation status, minimum delay |
| Timelock Cancellation (optional) | aptos/timelock_cancel.go | Cancel pending ops, verify cancellation |
Test Suite Setup:
- Create
e2e/config.<chain>.toml(example) - Update e2e/tests/setup.go with blockchain node and RPC clients
- Add suite to e2e/tests/runner_test.go
- Create helpers in
common.go(example)
Reference Implementations
When implementing your integration, refer to these existing implementations:
- EVM: sdk/evm/ - Most mature, includes all features
- Solana: sdk/solana/ - Excellent example of chain-specific complexity
- Aptos: sdk/aptos/ - Move-based chain without simulation
- Sui: sdk/sui/ - Recent addition with good patterns