Skip to content

Commit 4dbbbd3

Browse files
authored
Iris Milestone 1 (#4)
* add new contract * update deps, update readme * WIP call transfer from contract * pass args to transfer func * add test contract, readme * add payable * update readme * remove test, transfer assets works, add registry, add mint func * add purchase func * update readme * update email * purchase tokens with latest chain ext funcs * update ext * update chain ext, add new errors, add event struct, lock and transfer works * cleanup, add docs * update readmes, add composable access rules * limited use token * remove cars * happy path tests work * update get version func * update storage maps * rename func * add getters for registries * fix typos, handle option * update structure, CARs WIP * compilation works * register func works * update gitignore * add limit to constructor * register works, tests work, execute works * limited use token works with burn * rule executor works * modify storage with new struct, update tests, remove chain ext * move data retrieval to compoasable rules dir, create trait for rule executor * cross contract calls works! * :( * rule executor works * rename data_retrieval to rule executor, update docs * update docs, cleanup * update readme and .gitignore * add license * add copyright headers
1 parent 8c9d512 commit 4dbbbd3

File tree

2,618 files changed

+104579
-22
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2,618 files changed

+104579
-22
lines changed

iris_asset_exchange/.gitignore renamed to .gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Ignore build artifacts from the local tests sub-crate.
2-
/target/
2+
**/target/
33

44
# Ignore backup files creates by cargo fmt.
55
**/*.rs.bk

HEADER

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// This file is part of Iris.
2+
//
3+
// Copyright (C) 2022 Ideal Labs.
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.

LICENSE-GPL3

Lines changed: 226 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
1-
# Contracts
1+
# Iris Contracts
22

3-
A collection of smart contracts used on the [iris blockchain](https://github.com/iridium-labs/substrate/tree/iris).
3+
[![Built with ink!](https://raw.githubusercontent.com/paritytech/ink/master/.images/badge.svg)](https://github.com/paritytech/ink)
4+
5+
A collection of smart contracts used on the [iris blockchain](https://github.com/ideal-lab5/iris).
46

57
## Setup
68

79
Follow the [ink! documentation](https://paritytech.github.io/ink-docs/getting-started/setup) for a complete guide on getting started.
810

911
To compile a wasm blob and metadata for a contract, navigate to the contract's root directory and run:
1012

11-
``` bash
12-
cargo +nightly contract build
13-
```
14-
1513
### Note on Binaryen/wasm-opt
1614

1715
If your package manager doesn't have binaryen versions >= 99, then:

composable_access_rules/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Composable Access Rules
2+
3+
Composable Access Rules allows data owners to implement custom logic that data consumers are beholden to when fetching their data.
4+
5+
## Usage
6+
7+
Each composable access rule must implement the [ComposableAccessRule trait](./composable_access_rule.rs).
8+
To build a composable access rule, each contract must implement the execute function:
9+
10+
`fn execute(&mut self, asset_id: u32, consumer: ink_env::AccountId) -> bool`
11+
12+
## Building
13+
14+
`cargo +nightly contract build`
15+
16+
## Testing
17+
18+
`cargo +nightly test`
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Limited Use Contract
2+
3+
Specify a number of times that a consumer can use a token to access data associated with it.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
[package]
2+
name = "limited_use_rule"
3+
version = "1.0.0"
4+
edition = "2021"
5+
rust-version = "1.56.1"
6+
authors = ["Ideal Labs Developers <https://github.com/ideal-lab5>"]
7+
homepage = "https://idealabs.networks/"
8+
license = "GPL-3.0-or-later"
9+
publish = false
10+
repository = "https://github.com/ideal-lab5/iris"
11+
12+
[dependencies]
13+
ink_primitives = { version = "3.0.0-rc8", default-features = false }
14+
ink_metadata = { version = "3.0.0-rc8", default-features = false, features = ["derive"], optional = true }
15+
ink_env = { version = "3.0.0-rc8", default-features = false }
16+
ink_storage = { version = "3.0.0-rc8", default-features = false }
17+
ink_lang = { version = "3.0.0-rc8", default-features = false }
18+
ink_prelude = { version = "3.0.0-rc8", default-features = false }
19+
20+
scale = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
21+
scale-info = { version = "2.1.1", default-features = false, features = ["derive"], optional = true }
22+
traits = { path = "../traits", default-features = false }
23+
24+
[lib]
25+
name = "limited_use_rule"
26+
path = "lib.rs"
27+
crate-type = [
28+
# used for normal contract wasm blobs
29+
"cdylib",
30+
# used for ABI generation
31+
"rlib"
32+
]
33+
34+
[features]
35+
default = ["std"]
36+
std = [
37+
"ink_primitives/std",
38+
"ink_metadata/std",
39+
"ink_env/std",
40+
"ink_storage/std",
41+
"ink_lang/std",
42+
"scale/std",
43+
"scale-info/std",
44+
]
45+
ink-as-dependency = []
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
// This file is part of Iris.
2+
//
3+
// Copyright (C) 2022 Ideal Labs.
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
18+
#![cfg_attr(not(feature = "std"), no_std)]
19+
#![feature(trivial_bounds)]
20+
//!
21+
//! Limited Use Rule
22+
//!
23+
//! # Goal
24+
//! This contract allows data owners to impose limitations on the number
25+
//! of times an address may use a token to access data associated with the
26+
//! asset class
27+
//!
28+
use ink_lang as ink;
29+
use ink_storage::traits::{
30+
SpreadLayout,
31+
PackedLayout,
32+
SpreadAllocate
33+
};
34+
35+
pub use self::limited_use_rule::{
36+
LimitedUseRule,
37+
LimitedUseRuleRef,
38+
};
39+
40+
#[derive(
41+
scale::Encode, scale::Decode, PartialEq, Debug, Clone, Copy, SpreadLayout, PackedLayout, SpreadAllocate,
42+
)]
43+
#[cfg_attr(
44+
feature = "std",
45+
derive(scale_info::TypeInfo, ink_storage::traits::StorageLayout)
46+
)]
47+
struct Usage {
48+
asset_id: u32,
49+
access_attempts: u32,
50+
}
51+
52+
#[ink::contract]
53+
mod limited_use_rule {
54+
use ink_storage::traits::SpreadAllocate;
55+
use traits::ComposableAccessRule;
56+
use crate::Usage;
57+
use ink_prelude::vec::Vec;
58+
59+
#[ink(event)]
60+
pub struct LimitExceeded{}
61+
62+
#[ink(event)]
63+
pub struct AccessAllowed{}
64+
65+
#[ink(storage)]
66+
#[derive(SpreadAllocate)]
67+
pub struct LimitedUseRule {
68+
limit: u32,
69+
usage_counter: ink_storage::Mapping<AccountId, Vec<Usage>>,
70+
}
71+
72+
impl LimitedUseRule {
73+
#[ink(constructor)]
74+
pub fn new(limit: u32) -> Self {
75+
if limit <= 0 {
76+
panic!("limit must be positive");
77+
}
78+
ink_lang::utils::initialize_contract(|contract: &mut Self| {
79+
contract.limit = limit;
80+
})
81+
}
82+
83+
#[ink(message)]
84+
pub fn get_limit(&self) -> u32 {
85+
self.limit
86+
}
87+
}
88+
89+
impl ComposableAccessRule for LimitedUseRule {
90+
/// check if the number of times a caller has attempted access to the asset
91+
/// exceeds the pre-defined limit amount
92+
///
93+
/// * `asset_id`: The asset to which access is attempted
94+
///
95+
#[ink(message)]
96+
fn execute(&mut self, asset_id: u32, consumer: ink_env::AccountId) -> bool {
97+
if let Some(mut usage_attempts) = self.usage_counter.get(&consumer) {
98+
let index = usage_attempts.iter().position(|x| x.asset_id == asset_id).unwrap();
99+
let u = usage_attempts[index];
100+
if u.access_attempts < self.limit {
101+
usage_attempts.remove(index);
102+
let new_usage = Usage{
103+
asset_id: asset_id,
104+
access_attempts: u.access_attempts + 1,
105+
};
106+
let mut usage_vec = usage_attempts;
107+
usage_vec.push(new_usage);
108+
self.usage_counter.insert(&consumer, &usage_vec);
109+
self.env().emit_event(AccessAllowed{});
110+
return true;
111+
} else {
112+
self.env().emit_event(LimitExceeded{});
113+
return false;
114+
}
115+
} else {
116+
let mut new_usage_vec = Vec::new();
117+
new_usage_vec.push(Usage{
118+
asset_id: asset_id,
119+
access_attempts: 1,
120+
});
121+
self.usage_counter.insert(&consumer, &new_usage_vec);
122+
self.env().emit_event(AccessAllowed{});
123+
return true;
124+
}
125+
}
126+
}
127+
128+
#[cfg(test)]
129+
mod tests {
130+
use super::*;
131+
use ink_lang as ink;
132+
133+
#[ink::test]
134+
fn can_create_new_contract_with_positive_limit() {
135+
let limit = 10;
136+
let limited_use_contract = LimitedUseRule::new(limit);
137+
assert_eq!(limit, limited_use_contract.get_limit());
138+
}
139+
140+
#[ink::test]
141+
#[should_panic]
142+
fn panic_when_new_contract_with_zero_limit() {
143+
let limit = 0;
144+
let limited_use_contract = LimitedUseRule::new(limit);
145+
}
146+
147+
#[ink::test]
148+
#[should_panic]
149+
fn panic_when_new_contract_with_negative_limit() {
150+
let limit = -10;
151+
let limited_use_contract = LimitedUseRule::new(limit);
152+
}
153+
154+
/**
155+
* Tests for the `execute` function
156+
*/
157+
158+
fn setup_test(limit: u32, default_account: ink_env::AccountId) -> LimitedUseRule {
159+
let limited_use_contract = LimitedUseRule::new(limit);
160+
ink_env::test::set_caller::<ink_env::DefaultEnvironment>(default_account);
161+
limited_use_contract
162+
}
163+
164+
#[ink::test]
165+
fn can_execute_and_increment_on_first_access() {
166+
let accounts = ink_env::test::default_accounts::<ink_env::DefaultEnvironment>();
167+
let mut limited_use_contract = setup_test(2, accounts.alice);
168+
169+
// WHEN: I attempt to invoke the execute function
170+
limited_use_contract.execute(1, accounts.alice);
171+
// THEN: there is a usage attempt added
172+
let usage_tracker = limited_use_contract.usage_counter.get(accounts.alice).unwrap();
173+
let usage_len = usage_tracker.len();
174+
assert_eq!(1, usage_len);
175+
// AND: The only entry contains my asset id as accessed a single time
176+
assert_eq!(1, usage_tracker[0].asset_id);
177+
assert_eq!(1, usage_tracker[0].access_attempts);
178+
}
179+
180+
#[ink::test]
181+
fn can_execute_and_increment_on_second_access() {
182+
let accounts = ink_env::test::default_accounts::<ink_env::DefaultEnvironment>();
183+
let mut limited_use_contract = setup_test(2, accounts.alice);
184+
185+
// WHEN: I attempt to invoke the execute function
186+
limited_use_contract.execute(1, accounts.alice);
187+
// THEN: The access attempt value is incremented by one
188+
let usage_tracker_1 = limited_use_contract.usage_counter.get(accounts.alice).unwrap();
189+
assert_eq!(1, usage_tracker_1[0].access_attempts);
190+
191+
// WHEN: I attempt to invoke the execute function AGAIN
192+
limited_use_contract.execute(1, accounts.alice);
193+
// THEN: The access attempt value is incremented by one
194+
let usage_tracker_2 = limited_use_contract.usage_counter.get(accounts.alice).unwrap();
195+
assert_eq!(2, usage_tracker_2[0].access_attempts);
196+
}
197+
198+
#[ink::test]
199+
fn can_execute_and_not_increment_when_limit_exceeded() {
200+
let accounts = ink_env::test::default_accounts::<ink_env::DefaultEnvironment>();
201+
let mut limited_use_contract = setup_test(2, accounts.alice);
202+
203+
// WHEN: I attempt to invoke the execute function
204+
limited_use_contract.execute(1, accounts.alice);
205+
// THEN: The access attempt value is incremented by one
206+
let usage_tracker_1 = limited_use_contract.usage_counter.get(accounts.alice).unwrap();
207+
assert_eq!(1, usage_tracker_1[0].access_attempts);
208+
// WHEN: I attempt to invoke the execute function AGAIN
209+
limited_use_contract.execute(1, accounts.alice);
210+
// THEN: The access attempt value is incremented by one
211+
let usage_tracker_2 = limited_use_contract.usage_counter.get(accounts.alice).unwrap();
212+
assert_eq!(2, usage_tracker_2[0].access_attempts);
213+
// WHEN: I attempt to invoke the execute function AGAIN
214+
limited_use_contract.execute(1, accounts.alice);
215+
// THEN: The access attempt value is incremented by one
216+
let usage_tracker_3 = limited_use_contract.usage_counter.get(accounts.alice).unwrap();
217+
assert_eq!(2, usage_tracker_3[0].access_attempts);
218+
}
219+
}
220+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"rustc_fingerprint":11766580262192304820,"outputs":{"15697416045686424142":{"success":false,"status":"exit status: 1","code":1,"stdout":"","stderr":"error: `-Csplit-debuginfo` is unstable on this platform\n\n"},"10376369925670944939":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/driemworks/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"llvm14-builtins-abi\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\nunix\n","stderr":""},"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.63.0-nightly (4cbaac699 2022-05-25)\nbinary: rustc\ncommit-hash: 4cbaac699c14b7ac7cc80e54823b2ef6afeb64af\ncommit-date: 2022-05-25\nhost: x86_64-unknown-linux-gnu\nrelease: 1.63.0-nightly\nLLVM version: 14.0.4\n","stderr":""}},"successes":{}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"rustc_fingerprint":11766580262192304820,"outputs":{"960003148300528316":{"success":true,"status":"","code":0,"stdout":"___.wasm\nlib___.rlib\n___.wasm\nlib___.a\n/home/driemworks/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu\ndebug_assertions\npanic=\"abort\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"wasm32\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"wasm\"\ntarget_feature=\"llvm14-builtins-abi\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"unknown\"\ntarget_pointer_width=\"32\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\n","stderr":"warning: dropping unsupported crate type `dylib` for target `wasm32-unknown-unknown`\n\nwarning: dropping unsupported crate type `proc-macro` for target `wasm32-unknown-unknown`\n\nwarning: 2 warnings emitted\n\n"},"6696513553006607334":{"success":false,"status":"exit status: 1","code":1,"stdout":"","stderr":"error: `-Csplit-debuginfo` is unstable on this platform\n\n"},"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.63.0-nightly (4cbaac699 2022-05-25)\nbinary: rustc\ncommit-hash: 4cbaac699c14b7ac7cc80e54823b2ef6afeb64af\ncommit-date: 2022-05-25\nhost: x86_64-unknown-linux-gnu\nrelease: 1.63.0-nightly\nLLVM version: 14.0.4\n","stderr":""},"15697416045686424142":{"success":false,"status":"exit status: 1","code":1,"stdout":"","stderr":"error: `-Csplit-debuginfo` is unstable on this platform\n\n"},"10376369925670944939":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/driemworks/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"llvm14-builtins-abi\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}

0 commit comments

Comments
 (0)