Skip to content

Commit

Permalink
Merge pull request #87 from Itheum/develop
Browse files Browse the repository at this point in the history
V4.0.0 : Release Candidate - Support for mint donations
  • Loading branch information
newbreedofgeek authored May 7, 2024
2 parents 0211dc7 + 1cc95eb commit f3f93a5
Show file tree
Hide file tree
Showing 19 changed files with 379 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "datanftmint"
version = "3.0.0"
version = "4.0.0"
edition = "2021"
publish = false
authors = [ "Ovidiu Damian - Itheum","Bucur David - Itheum","Mark Paul - Itheum"]
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ This smart contract aims to offer the MultiversX community an audited NFT minter

### Setting up dev environment (project development bootstrap) + how to build (and upgrade)

- Uses `multiversx-sc-* 0.39.4` (In v3.0.0, we used 0.47.5) SDK libs (see Cargo.toml)
- Building requires minimum **mxpy 6.1.1** (In v2.0.0, we used mxpy 9.5.1). Check version using `mxpy --version`
- Uses `multiversx-sc-* 0.39.4` (In v3.0.0 and v4.0.0, we used 0.47.5) SDK libs (see Cargo.toml)
- Building requires minimum **mxpy 6.1.1** (In >v2.0.0, we used mxpy 9.5.1). Check version using `mxpy --version`
- To build the project, requires minimum Rust version `1.76.0-nightly` (In v3.0.0, we used 1.76.0-nightly). Check your Rust version by running `rustc --version`. To update your Rust, run `rustup update`. To set to nightly run `rustup default nightly`. Note that `mxpy deps install rust --overwrite` also brings in it's own compatible rust version so running `rustup default nightly` might have a higher rust version than what is used via `mxpy deps install rust --overwrite`.
- After you make sure you have the minimum Rust version you can then begin development. After you clone repo and before you run build, deploy or run the tests - follow these steps (most likely only needed the 1st time)
- [Upgrades] Note that when we upgrade smart contract, we should again follow the steps below too as lib version may have changed (but for upgrade I skipped the rustup default nightly cmd and did the others)
Expand Down Expand Up @@ -116,7 +116,7 @@ Once the main commit is locked in, we can then produce the code hash and build t

Note that if you already have a output-docker from a previous build and deploy then delete this folder.

Also note that if you are upgrading you may need to use a newer docker `sdk-rust-contract-builder` version. You can see the tags here https://hub.docker.com/r/multiversx/sdk-rust-contract-builder/tags. In v2.0.0, we used v5.3.0 and for v3.0.0, we used v6.1.1 for the build to upgrade to. We tested this on devnet before doing it on mainnet.
Also note that if you are upgrading you may need to use a newer docker `sdk-rust-contract-builder` version. You can see the tags here https://hub.docker.com/r/multiversx/sdk-rust-contract-builder/tags. In v2.0.0, we used v5.3.0 and for v3.0.0, v4.0.0, we used v6.1.1 for the build to upgrade to. We tested this on devnet before doing it on mainnet.

This process may take some time. After it's done you should see "Docker build ran successfully!". An output-docker folder will be created containing the WASM files built in a reproducible way and artifacts.json containing the code hash of the WASM files.

Expand Down
31 changes: 31 additions & 0 deletions interaction/devnet.snippets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -518,3 +518,34 @@ setBondContractAddress(){
--chain ${CHAIN_ID} \
--send || return
}

# v4.0.0
setMaxDonationPercentage(){
# $1 = max donation percentage value (1% -> 100 ; 100% -> 10000)

mxpy --verbose contract call ${ADDRESS} \
--recall-nonce \
--pem=${WALLET} \
--gas-limit=6000000 \
--function "setMaxDonationPercentage" \
--arguments ${1} \
--proxy ${PROXY} \
--chain ${CHAIN_ID} \
--send || return
}

setDonationTreasuryAddress(){
# $1 = address

address="0x$(mxpy wallet bech32 --decode ${1})"

mxpy --verbose contract call ${ADDRESS} \
--recall-nonce \
--pem=${WALLET} \
--gas-limit=6000000 \
--function "setDonationTreasuryAddress" \
--arguments $address \
--proxy ${PROXY} \
--chain ${CHAIN_ID} \
--send || return
}
33 changes: 33 additions & 0 deletions interaction/mainnet.snippets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -522,3 +522,36 @@ setBondContractAddressMainnet(){
--ledger-address-index 0 \
--send || return
}

# v4.0.0
setMaxDonationPercentageMainnet(){
# $1 = max donation percentage value (1% -> 100 ; 100% -> 10000)

mxpy --verbose contract call ${ADDRESS} \
--recall-nonce \
--gas-limit=6000000 \
--function "setMaxDonationPercentage" \
--arguments ${1} \
--proxy ${PROXY} \
--chain ${CHAIN_ID} \
--ledger \
--ledger-address-index 0 \
--send || return
}

