Comments (4)
In a discussion about a future look'and'feel for the upcoming pDSL there were some remarks that I wanted to memorize in this issue for the future implementation.
The following are some notes for the unfinished ERC-20 token implementation using the pdsl_core
library as of 15-01-2019 that can be found here.
Contract Definition
/// The storage data that is hold by the ERC-20 token.
#[derive(Debug, Encode, Decode)]
pub struct Erc20Token {
/// All peeps done by all users.
balances: storage::HashMap<Address, Balance>,
/// Balances that are spendable by non-owners.
allowances: storage::HashMap<AllowancePair, Balance>,
/// The total supply.
total_supply: storage::Value<Balance>,
/// The allocator for newly allocated entities.
alloc: storage::alloc::CellChunkAlloc,
}
should become similar or equal to
/// The storage data that is hold by the ERC-20 token.
#[derive(Contract)]
pub struct Erc20Token {
/// All peeps done by all users.
balances: storage::HashMap<Address, Balance>,
/// Balances that are spendable by non-owners.
allowances: storage::HashMap<AllowancePair, Balance>,
/// The total supply.
total_supply: Balance,
}
First-Class Environmentals
ContractEnv::caller()
should be just caller
.
Mutation Wrappers
self.balances.mutate_with(&from, |from| *from -= value)
Is jargony and difficult to understand, especially for people that are not using Rust on a regular basis.
It should become something similar or equal to
self.balances[from] -= value
Streamlined Derives
Derives for auxiliary structs should be straight forward and streamlined to contract usage.
#[derive(Debug, Hash, PartialEq, Eq, Encode, Decode)]
should become similar or equal to
#[derive(Debug, HashStorage)]
Also the entire dispatch of functions still has to be implemented in the upcoming pDSL.
from ink.
The current state and initial goal is to be able to write a simple smart contract like this:
use pdsl_lang::contract;
use pdsl_core::storage;
contract! {
/// A simple contract that has a value that can be
/// incremented, returned and compared.
struct Incrementer {
/// The internal value.
value: storage::Value<u32>,
}
impl Incrementer {
/// Automatically called when the contract is deployed.
pub(external) fn on_deploy(&mut self, init_value: u32) {
self.value.set(init_value);
}
/// Increments the internal counter.
pub(external) fn inc(&mut self, by: u32) {
self.value += by
}
/// Returns the internal counter.
pub(external) fn get(&self) -> u32 {
*self.value
}
/// Returns `true` if `x` is greater than the internal value.
pub(external) fn compare(&self, x: u32) -> bool {
x > *self.value
}
}
}
The generated code for the above smart contract should look approximately like the following:
use pdsl_core::storage;
pdsl_model::state! {
/// A simple contract that has a value that can be
/// incremented, returned and compared.
struct Incrementer {
/// The internal value.
value: storage::Value<u32>
}
}
pdsl_model::messages! {
/// Increments the internal counter.
0 => Inc(by: u32);
/// Returns the internal counter.
1 => Get() -> u32;
/// Returns `true` if `x` is greater than the internal value.
2 => Compare(with: u32) -> bool;
}
impl Adder {
/// Automatically called when the contract is deployed.
pub fn on_deploy(&mut self, env: &mut pdsl_model::EnvHandler, init_val: u32) {
self.value.set(init_val)
}
/// Increments the internal counter.
pub fn inc(&mut self, env: &mut pdsl_model::EnvHandler, by: u32) {
self.value += by
}
/// Returns the internal counter.
pub fn get(&self, env: &pdsl_model::EnvHandler) -> u32 {
*self.value
}
/// Returns `true` if `x` is greater than the internal value.
pub fn compare(&self, env: &pdsl_model::EnvHandler, x: u32) -> bool {
x > *self.value
}
}
fn instantiate() -> impl pdsl_model::Contract {
pdsl_model::ContractDecl::using::<Adder>()
.on_deploy(|env, init_val: u32| {
let (handler, state) = env.split_mut();
state.on_deploy(handler, init_val)
})
.on_msg_mut::<Inc>(|env, by: u32| {
let (handler, state) = env.split_mut();
state.inc(handler, by)
})
.on_msg::<Get>(|env, _| {
let (handler, state) = env.split();
state.get(handler)
})
.on_msg::<Compare>(|env, x: u32| {
let (handler, state) = env.split();
state.compare(handler, x)
})
.instantiate()
}
#[no_mangle]
fn deploy() {
instantiate().deploy()
}
#[no_mangle]
fn call() {
instantiate().dispatch()
}
from ink.
As of 589210f this is the actual generated code from the simple.rs
example above.
#![feature(prelude_import)]
#![no_std]
#[prelude_import]
use ::std::prelude::v1::*;
#[macro_use]
extern crate std as std;
use pdsl_core::storage;
use pdsl_lang::contract;
#[doc = " A simple contract that has a value that can be"]
#[doc = " incremented, returned and compared."]
struct Incrementer {
#[doc = " The internal value."]
value: storage::Value<u32>,
}
impl pdsl_core::storage::Flush for Incrementer {
fn flush(&mut self) {
self.value.flush()
}
}
impl pdsl_core::storage::alloc::AllocateUsing for Incrementer {
unsafe fn allocate_using<A>(alloc: &mut A) -> Self
where
A: pdsl_core::storage::alloc::Allocate,
{
use pdsl_core::storage::alloc::AllocateUsing;
Self {
value: AllocateUsing::allocate_using(alloc),
}
}
}
impl ::pdsl_model::ContractState for Incrementer {
const NAME: &'static [u8] = "Incrementer".as_bytes();
}
use pdsl_model::messages;
#[doc = " Returns `true` if `x` is greater than the internal value."]
#[rustc_copy_clone_marker]
struct Compare;
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::marker::Copy for Compare {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::clone::Clone for Compare {
#[inline]
fn clone(&self) -> Compare {
{
*self
}
}
}
impl ::pdsl_model::Message for Compare {
type Input = (u32);
type Output = bool;
const ID: ::pdsl_model::MessageHandlerSelector =
::pdsl_model::MessageHandlerSelector::new(0);
const NAME: &'static [u8] = "Compare".as_bytes();
}
#[doc = " Increments the internal counter."]
#[rustc_copy_clone_marker]
struct Inc;
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::marker::Copy for Inc {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::clone::Clone for Inc {
#[inline]
fn clone(&self) -> Inc {
{
*self
}
}
}
impl ::pdsl_model::Message for Inc {
type Input = (u32);
type Output = ();
const ID: ::pdsl_model::MessageHandlerSelector =
::pdsl_model::MessageHandlerSelector::new(1);
const NAME: &'static [u8] = "Inc".as_bytes();
}
#[doc = " Returns the internal counter."]
#[rustc_copy_clone_marker]
struct Get;
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::marker::Copy for Get {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::clone::Clone for Get {
#[inline]
fn clone(&self) -> Get {
{
*self
}
}
}
impl ::pdsl_model::Message for Get {
type Input = ();
type Output = u32;
const ID: ::pdsl_model::MessageHandlerSelector =
::pdsl_model::MessageHandlerSelector::new(2);
const NAME: &'static [u8] = "Get".as_bytes();
}
impl Incrementer {
#[doc = " Automatically called when the contract is deployed."]
pub fn on_deploy(&mut self, env: &mut pdsl_model::EnvHandler, init_value: u32) {
self.value.set(init_value);
}
#[doc = " Returns `true` if `x` is greater than the internal value."]
pub fn compare(&self, env: &pdsl_model::EnvHandler, x: u32) -> bool {
x > *self.value
}
#[doc = " Increments the internal counter."]
pub fn inc(&mut self, env: &mut pdsl_model::EnvHandler, by: u32) {
self.value += by
}
#[doc = " Returns the internal counter."]
pub fn get(&self, env: &pdsl_model::EnvHandler) -> u32 {
*self.value
}
}
fn instantiate() -> impl pdsl_model::Contract {
pdsl_model::ContractDecl::using::<Incrementer>()
.on_deploy(|env, init_value: u32| {
let (handler, state) = env.split_mut();
state.on_deploy(handler, init_value)
})
.on_msg::<Compare>(|env, x: u32| {
let (handler, state) = env.split();
state.compare(handler, x)
})
.on_msg_mut::<Inc>(|env, by: u32| {
let (handler, state) = env.split_mut();
state.inc(handler, by)
})
.on_msg::<Get>(|env, _| {
let (handler, state) = env.split();
state.get(handler)
})
.instantiate()
}
#[no_mangle]
fn deploy() {
instantiate().deploy()
}
#[no_mangle]
fn call() {
instantiate().dispatch()
}
from ink.
I am closing this since it has obviously reached a state that satisfies this issue.
from ink.
Related Issues (20)
- The function `set_contract_storage` in integration test it's missing a size check.
- Linter: Unprotected `terminate_contract`
- Linter: Unprotected `DelegateCall` call
- Immutable contracts allowed to change state via `env` HOT 4
- Add a lint for missing `no_main`
- IIP-3: Allow messages without `&self` receiver; opt out of automatic storage loading HOT 5
- Different gas value for `weight_to_fee()` in ink! integration and e2e tests HOT 6
- Split up `ink_linting` into two `dylint` libraries HOT 1
- Use standard Github's machines for test jobs
- Linter: Warn about using non-fallible APIs for `Lazy` and `Mapping` HOT 1
- Support expressions for `extension` and `function` during chain extension definition
- Event defintions with generics
- Deprecation of "legacy" inline events HOT 1
- Unify `call-runtime` and `e2e-call-runtime` examples
- Linter: Dangereous `self.env().transferred_value()` pattern
- Linter: Divide before multiply
- Add support and integration test for `caller_is_root`
- Migrate ink! CI from organization runners to standard GitHub runners
- Add links to linter warning details on use.ink
- Cross contract calling produces unsupported code HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ink.