Introduction

The Network of Momentum Multi-chain Infrastructure is an interoperability solution dedicated for the development of a sustainable, thriving ecosystem. Users are able to frictionlessly swap NoM assets between different blockchain networks through a seamless procedure enabled by user-friendly interfaces. This integration with the wider blockchain ecosystem will simultaneously attract more users (builders, developers, marketers, liquidity providers, etc.) and will also unlock a core component of the Network of Momentum: the Protocol Level Liquidity.

This documentation is intended to provide users and developers all the necessary information to interact, develop and maintain the Network of Momentum Multi-chain Infrastructure:

  • The Decentralized Bridge to wrap and unwrap native NoM assets
  • The Protocol Level Liquidity that enables the Orbital Program

Both components are covered in the Zenon Improvement Proposal ZIP:sumamu-0001. The complete ZIP can be found here.

FieldDescription
zipZIP:sumamu-0001
titleNoM Multichain infrastructure
author@sumamu @sumoshi
statusDraft
typeHard fork
acceptanceupon usage by the community
activationupon usage by the community
created2023-03-07
licenseGPL v3.0
linkhttps://forum.zenon.org/t/zip-sumamu-0001-final/1327

Architecture Overview

The whole design architecture of the decentralized cross-chain infrastructure is focused around security considerations.

The possibility to exchange and swap assets in a trustless, decentralized way between NoM and other networks is conditioned by the existence of a decentralized bridge solution.

The liquidity embedded in its current form does not have the means to distribute rewards to liquidity providers in a trustless and automated way.

Not a single centralized entity except the end user is able to move funds and several security mechanisms are organized in a layered structure to prevent and deter malicious actors from exploiting the infrastructure. The TSS participants are only able to sign transactions; they do not have the possibility to move user funds.

There are three distinct components that will enable a multi-chain vision with Orbital Program at its core:

  • The Core Contracts
  • The Protocol Level Liquidity
  • The Orchestrator Layer

The Orchestrator Layer will enable the relay and data transmissions between networks and will orchestrate the TSS signing ceremonies.

The Core Contracts will verify resulting signatures and interpret incoming events accordingly.

The Protocol Level Liquidity is a stand alone embedded contract that distributes the corresponding fraction of the dual-coin emission to eligible Liquidity Providers.

  • On-chain
    • Core Contracts
    • Protocol Level Liquidity
  • Off-chain
    • Orchestrator Layer: Orchestrator nodes based on Pillar nodes that form their own peer-to-peer network. Orchestrator nodes observe the Core Contract on each supported network and produce events that the Core Contracts validate. The orchestrator node will try to sign a confirmed event that was witnessed in the next TSS ceremony. The signing will succeed if there is a super-majority (>66%).

Unlike other bridge architectures, there is no additional peer-to-peer communication needed to confirm the event: each orchestrator node witness and processes all the events locally (after a finality threshold) and a successful TSS signing ceremony represents the off-chain consensus on which events are valid wraps and unwraps.

Modus Operandi

The decentralized bridge is based on lock-and-release / mint-and-burn mechanisms: native assets are locked / burned on one side and released /minted on the other side.

This particular interoperability solution allows easy transfers from NoM to other networks. The embedded bridge contract allows the control of native ZTS assets on NoM, while EVM Solidity contracts allow the control of wrapped ZTS assets on EVM compatible chains.

Depending on the direction of the swap, the following scenarios may appear:

  • Example native ZNN/wZNN (native ZNN and wZNN as ERC-20 token): Native ZNN is locked in the bridge embedded contract on NoM and its wrapped representation, wZNN is minted by the Ethereum contract. For the opposite direction, wZNN is burned by the Ethereum smart contract and native ZNN is released by the embedded bridge.

  • Example stablecoin DAI/zDAI (DAI as ERC-20 token and zDAI as ZTS token):

DAI stablecoin is locked in the Ethereum smart contract, while the bridge embedded contract mints the equivalent amount on NoM. For the opposite direction, zDAI is burned by the embedded contract and ERC-20 DAI is released by the Ethereum smart contract.

Compatibility

A robust interoperability solution must also maximize the compatibility with other distributed ledgers. Currently only NoM and EVM networks are supported. Other networks are based on different models and will be supported in the future.

Account model compatibility

EVM compatibility

The initial phase will consist of an implementation specifically designed for EVM compatibility (Ethereum, BNB Smart Chain, etc.):

  • Execution compatibility: Ethereum virtual machine (i.e. Solidity)
  • Cryptographic compatibility: ECDSA signatures (i.e. secp256k1)
  • API compatibility: ETH JSON-RPC (i.e. Ethereum JSON-RPC API)

This interoperability solution will unlock liquidity from a wide range of both Layer-1 and Layer-2 EVM compatible networks such as Ethereum, BNB Smart Chain, Polygon, Avalanche, Arbitrum, etc.

Liquidity pools will be gradually deployed on those networks for the wrapped representations of ZTS assets, enabling a seamless process for users to access and get onboarded into the NoM ecosystem.

Non-EVM compatibility

In the future, more non-EVM networks can be connected by implementing custom integrations (Polkadot, Cosmos, etc.):

  • Execution compatibility: Virtual machine type (i.e. WASM)
  • Cryptographic compatibility: EdDSA signatures (i.e. Ed25519)
  • API compatibility: custom API for each network

UTXO model compatibility

In the next phase, compatibility with UTXO networks (Bitcoin, Litecoin, etc.), in particular Bitcoin, is expected to be implemented and rolled-out. Further design changes are necessary for optimal integration with existent BIP340, BIP341 (e.g. Schnorr signatures - Musig2, MAST, Tapscript, etc.).

Confirmations to Finality

Different networks use different consensus protocols with different finality assumptions. In the table below one can find the number confirmations needed for a transaction to become final.

Orchestrator nodes proceed with the TSS signing ceremony only for finalized cross-chain transactions.

Network NameNetwork ClassChain identifierFinality
Network of Momentum116 momentums
Ethereum211 epoch ~ 6.4 minutes
Binance Smart Chain25633 seconds (6 secs after fast finality)
Bitcoin316 blocks ~ 60 minutes

Participants

Network of Momentum Multi-chain Infrastructure has four different type of participants: Guardians, Orchestrator Nodes, Liquidity Providers and the Administration Module.

Guardians

Guardians will be elected from prominent members of the community. Their main responsibility is to safeguard the infrastructure in case of an emergency. They will act as judges in case of a major failure of the infrastructure and they are responsible to appoint a new admin.

Administration Module

The role of the administration module is to manage the infrastructure. It cannot move funds and its permissions are limited in scope. The Core Contracts are designed to be managed by the community members through a governance module, similar to Accelerator-Z. At the moment the governance capabilities of NoM are insufficient to ensure this functionality. Until a solution is developed, the admin will be managed by the maintainers of the codebase.

Orchestrator Nodes

All the nodes of the orchestrator layer will run on Pillars. This design decision is based on the consideration that the security of the whole network depends on NoM consensus running nodes. Pillar operators already have both the technical background and know-how to operate nodes and a sufficient stake in the network to responsibly manage this critical piece of infrastructure. Pillars will be able to be part of the orchestrator peer-to-peer layer (libp2p) and participate in the threshold signature (TSS) ceremonies.

Liquidity Provides

Liquidity Provides (LPs) are users with available capital that are incentivized through the Orbital Program to directly participate into the network by staking their liquidity in order to receive dual-coin (ZNN and QSR) rewards. They must ensure adequate levels of liquidity for users to be able to frictionlessly swap their assets in and out of the ecosystem.

Orbital Program

Orbital Program is a protocol level liquidity program that incentivizes liquidity providers to participate and pool together liquidity for the wrapped representations of ZNN, QSR and ZTS tokens in exchange for the aforementioned fraction of the dual-coin emission. This program will create a sustainable model for external liquidity providers to participate into the network.

Without proper incentives, LPs may lack interest to join the Orbital Program and this in turn will hurt the ecosystem by limiting the potential of external users that would swap their assets to NoM. Moreover, beyond Orbital Program, new untapped markets and gateways to access NoM are necessary for a healthy development of the ecosystem.

What is the liquidity embedded contract?

The liquidity embedded contract is the initial placeholder that accumulates dual-coin rewards for the upcoming Orbital Program. The liquidity contract was upgraded to enable the Orbital Program and is based on the staking embedded contract.

How to participate in the Orbital Program?

A liquidity provider that wants to participate in the Orbital Program must supply a liquidity pool with the corresponding assets, swap the resulting LP token to NoM and lock it up into the liquidity embedded in order to be eligible for dual-coin rewards.

For example, several Ethereum users wants to become a liquidity providers (LPs). They must deposit ETH and wZNN into a pool in order to participate into the Orbital Program. Depending on how much liquidity they provide for the wZNN/ETH pool on Uniswap, they will receive a proportional amount of ERC-20 LP tokens. In the next step, the LP must swap the ERC-20 LP tokens to the ZTS zLP tokens (zLP) on NoM using the decentralized cross-chain bridge. In order to become eligible for receiving dual-coin rewards from NoM's emission, the LP must deposit the zLP tokens into the liquidity embedded contract. The liquidity embedded contract mirrors the staking embedded contract in terms of locking the tokens for a predefined time period. However, it differs from a rewards' perspective: participating LPs get both ZNN and QSR.

Assets

The bridge supports native assets as well as tokens from the source and destination networks.

Assets on NoM

  • ZTS = native Zenon Token Standard asset on NoM e.g. Zenon ZNN, Quasar QSR
  • zEVM-20 = wrapped Zenon Token Standard asset on NoM e.g. zDAI

Assets on EVM networks

  • wZTS = wrapped Zenon Token Standard asset on a particular destination network e.g. wZNN as ERC-20
  • EVM-20 = native EVM token on the EVM mainnet e.g. DAI on Ethereum mainnet

Assets on non-EVM networks

  • TBA

Assets on UTXO networks

  • TBA

Classification

  • ZTS and zEVM-20 assets are native to NoM.

  • EVM-20 and wZTS assets are native to the EVM network.

For example, an EVM-20 token can be:

  • ERC-20 for Ethereum mainnet
  • BEP-20 for BNB Smart Chain

Decentralized Bridge

The purpose of the Decentralized Bridge is to connect different networks by wrapping and unwrapping assets.

Decentralized Bridge components:

  1. Bridge embedded contract on NoM
  2. Orchestrator Layer as middleware
  3. Smart Contracts on bridged network

EVM account model

At the moment, only account model EVM networks are supported, starting with the Ethereum mainnet.

Wrap assets

Source NoM -> Destination EVM

  • ZNN (ZTS on NoM) -> wrap -> wZNN (ERC-20 on Ethereum)

Source EVM -> Destination NoM

  • DAI (ERC-20 on Ethereum) -> wrap -> zDAI (ZTS on NoM)

Unwrap assets

Source EVM -> Destination NoM

  • wZNN (ERC-20 on Ethereum) -> unwrap -> ZNN (ZTS on NoM)

Source NoM -> Destination EVM

  • zDAI (ZTS on NoM) -> unwrap -> DAI (ERC-20 on Ethereum)

Core Contracts

The Core Contracts are one of the most important elements of the NoM Multi-chain infrastructure. They are deployed on NoM - the bridge embedded contract and each network that will participate in the multi-chain infrastructure. They are the primary infrastructure contracts, which the Orchestrator Nodes observe and which fundamentally enable the cross-chain communication. In general, Core Contracts have a similar structure and can be broken down to a receiving side, which we'll define later.

There are Core Contracts on each network that is part of the ecosystem, with the Orchestrator Layer acting as a global observer of inter-network events.

EVM Smart Contracts

The EVM smart contracts are specifically designed for Ethereum Virtual Machine compatibility, including its specific secp256k1 elliptic curve.

EVM networks can be divided into layer-1 and layer-2 networks as follows:

Layer-1 EVM networks:

Integrated networks:

  • Ethereum
    • ChainID 1
    • Currency ETH

Upcoming integrations:

  • BNB Smart Chain
    • ChainID 56
    • Currency BNB
  • Avalanche C-Chain
    • ChainID 43114
    • Currency AVAX
  • Fantom Opera
    • ChainID 250
    • Currency FTM
  • Celo
    • ChainID 42220
    • Currency CELO

Layer-2 EVM networks:

Upcoming integrations:

  • Arbitrum
    • ChainID 42161
    • Currency ETH
  • Polygon
    • ChainID 137
    • Currency MATIC
  • Optimism
    • ChainID 10
    • Currency ETH

EVM Smart Contracts

The EVM smart contracts are deployed on the EVM networks integrated into the NoM Multi-chain Infrastructure.

Contract Anatomy

The code is written in Solidity v0.8.19 (latest as March 2023).

Imports

The smart contract uses the following openzeppelin standard contracts:

import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
  • using ECDSA for bytes32 - used to add the recover ECDSA signature functionality

  • using SafeERC20 for IERC20 - used to add the safeTransfer and safeTransferFrom functionalities

  • contract Bridge is Context - inherit _msgSender() method to get the sender

Modifiers

  • onlyAdministrator can only be called by owner of the administrator private key

  • isNotHalted can only be called if the bridge is not halted

Structs

  • TokenInfo is used to store information about the bridged tokens

  • RedeemInfo is used for redeeming funds and information regarding time challenges

Events

event RegisteredRedeem(uint256 indexed nonce, address indexed to, address indexed token, uint256 amount);
event Redeemed(uint256 indexed nonce, address indexed to, address indexed token, uint256 amount);
event Unwrapped(address indexed from, address indexed token, string to, uint256 amount);
event Halted();
event Unhalted();
event RevokedRedeem(uint256 indexed nonce);
event PendingAdministrator(address indexed newAdministrator);
event SetAdministrator(address indexed newAdministrator, address oldAdministrator);
event PendingTss(address indexed newTss);
event SetTss(address indexed newTss, address oldTss);
event PendingGuardians();
event SetGuardians();
  • RegisteredRedeem emitted when a redeem request is registered

  • Redeemed emitted when a redeem is completed

  • Unwrapped emitted when an unwrap request is registered

  • Halted emitted when the bridge is halted

  • Unhalted emitted when the bridge is unhalted

  • RevokedRedeem emitted when the administrator revokes an invalid redeem

  • PendingAdministrator emitted when a request for changing the administrator address is made

  • SetAdministrator emitted when the administrator address is set

  • PendingTss emitted when a request for changing the tss address is made

  • SetTss emitted when the tss address is set

  • PendingGuardians emitted when a request for changing the guardian addresses is made

  • SetGuardians emitted when the addresses of the guardians are set

