pwasm-tutorial
pwasm-tutorial copied to clipboard
Add real life example in tutorial
I'm currently trying to port some Solidity code into wasm using pwasm
. But I have a problem that I don't see enough examples or documentation to perform such a transform. For example, here is a simple Solidity contract:
contract Example {
string[] values;
function addValue(string value) public onlyOwner {
values.push(value);
}
function getValue(uint i) public returns(string) {
return values[i];
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
}
it's very simple but it shows all properties that real contracts have: it has onlyOwner
modifier, it works with dynamically-sized data and it push values into internal storage (which is not prealocated). Token examples are too simple and don't show how to perform such operations that are crucial for most contracts.
I'm playing with these storage_keys!
/pwasm_ethereum::write
and so on, but it doesn't look I'm even approaching the solution. Currently It's actually a blocker to me, without stretching storage I cannot migrate my code to wasm.
I'd appreciate any help because I'm currently stuck with that - I only see how I can write into preallocated fixed size storage, but I don't see how to dynamically increase it.
I managed to emulate an array, but I only could save ony fixed-sizd items smaller than 32 bytes. It won't work for string or any arbitrary-sized type. Stuck with that currently Code is based on step-3 sample
pub mod token {
use pwasm_std::Vec;
use pwasm_ethereum;
use parity_hash::H256;
use bigint::U256;
macro_rules! storage_keys {
() => {};
($($name:ident),*) => {
storage_keys!(0u8, $($name),*);
};
($count:expr, $name:ident) => {
static $name: H256 = H256([$count, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
};
($count:expr, $name:ident, $($tail:ident),*) => {
static $name: H256 = H256([$count, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
storage_keys!($count + 1u8, $($tail),*);
};
}
// eth_abi is a procedural macros https://doc.rust-lang.org/book/first-edition/procedural-macros.html
use pwasm_abi_derive::eth_abi;
#[eth_abi(TokenEndpoint, TokenClient)]
pub trait TokenInterface {
/// The constructor
fn constructor(&mut self, _total_supply: U256);
/// Total amount of tokens
#[constant]
fn totalSupply(&mut self) -> U256;
#[constant]
fn getNumbers(&mut self) -> Vec<U256>;
fn addNumber(&mut self, value: U256);
}
storage_keys!(
TOTAL_SUPPLY_KEY,
DATA_LEN,
DATA_KEY
);
pub struct TokenContract;
impl TokenInterface for TokenContract {
fn constructor(&mut self, total_supply: U256) {
// Set up the total supply for the token
pwasm_ethereum::write(&TOTAL_SUPPLY_KEY, &total_supply.into());
}
fn totalSupply(&mut self) -> U256 {
pwasm_ethereum::read(&TOTAL_SUPPLY_KEY).into()
}
fn getNumbers(&mut self) -> Vec<U256> {
let num: u8 = pwasm_ethereum::read(&DATA_LEN)[31];
let mut result = Vec::with_capacity(num as usize);
for i in 0..num {
let mut key = DATA_KEY.clone();
key[31] = i;
result.push(pwasm_ethereum::read(&key).into())
}
result
}
fn addNumber(&mut self, value: U256) {
let num: u8 = pwasm_ethereum::read(&DATA_LEN)[31];
let new_num: U256 = (num + 1).into();
pwasm_ethereum::write(&DATA_LEN, &new_num.into());
let mut key = DATA_KEY.clone();
key[31] = num;
pwasm_ethereum::write(&key, &value.into());
}
}
}