diff --git a/docs/dapp/opl/celer/ping-example.md b/docs/dapp/opl/celer/ping-example.md new file mode 100644 index 0000000000..6263099571 --- /dev/null +++ b/docs/dapp/opl/celer/ping-example.md @@ -0,0 +1,202 @@ +--- +description: Ping example with Celer IM +--- + +# Ping Example + +This tutorial demonstrates how to send a cross-chain message using +[Celer's Inter-Chain Messaging (IM)]. + +[Celer's Inter-Chain Messaging (IM)]: https://im-docs.celer.network/ + +You'll learn how to: + + - Deploy MessageBus-compatible contracts + - Send cross-chain messages + +We recommend using [Remix] for an easy-to-follow experience. +The only prerequisite is a set-up Metamask account. + +:::info + +If you're new to Remix, follow our basic guide for using Remix +[here][dapp-remix]. + +[dapp-remix]: /dapp/emerald/writing-dapps-on-emerald#create-dapp-on-emerald-with-remix---ethereum-ide + +::: + +## Overview Ping + +In this example, you'll deploy the same contract on two different chains. +You'll then send a `ping` from chain A to chain B, facilitated by Celer-IM. +The contract on chain B will receive the `ping` and emits an event with the +message which was received. + +## Contract Setup + +1. Open [Remix] and create a new file called `Ping.sol` +2. Paste the following contract and interface into it: + +
+ Ping.sol Contract + + ```solidity title="Ping.sol" showLineNumbers + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; + + interface IMessageBus { + function sendMessage( + address _receiver, + uint256 _dstChainId, + bytes calldata _message + ) external payable; + } + + + contract Ping { + address public messageBus; + + event MessageReceived( + address srcContract, + uint64 srcChainId, + address sender, + bytes message + ); + + + enum ExecutionStatus { + Fail, // execution failed, finalized + Success, // execution succeeded, finalized + Retry // execution rejected, can retry later + } + + constructor(address _messageBus) { + messageBus = _messageBus; + } + + modifier onlyMessageBus() { + require(msg.sender == messageBus, "caller is not message bus"); + _; + } + + + function sendPing( + address _dstContract, + uint64 _dstChainId, + bytes calldata _message + ) external payable { + bytes memory message = abi.encode(msg.sender, _message); + IMessageBus(messageBus).sendMessage{value: msg.value}(_dstContract, _dstChainId, message); + } + + function executeMessage( + address _srcContract, + uint64 _srcChainId, + bytes calldata _message, + address // executor + ) external payable onlyMessageBus returns (ExecutionStatus) { + (address sender, bytes memory message) = abi.decode( + (_message), + (address, bytes) + ); + emit MessageReceived(_srcContract, _srcChainId, sender, message); + return ExecutionStatus.Success; + } + } + ``` +
+ +### Key points + +- `messageBus`: Celer's MessageBus contract on the respective chain. +- `sendPing`: Initiates the cross-chain my calling Celers MessageBus. +- `executeMessage`: Called by Celer's MessageBus on the destination chian. + +## Compiling the Contract + +For compatibility with Sapphire, compile the contract using Solidity version +**`0.8.24`** or older. + +:::info + +You can also use Celer's framework contracts and interfaces by importing them + +```solidity +import "sgn-v2-contracts/contracts/message/framework/MessageBusAddress.sol"; +import "sgn-v2-contracts/contracts/message/framework/MessageReceiverApp.sol"; +import "sgn-v2-contracts/contracts/message/interfaces/IMessageBus.sol"; +``` + +but this will limit you to use only Solidity version **`0.8.9`**. + +::: + +### Deploying the Contract + +Deploy the Ping contract on two different chains: `BSC Testnet` and +`Sapphire Testnet`. + +#### Deploying on BSC Testnet + +1. Obtain BNB test token for `BSC Testnet` from the [BNB faucet] or their + discord. +2. In MetaMask, switch to the `BSC Testnet` network and select + `Injected Provider - MetaMask` as the environment in Remix. +3. Fill in the messageBus address for BSC Testnet: + `0xAd204986D6cB67A5Bc76a3CB8974823F43Cb9AAA`. +4. Deploy the contract on `BSC Testnet`. + + +[BNB faucet]: https://www.bnbchain.org/en/testnet-faucet + +#### Deploying on Sapphire Testnet + +1. Obtain TEST tokens for `Sapphire Testnet` from the [Oasis faucet]. +2. In Metamask, switch to the `Sapphire Testnet` network and select + `Injected Provider - MetaMask` as the environment in Remix +3. Fill in the messageBus address for BSC Testnet: + `0x9Bb46D5100d2Db4608112026951c9C965b233f4D`. +4. Deploy the contract on Sapphire Testnet + +[Oasis Faucet]: https://faucet.testnet.oasis.io/ + +## Executing Ping + +Now that you've deployed the contacts, you can send the ping message +cross-chain. + +You'll need the following three parameters: + +- `_dstContract`: The contract address of the reveiving contract on the + destination chain which you just deployed. +- `_dstChainId`: The chain id of the the destination chain. Which is in our + example `Sapphire Testnet` - `23295`. +- `message`: The encoded message. e.g. "Hello from BSC" - + `0x48656c6c6f2066726f6d20425343000000000000000000000000000000000000`. + +Additionally you'll have to pay a fee which you send as value. For sending the +ping 0.001 tBNB will be enough. + +:::info + +For the `Sapphire Testnet` an executor is running to relay the messages every +few mintues. If you deploy on mainnet please refer to the [Executor chapter] +on how to run an executor. +::: + +[Executor chapter]: ./README.md#executor + +:::info + +//TODO: add statement about encrypting the message for real use cases + +::: + +## Checking execution + +To see if you successfully send a ping message cross-chain you can watch for +new transactions at the [MessageBus address] from Celer or your deployed +contract Sapphire Testnet + +[MessageBus address]: https://explorer.oasis.io/testnet/sapphire/address/0x9Bb46D5100d2Db4608112026951c9C965b233f4D \ No newline at end of file diff --git a/docs/dapp/opl/celer/pingpong-example.md b/docs/dapp/opl/celer/pingpong-example.md deleted file mode 100644 index 0854e8faee..0000000000 --- a/docs/dapp/opl/celer/pingpong-example.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -description: PingPong example with Celer IM ---- - -# Ping Pong Example \ No newline at end of file diff --git a/docs/dapp/opl/opl-sdk/ping-example.md b/docs/dapp/opl/opl-sdk/ping-example.md new file mode 100644 index 0000000000..24dca58c15 --- /dev/null +++ b/docs/dapp/opl/opl-sdk/ping-example.md @@ -0,0 +1,195 @@ +--- +description: Ping example with OPL SDK +--- + +# Ping Example + +This tutorial demonstrates how to send a cross-chain message using +[Oasis OPL]. + +[Oasis OPL]: ./README.md + +You'll learn how to: + + - Deploy a Host contract + - Deploy a Enclave contract + - Send a cross-chain message + +We recommend using [Remix] for an easy-to-follow experience. +The only prerequisite is a set-up Metamask account. + +:::info + +If you're new to Remix, follow our basic guide for using Remix +[here][dapp-remix]. + +[dapp-remix]: /dapp/emerald/writing-dapps-on-emerald#create-dapp-on-emerald-with-remix---ethereum-ide + +::: + +## Overview Ping + +In this example, you'll deploy a `host` contract on *BSC Testnet* and a `enclave` +contract on *Sapphire Testnet*. +You'll then send a `ping` from the host contract to the enclave contract, +facilitated by the OPL SDK. +The enclave contract will receive the `ping` and emits an event with the +message which was received. + +## Contract Setup + +1. Open [Remix] and create a new file called `Ping.sol` +2. Paste the following Ping host contract into it: + +
+ Ping.sol Contract + + ```solidity title="Ping.sol" showLineNumbers + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; + + import {Host, Result} from "@oasisprotocol/sapphire-contracts/contracts/OPL.sol"; + + contract Ping is Host { + event MessageReceived(bytes message); + + constructor(address pong) Host(pong) { + registerEndpoint("pongMessage", _pongMessage); + } + + function startPing (bytes calldata _message) external payable { + postMessage("ping", abi.encode(_message)); + } + + function _pongMessage(bytes calldata _args) internal returns (Result) { + (bytes memory message) = abi.decode((_args), (bytes)); + emit MessageReceived(message); + return Result.Success; + } + } + ``` +
+ +3. Create a new file called `Pong.sol` +4. Paste the following Pong enclave contract into it: + +
+ Pong.sol Contract + + ```solidity title="Pong.sol" showLineNumbers + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; + + import {Enclave, Result, autoswitch} from "@oasisprotocol/sapphire-contracts/contracts/OPL.sol"; + + contract Pong is Enclave { + event MessageReceived(bytes message); + + constructor(address ping, bytes32 chain) Enclave(ping, autoswitch(chain)) { + registerEndpoint("ping", _pingMessage); + } + + function _pingMessage(bytes calldata _args) internal returns (Result) { + (bytes memory message) = abi.decode((_args), (bytes)); + emit MessageReceived(message); + return Result.Success; + } + } + ``` +
+ +### Key points + +- `Host`: Celer's MessageBus contract on the respective chain. +- `sendPing`: Initiates the cross-chain my calling Celers MessageBus. +- `executeMessage`: Called by Celer's MessageBus on the destination chian. + +## Compiling the Contract + +For compatibility with Sapphire, compile the contract using Solidity version +**`0.8.24`** or older. + +:::info + +You can also use Celer's framework contracts and interfaces by importing them + +```solidity +import "sgn-v2-contracts/contracts/message/framework/MessageBusAddress.sol"; +import "sgn-v2-contracts/contracts/message/framework/MessageReceiverApp.sol"; +import "sgn-v2-contracts/contracts/message/interfaces/IMessageBus.sol"; +``` + +but this will limit you to use only Solidity version **`0.8.9`**. + +::: + +### Deploying the Contract + +Deploy the Ping contract on two different chains: `BSC Testnet` and +`Sapphire Testnet`. + +#### Deploying on BSC Testnet + +1. Obtain BNB test token for `BSC Testnet` from the [BNB faucet] or their + discord. +2. In MetaMask, switch to the `BSC Testnet` network and select + `Injected Provider - MetaMask` as the environment in Remix. +3. Fill in the messageBus address for BSC Testnet: + `0xAd204986D6cB67A5Bc76a3CB8974823F43Cb9AAA`. +4. Deploy the contract on `BSC Testnet`. + + +[BNB faucet]: https://www.bnbchain.org/en/testnet-faucet + +#### Deploying on Sapphire Testnet + +1. Obtain TEST tokens for `Sapphire Testnet` from the [Oasis faucet]. +2. In Metamask, switch to the `Sapphire Testnet` network and select + `Injected Provider - MetaMask` as the environment in Remix +3. Fill in the messageBus address for BSC Testnet: + `0x9Bb46D5100d2Db4608112026951c9C965b233f4D`. +4. Deploy the contract on Sapphire Testnet + +[Oasis Faucet]: https://faucet.testnet.oasis.io/ + +## Executing Ping + +Now that you've deployed the contacts, you can send the ping message +cross-chain. + +You'll need the following three parameters: + +- `_dstContract`: The contract address of the reveiving contract on the + destination chain which you just deployed. +- `_dstChainId`: The chain id of the the destination chain. Which is in our + example `Sapphire Testnet` - `23295`. +- `message`: The encoded message. e.g. "Hello from BSC" - + `0x48656c6c6f2066726f6d20425343000000000000000000000000000000000000`. + +Additionally you'll have to pay a fee which you send as value. For sending the +ping 0.001 tBNB will be enough. + +:::info + +For the `Sapphire Testnet` an executor is running to relay the messages every +few mintues. If you deploy on mainnet please refer to the [Executor chapter] +on how to run an executor. +::: + +[Executor chapter]: ./README.md#executor + +:::info + +//TODO: add statement about encrypting the message for real use cases + +::: + +## Checking execution + +To see if you successfully send a ping message cross-chain you can watch for +new transactions at the [MessageBus address] from Celer or your deployed +contract Sapphire Testnet + +[MessageBus address]: https://explorer.oasis.io/testnet/sapphire/address/0x9Bb46D5100d2Db4608112026951c9C965b233f4D + +[Remix]: https://remix.ethereum.org/ diff --git a/sidebarDapp.ts b/sidebarDapp.ts index d8e3ba8789..4b63109fb7 100644 --- a/sidebarDapp.ts +++ b/sidebarDapp.ts @@ -79,7 +79,7 @@ export const sidebarDapp: SidebarsConfig = { }, items: [ 'dapp/opl/celer/networks', - 'dapp/opl/celer/pingpong-example', + 'dapp/opl/celer/ping-example', ], }, {