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

Tutorial step 5 - Uplift to latest ink! and Openbrush #16

Open
wants to merge 3 commits into
base: tutorial/payablemint-step5
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
18 changes: 5 additions & 13 deletions contracts/shiden34/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
[package]
name = "shiden34"
version = "1.0.0"
version = "3.1.0"
authors = ["Astar builder"]
edition = "2021"

[dependencies]
ink = { version = "~4.0.0", default-features = false}

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

openbrush = { tag = "3.0.0", git = "https://github.com/727-Ventures/openbrush-contracts", default-features = false, features = ["psp34", "ownable"] }
scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true }
openbrush = { tag = "v4.0.0-beta", git = "https://github.com/Brushfam/openbrush-contracts", default-features = false, features = ["psp34", "ownable"] }
payable_mint_pkg = { path = "../../logics", default-features = false }

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

[features]
default = ["std"]
std = [
"ink/std",
"scale/std",
"scale-info/std",

"openbrush/std",
"payable_mint_pkg/std",
]
ink-as-dependency = []
ink-as-dependency = []
74 changes: 45 additions & 29 deletions contracts/shiden34/lib.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![feature(min_specialization)]
#![cfg_attr(not(feature = "std"), no_std, no_main)]

#[openbrush::implementation(PSP34, PSP34Enumerable, PSP34Metadata, PSP34Mintable, Ownable)]
#[openbrush::contract]
pub mod shiden34 {
use openbrush::{
contracts::ownable::*,
contracts::psp34::extensions::{enumerable::*, metadata::*},
traits::{Storage, String},
};
use openbrush::traits::Storage;
use payable_mint_pkg::impls::payable_mint::*;
use payable_mint_pkg::traits::payable_mint::*;

#[ink(storage)]
#[derive(Default, Storage)]
pub struct Shiden34 {
#[storage_field]
psp34: psp34::Data<enumerable::Balances>,
psp34: psp34::Data,
#[storage_field]
ownable: ownable::Data,
#[storage_field]
metadata: metadata::Data,
#[storage_field]
enumerable: enumerable::Data,
#[storage_field]
payable_mint: types::Data,
}

impl PSP34 for Shiden34 {}
impl Ownable for Shiden34 {}
impl PSP34Enumerable for Shiden34 {}
impl PSP34Metadata for Shiden34 {}
impl PayableMint for Shiden34 {}
#[overrider(PSP34Mintable)]
#[openbrush::modifiers(only_owner)]
fn mint(&mut self, account: AccountId, id: Id) -> Result<(), PSP34Error> {
psp34::InternalImpl::_mint_to(self, account, id)
}

impl payable_mint_pkg::impls::payable_mint::payable_mint::Internal for Shiden34 {}
impl payable_mint::PayableMintImpl for Shiden34 {}

impl Shiden34 {
#[ink(constructor)]
Expand All @@ -40,11 +40,27 @@ pub mod shiden34 {
price_per_mint: Balance,
) -> Self {
let mut instance = Self::default();
instance._init_with_owner(instance.env().caller());
let collection_id = instance.collection_id();
instance._set_attribute(collection_id.clone(), String::from("name"), name);
instance._set_attribute(collection_id.clone(), String::from("symbol"), symbol);
instance._set_attribute(collection_id, String::from("baseUri"), base_uri);
let caller = instance.env().caller();
ownable::InternalImpl::_init_with_owner(&mut instance, caller);
let collection_id = psp34::PSP34Impl::collection_id(&instance);
metadata::InternalImpl::_set_attribute(
&mut instance,
collection_id.clone(),
String::from("name"),
name,
);
metadata::InternalImpl::_set_attribute(
&mut instance,
collection_id.clone(),
String::from("symbol"),
symbol,
);
metadata::InternalImpl::_set_attribute(
&mut instance,
collection_id,
String::from("baseUri"),
base_uri,
);
instance.payable_mint.max_supply = max_supply;
instance.payable_mint.price_per_mint = price_per_mint;
instance.payable_mint.last_token_id = 0;
Expand Down Expand Up @@ -79,20 +95,20 @@ pub mod shiden34 {
set_sender(accounts.bob);
let num_of_mints: u64 = 5;

assert_eq!(sh34.total_supply(), 0);
assert_eq!(PSP34Impl::total_supply(&sh34), 0);
test::set_value_transferred::<ink::env::DefaultEnvironment>(
PRICE * num_of_mints as u128,
);
assert!(sh34.mint(accounts.bob, num_of_mints).is_ok());
assert_eq!(sh34.total_supply(), num_of_mints as u128);
assert_eq!(sh34.balance_of(accounts.bob), 5);
assert_eq!(sh34.owners_token_by_index(accounts.bob, 0), Ok(Id::U64(1)));
assert_eq!(sh34.owners_token_by_index(accounts.bob, 1), Ok(Id::U64(2)));
assert_eq!(sh34.owners_token_by_index(accounts.bob, 2), Ok(Id::U64(3)));
assert_eq!(sh34.owners_token_by_index(accounts.bob, 3), Ok(Id::U64(4)));
assert_eq!(sh34.owners_token_by_index(accounts.bob, 4), Ok(Id::U64(5)));
assert!(payable_mint::PayableMintImpl::mint(&mut sh34, accounts.bob, num_of_mints).is_ok());
assert_eq!(PSP34Impl::total_supply(&sh34), num_of_mints as u128);
assert_eq!(PSP34Impl::balance_of(&sh34, accounts.bob), 5);
assert_eq!(PSP34EnumerableImpl::owners_token_by_index(&sh34, accounts.bob, 0), Ok(Id::U64(1)));
assert_eq!(PSP34EnumerableImpl::owners_token_by_index(&sh34, accounts.bob, 1), Ok(Id::U64(2)));
assert_eq!(PSP34EnumerableImpl::owners_token_by_index(&sh34, accounts.bob, 2), Ok(Id::U64(3)));
assert_eq!(PSP34EnumerableImpl::owners_token_by_index(&sh34, accounts.bob, 3), Ok(Id::U64(4)));
assert_eq!(PSP34EnumerableImpl::owners_token_by_index(&sh34, accounts.bob, 4), Ok(Id::U64(5)));
assert_eq!(
sh34.owners_token_by_index(accounts.bob, 5),
PSP34EnumerableImpl::owners_token_by_index(&sh34, accounts.bob, 5),
Err(TokenNotExists)
);
}
Expand Down
12 changes: 5 additions & 7 deletions logics/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
[package]
name = "payable_mint_pkg"
version = "0.3.0"
version = "3.1.0"
authors = ["Astar builder"]
edition = "2021"

[dependencies]
ink = { version = "~4.0.0", default-features = false}

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

openbrush = { tag = "3.0.0", git = "https://github.com/727-Ventures/openbrush-contracts", default-features = false, features = ["psp34", "ownable"] }
scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true }
openbrush = { tag = "v4.0.0-beta", git = "https://github.com/Brushfam/openbrush-contracts", default-features = false, features = ["psp34", "ownable"] }

[lib]
path = "lib.rs"
Expand All @@ -23,4 +21,4 @@ std = [
"scale/std",
"scale-info",
"openbrush/std",
]
]
117 changes: 53 additions & 64 deletions logics/impls/payable_mint/payable_mint.rs
Original file line number Diff line number Diff line change
@@ -1,110 +1,101 @@
use ink::prelude::string::{String as PreludeString, ToString};

use crate::impls::payable_mint::types::Data;
pub use crate::traits::payable_mint::PayableMint;
use openbrush::{
contracts::{
ownable::*,
psp34::extensions::{enumerable::*, metadata::*},
use ink::prelude::string::ToString;
use openbrush::contracts::{
ownable,
ownable::only_owner,
psp34,
psp34::{
extensions::{
metadata,
metadata::{Id, PSP34MetadataImpl},
},
PSP34Error, PSP34Impl,
},
modifiers,
traits::{AccountId, Balance, Storage, String},
};

pub trait Internal {
/// Check if the transferred mint values is as expected
fn check_value(&self, transferred_value: u128, mint_amount: u64) -> Result<(), PSP34Error>;

/// Check amount of tokens to be minted
fn check_amount(&self, mint_amount: u64) -> Result<(), PSP34Error>;

/// Check if token is minted
fn token_exists(&self, id: Id) -> Result<(), PSP34Error>;
}

impl<T> PayableMint for T
where
T: Storage<Data>
+ Storage<psp34::Data<enumerable::Balances>>
+ Storage<ownable::Data>
+ Storage<metadata::Data>
+ psp34::Internal,
use openbrush::traits::{AccountId, Balance, Storage, String};

#[openbrush::trait_definition]
pub trait PayableMintImpl:
Storage<Data>
+ Storage<psp34::Data>
+ Storage<ownable::Data>
+ Storage<metadata::Data>
+ Internal
+ PSP34Impl
+ psp34::InternalImpl
+ psp34::extensions::metadata::Internal
+ PSP34MetadataImpl
{
default fn mint(&mut self, to: AccountId, mint_amount: u64) -> Result<(), PSP34Error> {
#[ink(message, payable)]
fn mint(&mut self, to: AccountId, mint_amount: u64) -> Result<(), PSP34Error> {
self.check_value(Self::env().transferred_value(), mint_amount)?;
self.check_amount(mint_amount)?;

let next_to_mint = self.data::<Data>().last_token_id + 1; // first mint id is 1
let mint_offset = next_to_mint + mint_amount;

for mint_id in next_to_mint..mint_offset {
self.data::<psp34::Data<enumerable::Balances>>()
._mint_to(to, Id::U64(mint_id))?;
psp34::InternalImpl::_mint_to(self, to, Id::U64(mint_id))?;
self.data::<Data>().last_token_id += 1;
}

Ok(())
}

/// Set new value for the baseUri
#[modifiers(only_owner)]
default fn set_base_uri(&mut self, uri: PreludeString) -> Result<(), PSP34Error> {
let id = self
.data::<psp34::Data<enumerable::Balances>>()
.collection_id();
self.data::<metadata::Data>()
._set_attribute(id, String::from("baseUri"), uri.into_bytes());
#[ink(message)]
#[openbrush::modifiers(only_owner)]
fn set_base_uri(&mut self, uri: String) -> Result<(), PSP34Error> {
let id = PSP34Impl::collection_id(self);
metadata::Internal::_set_attribute(self, id, String::from("baseUri"), uri);

Ok(())
}

/// Get URI from token ID
default fn token_uri(&self, token_id: u64) -> Result<PreludeString, PSP34Error> {
#[ink(message)]
fn token_uri(&self, token_id: u64) -> Result<String, PSP34Error> {
self.token_exists(Id::U64(token_id))?;
let value = self.get_attribute(
self.data::<psp34::Data<enumerable::Balances>>()
.collection_id(),
let base_uri = PSP34MetadataImpl::get_attribute(
self,
PSP34Impl::collection_id(self),
String::from("baseUri"),
);
let mut token_uri = PreludeString::from_utf8(value.unwrap()).unwrap();
token_uri = token_uri + &token_id.to_string() + &PreludeString::from(".json");
let token_uri = base_uri.unwrap() + &token_id.to_string() + &String::from(".json");
Ok(token_uri)
}

/// Withdraws funds to contract owner
#[modifiers(only_owner)]
default fn withdraw(&mut self) -> Result<(), PSP34Error> {
#[ink(message)]
#[openbrush::modifiers(only_owner)]
fn withdraw(&mut self) -> Result<(), PSP34Error> {
let balance = Self::env().balance();
let current_balance = balance
.checked_sub(Self::env().minimum_balance())
.unwrap_or_default();
let owner = self.data::<ownable::Data>().owner.get().unwrap().unwrap();
Self::env()
.transfer(self.data::<ownable::Data>().owner(), current_balance)
.transfer(owner, current_balance)
.map_err(|_| PSP34Error::Custom(String::from("WithdrawalFailed")))?;
Ok(())
}

/// Get max supply of tokens
default fn max_supply(&self) -> u64 {
#[ink(message)]
fn max_supply(&self) -> u64 {
self.data::<Data>().max_supply
}

/// Get token price
default fn price(&self) -> Balance {
#[ink(message)]
fn price(&self) -> Balance {
self.data::<Data>().price_per_mint
}
}

/// Helper trait for PayableMint
impl<T> Internal for T
where
T: Storage<Data> + Storage<psp34::Data<enumerable::Balances>>,
{
pub trait Internal: Storage<Data> + psp34::Internal {
/// Check if the transferred mint values is as expected
default fn check_value(
&self,
transferred_value: u128,
mint_amount: u64,
) -> Result<(), PSP34Error> {
fn check_value(&self, transferred_value: u128, mint_amount: u64) -> Result<(), PSP34Error> {
if let Some(value) = (mint_amount as u128).checked_mul(self.data::<Data>().price_per_mint) {
if transferred_value == value {
return Ok(());
Expand All @@ -114,7 +105,7 @@ where
}

/// Check amount of tokens to be minted
default fn check_amount(&self, mint_amount: u64) -> Result<(), PSP34Error> {
fn check_amount(&self, mint_amount: u64) -> Result<(), PSP34Error> {
if mint_amount == 0 {
return Err(PSP34Error::Custom(String::from("CannotMintZeroTokens")));
}
Expand All @@ -127,10 +118,8 @@ where
}

/// Check if token is minted
default fn token_exists(&self, id: Id) -> Result<(), PSP34Error> {
self.data::<psp34::Data<enumerable::Balances>>()
.owner_of(id)
.ok_or(PSP34Error::TokenNotExists)?;
fn token_exists(&self, id: Id) -> Result<(), PSP34Error> {
self._owner_of(&id).ok_or(PSP34Error::TokenNotExists)?;
Ok(())
}
}
3 changes: 1 addition & 2 deletions logics/impls/payable_mint/types.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use openbrush::traits::Balance;
pub const STORAGE_KEY: u32 = openbrush::storage_unique_key!(Data);

#[derive(Default, Debug)]
#[openbrush::upgradeable_storage(STORAGE_KEY)]
#[openbrush::storage_item]
pub struct Data {
pub last_token_id: u64,
pub max_supply: u64,
Expand Down
1 change: 0 additions & 1 deletion logics/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![feature(min_specialization)]

pub mod impls;
pub mod traits;