-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from msgport/bear-pingpong
Add PingPong Example
- Loading branch information
Showing
10 changed files
with
285 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"ORMP_PORT": "0x2cd1867Fb8016f93710B6386f7f9F1D540A60812", | ||
"FEE": 10000000000000000 | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"ORMP_PORT": "0x2cd1867Fb8016f93710B6386f7f9F1D540A60812", | ||
"FEE": 5000000000000000000000 | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"PingPong": "0x0c8541f3A9B5384029BFdbA5e8f8D6E4242FC02a" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"PingPong": "0xC0FFF7abA8C095ce1c074C743c7526aa7432535E" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
# Cross-chain PingPong | ||
|
||
## Preparation | ||
|
||
### Install foundry | ||
|
||
```bash | ||
curl -L https://foundry.paradigm.xyz | bash | ||
foundryup | ||
forge install | ||
``` | ||
|
||
### Clone repo and submodules | ||
|
||
```bash | ||
git clone --recursive https://github.com/msgport/msgport-examples.git | ||
``` | ||
|
||
### Account with balance | ||
|
||
Before proceeding with the tutorial, you need an account with sufficient balance. This is required to perform contract operations in both the Koi and Sepolia testnets. If you don't have an account with sufficient balance, you may encounter difficulties when interacting with these contracts. Once you have the account, copy and create a `.env` file based on the `.env.example` file in the root of the repository. This will allow you to continue with the tutorial. | ||
|
||
## Overview | ||
|
||
This examples is designed very simple and straightforward, aims to illustrate how to integrate the Msgport protocol for a dapp. | ||
|
||
In this example, we will deploy the `PingPong` contract in both the Koi and Sepolia testnets. We will then call the `ping()` function of the `PingPong` contract in the Koi testnet, which will trigger the cross-chain message delivery and invoke the `pong()` function of the `PingPong` contract in the Sepolia testnet. Once the `pong` is received in the Sepolia testnet, it will call `ping` back and trigger the `pongReceive()` function of the source chain. | ||
|
||
### Deploy PingPong in the Koi testnet | ||
|
||
```sh | ||
forge script src/pingpong/script/Deploy.s.sol:DPingPongSource --broadcast --rpc-url https://koi-rpc.darwinia.network | ||
``` | ||
|
||
The output: | ||
|
||
```sh | ||
== Logs == | ||
PingPong has been deployed at chain: 701, contract: 0xC0FFF7abA8C095ce1c074C743c7526aa7432535E | ||
|
||
## Setting up 1 EVM. | ||
========================== | ||
Chain 701 | ||
|
||
Estimated gas price: 150.706512128 gwei | ||
Estimated total gas used for script: 703866 | ||
Estimated amount required: 0.106077189865486848 ETH | ||
|
||
========================== | ||
|
||
##### 701 | ||
✅ [Success]Hash: 0xfa05e4ee172254dededb2f8e7364dea987cb768c2541afb989224b97fa429cf1 | ||
Contract Address: 0xC0FFF7abA8C095ce1c074C743c7526aa7432535E | ||
Block: 193754 | ||
Paid: 0.040809967125653248 ETH (541582 gas * 75.353256064 gwei) | ||
|
||
``` | ||
|
||
### Deploy PingPong in the Sepolia testnet | ||
|
||
```sh | ||
forge script src/pingpong/script/Deploy.s.sol:DPingPongTarget --broadcast --rpc-url https://ethereum-sepolia.publicnode.com | ||
``` | ||
|
||
The output: | ||
|
||
```sh | ||
== Logs == | ||
PingPong has been deployed at chain: 11155111, contract: 0x0c8541f3A9B5384029BFdbA5e8f8D6E4242FC02a | ||
|
||
## Setting up 1 EVM. | ||
========================== | ||
Chain 11155111 | ||
|
||
Estimated gas price: 48.991176468 gwei | ||
Estimated total gas used for script: 736711 | ||
Estimated amount required: 0.036092338606916748 ETH | ||
========================== | ||
|
||
##### sepolia | ||
✅ [Success]Hash: 0xbf8c63f6cd7fbae37a6b92a51279b41bf0deabafff82f9ae18857c60e37dccf4 | ||
Block: 6243115 | ||
Paid: 0.00055404038891591 ETH (22490 gas * 24.634966159 gwei) | ||
|
||
|
||
##### sepolia | ||
✅ [Success]Hash: 0xb1d86cf0d529a8eee8e91462119a13ddcf22d19f41eb7d2f8c85afd8dee297ad | ||
Contract Address: 0x0c8541f3A9B5384029BFdbA5e8f8D6E4242FC02a | ||
Block: 6243115 | ||
Paid: 0.013340967383541814 ETH (541546 gas * 24.634966159 gwei) | ||
``` | ||
|
||
### Send Ping from the Koi testnet | ||
|
||
```sh | ||
forge script src/pingpong/script/SendPing.s.sol:SendPing --broadcast --rpc-url https://koi-rpc.darwinia.network --gas-estimate-multiplier 200 | ||
``` | ||
|
||
The output: | ||
|
||
```sh | ||
== Logs == | ||
The message has been sent to chain: 11155111, msgId: 0x2356043973bba1b6881ecf15b326fdc243fd2e7b2498fb12c4149e652421e81d | ||
|
||
## Setting up 1 EVM. | ||
========================== | ||
Chain 701 | ||
|
||
Estimated gas price: 150.706512128 gwei | ||
Estimated total gas used for script: 285696 | ||
Estimated amount required: 0.043056247688921088 ETH | ||
|
||
========================== | ||
|
||
##### 701 | ||
✅ [Success]Hash: 0x77d07b664edf1813e41a9284ac895f9335625203efd6b44771e2c3326dbc7f09 | ||
Block: 193773 | ||
Paid: 0.014324503271254272 ETH (190098 gas * 75.353256064 gwei) | ||
``` | ||
|
||
After sending the ping, you can find the msgId in the output. The msgId can be used to track the status of the ping message in the [Msgport Scan](https://scan.msgport.xyz/). For example, you can check out the status on the Msgport Scan website by entering the msgId and selecting the network. If the status changes from "inflight" to "success", it means that the "pong" function in the target chain has been called successfully. It will then call back and trigger the `PongReceive` event in the Koi testnet. | ||
|
||
To check the `PongReceive` event in the Koi testnet, you can wait for about 5 minutes and check the events for the PingPong contract in the Koi testnet. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
pragma solidity ^0.8.17; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {stdJson} from "forge-std/StdJson.sol"; | ||
import {console2 as console} from "forge-std/console2.sol"; | ||
|
||
import "../../../script/ScriptTools.sol"; | ||
import "../src/PingPong.sol"; | ||
|
||
contract DPingPongSource is Script { | ||
using stdJson for string; | ||
using ScriptTools for string; | ||
|
||
function run() public { | ||
vm.setEnv("FOUNDRY_ROOT_CHAINID", vm.toString(block.chainid)); | ||
vm.setEnv("FOUNDRY_EXPORTS_OVERWRITE_LATEST", vm.toString(true)); | ||
|
||
string memory input = ScriptTools.readInput("constructor"); | ||
address port_address = input.readAddress(".ORMP_PORT"); | ||
uint256 fee = input.readUint(".FEE"); | ||
|
||
vm.startBroadcast(vm.envUint("PRIVATE_KEY")); | ||
PingPong pingpong = new PingPong(port_address, fee); | ||
vm.stopBroadcast(); | ||
|
||
console.log("PingPong has been deployed at chain: %s, contract: %s", block.chainid, address(pingpong)); | ||
ScriptTools.exportContract("pingpong", "PingPong", address(pingpong)); | ||
} | ||
} | ||
|
||
contract DPingPongTarget is Script { | ||
using stdJson for string; | ||
using ScriptTools for string; | ||
|
||
function run() public { | ||
vm.setEnv("FOUNDRY_ROOT_CHAINID", vm.toString(block.chainid)); | ||
vm.setEnv("FOUNDRY_EXPORTS_OVERWRITE_LATEST", vm.toString(true)); | ||
|
||
string memory input = ScriptTools.readInput("constructor"); | ||
address port_address = input.readAddress(".ORMP_PORT"); | ||
uint256 fee = input.readUint(".FEE"); | ||
|
||
vm.startBroadcast(vm.envUint("PRIVATE_KEY")); | ||
PingPong pingpong = new PingPong(port_address, fee); | ||
// transfer fee to the PingPong contract ahead. | ||
payable(pingpong).transfer(fee); | ||
vm.stopBroadcast(); | ||
|
||
console.log("PingPong has been deployed at chain: %s, contract: %s", block.chainid, address(pingpong)); | ||
ScriptTools.exportContract("pingpong", "PingPong", address(pingpong)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
pragma solidity ^0.8.17; | ||
|
||
import {stdJson} from "forge-std/StdJson.sol"; | ||
import {Script} from "forge-std/Script.sol"; | ||
import {console2 as console} from "forge-std/console2.sol"; | ||
import {Surl} from "surl/Surl.sol"; | ||
|
||
import "../../../script/ScriptTools.sol"; | ||
import "../src/PingPong.sol"; | ||
|
||
contract SendPing is Script { | ||
using Surl for *; | ||
using stdJson for string; | ||
using ScriptTools for string; | ||
|
||
function run() public { | ||
// Darwinia Koi network as source chain | ||
uint256 fromChainId = 701; | ||
// Sepolia as target chain | ||
uint256 toChainId = 11155111; | ||
|
||
vm.setEnv("FOUNDRY_ROOT_CHAINID", vm.toString(fromChainId)); | ||
string memory input = ScriptTools.readInput("constructor"); | ||
uint256 fee = input.readUint(".FEE"); | ||
string memory souceContract = ScriptTools.readOutput("pingpong"); | ||
address pingpongSource = souceContract.readAddress(".PingPong"); | ||
vm.setEnv("FOUNDRY_ROOT_CHAINID", vm.toString(toChainId)); | ||
string memory targetContract = ScriptTools.readOutput("pingpong"); | ||
address pingpongTarget = targetContract.readAddress(".PingPong"); | ||
bytes memory message = abi.encodeCall(PingPong.pong, ()); | ||
|
||
vm.startBroadcast(vm.envUint("PRIVATE_KEY")); | ||
PingPong pingpong = PingPong(payable(pingpongSource)); | ||
bytes32 msgId = pingpong.ping{value: fee}(toChainId, pingpongTarget, message); | ||
vm.stopBroadcast(); | ||
|
||
console.log("The message has been sent to chain: %s, msgId: %s", toChainId, vm.toString(msgId)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.17; | ||
|
||
import "msgport/user/Application.sol"; | ||
import "msgport/interfaces/IMessagePort.sol"; | ||
|
||
contract PingPong is Application { | ||
event ReceivedToken(address indexed from, uint256 value); | ||
|
||
event PingSent(uint256 fromChainId, uint256 toChainId, bytes32 msgId); | ||
event PongSent(uint256 fromChainId, uint256 toChainId, bytes32 msgId); | ||
event PongReceive(uint256 fromChainId, uint256 toChainId); | ||
|
||
// The port address, which can be any messaging protocols that under the Msgport protocol. | ||
address public immutable PORT; | ||
uint256 public immutable Fee; | ||
bytes public Params = | ||
hex"000000000000000000000000000000000000000000000000000000000001da53000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"; | ||
|
||
constructor(address port, uint256 fee) { | ||
PORT = port; | ||
Fee = fee; | ||
} | ||
|
||
function ping(uint256 toChainId, address toDapp, bytes memory message) public payable returns (bytes32 msgId) { | ||
msgId = IMessagePort(PORT).send{value: Fee}(toChainId, toDapp, message, Params); | ||
emit PingSent(block.chainid, toChainId, msgId); | ||
return msgId; | ||
} | ||
|
||
function pong() public returns (bytes32 msgId) { | ||
uint256 fromChainId = _fromChainId(); | ||
address fromDapp = _xmsgSender(); | ||
address localPort = _msgPort(); | ||
require(localPort == PORT); | ||
|
||
// Call back to the pongReceive() function in the source chain. | ||
bytes memory message = abi.encodeWithSignature("pongReceive()"); | ||
msgId = ping(fromChainId, fromDapp, message); | ||
emit PongSent(block.chainid, fromChainId, msgId); | ||
|
||
return msgId; | ||
} | ||
|
||
function pongReceive() public { | ||
uint256 fromChainId = _fromChainId(); | ||
address localPort = _msgPort(); | ||
require(localPort == PORT); | ||
|
||
emit PongReceive(fromChainId, block.chainid); | ||
} | ||
|
||
receive() external payable { | ||
emit ReceivedToken(msg.sender, msg.value); | ||
} | ||
} |