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

Create the Mother of All Contracts #1245

Merged
merged 26 commits into from
May 18, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7a77b19
first iteration of the BIOC
agryaznov May 3, 2022
1ae9402
Merge branch 'master' into ag-bioc
agryaznov May 9, 2022
7e9f2d4
clippy fixes
agryaznov May 9, 2022
fad2a83
suppress unused var warning for debug fn
agryaznov May 9, 2022
cb625f6
suppress unused var warning 2nd try
agryaznov May 9, 2022
f7daf11
+ tests
agryaznov May 9, 2022
6432506
Apply suggestions from code review
agryaznov May 10, 2022
b7f136b
renamed to `mother`; added storage
agryaznov May 10, 2022
6b89f7d
refactor
agryaznov May 10, 2022
2fe986c
added a Mapping into contract storage
agryaznov May 10, 2022
70340ff
default constructor
agryaznov May 10, 2022
13f54c6
reverted fix
agryaznov May 10, 2022
0cd95fb
fix
agryaznov May 10, 2022
898089f
Apply suggestions from code review
agryaznov May 12, 2022
0e2d9a9
make it build (but not instantiate)
agryaznov May 12, 2022
a7fa5d0
Merge branch 'master' into ag-bioc
agryaznov May 12, 2022
040a258
fmt
agryaznov May 12, 2022
e7fb691
Update examples/mother/lib.rs
agryaznov May 12, 2022
e8fd72d
Apply suggestions from code review
agryaznov May 17, 2022
0685234
reverted constructor delegation to satisfy CI (until #1259 fixed)
agryaznov May 17, 2022
b604617
added required input types
agryaznov May 17, 2022
4d641a3
custom event added
agryaznov May 17, 2022
6d8e348
CI clippy satisfaction
agryaznov May 17, 2022
3491cfd
trick to satisfy the CI until #1258 is fixed
agryaznov May 17, 2022
ffabda0
Merge branch 'master' into ag-bioc
agryaznov May 18, 2022
ca2963f
Revert "trick to satisfy the CI until #1258 is fixed"
agryaznov May 18, 2022
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
12 changes: 12 additions & 0 deletions examples/mother/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# 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

*~
#*#
38 changes: 38 additions & 0 deletions examples/mother/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[package]
name = "mother"
description = "Mother of all contracts"
version = "3.0.1"
authors = ["Parity Technologies <[email protected]>"]
edition = "2021"
publish = false

[dependencies]
ink_primitives = { version = "3.0.1", path = "../../crates/primitives", default-features = false }
ink_metadata = { version = "3.0.1", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true }
ink_env = { version = "3.0.1", path = "../../crates/env", default-features = false }
ink_storage = { version = "3.0.1", path = "../../crates/storage", default-features = false }
ink_lang = { version = "3.0.1", path = "../../crates/lang", default-features = false }
ink_prelude = { version = "3.0.1", path = "../../crates/prelude", default-features = false }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2", default-features = false, features = ["derive"], optional = true }

[lib]
name = "mother"
path = "lib.rs"
crate-type = [
# Used for normal contract Wasm blobs.
"cdylib",
]

[features]
default = ["std"]
std = [
"ink_metadata/std",
"ink_env/std",
"ink_storage/std",
"ink_primitives/std",
"scale/std",
"scale-info/std",
]
ink-as-dependency = []
217 changes: 217 additions & 0 deletions examples/mother/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
//! # Mother of All Contracts
//!
//! This contracts is intented to
//! demonstrate rich posibilities of ink! contracts, namely:
//!
//! 1. Use complicated nested input and ouput types.
//! This is done through the real use case example of data structure
//! needed to store a candle auction data.
//! 2. Make contract fail with `ContractTrapped`.
//! 3. Make contract fail with returning an Error.
//! 4. Perform debug printing from contract into node's log.

#![cfg_attr(not(feature = "std"), no_std)]

use ink_lang as ink;

#[ink::contract]
mod mother {
use ink_prelude::{
string::{
String,
ToString,
},
vec::Vec,
};

use ink_lang::utils::initialize_contract;
use ink_storage::{
traits::{
PackedLayout,
SpreadAllocate,
SpreadLayout,
StorageLayout,
},
Mapping,
};

use ink_storage::traits::KeyPtr;
/// Struct for storing winning bids per bidding sample (a block).
/// Vector index corresponds to sample number.
#[derive(
Default,
scale::Encode,
scale::Decode,
PartialEq,
Debug,
Clone,
SpreadLayout,
PackedLayout,
SpreadAllocate,
)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo, StorageLayout,))]
pub struct Bids(Vec<Option<(AccountId, Balance)>>);

