Skip to content
Merged
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
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 @@ -167,6 +173,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 @@ -27,6 +27,9 @@ pub trait TokenConfigurationV0Getters {
/// Returns if we start as paused.
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 @@ -78,6 +81,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 @@ -168,6 +173,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 @@ -34,6 +34,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 = "default_allow_transfer_to_frozen_balance")]
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 @@ -71,6 +74,11 @@ fn default_starts_as_paused() -> bool {
false
}

// Default function for `allow_transfer_to_frozen_balance`
fn default_allow_transfer_to_frozen_balance() -> bool {
true
}

fn default_token_keeps_history_rules() -> TokenKeepsHistoryRules {
TokenKeepsHistoryRules::V0(TokenKeepsHistoryRulesV0 {
keeps_transfer_history: true,
Expand Down Expand Up @@ -143,13 +151,14 @@ impl fmt::Display for TokenConfigurationV0 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"TokenConfigurationV0 {{\n conventions: {:?},\n conventions_change_rules: {:?},\n base_supply: {},\n max_supply: {:?},\n keeps_history: {},\n start_as_paused: {},\n max_supply_change_rules: {:?},\n distribution_rules: {},\n manual_minting_rules: {:?},\n manual_burning_rules: {:?},\n freeze_rules: {:?},\n unfreeze_rules: {:?},\n destroy_frozen_funds_rules: {:?},\n emergency_action_rules: {:?},\n main_control_group: {:?},\n main_control_group_can_be_modified: {:?}\n}}",
"TokenConfigurationV0 {{\n conventions: {:?},\n conventions_change_rules: {:?},\n base_supply: {},\n max_supply: {:?},\n keeps_history: {},\n start_as_paused: {},\n allow_transfer_to_frozen_balance: {},\n max_supply_change_rules: {:?},\n distribution_rules: {},\n manual_minting_rules: {:?},\n manual_burning_rules: {:?},\n freeze_rules: {:?},\n unfreeze_rules: {:?},\n destroy_frozen_funds_rules: {:?},\n emergency_action_rules: {:?},\n main_control_group: {:?},\n main_control_group_can_be_modified: {:?}\n}}",
self.conventions,
self.conventions_change_rules,
self.base_supply,
self.max_supply,
self.keeps_history,
self.start_as_paused,
self.allow_transfer_to_frozen_balance,
self.max_supply_change_rules,
self.distribution_rules,
self.manual_minting_rules,
Expand Down Expand Up @@ -190,6 +199,7 @@ impl TokenConfigurationV0 {
keeps_direct_purchase_history: true,
}),
start_as_paused: false,
allow_transfer_to_frozen_balance: true,
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 @@ -240,6 +240,7 @@ impl<C> Platform<C> {
max_supply: None,
keeps_history: TokenKeepsHistoryRulesV0::default().into(),
start_as_paused: false,
allow_transfer_to_frozen_balance: true,
max_supply_change_rules: ChangeControlRulesV0::default().into(),
distribution_rules: TokenDistributionRulesV0 {
perpetual_distribution: None,
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,15 @@ 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, TokenTransferRecipientIdentityNotExistError};
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 @@ -78,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 @@ -103,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 Down
Loading
Loading