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

Minor fixes, add tests #2

Open
wants to merge 1 commit into
base: dn-mvp
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2,431 changes: 2,143 additions & 288 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 4 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,18 @@ members = [

[workspace.package]
version = "0.1.0"
authors = ["breathx <[email protected]>"]
edition = "2021"
license = "GPL-3.0"

[workspace.dependencies]
gstd = "1.1.1"
gtest = "1.1.1"
gclient = "1.1.1"
gear-core = "1.1.1"
gwasm-builder = { package = "gear-wasm-builder", version = "1.1.1" }
parity-scale-codec = { version = "3.6", default-features = false }
sails-clientgen = { git = "https://github.com/gear-tech/sails" }
sails-exec-context-gstd = { git = "https://github.com/gear-tech/sails" }
sails-idl-meta ={ git = "https://github.com/gear-tech/sails" }
sails-idlgen = { git = "https://github.com/gear-tech/sails" }
sails-idlparser = { git = "https://github.com/gear-tech/sails" }
sails = { git = "https://github.com/gear-tech/sails" }
sails-rtl = { git = "https://github.com/gear-tech/sails" }
sails-sender = { git = "https://github.com/gear-tech/sails" }
sails-macros = { git = "https://github.com/gear-tech/sails" }
sails-idl-gen = { git = "https://github.com/gear-tech/sails", rev = "51b731ef8f064a23c6c98fa92d06eeafe44d3f9d" }
sails-rtl = { git = "https://github.com/gear-tech/sails", rev = "51b731ef8f064a23c6c98fa92d06eeafe44d3f9d" }
scale-info = { version = "2.10", default-features = false }
primitive-types = { version = "*", default-features = false }
derive-more = { version = "*", default-features = false, features = ["display"] }
Expand Down
7 changes: 4 additions & 3 deletions app/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
[package]
name = "erc20"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true

[dependencies]
gstd.workspace = true
primitive-types.workspace = true
log.workspace = true
sails-macros.workspace = true
sails-rtl.workspace = true
sails-idl-meta.workspace = true
parity-scale-codec.workspace = true
scale-info.workspace = true

[dev-dependencies]
env_logger.workspace = true
gclient.workspace = true
gtest.workspace = true
gear-core.workspace = true
tokio = "1"

[build-dependencies]
gwasm-builder.workspace = true
24 changes: 12 additions & 12 deletions app/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@

// TODO (sails): consider sub-services inside (for observing state, for example)
// TODO (sails): rename gstd event depositor here to use `notifier`::`Notifier`/`Informer`.
use gstd::{msg, String};
use sails_macros::{gprogram, groute};
use gstd::{msg, ActorId, String};
use sails_rtl::gstd::{gprogram, groute};
use services::{admin, aggregated, erc20, pausable, roles};

pub mod services;

pub struct BreathxProgram(());
type ServiceOf<T> = <T as sails_rtl::gstd::services::Service>::Exposure;

pub struct Program(());

// TODO (sails): allow to import all necessary macros at once (gprogram, grout, etc).
// TODO (sails): stop forcing deriving default on `BreathxProgram`.
// TODO (sails): stop forcing deriving default on `Program`.
#[gprogram]
impl BreathxProgram {
impl Program {
// TODO (sails): fix arguments are unused.
// TODO (sails): `#[gconstructor]`
pub fn new(name: String, symbol: String, decimals: u8) -> Self {
let source = msg::source();
let program = Self(());

let roles_service = roles::GstdDrivenService::seed();

Expand All @@ -29,16 +32,15 @@ impl BreathxProgram {
let pausable_service = <pausable::GstdDrivenService>::seed(roles_service.clone(), source);

let aggregated_service =
<aggregated::GstdDrivenService>::seed(erc20_service, pausable_service);
<aggregated::GstdDrivenService>::seed(erc20_service, program.pausable());

<admin::GstdDrivenService>::seed(roles_service, aggregated_service, source);
<admin::GstdDrivenService>::seed(roles_service, program.pausable(), source);

Self(())
}

#[groute]
pub fn admin(&self) -> admin::GstdDrivenService {
admin::GstdDrivenService::new(self.roles(), self.aggregated())
admin::GstdDrivenService::new(self.roles(), self.pausable())
}

// TODO (sails): service Erc20: Pausable [pipeline]
Expand All @@ -48,13 +50,11 @@ impl BreathxProgram {
aggregated::GstdDrivenService::new(self.erc20(), self.pausable())
}

#[groute]
pub fn pausable(&self) -> pausable::GstdDrivenService {
pausable::GstdDrivenService::new(self.roles())
}

#[groute]
pub fn roles(&self) -> roles::GstdDrivenService {
fn roles(&self) -> roles::GstdDrivenService {
roles::GstdDrivenService::new()
}

Expand Down
148 changes: 145 additions & 3 deletions app/src/services/admin/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@ use crate::services::erc20::{
use gstd::{prelude::*, ActorId};
use primitive_types::U256;

pub fn mint(balances: &mut BalancesMap, to: ActorId, value: U256) -> Result<bool> {
pub fn mint(
balances: &mut BalancesMap,
total_supply: &mut U256,
to: ActorId,
value: U256,
) -> Result<bool> {
if value.is_zero() {
return Ok(false);
}

let new_total_supply = total_supply
.checked_add(value)
.ok_or(Error::NumericOverflow)?;

let new_to = funcs::balance_of(balances, to)
.checked_add(value)
.ok_or(Error::NumericOverflow)?;
Expand All @@ -19,14 +28,21 @@ pub fn mint(balances: &mut BalancesMap, to: ActorId, value: U256) -> Result<bool
};

balances.insert(to, non_zero_new_to);
*total_supply = new_total_supply;

Ok(true)
}

pub fn burn(balances: &mut BalancesMap, from: ActorId, value: U256) -> Result<bool> {
pub fn burn(
balances: &mut BalancesMap,
total_supply: &mut U256,
from: ActorId,
value: U256,
) -> Result<bool> {
if value.is_zero() {
return Ok(false);
}
let new_total_supply = total_supply.checked_sub(value).ok_or(Error::Underflow)?;

let new_from = funcs::balance_of(balances, from)
.checked_sub(value)
Expand All @@ -37,7 +53,7 @@ pub fn burn(balances: &mut BalancesMap, from: ActorId, value: U256) -> Result<bo
} else {
balances.remove(&from);
}

*total_supply = new_total_supply;
Ok(true)
}

Expand Down Expand Up @@ -80,3 +96,129 @@ pub fn balances(balances: &BalancesMap, skip: usize, take: usize) -> Vec<(ActorI
.map(|(&id, &v)| (id, v))
.collect()
}

#[cfg(test)]
mod tests {
use super::*;
use crate::admin::funcs;
use utils::*;

macro_rules! assert_ok {
( $x:expr, $y: expr $(,)? ) => {{
assert_eq!($x.unwrap(), $y);
}};
}

macro_rules! assert_err {
( $x:expr, $y: expr $(,)? ) => {{
assert_eq!($x.err().expect("Ran into Ok value"), $y);
}};
}

#[test]
fn mint() {
// Initializing thread logger.
let _ = env_logger::try_init();

// Creating map
let mut map = balances_map([]);
let mut total_supply: U256 = 100.into();
let value: U256 = 100.into();
// # Test case #1.
// Successful Mint
{
assert_ok!(
funcs::mint(&mut map, &mut total_supply, alice(), value),
true
);
let expected_balance: NonZeroU256 = value.try_into().unwrap();
assert_eq!(*map.get(&alice()).unwrap(), expected_balance);
assert_eq!(total_supply, 200.into());
}
// # Test case #2.
// Mint with value equal to 0
{
assert_ok!(
funcs::mint(&mut map, &mut total_supply, alice(), 0.into()),
false
);
}
}

#[test]
fn burn() {
// Initializing thread logger.
let _ = env_logger::try_init();

// Creating map
let mut map = balances_map([(dave(), U256::MAX)]);
let mut total_supply: U256 = 100.into();
let value: U256 = 100.into();
// # Test case #1.
// Successful Burn
{
assert_ok!(
funcs::burn(&mut map, &mut total_supply, dave(), value),
true
);
let expected_balance: NonZeroU256 = (U256::MAX - value).try_into().unwrap();
assert_eq!(*map.get(&dave()).unwrap(), expected_balance);
assert_eq!(total_supply, 0.into());
}
// # Test case #2.
// Burn with value equal to 0
{
assert_ok!(
funcs::burn(&mut map, &mut total_supply, dave(), 0.into()),
false
);
}

// # Test case #3.
// Burn with Error: Underflow
{
assert_err!(
funcs::burn(&mut map, &mut total_supply, alice(), value),
Error::Underflow
);
}
}

mod utils {
use super::{AllowancesMap, BalancesMap};
use gstd::{ActorId, ToString};
use primitive_types::U256;

pub fn allowances_map<const N: usize>(
content: [(ActorId, ActorId, U256); N],
) -> AllowancesMap {
content
.into_iter()
.map(|(k1, k2, v)| ((k1, k2), v.try_into().unwrap()))
.collect()
}

pub fn balances_map<const N: usize>(content: [(ActorId, U256); N]) -> BalancesMap {
content
.into_iter()
.map(|(k, v)| (k, v.try_into().unwrap()))
.collect()
}

pub fn alice() -> ActorId {
1u64.into()
}

pub fn bob() -> ActorId {
2u64.into()
}

pub fn charlie() -> ActorId {
3u64.into()
}

pub fn dave() -> ActorId {
4u64.into()
}
}
}
Loading