Constants

  • uint256 constant uint256max stores type(uint256).max

  • uint32 private constant networkClass for EVM networks is hard coded to 2

  • uint8 private constant minNominatedGuardians must coincide with the MinGuardians constant from the embedded contract and is hard coded to 5

Variables

  • estimatedBlockTime is set for each network depending on the block time interval; it is used by the orchestrator to know how much to wait for one confirmation

  • confirmationsToFinality is the number of confirmations required to achieve finality for a given network; it is used by the orchestrator to confirm an event

  • halted indicates if the bridge is halted or not

  • allowKeyGen indicates wether or not the tss address can be changed with a valid signature; the admin can always change the tss address

  • administrator is the EVM compatible address of the admin

  • administratorDelay is the delay required for changing the admin; it cannot be lower than minAdministratorDelay

  • minAdministratorDelay is the minimum delay required for changing the admin

  • tss is the TSS address jointly created during the key generation ceremony

  • softDelay is the delay required for the time challenge security primitive; it cannot be lower than minSoftDelay

  • minSoftDelay is the minimum delay required for the time challenge security primitive

  • guardians is the array containing the addresses of the guardians

  • nominatedGuardians is the array containing the addresses of the nominated guardians

  • guardiansVotes is the array containing the votes for the guardians

  • votesCount is a mapping containing the proposed admin votes of each guardian

  • unhaltedAt is the last block height at which the bridge was unhalted

  • unhaltDuration is the duration in blocks during which the bridge is still halted after the unhaltedAt block height; it cannot be lower than minUnhaltDuration

  • minUnhaltDuration is the minimum duration in blocks during which the bridge is still halted after the unhaltedAt block height

  • actionsNonce is the nonce required for a valid signature at a particular state of the bridge; must be always incremented after a signature is validated

  • contractDeploymentHeight is the block height at which the contract was deployed; it is used by the orchestrator to know the height to scan events

Contract implementation

Constructor

In the constructor we set the following variables:

  • administrator
  • minUnhaltDuration
  • unhaltDuration
  • minAdministratorDelay
  • administratorDelay
  • minSoftDelay
  • softDelay
  • guardians
  • guardiansVotes
  • estimatedBlockTime
  • confirmationsToFinality
  • contractDeploymentHeight

redeem method

The first and the second step of the redeem process. During the first step a time challenge will start. During the second step, after softDelay, the funds will be released/minted. The bridge must not be halted, the request must not have been revoked before, the token should be redeemable and the TSS signature valid.

Parameters

  • to - EVM address that will receive the funds
  • token - EVM-20 token address
  • amount - amount of token
  • nonce - unique identifier of the redeem request
  • signature - signature generated by the current TSS

Returns

  • None

unwrap method

Register an unwrap request. Tokens will be locked/burned. The bridge must not be halted and the token must be bridgeable.

Parameters

  • token - EVM-20 token address
  • amount - amount of token
  • to - NoM address

Returns

  • None

setTokenInfo method

Adds or edits an existing tokenInfo. It contains information about permitted tokens to swap or redeem and their delays. Can be called only by the administrator. Guarded by a time challenge.

Parameters

  • token - EVM-20 token address
  • minAmount - minimum amount of the token for unwrapping
  • redeemDelay - delay in blocks after the first redeem step in order to receive the funds
  • bridgeable - whether the token can be unwrapped
  • redeemable - whether the token can be redeemed
  • isOwned - whether this contract has owner rights for the EVM-20

Returns

  • None

halt method

Halts the network. It does not require a signature if called by the administrator. Otherwise, a TSS signature is needed.

Parameters

  • signature - current TSS signature

Returns

  • None

unhalt method

Sets halted to false and updates the haltedAt block such that unhaltDelay starts. Can only be called by the administrator.

Parameters

  • None

Returns

  • None

revokeRedeems method

Revokes invalid redeem requests.

Parameters

  • nonces - an array containing the unique identifiers for each request

Returns

  • None

setAdministrator method

Changes the administrator address. Can only be called by the administrator. Guarded by a time challenge.

Parameters

  • newAdministrator - new administrator address

Returns

  • None

setTss method

Changes the TSS address. If called by the administrator, no signature is required and the time challenge starts. Otherwise, a valid TSS signature is required in order to validate the new address.

Parameters

  • newTss - new TSS address
  • oldSignature - signature from the current TSS
  • newSignature - signature from the new TSS

Returns

  • None

emergency method

Sets administrator to address(0), TSS to address(0) and halts the bridge. Can only be called by the administrator. It enables guardians to propose.

Parameters

  • None

Returns

  • None

nominateGuardians

Nominate the guardians that are responsible to propose a new administrator in case of an emergency. Guarded by a time challenge. Can only be called by the administrator.

Parameters

  • newGuardians - an array containing the new guardian addresses

Returns

  • None

proposeAdministrator method

Will vote for a new administrator address. Can only be called by a guardian only if the bridge is in emergency state (the address of the administrator is address(0)).

Parameters

  • newAdministrator - new administrator address

Returns

  • None

setSoftDelay method

Sets the delay for the time challenge. Can only be called by the administrator.

Parameters

  • delay - delay in blocks

Returns

  • None

setUnhaltDuration method

Sets the delay during which the bridge remains halted after calling unhalt. Can only be called by the administrator.

Parameters

  • duration - duration in blocks

Returns

  • None

setEstimatedBlockTime method

Sets the delay in which the bridge remains halted after calling unhalt. Can only be called by the administrator.

Parameters

  • blockTime - block time in seconds; it is used by the orchestrator layer

Returns

  • None

setAllowKeyGen method

Sets allowKeyGen to true that permits the TSS address to be changed by an address different from the administrator. Can only be called by the administrator.

Parameters

  • value - true or false

Returns

  • None

setConfirmationsToFinality method

Sets the confirmations required by an event to be confirmed. Used by the orchestrator layer. Can only be called by the administrator.

Parameters

  • confirmations - number of confirmations in blocks

Returns

  • None

Unit Tests

TBA

Bridge Embedded Contract

The Bridge Embedded Contract is the embedded contract for the decentralized bridge deployed on the Network of Momentum.

Helper methods

CheckECDSASignature method

Checks if the ECDSA signature is correct or returns error in case it fails.

Parameters

  • message - the message in []byte format
  • pubKeyStr - the public key in string format
  • signatureStr - the signature in string format

Returns

  • bool - true if the signature passes, false otherwise

CanPerformAction method

Checks if the parameters of the bridge are correct or returns error in case it fails.

Parameters

  • AccountVmContext - current context of the VM

Returns

  • BridgeInfoVariable - information regarding the bridge
  • OrchestratorInfo - information regarding the orchestrator

CheckBridgeInitialized method

Checks if the bridge is properly initialized or returns error in case it fails.

Parameters

  • AccountVmContext - current context of the VM

Returns

  • BridgeInfoVariable - information regarding the bridge

CheckOrchestratorInfoInitialized method

Checks if the orchestrator is properly initialized or returns error in case it fails.

Parameters

  • AccountVmContext - current context of the VM

Returns

  • OrchestratorInfo - information regarding the orchestrator

CheckBridgeHalted method

Checks if the bridge is halted or returns error in case it fails.