/// Auction statuses.
/// Logic inspired by
/// [Parachain Auction](https://github.com/paritytech/polkadot/blob/master/runtime/common/src/traits.rs#L160)
#[derive(
scale::Encode, scale::Decode, PartialEq, Debug, Clone, SpreadLayout, PackedLayout,
)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo, StorageLayout))]
pub enum Status {
/// An auction has not started yet.
NotStarted,
/// We are in the starting period of the auction, collecting initial bids.
OpeningPeriod,
/// We are in the ending period of the auction, where we are taking snapshots of the winning
/// bids. Snapshots are taken currently on per-block basis, but this logic could be later evolve
/// to take snapshots of on arbitrary length (in blocks)
EndingPeriod(BlockNumber),
/// Candle was blown
Ended,
/// We have completed the bidding process and are waiting for the Random Function to return some acceptable
/// randomness to select the winner. The number represents how many blocks we have been waiting.
RfDelay(BlockNumber),
}

impl SpreadAllocate for Status {
#[inline]
fn allocate_spread(ptr: &mut KeyPtr) -> Self {
ptr.advance_by(<BlockNumber>::FOOTPRINT * 2);
Self::NotStarted
}
}
/// Struct for storing auction data.
#[derive(
Debug,
PartialEq,
scale::Encode,
scale::Decode,
Clone,
SpreadLayout,
PackedLayout,
SpreadAllocate,
)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo, StorageLayout))]
pub struct Auction {
/// Branded name of the auction event
name: String,
/// Some hash identifiyng the auction subject
subject: Hash,
/// Structure storing the bids being made
bids: Bids,
/// Auction terms encoded as:
/// [start_block, opening_period, closing_period]
terms: [BlockNumber; 3],
/// Auction status
status: Status,
/// Candle auction can have no winner.
/// If auction is finalized, that means that the winner is determined.
finalized: bool,
}

impl Default for Auction {
fn default() -> Auction {
Auction {
name: String::default(),
subject: Hash::default(),
bids: Bids::default(),
terms: <[BlockNumber; 3]>::default(),
status: Status::OpeningPeriod,
finalized: false,
}
}
}

/// Way to fail a contract execution.
#[derive(scale::Encode, scale::Decode, Debug, PartialEq)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum Failure {
Revert(String),
Panic,
}

/// Storage of the contract.
#[ink(storage)]
#[derive(Default, SpreadAllocate)]
pub struct Mother {
auction: Auction,
balances: Mapping<AccountId, Balance>,
}

impl Mother {
#[ink(constructor)]
pub fn new(auction: Auction) -> Self {
initialize_contract(|c: &mut Self| {
c.balances = <Mapping<AccountId, Balance>>::default();
c.auction = auction;
})
}

#[ink(constructor)]
pub fn default() -> Self {
Self::new(Auction::default())
}

/// Takes an auction data struct as input and returns it back.
#[ink(message)]
pub fn echo_auction(&mut self, auction: Auction) -> Auction {
auction
}

/// Fails contract execution in the required way.
#[ink(message)]
pub fn revert_or_trap(&mut self, fail: Option<Failure>) -> Result<(), Failure> {
match fail {
Some(Failure::Revert(_)) => {
Err(Failure::Revert("Reverting on user demand!".to_string()))
}
Some(Failure::Panic) => {
panic!("Trapping on user demand!")
}
None => Ok(()),
}
}

/// Prints the specified string into node's debug log.
#[ink(message)]
pub fn debug_log(&mut self, message: String) {
ink_env::debug_println!("debug_log: {}", message);
}
}

#[cfg(test)]
mod tests {
use super::*;
use ink_lang as ink;

#[ink::test]
fn echo_auction_works() {
let auction = Auction::default();
let mut contract = Mother::default();
assert_eq!(contract.echo_auction(auction.clone()), auction);
}

#[ink::test]
fn revert_works() {
let mut contract = Mother::default();
assert_eq!(
contract.revert_or_trap(Some(Failure::Revert(
"Testing reverting on demand!".to_string()
))),
Err(Failure::Revert("Reverting on user demand!".to_string()))
);
contract
.revert_or_trap(None)
.expect("Contract unexpected failure!");
}

#[ink::test]
#[should_panic]
fn trap_works() {
let mut contract = Mother::default();
let _ = contract.revert_or_trap(Some(Failure::Panic));
}
}
}