setDonationTreasuryAddressMainnet(){
# $1 = address

address="0x$(mxpy wallet bech32 --decode ${1})"

mxpy --verbose contract call ${ADDRESS} \
--recall-nonce \
--gas-limit=6000000 \
--function "setDonationTreasuryAddress" \
--arguments $address \
--proxy ${PROXY} \
--chain ${CHAIN_ID} \
--ledger \
--ledger-address-index 0 \
--send || return
}
4 changes: 2 additions & 2 deletions meta/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion meta/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "datanftmint-meta"
version = "3.0.0"
version = "4.0.0"
edition = "2021"
publish = false
authors = [ "Ovidiu Damian - Itheum","Bucur David - Itheum","Mark Paul - Itheum"]
Expand Down
1 change: 1 addition & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ pub const ERR_ONLY_WITHDRAWAL_ADDRESS_CAN_WITHDRAW: &str =
pub const ERR_WITHDRAWAL_ADDRESS_NOT_SET: &str = "Withdrawal address not set";
pub const ERR_WRONG_AMOUNT_OF_FUNDS: &str = "Wrong amount of funds";
pub const ERR_WRONG_BOND_PERIOD: &str = "Wrong bond period";
pub const ERR_PERCENTAGE_TOO_HIGH: &str = "Percentage too high";
13 changes: 12 additions & 1 deletion src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ pub trait EventsModule {
#[event("setTreasuryAddress")]
fn treasury_address_event(&self, #[indexed] treasury_address: &ManagedAddress);

// Emitted whenever donation treasury address is set
#[event("setDonationTreasuryAddress")]
fn donation_treasury_address_event(
&self,
#[indexed] donation_treasury_address: &ManagedAddress,
);

// Emitted whenever max donation percentage is set
#[event("setMaxDonationPercentage")]
fn max_donation_percentage_event(&self, #[indexed] max_donation_percentage: &u64);

// Emitted whenever whitelist enabling changes value
#[event("whitelistEnableToggle")]
fn whitelist_enable_toggle_event(&self, #[indexed] enable_value: &bool);
Expand Down Expand Up @@ -129,7 +140,7 @@ pub trait EventsModule {
#[indexed] token: &EgldOrEsdtTokenIdentifier,
#[indexed] price: &BigUint,
#[indexed] bond_amount: &BigUint,
#[indexed] extra_assets: &ManagedVec<ManagedBuffer>
#[indexed] extra_assets: &ManagedVec<ManagedBuffer>,
);

#[event("setWithdrawalAddress")]
Expand Down
57 changes: 51 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use crate::{
callbacks::CallbackProxy,
errors::{
ERR_ALREADY_IN_WHITELIST, ERR_CONTRACT_ALREADY_INITIALIZED, ERR_DATA_STREAM_IS_EMPTY,
ERR_ISSUE_COST, ERR_NOT_IN_WHITELIST, ERR_WHITELIST_IS_EMPTY, ERR_WRONG_AMOUNT_OF_FUNDS,
ERR_WRONG_BOND_PERIOD,
ERR_ISSUE_COST, ERR_NOT_IN_WHITELIST, ERR_PERCENTAGE_TOO_HIGH, ERR_WHITELIST_IS_EMPTY,
ERR_WRONG_AMOUNT_OF_FUNDS, ERR_WRONG_BOND_PERIOD,
},
storage::DataNftAttributes,
};
Expand Down Expand Up @@ -148,6 +148,7 @@ pub trait DataNftMint:
title: ManagedBuffer,
description: ManagedBuffer,
lock_period_sec: u64,
donation_percentage: u64,
extra_assets: MultiValueEncoded<ManagedBuffer>,
) -> DataNftAttributes<Self::Api> {
self.require_ready_for_minting_and_burning();
Expand All @@ -161,6 +162,19 @@ pub trait DataNftMint:
self.require_title_description_are_valid(&title, &description);
self.require_sft_is_valid(&royalties, &supply);

let donation_supply = if donation_percentage > 0 {
require!(
donation_percentage <= self.max_donation_percentage().get(),
ERR_PERCENTAGE_TOO_HIGH
);

let donation_supply =
&supply * &BigUint::from(donation_percentage) / BigUint::from(10_000u64);
donation_supply
} else {
BigUint::zero()
};

let caller = self.blockchain().get_caller();
let current_time = self.blockchain().get_block_timestamp();
self.require_minting_is_allowed(&caller, current_time);
Expand Down Expand Up @@ -206,14 +220,14 @@ pub trait DataNftMint:
};

let token_identifier = self.token_id().get_token_id();
let extra_assets_vec = extra_assets.into_vec_of_buffers();
let extra_assets_vec = extra_assets.into_vec_of_buffers();
self.mint_event(
&caller,
&one_token,
&payment.token_identifier,
&price,
&payment.amount,
&extra_assets_vec
&extra_assets_vec,
);

let nonce = self.send().esdt_nft_create(
Expand All @@ -234,8 +248,24 @@ pub trait DataNftMint:
payment,
);

self.send()
.direct_esdt(&caller, &token_identifier, nonce, &supply);
if donation_supply > BigUint::zero() {
let donation_treasury_address = self.donation_treasury_address().get();
self.send().direct_esdt(
&donation_treasury_address,
&token_identifier,
nonce,
&donation_supply,
);
self.send().direct_esdt(
&caller,
&token_identifier,
nonce,
&(&supply - &donation_supply),
);
} else {
self.send()
.direct_esdt(&caller, &token_identifier, nonce, &supply);
}

attributes
}
Expand Down Expand Up @@ -268,6 +298,21 @@ pub trait DataNftMint:
self.treasury_address().set(&address);
}

#[endpoint(setDonationTreasuryAddress)]
fn set_donation_treasury_address(&self, address: ManagedAddress) {
self.require_is_privileged(&self.blockchain().get_caller());
self.donation_treasury_address_event(&address);
self.donation_treasury_address().set(&address);
}

#[endpoint(setMaxDonationPercentage)]
fn set_max_donation_percentage(&self, percentage: u64) {
self.require_is_privileged(&self.blockchain().get_caller());
require!(percentage <= 10_000, ERR_PERCENTAGE_TOO_HIGH);
self.max_donation_percentage_event(&percentage);
self.max_donation_percentage().set(percentage);
}

// Endpoint that will be used by privileged address to change the contract pause value.
#[endpoint(setIsPaused)]
fn set_is_paused(&self, is_paused: bool) {
Expand Down
4 changes: 4 additions & 0 deletions src/requirements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub trait RequirementsModule: crate::storage::StorageModule {
if self.treasury_address().is_empty() {
is_mint_ready = false;
}

if self.bond_contract_address().is_empty() {
is_mint_ready = false;
}
Expand All @@ -35,6 +36,9 @@ pub trait RequirementsModule: crate::storage::StorageModule {
if self.bond_contract_address().is_empty() {
is_mint_ready = false;
}
if self.donation_treasury_address().is_empty() {
is_mint_ready = false;
}
require!(is_mint_ready, ERR_MINTING_AND_BURNING_NOT_ALLOWED);
}

Expand Down
8 changes: 8 additions & 0 deletions src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ pub trait StorageModule {
#[storage_mapper("treasury_address")]
fn treasury_address(&self) -> SingleValueMapper<ManagedAddress>;

#[view(getDonationTreasuryAddress)]
#[storage_mapper("donation_treasury_address")]
fn donation_treasury_address(&self) -> SingleValueMapper<ManagedAddress>;

#[view(getMaxDonationPercentage)]
#[storage_mapper("max_donation_percentage")]
fn max_donation_percentage(&self) -> SingleValueMapper<u64>;

#[view(getWithdrawalAddress)]
#[storage_mapper("withdrawal_address")]
fn withdrawal_address(&self) -> SingleValueMapper<ManagedAddress>;
Expand Down
3 changes: 3 additions & 0 deletions src/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub struct UserDataOut<M: ManagedTypeApi> {
pub total_minted: BigUint<M>,
pub frozen: bool,
pub frozen_nonces: ManagedVec<M, u64>,
pub max_donation_percentage: u64,
}

//Module that handles read-only endpoints (views) for the smart contract
Expand Down Expand Up @@ -47,6 +48,7 @@ pub trait ViewsModule: crate::storage::StorageModule {
.frozen_sfts_per_address(&address)
.iter()
.collect::<ManagedVec<u64>>();
let max_donation_percentage = self.max_donation_percentage().get();

let user_data = UserDataOut {
anti_spam_tax_value,
Expand All @@ -62,6 +64,7 @@ pub trait ViewsModule: crate::storage::StorageModule {
total_minted,
frozen,
frozen_nonces,
max_donation_percentage,
};
user_data
}
Expand Down
1 change: 1 addition & 0 deletions tests/endpoints/burn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ fn burn_token_test() {
ITHEUM_TOKEN_IDENTIFIER,
0u64,
100u64 + 100u64,
0u64,
None,
);

Expand Down
Loading

0 comments on commit f3f93a5

Please sign in to comment.