Parameters

  • BridgeInfoVariable - information regarding the bridge
  • AccountVmContext - current context of the VM

Returns

  • nil - the bridge is not halted

Contract implementation

The implementation of the Bridge Embedded Contract has a total of 20 methods that can be called by sending a specifically crafted account block:

WrapTokenMethod method

Method for wrapping assets. If the bridge is initialized, not halted, the destination network and the token pair exists, than a wrap token request is created.

Parameters

  • NetworkClass - the class of the destination network
  • ChainId - the chain identifier of the destination network
  • ToAddress - the address that can redeem the funds on the destination network
  • TokenStandard - the ZTS used in the send block
  • Amount - the amount used in the send block

Returns

  • AccountBlock - only if the token is owned, a burn call to the token contract is performed that burns the received tokens

UpdateWrapRequestMethod method

Method for updating the wrap request. If the signature is valid and is generated by the TSS public key, it is saved in the wrap request signature field and can be used to redeem the funds.

Parameters

  • Id - represents the id of a wrap requests
  • Signature - a base64 encoded ECDSA signature used to redeem funds on the destination network

Returns

  • None

UnwrapTokenMethod method

Method for unwrapping assets. It is the first step in redeeming funds on NoM. Normally this method would be called by an orchestrator node after a signing ceremony to register an unwrap request.

Parameters

  • NetworkClass - the class of the source network
  • ChainId - the chain identifier of the source network
  • TransactionHash - hash of the transaction on the source network
  • LogIndex - log index in the block of the transaction that locked/burned the funds on the source network; together with txHash it creates a unique identifier for a transaction
  • ToAddress - destination NoM address
  • TokenAddress - address of the locked/burned token on the source network
  • Amount - amount of token that was locked/burned
  • Signature - the signature as base64 encoded string of the unwrap request

Returns

  • None

SetNetworkMethod method

Method for setting a network. Used to add or edit an already existing bridged network.

Parameters

  • NetworkClass - class of the network
  • ChainId- chain identifier of the network
  • Name- new name of the network
  • ContractAddress - new address the bridge contract was deployed to
  • Metadata - JSON encoded string used in case the orchestrator needs additional data for the network

Returns

  • None

RemoveNetworkMethod method

Method for removing a network uniquely identified by its class and chain identifier.

Parameters

  • NetworkClass - class of the network
  • ChainId- chain identifier of the network

Returns

  • None

SetNetworkMetadataMethod method

Method for setting metadata for a network.

Parameters

  • NetworkClass - class of the network
  • ChainId- chain identifier of the network
  • Metadata - JSON encoded string containing the new metadata

Returns

  • None

SetTokenPairMethod method

Method for setting a token pair for a network. It will add a new pair or edit an existing one; guarded by the time challenge primitive.

Parameters

  • NetworkClass - network class of the network to add this pair to
  • ChainId - chain identifier of the network to add this pair to
  • TokenStandard - first component of the pair i.e. ZTS
  • TokenAddress - second component of the pair i.e. EVM-20
  • Bridgeable - boolean variable that specifies if the ZTS can be wrapped on NoM
  • Redeemable - boolean variable that specifies if the EVM-20 can be redeemed on NoM
  • Owned - boolean variable that specifies if the embedded bridge contract is the owner of the ZTS from the pair; if true, when wrapping the ZTS, the token will be burned, otherwise it will be locked
  • MinAmount - minimum amount for wrapping the ZTS
  • FeePercentage - fee deducted from the amount when wrapping
  • RedeemDelay - delay in momentums until redeeming is possible on NoM
  • Metadata - JSON encoded string containing metadata about the pair; used by the orchestrator

Returns

  • None

RemoveTokenPairMethod method

Method for removing a token pair for a network.

Parameters

  • NetworkClass - class of the network that contains the pair
  • ChainId - chain identifier of the network that contains the pair
  • TokenStandard - ZTS of the pair
  • TokenAddress - EVM-20 address of the pair

Returns

  • None

HaltMethod method

Method for halting the bridge. If called by the administrator it doesn't need a signature, otherwise it needs a TSS signature with the current tssNonce.

Parameters

  • Signature - base64 encoded string containing the TSS signature

Returns

  • None

UnhaltMethod method

Method for unhalting the bridge. Can be called only by the administrator.

Parameters

  • None

Returns

  • None

EmergencyMethod method

Method for putting the bridge embedded contract into emergency mode. This method nullifies the administrator address, tss public key and halts the bridge. It can be called in the extreme case when the administrator private key has been compromised.

Parameters

  • None

Returns

  • None

ChangeTssECDSAPubKeyMethod method

Method for changing the TSS public key. Guarded by time challenge when called by the administrator. Otherwise it can be changed by the TSS using a signature from the current tss, one from the new tss and the new tss public key.

Parameters

  • PubKey - base64 encoded string representing the new TSS public key
  • OldPubKeySignature - base64 encoded string representing the changeTss message signed by the current TSS
  • NewPubKeySignature - base64 encoded string representing the changeTss message signed by corresponding private key

Returns

  • None

ChangeAdministratorMethod method

Method for changing the admin. Can be called only by the administrator. Guarded by a time challenge with administratorDelay.

Parameters

  • Address - address of the new administrator

Returns

  • None

SetAllowKeygenMethod method

Method that enables or disables the TSS key generation.

Parameters

  • Bool - true or false value that indicates whether the orchestrator nodes should start a key generation ceremony or not

Returns

  • None

SetOrchestratorInfoMethod method

Method for setting the information regarding the orchestrator layer.

Parameters

  • WindowSize - size in momentums of a window used in the orchestrator to determine which signing ceremony should occur, wrap or unwrap request and to determine the key sign ceremony timeout
  • KeyGenThreshold - minimum number of participants of a key generation ceremony
  • ConfirmationsToFinality - minimum number of momentums to consider a wrap request confirmed
  • EstimatedMomentumTime - time in seconds between momentums

Returns

  • None

SetBridgeMetadataMethod method

Method for setting the metadata for the bridge.

Parameters

  • String - JSON encoded string containing additional information needed for the orchestrator layer

Returns

  • None

RevokeUnwrapRequestMethod method

Method for revoking an unwrap request. This should be called if an unwrap request does not a have corresponding transaction on the source network that locks/burns the tokens.

Parameters

  • TransactionHash - first component to uniquely identify an unwrap request
  • LogIndex - second component to uniquely identify an unwrap request

Returns

  • None

RedeemMethod method

Method for redeeming assets. It is the second step in order to redeem funds after an unwrap request is created. In order to redeem the unwrap request the following conditions must be present: the bridge must not be halted, the network and token pair must exist and the request have not been redeemed or revoked before.

Parameters

  • TransactionHash - first component to uniquely identify an unwrap request
  • LogIndex - second component to uniquely identify an unwrap request

Returns

  • AccountBlock - if the ZTS to be redeemed is owned, an account block to mint the amount will be sent to the token contract, otherwise a block sending the tokens will be sent to the user

NominateGuardiansMethod method

Method for nominating guardians. Can only be called by the administrator in order to propose new guardians. Guarded by a time challenge. The number of guardian addresses must be higher than minGuardians and each address in the array must be unique. ZeroAddress is not accepted.

Parameters

  • []Address - contains the new guardian addresses

Returns

  • None

ProposeAdministratorMethod method

