Work with multiple functions in a single Cross-Chain dApp
Great work. We can now pack multiple values into a message. In this section, we will learn how to encode the function name and depending on that its parameters in the message. Let's imagine a more advanced calculator that not only has a single add function but also a concatenate function, that lets you concatenate two strings.
For the add function we need to encode two numbers. For the concatenate function we need to encode two strings. How can we go about this? The concept is easy: It's like packing an envelope into another envelope:
pragma solidity ^0.8.18;import "@teleporter/ITeleporterMessenger.sol";import "./CalculatorActions.sol"; contract CalculatorSenderOnCChain { ITeleporterMessenger public immutable teleporterMessenger = ITeleporterMessenger(0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf); function sendAddMessage(address destinationAddress, uint256 num1, uint256 num2) external { teleporterMessenger.sendCrossChainMessage( TeleporterMessageInput({ // Replace with chain id of your Avalanche L1 (see instructions in Readme) destinationBlockchainID: 0x92756d698399805f0088fc07fc42af47c67e1d38c576667ac6c7031b8df05293, destinationAddress: destinationAddress, feeInfo: TeleporterFeeInfo({feeTokenAddress: address(0), amount: 0}), requiredGasLimit: 100000, allowedRelayerAddresses: new address[](0), message: encodeAddData(num1, num2) }) ); } function sendConcatenateMessage(address destinationAddress, string memory text1, string memory text2) external { teleporterMessenger.sendCrossChainMessage( TeleporterMessageInput({ // Replace with chain id of your Avalanche L1 (see instructions in Readme) destinationBlockchainID: 0x382d2a20c299b03b638dd4d42b96e7401f6c3e88209b764abce83cf71c0c30cd, destinationAddress: destinationAddress, feeInfo: TeleporterFeeInfo({feeTokenAddress: address(0), amount: 0}), requiredGasLimit: 100000, allowedRelayerAddresses: new address[](0), message: encodeConcatenateData(text1, text2) }) ); } // Encode helpers function encodeAddData(uint256 a, uint256 b) public pure returns (bytes memory) { bytes memory paramsData = abi.encode(a, b); return abi.encode(CalculatorAction.add, paramsData); } function encodeConcatenateData(string memory a, string memory b) public pure returns (bytes memory) { bytes memory paramsData = abi.encode(a, b); return abi.encode(CalculatorAction.concatenate, paramsData); }}
As you can see here we are calling abi.encode twice in the encode helpers. The first time we encode the function paramters and the second time we encode the function name with the byte array containing paramters.
Then based on the function name we decide how to unpack the paramters
// Route to the appropriate function. if (actionType == CalculatorAction.add) { (uint256 a, uint256 b) = abi.decode(paramsData, (uint256, uint256)); _calculatorAdd(a, b);} else if (actionType == ...) { (string memory text1, string memory text2) = abi.decode(paramsData, (string, string)); _calculatorConcatenateStrings(text1, text2);} else { revert("CalculatorReceiverOnSubnet: invalid action");}
For the add function we decode two numbers and for the concatenate function we decode two strings. After the decoding we call the appropriate internal function.
[⠃] Compiling...[⠆] Compiling 2 files with Solc 0.8.18[⠰] Solc 0.8.18 finished in 240.23msCompiler run successful!Deployer: 0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FCDeployed to: 0x8B3BC4270BE2abbB25BC04717830bd1Cc493a461Transaction hash: 0xf9cce28a714764bb265bba7522bfd10d620fa0cb0f5dae26de2ac773b0a878ee
[⠊] Compiling...[⠢] Compiling 1 files with Solc 0.8.18[⠆] Solc 0.8.18 finished in 148.40msCompiler run successful!Deployer: 0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FCDeployed to: 0x5DB9A7629912EBF95876228C24A848de0bfB43A9Transaction hash: 0xa8efb88abfef486d2caba30cb4146b1dc56a0ee88c7fb4c46adccdf1414ae39e