diff --git a/README.md b/README.md index 44b2dea..279654e 100644 --- a/README.md +++ b/README.md @@ -4,55 +4,53 @@ 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. -## Contracts SDK +## 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 -#### PSP22 Wrapper +## Steps +#### Download a Substrate node with both EVM and Ink contract pallet +e.g. Astar https://github.com/AstarNetwork/Astar/releases -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`. +Then run it: `./astar-collator --dev --tmp` -#### PSP34 Wrapper +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 -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. +#### Deploy the Storage EVM Solidity contract via Remix connecting to the local node from step1: +The Storage contract is located at `./solidity/Storage.sol` -## Library +#### Install `Cargo contract` inside a repo without rust toolchain: +`cargo install --force --locked cargo-contract` -#### XVM environment +`cargo contract --version` +... cargo contract version is 4.1.1 works for my Wasm Ink! 4.3.0 version -Implementation of XVM chain extension added to a custom `XvmDefaultEnvironment`. +#### 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) -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)`. +#### Use https://ui.use.ink/ to deploy the compiled wasm with the already deployed Solidity contract address from above -#### XVM Builder +Although it says Contract Reverted. Decoding Failed, that is OKAY! -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. +Go to https://polkadot.js.org/apps/#/contracts and follow the tutorial link posted above -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)` +#### Reference: +https://substrate.stackexchange.com/questions/11435/xvm-ink-wasm-to-evm-contract-reverted-decoding-failed -## Usage +https://medium.com/astar-network/cross-virtual-machine-creating-a-portal-to-the-future-of-smart-contracts-a96c6d2f79b8 -##### Try it! +https://theastarbulletin.news/how-to-implement-a-contract-using-xvm-1c94d2072c30 -1. Clone the repo -2. Run `yarn` -3. Build ink! contracts `yarn build:ink` +https://docs.astar.network/docs/learn/interoperability/xvm/#interfaces -**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 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..c3cc619 --- /dev/null +++ b/ink/contracts/store_xvm/lib.rs @@ -0,0 +1,67 @@ +#![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 } + } + + //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()); + self.env() + .extension() + .xvm_call( + super::EVM_ID, + Vec::from(self.evm_address.as_ref()), + encoded_input, + 0 + ) + .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