Method for proposing an admin. This method can only be called by a guardian if the bridge is in emergency mode i.e. the administrator address is set to ZeroAddress. After each guardian votes for an address, the votes are counted and if there is a majority (50% + 1), the administrator will be set with that address.

Parameters

  • Address - voted address

Returns

  • None

Bridge Embedded Constants

Bridge constants are hard coded into the embedded.go file as network constants.

  • InitialBridgeAdministrator is the hard-coded address for the administration module, managed by the maintainers of the codebase as Address

  • MaximumFee is the maximum fee for a wrap request as uint32; equivalent to 100% fee

  • MinUnhaltDurationInMomentums is the minimum amount of time, measured in momentums, until the bridge functionality is restored from a halted state as uint64

  • MinAdministratorDelay is the minimum delay required by the time challenge for admin operations as uint64

  • MinSoftDelay is the minimum delay required by time challenge for all operations excluding the admin and the guardians as uint64

  • MinGuardians is the minimum number of guardians required for the bridge to become operational as unit32

  • DecompressedECDSAPubKeyLength is the size of the decompressed ECDSA public key in bytes

  • CompressedECDSAPubKeyLengthis the size of the compressed ECDSA public key in bytes

  • ECDSASignatureLength is the size of the ECDSA signature in bytes

  • EdDSAPubKeyLength is the size of the EdDSA public key in bytes

InitialBridgeAdministrator   = types.ParseAddressPanic("z1qz8q0x3rs36z2kw8eltf8r323hlcn64jnujkuz")
MaximumFee                   = uint32(10000)
MinUnhaltDurationInMomentums = uint64(6 * MomentumsPerHour) //main net
MinAdministratorDelay        = uint64(2 * MomentumsPerEpoch) // main net
MinSoftDelay                 = uint64(MomentumsPerEpoch)     // main net
MinGuardians                 = 5
DecompressedECDSAPubKeyLength = 65
CompressedECDSAPubKeyLength   = 33
ECDSASignatureLength          = 65
EdDSAPubKeyLength             = 32

Bridge Embedded Error States

Bridge error states.

ErrUnknownNetwork                       = errors.New("unknown network")
ErrInvalidToAddress                     = errors.New("invalid destination address")
ErrBridgeNotInitialized                 = errors.New("bridge info is not initialized")
ErrOrchestratorNotInitialized           = errors.New("orchestrator info is not initialized")
ErrTokenNotBridgeable                   = errors.New("token not bridgeable")
ErrNotGuardian                          = errors.New("sender is not a guardian")
ErrTokenNotRedeemable                   = errors.New("token not redeemable")
ErrBridgeHalted                         = errors.New("bridge is halted")
ErrInvalidRedeemPeriod                  = errors.New("invalid redeem period")
ErrInvalidRedeemRequest                 = errors.New("invalid request")
ErrInvalidTransactionHash               = errors.New("invalid transaction hash")
ErrInvalidNetworkName                   = errors.New("invalid network name")
ErrInvalidContractAddress               = errors.New("invalid contract address")
ErrInvalidToken                         = errors.New("invalid token standard or token address")
ErrTokenNotFound                        = errors.New("token not found")
ErrInvalidEDDSASignature                = errors.New("invalid ed25519 signature")
ErrInvalidEDDSAPubKey                   = errors.New("invalid eddsa public key")
ErrInvalidECDSASignature                = errors.New("invalid secp256k1 signature")
ErrInvalidDecompressedECDSAPubKeyLength = errors.New("invalid decompressed secp256k1 public key length")
ErrInvalidCompressedECDSAPubKeyLength   = errors.New("invalid compressed secp256k1 public key length")
ErrNotAllowedToChangeTss                = errors.New("changing the tss public key is not allowed")
ErrInvalidJsonContent                   = errors.New("metadata does not respect the JSON format")
ErrInvalidMinAmount                     = errors.New("invalid min amount")
ErrTimeChallengeNotDue                  = errors.New("time challenge not due")
ErrNotEmergency                         = errors.New("bridge not in emergency")
ErrInvalidGuardians                     = errors.New("invalid guardians")
ErrSecurityNotInitialized               = errors.New("security not initialized")
ErrBridgeNotHalted                      = errors.New("bridge not halted")

Bridge Embedded JSON-RPC API

The JSON-RPC API for the bridge embedded contract.

JSON-RPC API Methods

GetBridgeInfo method

Returns the current bridge information or error in case it fails.

Parameters

  • None

Returns

  • BridgeInfoVariable - the current bridge information
type BridgeInfoVariable struct {
	// Administrator address
	Administrator types.Address `json:"administrator"`
	// ECDSA pub key generated by the orchestrator from key gen ceremony
	CompressedTssECDSAPubKey   string `json:"compressedTssECDSAPubKey"`
	DecompressedTssECDSAPubKey string `json:"decompressedTssECDSAPubKey"`
	// This specifies whether the orchestrator should key gen or not
	AllowKeyGen bool `json:"allowKeyGen"`
	// This specifies whether the bridge is halted or not
	Halted bool `json:"halted"`
	// Height at which the administrator called unhalt method, UnhaltDurationInMomentums starts from here
	UnhaltedAt uint64 `json:"unhaltedAt"`
	// After we call the unhalt embedded method, the bridge will still be halted for UnhaltDurationInMomentums momentums
	UnhaltDurationInMomentums uint64 `json:"unhaltDurationInMomentums"`
	// An incremental nonce used for signing messages
	TssNonce uint64 `json:"tssNonce"`
	// Additional metadata
	Metadata string `json:"metadata"`
}

Example

// todo

GetSecurityInfo method

Returns the current security information or error in case it fails.

Parameters

  • None

Returns

  • SecurityInfoVariable - the current security information
// SecurityInfoVariable This refers to time challenge security
type SecurityInfoVariable struct {
	// addresses that can vote for the new administrator once the bridge is in emergency
	Guardians []types.Address `json:"guardians"`
	// votes of the active guardians
	GuardiansVotes []types.Address `json:"guardiansVotes"`
	// delay upon which the new administrator or guardians will be active
	AdministratorDelay uint64 `json:"administratorDelay"`
	// delay upon which all other time challenges will expire
	SoftDelay uint64 `json:"softDelay"`
}

Example

// todo

GetOrchestratorInfo method

Returns the current orchestrator information or error in case it fails.

Parameters

  • None

Returns

  • OrchestratorInfo - the current orchestrator information
type OrchestratorInfo struct {
	// Momentums period in which only one signing ceremony (wrap or unwrap) can occur in the orchestrator
	WindowSize uint64 `json:"windowSize"`
	// This variable is used in the orchestrator to wait for at least KeyGenThreshold participants for a key gen ceremony
	KeyGenThreshold uint32 `json:"keyGenThreshold"`
	// Momentums until orchestrator can process wrap requests
	ConfirmationsToFinality uint32 `json:"confirmationsToFinality"`
	// Momentum time
	EstimatedMomentumTime uint32 `json:"estimatedMomentumTime"`
	// This variable is a reference for the orchestrator to check the last 24h of momentums for producing pillars
	AllowKeyGenHeight uint64 `json:"allowKeyGenHeight"`
}

Example

// todo

GetTimeChallengesInfo method

Returns a list of time challenges or error in case it fails.

Parameters

  • None

Returns

  • TimeChallengesList - the current a list of time challenges
