Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ impl TokenConfigurationV0Getters for TokenConfiguration {
}
}

fn is_allowed_transfer_to_frozen_balance(&self) -> bool {
match self {
TokenConfiguration::V0(v0) => v0.is_allowed_transfer_to_frozen_balance(),
}
}

/// Returns the maximum supply.
fn max_supply(&self) -> Option<TokenAmount> {
match self {
Expand Down Expand Up @@ -160,6 +166,13 @@ impl TokenConfigurationV0Setters for TokenConfiguration {
}
}

/// Allow or not a transfer and mint tokens to frozen identity token balances
fn allow_transfer_to_frozen_balance(&mut self, allow: bool) {
match self {
TokenConfiguration::V0(v0) => v0.allow_transfer_to_frozen_balance(allow),
}
}

/// Sets the base supply.
fn set_base_supply(&mut self, base_supply: u64) {
match self {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ pub trait TokenConfigurationV0Getters {
fn keeps_history(&self) -> &TokenKeepsHistoryRules;
fn start_as_paused(&self) -> bool;

/// Allow to transfer and mint tokens to frozen identity token balances
fn is_allowed_transfer_to_frozen_balance(&self) -> bool;

/// Returns the maximum supply.
fn max_supply(&self) -> Option<TokenAmount>;

Expand Down Expand Up @@ -69,6 +72,9 @@ pub trait TokenConfigurationV0Setters {
/// Sets the conventions change rules.
fn set_conventions_change_rules(&mut self, rules: ChangeControlRules);

/// Allow or not a transfer and mint tokens to frozen identity token balances
fn allow_transfer_to_frozen_balance(&mut self, allow: bool);

/// Sets the base supply.
fn set_base_supply(&mut self, base_supply: TokenAmount);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ impl TokenConfigurationV0Getters for TokenConfigurationV0 {
self.start_as_paused
}

/// Allow to transfer and mint tokens to frozen identity token balances
fn is_allowed_transfer_to_frozen_balance(&self) -> bool {
self.allow_transfer_to_frozen_balance
}

/// Returns the maximum supply.
fn max_supply(&self) -> Option<TokenAmount> {
self.max_supply
Expand Down Expand Up @@ -163,6 +168,11 @@ impl TokenConfigurationV0Setters for TokenConfigurationV0 {
self.conventions_change_rules = rules;
}

/// Allow or not a transfer and mint tokens to frozen identity token balances
fn allow_transfer_to_frozen_balance(&mut self, allow: bool) {
self.allow_transfer_to_frozen_balance = allow;
}

/// Sets the base supply.
fn set_base_supply(&mut self, base_supply: TokenAmount) {
self.base_supply = base_supply;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ pub struct TokenConfigurationV0 {
/// Do we start off as paused, meaning that we can not transfer till we unpause.
#[serde(default = "default_starts_as_paused")]
pub start_as_paused: bool,
/// Allow to transfer and mint tokens to frozen identity token balances
#[serde(default)]
pub allow_transfer_to_frozen_balance: bool,
/// Who can change the max supply
/// Even if set no one can ever change this under the base supply
#[serde(default = "default_change_control_rules")]
Expand Down Expand Up @@ -176,6 +179,7 @@ impl TokenConfigurationV0 {
keeps_burning_history: true,
}),
start_as_paused: false,
allow_transfer_to_frozen_balance: false,
max_supply_change_rules: ChangeControlRulesV0 {
authorized_to_make_change: AuthorizedActionTakers::NoOne,
admin_action_takers: AuthorizedActionTakers::NoOne,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ use dpp::block::block_info::BlockInfo;
use dpp::consensus::ConsensusError;
use dpp::consensus::state::identity::RecipientIdentityDoesNotExistError;
use dpp::consensus::state::state_error::StateError;
use dpp::consensus::state::token::TokenMintPastMaxSupplyError;
use dpp::consensus::state::token::{IdentityTokenAccountFrozenError, TokenMintPastMaxSupplyError};
use dpp::data_contract::accessors::v0::DataContractV0Getters;
use dpp::data_contract::accessors::v1::DataContractV1Getters;
use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters;
use dpp::prelude::Identifier;
use dpp::tokens::info::v0::IdentityTokenInfoV0Accessors;
use dpp::validation::SimpleConsensusValidationResult;
use drive::state_transition_action::batch::batched_transition::token_transition::token_mint_transition_action::{TokenMintTransitionAction, TokenMintTransitionActionAccessorsV0};
use dpp::version::PlatformVersion;
use drive::error::drive::DriveError;
use drive::query::TransactionArg;
use drive::state_transition_action::batch::batched_transition::token_transition::token_base_transition_action::TokenBaseTransitionActionAccessorsV0;
use crate::error::Error;
use crate::execution::types::execution_operation::{RetrieveIdentityInfo, ValidationOperation};
use crate::execution::types::state_transition_execution_context::{StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0};
Expand Down Expand Up @@ -142,6 +144,39 @@ impl TokenMintTransitionActionStateValidationV0 for TokenMintTransitionAction {
}
}

// We need to verify that account we are transferring to not frozen
if !self
.base()
.token_configuration()?
.is_allowed_transfer_to_frozen_balance()
{
let (info, fee_result) = platform.drive.fetch_identity_token_info_with_costs(
self.token_id().to_buffer(),
recipient.to_buffer(),
block_info,
true,
transaction,
platform_version,
)?;

execution_context
.add_operation(ValidationOperation::PrecalculatedOperation(fee_result));

if let Some(info) = info {
if info.frozen() {
return Ok(SimpleConsensusValidationResult::new_with_error(
ConsensusError::StateError(StateError::IdentityTokenAccountFrozenError(
IdentityTokenAccountFrozenError::new(
self.token_id(),
recipient,
"mint".to_string(),
),
)),
));
}
};
}

Ok(SimpleConsensusValidationResult::new())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ use dpp::block::block_info::BlockInfo;
use dpp::consensus::ConsensusError;
use dpp::consensus::state::state_error::StateError;
use dpp::consensus::state::token::{IdentityDoesNotHaveEnoughTokenBalanceError, IdentityTokenAccountFrozenError, TokenIsPausedError};
use dpp::data_contract::accessors::v1::DataContractV1Getters;
use dpp::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters;
use dpp::prelude::Identifier;
use dpp::tokens::info::v0::IdentityTokenInfoV0Accessors;
use dpp::tokens::status::v0::TokenStatusV0Accessors;
use dpp::validation::SimpleConsensusValidationResult;
use drive::state_transition_action::batch::batched_transition::token_transition::token_transfer_transition_action::TokenTransferTransitionAction;
use dpp::version::PlatformVersion;
use drive::query::TransactionArg;
use drive::state_transition_action::batch::batched_transition::token_transition::token_base_transition_action::TokenBaseTransitionActionAccessorsV0;
use drive::state_transition_action::batch::batched_transition::token_transition::token_transfer_transition_action::v0::TokenTransferTransitionActionAccessorsV0;
use crate::error::Error;
use crate::execution::types::execution_operation::ValidationOperation;
Expand Down Expand Up @@ -59,7 +62,9 @@ impl TokenTransferTransitionActionStateValidationV0 for TokenTransferTransitionA
platform_version,
)?
.unwrap_or_default();

execution_context.add_operation(ValidationOperation::RetrieveIdentityTokenBalance);

if balance < self.amount() {
return Ok(SimpleConsensusValidationResult::new_with_error(
ConsensusError::StateError(StateError::IdentityDoesNotHaveEnoughTokenBalanceError(
Expand All @@ -75,6 +80,7 @@ impl TokenTransferTransitionActionStateValidationV0 for TokenTransferTransitionA
}

// We need to verify that our token account is not frozen

let (info, fee_result) = platform.drive.fetch_identity_token_info_with_costs(
self.token_id().to_buffer(),
owner_id.to_buffer(),
Expand All @@ -83,7 +89,9 @@ impl TokenTransferTransitionActionStateValidationV0 for TokenTransferTransitionA
transaction,
platform_version,
)?;

execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee_result));

if let Some(info) = info {
if info.frozen() {
return Ok(SimpleConsensusValidationResult::new_with_error(
Expand All @@ -98,6 +106,39 @@ impl TokenTransferTransitionActionStateValidationV0 for TokenTransferTransitionA
}
};

// We need to verify that account we are transferring to not frozen
if !self
.base()
.token_configuration()?
.is_allowed_transfer_to_frozen_balance()
{
let (info, fee_result) = platform.drive.fetch_identity_token_info_with_costs(
self.token_id().to_buffer(),
self.recipient_id().to_buffer(),
block_info,
true,
transaction,
platform_version,
)?;

execution_context
.add_operation(ValidationOperation::PrecalculatedOperation(fee_result));

if let Some(info) = info {
if info.frozen() {
return Ok(SimpleConsensusValidationResult::new_with_error(
ConsensusError::StateError(StateError::IdentityTokenAccountFrozenError(
IdentityTokenAccountFrozenError::new(
self.token_id(),
self.recipient_id(),
"transfer".to_string(),
),
)),
));
}
};
}

// We need to verify that the token is not paused
let (token_status, fee_result) = platform.drive.fetch_token_status_with_costs(
self.token_id().to_buffer(),
Expand All @@ -106,7 +147,9 @@ impl TokenTransferTransitionActionStateValidationV0 for TokenTransferTransitionA
transaction,
platform_version,
)?;

execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee_result));

if let Some(status) = token_status {
if status.paused() {
return Ok(SimpleConsensusValidationResult::new_with_error(
Expand Down
Loading
Loading