Create Custom Contracts
The following will guide you through an example implementation of using SKALE’s Native Messaging Layer to send custom information back and forth between SKALE Chains. The following implements a bi-directional flow of data to showcase both sending and receiving clearly, however, contracts can easily implement a one-way flow.
Custom Contract
Section titled “Custom Contract”// SDPX-License-Identifier: MITpragma solidity 0.8.9;
import { IMessageProxyForSchain } from "./IMessageProxyForSchain.sol";
contract SendNumber {
/// @notice lastNumber is the last value recieved via IMA. This is for testing purposes uint256 public lastNumber;
/// @notice the dstChainHash is the keccak256 hash of the SKALE Chain name i.e keccak256(abi.encodePacked("elated-tan-skat")) bytes32 public dstChainHash;
/// @notice the dstContractAddr is the address of the receiving contract on the other chain address public dstContractAddr;
/// @notice messageProxy is a predeployed contract on all SKALE Chains IMessageProxyForSchain public messageProxy = IMessageProxyForSchain(0xd2AAa00100000000000000000000000000000000);
event NumberReceived(uint256 indexed number, address indexed sender);
constructor( bytes32 _dstChainHash, address _dstContractAddr ) { dstChainHash = _dstChainHash; dstContractAddr = _dstContractAddr; }
function sendNumberToChain(uint256 number) external { /// this is how you post a message to IMA messageProxy.postOutgoingMessage( dstChainHash, dstContractAddr, abi.encode(number) ); }
/// @notice this is how you recieve a message from IMA function postMessage( bytes32 schainHash, address sender, bytes calldata data ) external { if (schainHash != dstChainHash) revert("Invalid Chain Hash"); (uint256 number) = abi.decode(data, (uint256)); lastNumber = number; emit NumberReceived(number, sender); }}
Key Notes
Section titled “Key Notes”- This contract is both a sender and receiver via IMA
- This means it implements both postOutgoingMessage via MessageProxy interface AND postMessage which is the receiving part
- This contract takes two constructor arguments to set the destination (dst) chain and contract which are later used to check and validate messages