type TimeChallengesList struct {
	Count int                             `json:"count"`
	List  []*definition.TimeChallengeInfo `json:"list"`
}
type TimeChallengeInfo struct {
	MethodName           string
	ParamsHash           types.Hash
	ChallengeStartHeight uint64
}

Example

// todo

GetNetworkInfo method

Returns the current network information or error in case it fails.

Parameters

  • networkClass - network class in uint32 format
  • chainId - chain identifier in uint32 format

Returns

  • NetworkInfo - the current network information.
// NetworkInfoVariable One network will always be znn, so we just need the other one
type NetworkInfoVariable struct {
	NetworkClass    uint32   `json:"networkClass"`
	Id              uint32   `json:"chainId"`
	Name            string   `json:"name"`
	ContractAddress string   `json:"contractAddress"`
	Metadata        string   `json:"metadata"`
	TokenPairs      [][]byte `json:"tokenPairs"`
}

Example

// todo

GetAllNetworks method

Returns a list of all the available networks.

Parameters

  • pageIndex - the page index in uint32 format
  • pageSize - the size of the page in uint32 format

Returns

  • NetworkInfoList - a list of available networks
type NetworkInfoList struct {
	Count int                       `json:"count"`
	List  []*definition.NetworkInfo `json:"list"`
}

Example

// todo

getToken method

Returns a token by tokenStandard or error in case it fails.

Parameters

  • zts - the Zenon Token Standard, in ZenonTokenStandard format

Returns

  • Token - the current token information
type TokenInfo struct {
	Owner       types.Address `json:"owner"`
	TokenName   string        `json:"tokenName"`
	TokenSymbol string        `json:"tokenSymbol"`
	TokenDomain string        `json:"tokenDomain"`
	TotalSupply *big.Int      `json:"totalSupply"`
	MaxSupply   *big.Int      `json:"maxSupply"`
	Decimals    uint8         `json:"decimals"`
	IsMintable  bool          `json:"isMintable"`
	// IsBurnable = true implies that anyone can burn the token.
	// The Owner can burn the token even if IsBurnable = false.
	IsBurnable bool `json:"isBurnable"`
	IsUtility  bool `json:"isUtility"`

	TokenStandard types.ZenonTokenStandard `json:"tokenStandard"`
}

Example

// todo

getRedeemableIn method

Returns the number of momentums until an UnwrapTokenRequest becomes redeemable.

Parameters

  • unwrapTokenRequest - the unwrap token request
  • tokenPair - the token pair
  • momentum - the momentum

Returns

  • redeemableIn - the number of momentums until an UnwrapTokenRequest becomes redeemable in uint64 format
var redeemableIn uint64

Example

// todo

getConfirmationsToFinality method

Returns the number of confirmations to finality for a WrapTokenRequest or error in case it fails.

Parameters

  • wrapTokenRequest - the wrap request for a particular token
  • confirmationsToFinality - the number of confirmations required to achieve finality in uint32 format
  • momentum - the momentum

Returns

  • actualConfirmationsToFinality - the number of confirmations to achieve finality on the destination network in uint64 format
var actualConfirmationsToFinality uint64

Example

// todo

GetWrapTokenRequestById method

Returns the token for the wrap request or error in case it fails.

Parameters

  • id - the hash of the wrap request, in Hash format

Returns

  • wrapTokenRequest - the wrap token request in WrapTokenRequest format
type WrapTokenRequest struct {
	*definition.WrapTokenRequest
	TokenInfo               *api.Token `json:"token"`
	ConfirmationsToFinality uint64     `json:"confirmationsToFinality"`
}

Example

// todo

GetAllWrapTokenRequests method

Returns a list of tokens for all wrap requests or error in case it fails.

Parameters

  • pageIndex - the page index in uint32 format
  • pageSize - the size of the page in uint32 format

Returns

  • wrapTokenRequestList - a list of wrap token requests
type WrapTokenRequestList struct {
	Count int                 `json:"count"`
	List  []*WrapTokenRequest `json:"list"`
}

Example

// todo

GetAllWrapTokenRequestsByToAddress method

Returns a list of wrap requests that match a particular address or error in case it fails.

Parameters

  • pageIndex - the page index in uint32 format
  • pageSize - the size of the page in uint32 format
  • toAddress - the address in string format

Returns

  • wrapTokenRequestList - a list of wrap token requests
type WrapTokenRequestList struct {
	Count int                 `json:"count"`
	List  []*WrapTokenRequest `json:"list"`
}

Example

// todo

GetAllWrapTokenRequestsByToAddressNetworkClassAndChainId method

Returns a list of wrap requests that match a particular address, network class and chain identifier.

Parameters

  • toAddress - the address in string format
  • networkClass - the network class
  • pageIndex - the page index in uint32 format
  • pageSize - the size of the page in uint32 format

Returns

  • wrapTokenRequestList - a list of wrap token requests
type WrapTokenRequestList struct {
	Count int                 `json:"count"`
	List  []*WrapTokenRequest `json:"list"`
}

Example

// todo

GetAllUnsignedWrapTokenRequests method

Returns a list of unsigned wrap requests or error in case it fails.

Parameters

  • pageIndex - the page index in uint32 format
  • pageSize - the size of the page in uint32 format

Returns

  • wrapTokenRequestList - a list of unsigned wrap token requests

Example

// todo

GetUnwrapTokenRequestByHashAndLog method

Returns a list of unwrap token requests that match a particular Hash and Log or error in case it fails.

Parameters

  • txHash - the transaction hash in Hash format
  • logIndex - the log index in uint32 format

Returns

  • unwrapTokenRequest - the unwrap token request
type UnwrapTokenRequest struct {
	RegistrationMomentumHeight uint64                   `json:"registrationMomentumHeight"`
	NetworkClass               uint32                   `json:"networkClass"`
	ChainId                    uint32                   `json:"chainId"`
	TransactionHash            types.Hash               `json:"transactionHash"`
	LogIndex                   uint32                   `json:"logIndex"`
	ToAddress                  types.Address            `json:"toAddress"`
	TokenAddress               string                   `json:"tokenAddress"`
	TokenStandard              types.ZenonTokenStandard `json:"tokenStandard"`
	Amount                     *big.Int                 `json:"amount"`
	Signature                  string                   `json:"signature"`
	Redeemed                   uint8                    `json:"redeemed"`
	Revoked                    uint8                    `json:"revoked"`
}

Example

// todo

GetAllUnwrapTokenRequests method

Returns a list of all unwrap token requests or error in case it fails.

Parameters

  • pageIndex - the page index in uint32 format
  • pageSize - the size of the page in uint32 format

Returns

  • unwrapTokenRequestList - a list of unwrap token requests

Example

// todo

GetAllUnwrapTokenRequestsByToAddress method

Returns a list of all unwrap token requests that match a particular address.

Parameters

  • toAddress - the address in string format
  • pageIndex - the page index in uint32 format
  • pageSize - the size of the page in uint32 format

Returns

  • unwrapTokenRequestList - a list of unwrap token requests

Example

// todo

GetFeeTokenPair method

Returns the fee for a particular token pair or error in case it fails.

Parameters

  • zts - the Zenon Token Standard, in ZenonTokenStandard format

Returns

  • ZtsFeesInfo - ZTS fee information
