[examples/lang] Add erc20 token example using the eDSL

parent 082875ba
[target.wasm32-unknown-unknown]
rustflags = [
"-C", "overflow-checks=on",
"-C", "link-args=-z stack-size=65536 --import-memory"
]
[package]
name = "erc20"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
pdsl_core = { path = "../../../core" }
pdsl_model = { path = "../../../model" }
pdsl_lang = { path = "../../../lang" }
parity-codec = { version = "3.1", default-features = false, features = ["derive"] }
[lib]
name = "erc20"
crate-type = ["cdylib"]
[features]
default = []
test-env = [
"pdsl_core/test-env",
"pdsl_model/test-env",
"pdsl_lang/test-env",
]
[profile.release]
panic = "abort"
lto = true
debug = true
opt-level = "z"
#!/bin/bash
# Deprecated Note:
# The wasm-build executable that is used to tree-shake the wasm binary
# resulting from the cargo build in the first step expects to find it
# under target/release/wasm32-unknown-unknown/ in the cwd.
PROJNAME=erc20
#cargo clean
#rm Cargo.lock
CARGO_INCREMENTAL=0 cargo +nightly build --release --target=wasm32-unknown-unknown --verbose
wasm2wat -o target/$PROJNAME.wat target/wasm32-unknown-unknown/release/$PROJNAME.wasm
cat target/$PROJNAME.wat | sed "s/(import \"env\" \"memory\" (memory (;0;) 2))/(import \"env\" \"memory\" (memory (;0;) 2 16))/" > target/$PROJNAME-fixed.wat
# wat2wasm -o target/$PROJNAME.wasm target/$PROJNAME-fixed.wat
# wasm-opt -Oz target/$PROJNAME.wasm -o target/$PROJNAME-opt.wasm
#wasm-build target enyzme --target-runtime=substrate --final=adder --save-raw=./target/enzyme-deployed.wasm --target wasm32-unknown-unknown
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of pDSL.
//
// pDSL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// pDSL is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with pDSL. If not, see <http://www.gnu.org/licenses/>.
#![no_std]
use pdsl_core::{
env::{
Address,
Balance,
},
storage,
};
use pdsl_lang::contract;
contract! {
/// The storage items for a typical ERC20 token implementation.
struct Erc20 {
/// All peeps done by all users.
balances: storage::HashMap<Address, Balance>,
/// Balances that are spendable by non-owners.
///
/// # Note
///
/// Mapping: (from, to) -> allowed
allowances: storage::HashMap<(Address, Address), Balance>,
/// The total supply.
total_supply: storage::Value<Balance>,
}
impl Deploy for Erc20 {
fn deploy(&mut self, init_value: Balance) {
// We have to set total supply to `0` in order to initialize it.
// Otherwise accesses to total supply will panic.
self.total_supply.set(0);
self.mint_for(env.caller(), init_value);
}
}
impl Erc20 {
/// Returns the total number of tokens in existence.
pub(external) fn total_supply(&self) -> Balance {
*self.total_supply
}
/// Returns the balance of the given address.
pub(external) fn balance_of(&self, owner: Address) -> Balance {
*self.balances.get(&owner).unwrap_or(&0)
}
/// Returns the amount of tokens that an owner allowed to a spender.
pub(external) fn allowance(&self, owner: Address, spender: Address) -> Balance {
*self.allowances.get(&(owner, spender)).unwrap_or(&0)
}
/// Transfers token from the sender to the `to` address.
pub(external) fn transfer(&mut self, to: Address, value: Balance) -> bool {
self.transfer_impl(env.caller(), to, value);
true
}
/// Approve the passed address to spend the specified amount of tokens
/// on the behalf of the message's sender.
pub(external) fn approve(&mut self, spender: Address, value: Balance) -> bool {
let owner = env.caller();
self.allowances.insert((owner, spender), value);
Self::emit_approval(owner, spender, value);
true
}
/// Transfer tokens from one address to another.
pub(external) fn transfer_from(&mut self, from: Address, to: Address, value: Balance) -> bool {
self.allowances[&(from, to)] -= value;
self.transfer_impl(from, to, value);
let new_allowance = self.allowances[&(from, to)];
Self::emit_transfer(from, to, value);
Self::emit_approval(from, to, new_allowance);
true
}
}
impl Erc20 {
/// Transfers token from a specified address to another address.
fn transfer_impl(&mut self, from: Address, to: Address, value: Balance) {
self.balances[&from] -= value;
self.balances[&to] += value;
Self::emit_transfer(from, to, value);
}
/// Decrease balance from the address.
///
/// # Panics
///
/// If `from` does not have enough balance.
#[allow(unused)]
fn burn_for(&mut self, from: Address, value: Balance){
self.balances[&from] -= value;
self.total_supply -= value;
Self::emit_transfer(from, None, value);
}
/// Increase balance for the receiver out of nowhere.
fn mint_for(&mut self, receiver: Address, value: Balance) {
self.balances[&receiver] += value;
self.total_supply += value;
Self::emit_transfer(None, receiver, value);
}
/// Emits an approval event.
fn emit_approval(
_from: Address,
_to: Address,
value: Balance,
) {
assert!(value > 0);
// emit event - This is not yet implemented in SRML contracts.
}
/// Emits a transfer event.
fn emit_transfer<F, T>(
from: F,
to: T,
value: Balance,
)
where
F: Into<Option<Address>>,
T: Into<Option<Address>>,
{
let (from, to) = (from.into(), to.into());
assert!(from.is_some() || to.is_some());
assert!(value > 0);
// emit event - This is not yet implemented in SRML contracts.
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment