Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a simple storage Solidity contract wrapper #13

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 35 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 9 additions & 0 deletions ink/.gitignore
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions ink/contracts/store_xvm/.gitignore
Original file line number Diff line number Diff line change
@@ -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
30 changes: 30 additions & 0 deletions ink/contracts/store_xvm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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 = []
67 changes: 67 additions & 0 deletions ink/contracts/store_xvm/lib.rs
Original file line number Diff line number Diff line change
@@ -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<u8> {
let mut encoded = STORE_SELECTOR.to_vec();
let input = [Token::Uint(value)];
encoded.extend(&ethabi::encode(&input));
encoded
}

}

}
2 changes: 1 addition & 1 deletion ink/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[toolchain]
channel = "1.69.0"
channel = "1.74"
components = [ "rustfmt", "clippy" ]
targets = [ "wasm32-unknown-unknown"]
profile = "minimal"
13 changes: 13 additions & 0 deletions solidity/Storage.sol
Original file line number Diff line number Diff line change
@@ -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;
}
}