type ZtsFeesInfo struct {
	TokenStandard  types.ZenonTokenStandard `json:"tokenStandard"`
	AccumulatedFee *big.Int                 `json:"accumulatedFee"`
}

Example

// todo

Bridge Embedded Unit Tests

The unit tests are available here with 81.8% code coverage.

Orchestrator Layer

The purpose of the Orchestrator Layer is to assure the off-chain communication and TSS signing of wrap and unwrap requests for the integrated networks.

OS support

Currently only Linux based operating systems are supported. This is due to the fact that Pillar nodes already running on public infrastructure have dedicated support for Linux based operating systems.

OSLinuxWindowsMacOS
YesNoNo

Data directory

  • DefaultDataDir is the default data directory for the orchestrator node located at ~/.orchestrator

  • orchestrator is executable file of the Orchestrator node

  • config.json is the configuration file

Configuration

Producer key

The Pillar operator must set his producer keyStore in ~/.orchestrator and provide the name and passphrase in config.json

After the first run, in config.json, from producer key an EVM address will automatically get generated and the field evmAddress will be populated.

IMPORTANT: An ETH deposit is mandatory for the generated evmAddress that will be used as gas in case a halt transaction is necessary to be performed on-chain.

Secrets

IMPORTANT: The Pillar operator must backup the ~/.orchestrator/tss folder containing the generated TSS shard in case a hardware failure occurs. Without it, the node can no longer participate in the keysign ceremonies, until it participates in another successful keygen ceremony.

Ports

The default port is 55055.

If you start with the default ports, please make sure that they are not occupied by other programs or blocked by the firewall.

netstat -nlp | grep 55055 

Install from source

Go 1.20 or later is required. Check the Go documentation for more info.

go env

Build from source:

go build --ldflags '-extldflags "-Wl,--allow-multiple-definition"' -o ./orchestrator

orchestrator service:

// todo

Connectors

Each Orchestrator Node is connected to both NoM and the supported destination network using the JSON-RPC API. There are several types of connectors that provide different degrees of confidence for transaction finality.

Local Connectors

Full Node

The ideal configuration for an Orchestrator Node is to run its own full nodes for all supported networks. This way, it has a precise overview of the network state and does not rely to any third party that can be either maliciously corrupted or censored. Running full nodes also can detect chain reorganizations called reorgs.

Example of chain reorgs for a Bitcoin full node running continuously since 17 December 2016:

  • Actual reorgs: 4 (1 every 84,352 blocks / 570.3 days)
  • Avoided reorgs: 174 (1 every 1,939 blocks / 13.1 days)

Light Node

Light Nodes decrease the load required to run a full node. Some implementations are better than others and if properly used can effectively displace the need for a full node.

Remote Connectors

Decentralized RPC Providers

Decentralized RPC Providers:

Decentralized RPC Providers should only be used for redundancy purposes.

Centralized RPC Providers

Centralized RPC Providers:

  • Infura
  • Alchemy
  • Quicknode

Centralized RPC Providers should only be used for redundancy purposes.

Protocol Level Liquidity

The purpose of the Protocol Level Liquidity is to distribute dual-coin liquidity rewards in ZNN and QSR to eligible Liquidity Providers.

Liquidity Embedded Contract

The Liquidity Embedded Contract is the embedded contract for the Orbital Program deployed on the Network of Momentum.

Contract implementation

The implementation of the Liquidity Embedded Contract has a total of 14 methods that can be called by sending a specifically crafted account block:

UpdateEmbeddedLiquidityMethod method

Method for updating the embedded liquidity contract.

Parameters

  • None

Returns

  • None

SetTokenTupleMethod method

Method for setting a token tuple and their corresponding reward percentages for the Orbital Program. Can only be set by the administrator.

Parameters

  • TokenStandards - an array containing the ZTS allowed for staking
  • ZnnPercentages - an array containing the ZNN percentage rewards for each ZTS in the TokenStandards array
  • QsrPercentages - an array containing the QSR percentage rewards for each ZTS in the TokenStandards array
  • MinAmounts - an array containing the minimum amounts for staking each ZTS in the TokenStandards array

Returns

  • None

LiquidityStakeMethod method

Method for staking the liquidity for the Orbital Program.

Parameters

  • stakeTime - stake time in seconds that should be a multiple of number in seconds for a month
  • tokenStandard - fetched from the send block
  • amount - fetched from the send block

Returns

  • None

CancelLiquidityStakeMethod method

Method for cancelling the liquidity stake for the Orbital Program.

Parameters

  • id - a hash that uniquely identifies the stake entry to be canceled

Returns

  • None

UpdateRewardEmbeddedLiquidityMethod method

Method to be called when the Liquidity Contract is updated. It contains the new mechanism for distributing dual-coin rewards.

Parameters

  • None

Returns

  • None

SetIsHalted method

Method for halting or unhalting the liquidity staking. Can only be called by the administrator.

Parameters

  • bool - true or false

Returns

  • None

UnlockLiquidityStakeEntries method

Method for unlocking the liquidity staking entries for a ZTS that is no longer allowed for staking.

Parameters

  • tokenStandard - fetched from the send block

Returns

  • None

SetAdditionalReward method

Method for setting an additional reward for the liquidity staking. Can only be called by the administrator.

Parameters

  • znnRewards - additional ZNN rewards for the next epochs
  • qsrRewards - additional QSR rewards for the next epochs

Returns

  • None

ChangeAdministratorLiquidity method

Method for changing the administrator for the liquidity embedded contract. Can only be called by the administrator. Guarded by a time challenge.

Parameters

  • address - address of the new administrator

Returns

  • None

NominateGuardiansLiquidity method

Method for nominating the guardians for the liquidity embedded contract. Can only be called by the Administrator. Guarded by a time challenge.

Parameters

  • []address - an array containing the new addresses

Returns

  • None

ProposeAdministratorLiquidity method

Method for proposing a new administrator for the liquidity embedded contract. Can only be called by a guardian if the embedded liquidity contract is in an emergency state.

Parameters

  • address - voted address

Returns

  • None

EmergencyLiquidity method

Method for putting the liquidity embedded contract into emergency mode. Can only be called by the administrator.

Parameters

  • None

Returns

  • None

Liquidity Embedded JSON-RPC API

The JSON-RPC API for the liquidity embedded contract.

JSON-RPC API Methods

GetLiquidityInfo method

Returns the current liquidity information or error in case it fails.

Parameters

  • None

Returns

  • LiquidityInfo - the current bridge information
type LiquidityInfo struct {
	Administrator types.Address `json:"administrator"`
	IsHalted      bool          `json:"isHalted"`
	ZnnReward     *big.Int      `json:"znnReward"`
	QsrReward     *big.Int      `json:"qsrReward"`
	TokenTuples   []TokenTuple  `json:"tokenTuples"`
}

Example

// todo

GetSecurityInfo method

Returns the current security information or error in case it fails.

Parameters

  • None

Returns

  • SecurityInfoVariable - the current security information
// SecurityInfoVariable This refers to time challenge security
type SecurityInfoVariable struct {
	// addresses that can vote for the new administrator once the bridge is in emergency
	Guardians []types.Address `json:"guardians"`
	// votes of the active guardians
	GuardiansVotes []types.Address `json:"guardiansVotes"`
	// delay upon which the new administrator or guardians will be active
	AdministratorDelay uint64 `json:"administratorDelay"`
	// delay upon which all other time challenges will expire
	SoftDelay uint64 `json:"softDelay"`
}

