From 9f87beb83d5a3dfa54a548f0b582eef00db76e90 Mon Sep 17 00:00:00 2001 From: AuroraLantean Date: Tue, 7 May 2024 13:52:10 +0300 Subject: [PATCH 1/6] add store_xvm example --- README.md | 29 +++++++++++++ ink/.gitignore | 9 ++++ ink/contracts/store_xvm/.gitignore | 9 ++++ ink/contracts/store_xvm/Cargo.toml | 30 ++++++++++++++ ink/contracts/store_xvm/lib.rs | 66 ++++++++++++++++++++++++++++++ ink/rust-toolchain.toml | 2 +- solidity/Storage.sol | 13 ++++++ 7 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 ink/.gitignore create mode 100644 ink/contracts/store_xvm/.gitignore create mode 100644 ink/contracts/store_xvm/Cargo.toml create mode 100755 ink/contracts/store_xvm/lib.rs create mode 100644 solidity/Storage.sol diff --git a/README.md b/README.md index 44b2dea..abfc4ce 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,36 @@ This repository contains examples contracts using XVM to call EVM from ink! need It contains an implementation of XVM chain-extension to use in your contracts. As well as ink! contracts SDK that implements XVM chain-extension to be used as is. +## Reference: +This repo code is copied initially from the repos below +https://github.com/realtakahashi/ink-xvm-sdk +https://github.com/AstarNetwork/ink-xvm-sdk + +## Steps +Deploy my EVM Solidity contract via Remix connecting to my local node: ./solidity/Storage.sol + +Inside a non rust toolchain repo: +`cargo install --version 3.2.0 cargo-contract` +`cargo contract --version` +... cargo contract version is 3.2.0, good for my Wasm Ink! 4.3.0 version + +Compile wrapper wasm contract: +`cargo contract build --manifest-path ink/contracts/store_xvm/Cargo.toml` +... should succeed with the following: + - store_xvm.contract (code + metadata) + - store_xvm.wasm (the contract's code) + - store_xvm.json (the contract's metadata) + +Use https://ui.use.ink/ to deploy the compiled wasm with an already deployed Solidity contract address + + ## Contracts SDK +XVMv2 can only process transactions that returns `()` hence query values is not supported yet. These contracts only implement functions that modify state. +Transactions pass multiple layers of XVM abstractions in one line. All cross-VM communication looks like it all going inside the smart contract. + +#### ERC20 + +This implementation is a controller of an underlying `ERC20` on EVM. Interact with `H160` addresses #### PSP22 Wrapper diff --git a/ink/.gitignore b/ink/.gitignore new file mode 100644 index 0000000..8de8f87 --- /dev/null +++ b/ink/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/ink/contracts/store_xvm/.gitignore b/ink/contracts/store_xvm/.gitignore new file mode 100644 index 0000000..8de8f87 --- /dev/null +++ b/ink/contracts/store_xvm/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/ink/contracts/store_xvm/Cargo.toml b/ink/contracts/store_xvm/Cargo.toml new file mode 100644 index 0000000..340197c --- /dev/null +++ b/ink/contracts/store_xvm/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "store_xvm" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { version = "4.3.0", default-features = false } + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true } + +ethabi = { git = "https://github.com/akru/ethabi", default-features = false } + +hex-literal = "0.4.1" +xvm-environment = { path = "../../lib/xvm-environment", default-features = false } + + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + "xvm-environment/std", +] +ink-as-dependency = [] diff --git a/ink/contracts/store_xvm/lib.rs b/ink/contracts/store_xvm/lib.rs new file mode 100755 index 0000000..6460f21 --- /dev/null +++ b/ink/contracts/store_xvm/lib.rs @@ -0,0 +1,66 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +/// EVM ID (from astar runtime) +const EVM_ID: u8 = 0x0F; + +#[ink::contract(env = xvm_environment::XvmDefaultEnvironment)] +pub mod store_xvm { + use ethabi::{ + ethereum_types::{ + H160, + U256, + }, + Token, + }; + use hex_literal::hex; + use ink::prelude::vec::Vec; + + /*"methodIdentifiers": { + "retrieve()": "2e64cec1", + "store(uint256)": "6057361d" + }*/ + const RETRIEVE_SELECTOR: [u8; 4] = hex!["2e64cec1"]; + const STORE_SELECTOR: [u8; 4] = hex!["6057361d"]; + + #[ink(storage)] + #[derive(Default)] + pub struct StoreXvm { + //#[storage_field] + //number: uint128, + evm_address: [u8; 20], + } + + impl StoreXvm { + #[ink(constructor)] + pub fn new(evm_address: [u8; 20]) -> Self { + //let mut instance = Self::default(); + //instance.number.set(); + //instance.evm_address = evm_address; + //instance + Self { evm_address } + } + + #[ink(message)] + pub fn store(&mut self, value: u128) -> bool { + let encoded_input = Self::store_encode( value.into()); + self.env() + .extension() + .xvm_call( + super::EVM_ID, + Vec::from(self.evm_address.as_ref()), + encoded_input, + value + ) + .is_ok() + } + + fn store_encode(value: U256) -> Vec { + let mut encoded = STORE_SELECTOR.to_vec(); + let input = [Token::Uint(value)]; + encoded.extend(ðabi::encode(&input)); + encoded + } + + } + +} diff --git a/ink/rust-toolchain.toml b/ink/rust-toolchain.toml index f6f6d36..142e1a5 100644 --- a/ink/rust-toolchain.toml +++ b/ink/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.69.0" +channel = "1.74" components = [ "rustfmt", "clippy" ] targets = [ "wasm32-unknown-unknown"] profile = "minimal" diff --git a/solidity/Storage.sol b/solidity/Storage.sol new file mode 100644 index 0000000..10bffb2 --- /dev/null +++ b/solidity/Storage.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier:MIT +pragma solidity 0.8.21; + +contract Storage { + uint256 number; + + function store(uint256 num) public { + number = num; + } + function retrieve() public view returns (uint256) { + return number; + } +} \ No newline at end of file From e9c02202482e4e412a0ad5fbf8272df866d624e8 Mon Sep 17 00:00:00 2001 From: AuroraLantean Date: Tue, 7 May 2024 15:53:47 +0300 Subject: [PATCH 2/6] correct xvm_call(..., value) --- ink/contracts/store_xvm/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ink/contracts/store_xvm/lib.rs b/ink/contracts/store_xvm/lib.rs index 6460f21..c3cc619 100755 --- a/ink/contracts/store_xvm/lib.rs +++ b/ink/contracts/store_xvm/lib.rs @@ -40,6 +40,7 @@ pub mod store_xvm { Self { evm_address } } + //https://docs.astar.network/docs/learn/interoperability/xvm/#interfaces #[ink(message)] pub fn store(&mut self, value: u128) -> bool { let encoded_input = Self::store_encode( value.into()); @@ -49,7 +50,7 @@ pub mod store_xvm { super::EVM_ID, Vec::from(self.evm_address.as_ref()), encoded_input, - value + 0 ) .is_ok() } From 9b524ac1e384309d99643035d1b006dbab6d893b Mon Sep 17 00:00:00 2001 From: AuroraLantean Date: Tue, 7 May 2024 17:10:50 +0300 Subject: [PATCH 3/6] add EVM config --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index abfc4ce..67bf414 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,16 @@ https://github.com/realtakahashi/ink-xvm-sdk https://github.com/AstarNetwork/ink-xvm-sdk ## Steps +Download an Astar Network node(a Substrate node with both EVM and Ink contract pallet) from https://github.com/AstarNetwork/Astar/releases +Then run it: `./astar-collator --dev --tmp` + +https://docs.astar.network/docs/build/environment/local-network/ +Configure Metamask to use: +Name: Astar +URL: http://127.0.0.1:9944 +ChainID: 4369 Astar +Currency Symbol: ASTL + Deploy my EVM Solidity contract via Remix connecting to my local node: ./solidity/Storage.sol Inside a non rust toolchain repo: From 9823de98b77c9919e264f639b4258b633d6ec587 Mon Sep 17 00:00:00 2001 From: AuroraLantean Date: Fri, 10 May 2024 11:53:49 +0300 Subject: [PATCH 4/6] update Readme --- README.md | 76 ++++++++++++------------------------------------------- 1 file changed, 16 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 67bf414..8a0acb1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ https://github.com/realtakahashi/ink-xvm-sdk https://github.com/AstarNetwork/ink-xvm-sdk ## Steps -Download an Astar Network node(a Substrate node with both EVM and Ink contract pallet) from https://github.com/AstarNetwork/Astar/releases +#### 1. Download a Substrate node with both EVM and Ink contract pallet +e.g. Astar https://github.com/AstarNetwork/Astar/releases Then run it: `./astar-collator --dev --tmp` https://docs.astar.network/docs/build/environment/local-network/ @@ -20,78 +21,33 @@ URL: http://127.0.0.1:9944 ChainID: 4369 Astar Currency Symbol: ASTL -Deploy my EVM Solidity contract via Remix connecting to my local node: ./solidity/Storage.sol +#### 2. Deploy the Storage EVM Solidity contract via Remix connecting to the local node from step1: +The Storage contract is located at `./solidity/Storage.sol` -Inside a non rust toolchain repo: +#### Install `Cargo contract` inside a repo without rust toolchain: `cargo install --version 3.2.0 cargo-contract` `cargo contract --version` ... cargo contract version is 3.2.0, good for my Wasm Ink! 4.3.0 version -Compile wrapper wasm contract: -`cargo contract build --manifest-path ink/contracts/store_xvm/Cargo.toml` -... should succeed with the following: +#### Compile wrapper wasm contract: +`cargo contract build --manifest-path PATH_TO_XVM_FOLDER/Cargo.toml` +... this should succeed with the following: - store_xvm.contract (code + metadata) - store_xvm.wasm (the contract's code) - store_xvm.json (the contract's metadata) -Use https://ui.use.ink/ to deploy the compiled wasm with an already deployed Solidity contract address +#### Use https://ui.use.ink/ to deploy the compiled wasm with the already deployed Solidity contract address from above +Then I got `Contract Reverted! DispatchError: DecodingFailed Input passed to a contract API function failed to decode as expected type...` -## Contracts SDK -XVMv2 can only process transactions that returns `()` hence query values is not supported yet. These contracts only implement functions that modify state. -Transactions pass multiple layers of XVM abstractions in one line. All cross-VM communication looks like it all going inside the smart contract. -#### ERC20 +#### Reference: +https://substrate.stackexchange.com/questions/11435/xvm-ink-wasm-to-evm-contract-reverted-decoding-failed -This implementation is a controller of an underlying `ERC20` on EVM. Interact with `H160` addresses +https://medium.com/astar-network/cross-virtual-machine-creating-a-portal-to-the-future-of-smart-contracts-a96c6d2f79b8 -#### PSP22 Wrapper +https://theastarbulletin.news/how-to-implement-a-contract-using-xvm-1c94d2072c30 -This implementation is a wrapper of an underlying `ERC20` on EVM. Interact with native substrate addresses. -As it implements wrapper pattern it has `deposit` & `withdraw` function and can be used as a bridgeless solution between WASM VM & EVM. -It implements `PSP22` standard, thus can be used in any DEX/wallet supporting it. -Please have a look at the tests that describe the flow to use `deposit` and `withdraw`. +https://docs.astar.network/docs/learn/interoperability/xvm/#interfaces -#### PSP34 Wrapper - -This implementation is a wrapper of an underlying `ERC721` on EVM. Interact with substrate native substrate addresses. -As it implements wrapper pattern it has `deposit` & `withdraw` function and can be used as a bridgeless solution between WASM VM & EVM. -It implements `PSP34` standard, and thus can be used in any DEX/wallet supporting it. - -## Library - -#### XVM environment - -Implementation of XVM chain extension added to a custom `XvmDefaultEnvironment`. - -1. Import the crate in your Cargo.toml -2. Add it to your contract in ink! macro `#[ink::contract(env = xvm_sdk::XvmDefaultEnvironment)]`. -3. In your contract use it with `self.env().extension().xvm_call(..args)`. - -#### XVM Builder - -This crate exposes `Xvm` struct that implements xvm_call with chain-extension builder from ink_env. -It makes it compatible with other custom environment like openbrush. -Have a look at PSP22 Wrapper for an example. - -1. Import the crate in your Cargo.toml -2. Import struct in your contract use `use xvm_helper::*;` -3. Use it with `XvmErc20::transfer(..args)` - -## Usage - -##### Try it! - -1. Clone the repo -2. Run `yarn` -3. Build ink! contracts `yarn build:ink` - -**To run on local node:** -Ensure you have a local node running with `./target/release/astar-collator --dev -lruntime::contracts=debug -l=runtime=debug,xvm=trace --enable-evm-rpcp` (to have XVM and ink! logs). -Then run `yarn test`. - -**To run on Shibuya:** -Create a .env file from .env.example and fill it with your credentials: -Add your Shibuya EVM private key in `ACCOUNT_PRIVATE_KEY_EVM` -And your Shibuya Substrate passphrase in `SUBSTRATE_MNEMO`. -Then run `yarn test:shibuya`. +Code are copied from https://github.com/realtakahashi/ink-xvm-sdk and https://github.com/AstarNetwork/ink-xvm-sdk \ No newline at end of file From e36b9e9dc61087f53cf99231eab0c3c723676b73 Mon Sep 17 00:00:00 2001 From: AuroraLantean Date: Fri, 10 May 2024 11:58:22 +0300 Subject: [PATCH 5/6] update readme --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8a0acb1..64bd8a3 100644 --- a/README.md +++ b/README.md @@ -10,22 +10,24 @@ https://github.com/realtakahashi/ink-xvm-sdk https://github.com/AstarNetwork/ink-xvm-sdk ## Steps -#### 1. Download a Substrate node with both EVM and Ink contract pallet +#### Download a Substrate node with both EVM and Ink contract pallet e.g. Astar https://github.com/AstarNetwork/Astar/releases + Then run it: `./astar-collator --dev --tmp` https://docs.astar.network/docs/build/environment/local-network/ Configure Metamask to use: -Name: Astar -URL: http://127.0.0.1:9944 -ChainID: 4369 Astar +Name: Astar, +URL: http://127.0.0.1:9944 , +ChainID: 4369 Astar , Currency Symbol: ASTL -#### 2. Deploy the Storage EVM Solidity contract via Remix connecting to the local node from step1: +#### Deploy the Storage EVM Solidity contract via Remix connecting to the local node from step1: The Storage contract is located at `./solidity/Storage.sol` #### Install `Cargo contract` inside a repo without rust toolchain: `cargo install --version 3.2.0 cargo-contract` + `cargo contract --version` ... cargo contract version is 3.2.0, good for my Wasm Ink! 4.3.0 version From bd9246052894edea8f5cefa0e53dce3a877214ff Mon Sep 17 00:00:00 2001 From: AuroraLantean Date: Fri, 10 May 2024 15:24:16 +0300 Subject: [PATCH 6/6] add solution --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 64bd8a3..279654e 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,10 @@ Currency Symbol: ASTL The Storage contract is located at `./solidity/Storage.sol` #### Install `Cargo contract` inside a repo without rust toolchain: -`cargo install --version 3.2.0 cargo-contract` +`cargo install --force --locked cargo-contract` `cargo contract --version` -... cargo contract version is 3.2.0, good for my Wasm Ink! 4.3.0 version +... cargo contract version is 4.1.1 works for my Wasm Ink! 4.3.0 version #### Compile wrapper wasm contract: `cargo contract build --manifest-path PATH_TO_XVM_FOLDER/Cargo.toml` @@ -40,8 +40,9 @@ The Storage contract is located at `./solidity/Storage.sol` #### Use https://ui.use.ink/ to deploy the compiled wasm with the already deployed Solidity contract address from above -Then I got `Contract Reverted! DispatchError: DecodingFailed Input passed to a contract API function failed to decode as expected type...` +Although it says Contract Reverted. Decoding Failed, that is OKAY! +Go to https://polkadot.js.org/apps/#/contracts and follow the tutorial link posted above #### Reference: https://substrate.stackexchange.com/questions/11435/xvm-ink-wasm-to-evm-contract-reverted-decoding-failed