Client contracts implementation logic

Send and receive arbitrary messages between EVM and non-EVM chains

To implement a smart contract, you need to extend it from the abstract class made by the Asterizm team.

Examples of client contract implementation can be found in the official repository -

Important! To support different types of networks (currently EVM and TVM) we decided to convert all address variables to the uint format. It is necessary to take this into account when integrating the protocol.

To simplify the process, we have implemented the following libraries:

The developer of the client contract must follow several steps:

Add a library

You need to add AsterizmProtocol library to your package.json: “asterizmprotocol”: “^1.0.1" and update packages - npm i

Import abstract contract

You need to import an Asterizm abstract client contract into your contract: For EVM: import "asterizmprotocol/contracts/evm/AsterizmClient.sol" (you can also use import "asterizmprotocol/contracts/evm/AsterizmClientUpgradeable.sol" for upgradeable client contracts, example) For TVM: import "asterizmprotocol/contracts/tvm/AsterizmClient.tsol"

Call the class constructor

Call constructor of base client contract setting of necessary parameters: For EVM: AsterizmClient(IInitializerSender _initializerLib, bool _useForceOrder, bool _disableHashValidation) For TVM: In this network, the constructor does not take any parameters as input, instead static parameters are used initializerLib_, useForceOrder_, disableHashValidation_ initializerLib - initializer contract address (see the list of supported networks), useForceOrder - flag of strict message order (see Best practices), disableHashValidation - disable transfer hash validation flag (see Best practices)

Adding trusted addresses

A list of trusted addresses must be populated for the system. This list contains trusted contract addresses for each supported network. This is done by one of two methods:

addTrustedAddress(uint64 _chainId, uint _trusterAddress)

addTrustedAddresses(uint64[] _chainId, uint[] _trusterAddress)

Sending messages

To initialize the transfer you need to call the transfer initialization method:

For EVM: _initAsterizmTransfer(uint64 _dstChainId, bytes _payload)

For TVM: _initAsterizmTransfer(uint64 _dstChainId, TvmCell _payload)

_dstChainId - destination network ID (see the list of supported networks), _payload - instructions encoded in bytes, for example with abi.encode() method

Please note: it is not necessary to specify a contract address in the destination network - it is taken from the list of trusted addresses (read Adding trusted addresses).

Examples of transfer initialization:

Receive and execute messages

You need to implement _asterizmReceive() method to receive and execute data in the destination network. This method accepts one _dto parameter type ClAsterizmReceiveRequestDto, which contains all transfer data.

To retrieve the transferred instructions, the _dto.payload parameter must be decoded into the originally transferred data type, for example using the abi.decode()method.


For EVM networks only.

You need to implement the _buildPackedPayload()method. This method is necessary for the internal protocol logic to convert your payload from abi.encode() format into abi.encodePacked(). This conversion is necessary to implement cross-chain hashing.

Cross-chain data hashing logic

Asterizm protocol has a universal cross-chain data hashing logic. It is required to check the validity and integrity of the data transferred within a cross-chain transaction.

The protocol currently supports the following network types: EVM and TVM. Asterizm independently selects the hashing method depending on what types the source and destination networks are at the abstraction level of the client smart contract.


Check out an example of hashing implementation for EVM networks.

As mentioned above, in EVM networks you need to implement the method _buildPackedPayload()- example.


In TVM networks there are several versions of the hashing implementation, so you have to choose the version based on your requirements:

  • buildCrosschainHashV1()- this version of hashing implementation is relatively cheap, but it has a nuance - if your payload involves sending such data types as bytes or string, you should add these data to the very end of the list when packing (abi.encode()) otherwise hash validation errors may occur in the destination network. Use this method if you do not need to send a large number of bytes or string parameters, or to save on gas.

  • buildCrosschainHashV2()- this version of hashing has a much higher gas price but avoids the problem of the first version related to the position of bytes and string data in your payload. Use this version if you need to send bytes or string data types.

Check out an example of hashing implementation for TVM networks.


In case you perform cross-chain transfer between different types of networks (EVM->TVM, TVM->EVM) it is strongly recommended not to use bool type in payload parameters. Otherwise, validation of transfer integrity in the destination network will fail.

Congratulations! The contracts for messaging in the required networks are ready and can be deployed to the networks supported by Asterizm

Estimating message fees

To understand the payment process and the calculation of cross-chain transaction fees, please see the Fees management section

Upgradeable client contracts

The protocol allows for the creation of upgradable client contracts on EVM networks, enabling the separation of system logic and data at the contract level.

To implement an upgradable client contract, you should inherit from"asterizmprotocol/contracts/evm/AsterizmClientUpgradeable.sol" contract abstraction, and instead of using a contract constructor you should utilize a special initialization function as follows: function initialize(IInitializerSender _initializerLib) initializer public { __AsterizmClientUpgradeable_init(_initializerLib, true, true); }

Here is an example of how to implement an upgradable contract:

You are almost there!

Get ready to make your transactions confidential using the Client off-chain module - you will learn how to set it up in the next section.

Last updated