Example

// todo

GetLiquidityStakeEntriesByAddress method

Returns the current liquidity staking entries by address or error in case it fails.

Parameters

  • address - the address in Address format
  • pageIndex - the page index in uint32 format
  • pageSize - the size of the page in uint32 format

Returns

  • LiquidityStakeList - the current liquidity staking list
type LiquidityStakeList struct {
	TotalAmount         *big.Int                          `json:"totalAmount"`
	TotalWeightedAmount *big.Int                          `json:"totalWeightedAmount"`
	Count               int                               `json:"count"`
	Entries             []*definition.LiquidityStakeEntry `json:"list"`
}

Example

// todo

GetUncollectedReward method

Returns the RewardDeposit for a particular address or error in case it fails.

Parameters

  • address - the address in Address format

Returns

  • RewardDeposit - the current uncollected reward deposit
type RewardDeposit struct {
	Address *types.Address `json:"address"`
	Znn     *big.Int       `json:"znnAmount"`
	Qsr     *big.Int       `json:"qsrAmount"`
}

Example

// todo

GetFrontierRewardByPage method

Returns the RewardHistoryList for a particular address or error in case it fails.

Parameters

  • address - the address in Address format
  • pageIndex - the page index in uint32 format
  • pageSize - the size of the page in uint32 format

Returns

  • RewardHistoryList - the current reward history list
type RewardHistoryList struct {
	Count int64                 `json:"count"`
	List  []*RewardHistoryEntry `json:"list"`
}

Example

// todo

GetTimeChallengesInfo method

Returns a list of time challenges or error in case it fails.

Parameters

  • None

Returns

  • TimeChallengesList - the current a list of time challenges
type TimeChallengesList struct {
	Count int                             `json:"count"`
	List  []*definition.TimeChallengeInfo `json:"list"`
}
type TimeChallengeInfo struct {
	MethodName           string
	ParamsHash           types.Hash
	ChallengeStartHeight uint64
}

Example

// todo

Liquidity Embedded Constants

Liquidity constants are hard coded into the embedded.go file as network constants.

  • LiquidityZnnTotalPercentages represent the maximum sum for the ZNN percentage rewards of each allowed ZTS

  • LiquidityQsrTotalPercentages represent the maximum sum for the QSR percentage rewards of each allowed ZTS

  • LiquidityStakeWeights represent the liquidity staking weights depending on the number of months a user locks the liquidity

    LiquidityZnnTotalPercentages         uint32 = 10000
    LiquidityQsrTotalPercentages         uint32 = 10000
    LiquidityStakeWeights                       = []int64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
    }

Liquidity Embedded Error States

Liquidity error states.

ErrInvalidPercentages = errors.New("invalid percentages")
ErrInvalidRewards     = errors.New("invalid liquidity stake rewards")

Liquidity Embedded Unit Tests

The unit tests are available here with 74.5% code coverage.

License

The implementation is fully open source on Github with a permissive licensing model - GNU General Public License v3.0 to allow builders to develop a healthy middleware ecosystem for the Network of Momentum by integrate more networks.

Security

The philosophy underpinning the architecture is based on the Law of Action-Reaction. There can be no effect without a cause: every redeem transaction processed by the bridge must adhere to this causality principle. This means that funds must be locked/burned on the source network in order to be redeemed on the destination network.

Time-challenge security primitive

Every sensitive action is split into two separate stages and is safeguarded by a time-challenge security primitive. This primitive is used throughout the codebase for every sensitive action that either involves moving funds or other critical actions.

Additionally, the two step procedure is enforced in both wrapping or unwrapping assets:

  1. REQUEST: this action signals the intention of a user to wrap or unwrap his assets.

  2. REDEEM: this action settles the user's request and actually delivers the swapped assets to its corresponding address.

After the redeem request is created, there is a window during which the funds are unredeemable. Also during this window, the orchestrator nodes will check if there is a corresponding transaction on the source network that locks/burns the funds. In case it doesn't exist, the orchestrator nodes will start the halting process of the bridge.

Realtime Monitoring

The NoM Multi-chain infrastructure project expects all participants to develop and maintain their own security monitoring strategies. This expectation is based on the value of having heterogeneous monitoring strategies across the Guardian set as a function of Wormhole's defense in depth approach, increasing the likelihood of detecting fraudulent activity.

Pillar operators participating in the Orchestrator Layer (running orchestrator nodes) should aim to capture all of the following domains with their monitoring strategies:

  • Orchestrator node monitoring: TSS ceremonies, peer-to-peer messages, logs, etc.
  • Blockchain node monitoring: transaction activity, peer-to-peer messages, reorgs, logs, etc.
  • Smart Contracts activity: on-chain state, emitted events, etc.
  • Administrator Module activity: on-chain state
  • Social media monitoring
  • Bug bounty program
  • Github security reporting
  • Audit findings
  • Forum thread

The orchestrator layer has a powerful built-in logging library.

Lastly, if any user detects a security event via their monitoring system, they are urged to engage with the Pillar operators or the admin in order to activate the emergency state.

Emergency Mode

The emergency mode for the decentralized bridge is designed to prevent any damage should a failure occurs. Only the administrator can put the bridge on each network in an emergency state.

There are 4 possible states in total:

LiveState      uint8 = 0
KeyGenState    uint8 = 1
HaltedState    uint8 = 2
EmergencyState uint8 = 3

Distributed Halting Mechanism

The decentralized bridge has a built-in distributed halting mechanism that will halt it in case it observes an event on a destination network that has no corresponding event on the source network. Concretely, redeem requests without lock/burn associated transactions will trigger a signing ceremony to halt the bridge on each network. Only the administrator and the orchestrator nodes can call the halting procedure via the dedicated halt method.

Guardians Voting System

In the extreme case that the bridge is in emergency state the administrator address becomes null. A new administrator must be voted by the guardians in order to restore functionality. Once a voted address reaches a quorum of 50% + 1 votes out of the total number of guardians, it becomes the new administrator.

Deployed Contracts

Here you can find the addresses for the deployed core contracts on all the networks that the NoM Multi-chain Infrastructure supports, including testnet deployments.

Mainnet Deployments

Mainnet Core Contracts

Network nameNetwork ClassChain IDContract Address
Network of Momentum11
Ethereum21TBA
Binance Smart Chain256TBA
Avalanche (C-Chain)243114TBA
Fantom2250TBA
Celo242220TBA
Arbitrum242161TBA
Polygon2137TBA
Optimism210TBA
Bitcoin3N/AN/A
Litecoin3N/AN/A

Testnet Deployments

Testnet Core Contracts

Network nameNetwork ClassChain IDContract Address
Network of Momentum11
Ethereum21TBA
Binance Smart Chain256TBA
Avalanche (C-Chain)243114TBA
Fantom2250TBA
Celo242220TBA
Arbitrum242161TBA
Polygon2137TBA
Optimism210TBA
Bitcoin3N/AN/A
Litecoin3N/AN/A

Audits

The core components of the NoM multi-chain infrastructure (go-tss and tss-lib libraries) are properly audited are are used in production by high ranking cryptocurrencies like Thorchain.

References

  1. Orbital Program

  2. Hyperspace interoperability: cross-chain bridge