diff --git a/execution_engine/src/runtime/mint_internal.rs b/execution_engine/src/runtime/mint_internal.rs index ed98c899e0..ae77487561 100644 --- a/execution_engine/src/runtime/mint_internal.rs +++ b/execution_engine/src/runtime/mint_internal.rs @@ -97,6 +97,11 @@ where fn allow_unrestricted_transfers(&self) -> bool { self.context.engine_config().allow_unrestricted_transfers() } + + /// Validate URef against context access rights. + fn is_valid_uref(&self, uref: &URef) -> bool { + self.context.access_rights().has_access_rights_to_uref(uref) + } } // TODO: update Mint + StorageProvider to better handle errors diff --git a/execution_engine_testing/test_support/src/wasm_test_builder.rs b/execution_engine_testing/test_support/src/wasm_test_builder.rs index fafd7115df..13e2ea6e21 100644 --- a/execution_engine_testing/test_support/src/wasm_test_builder.rs +++ b/execution_engine_testing/test_support/src/wasm_test_builder.rs @@ -705,8 +705,8 @@ where /// Panics if the total supply can't be found. pub fn total_supply( &self, - maybe_post_state: Option, protocol_version: ProtocolVersion, + maybe_post_state: Option, ) -> U512 { let post_state = maybe_post_state .or(self.post_state_hash) @@ -759,7 +759,7 @@ where let post_state = maybe_post_state .or(self.post_state_hash) .expect("builder must have a post-state hash"); - let total_supply = self.total_supply(Some(post_state), protocol_version); + let total_supply = self.total_supply(protocol_version, Some(post_state)); let rate = self.round_seigniorage_rate(Some(post_state), protocol_version); rate.checked_mul(&Ratio::from(total_supply)) .map(|ratio| ratio.to_integer()) diff --git a/execution_engine_testing/tests/src/test/private_chain/burn_fees_and_refund.rs b/execution_engine_testing/tests/src/test/private_chain/burn_fees_and_refund.rs index 95cb758ab4..b5907c8a36 100644 --- a/execution_engine_testing/tests/src/test/private_chain/burn_fees_and_refund.rs +++ b/execution_engine_testing/tests/src/test/private_chain/burn_fees_and_refund.rs @@ -121,7 +121,7 @@ fn test_burning_fees( .expect("should have rewards purse"); let rewards_purse_uref = rewards_purse_key.into_uref().expect("should be uref"); assert_eq!(builder.get_purse_balance(rewards_purse_uref), U512::zero()); - let total_supply_before = builder.total_supply(None, protocol_version); + let total_supply_before = builder.total_supply(protocol_version, None); // TODO: reevaluate this test, considering fee / refund / pricing modes // let exec_request_1 = ExecuteRequestBuilder::module_bytes( // *DEFAULT_ADMIN_ACCOUNT_ADDR, @@ -139,7 +139,7 @@ fn test_burning_fees( // U512::zero(), // "proposer should not receive anything", // ); - let total_supply_after = builder.total_supply(None, protocol_version); + let total_supply_after = builder.total_supply(protocol_version, None); assert_eq!( total_supply_before - total_supply_after, expected_burn_amount, @@ -149,11 +149,11 @@ fn test_burning_fees( TransferRequestBuilder::new(MINIMUM_ACCOUNT_CREATION_BALANCE, *ACCOUNT_1_ADDR) .with_initiator(*DEFAULT_ADMIN_ACCOUNT_ADDR) .build(); - let total_supply_before = builder.total_supply(None, protocol_version); + let total_supply_before = builder.total_supply(protocol_version, None); builder .transfer_and_commit(transfer_request) .expect_success(); - let total_supply_after = builder.total_supply(None, protocol_version); + let total_supply_after = builder.total_supply(protocol_version, None); match fee_handling { FeeHandling::PayToProposer | FeeHandling::Accumulate | FeeHandling::NoFee => { diff --git a/execution_engine_testing/tests/src/test/private_chain/restricted_auction.rs b/execution_engine_testing/tests/src/test/private_chain/restricted_auction.rs index 7173cf6eb5..b2eee1ecc0 100644 --- a/execution_engine_testing/tests/src/test/private_chain/restricted_auction.rs +++ b/execution_engine_testing/tests/src/test/private_chain/restricted_auction.rs @@ -19,7 +19,7 @@ fn should_not_distribute_rewards_but_compute_next_set() { let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); for _ in 0..3 { builder.distribute( @@ -101,7 +101,7 @@ fn should_not_distribute_rewards_but_compute_next_set() { era_info ); - let total_supply_after_distribution = builder.total_supply(None, protocol_version); + let total_supply_after_distribution = builder.total_supply(protocol_version, None); assert_eq!( initial_supply, total_supply_after_distribution, "total supply of tokens should not increase after an auction is ran" diff --git a/execution_engine_testing/tests/src/test/system_contracts/auction/distribute.rs b/execution_engine_testing/tests/src/test/system_contracts/auction/distribute.rs index ebf3ce49ee..3144f4900b 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/auction/distribute.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/auction/distribute.rs @@ -96,8 +96,8 @@ fn withdraw_bid( ) { let auction = builder.get_auction_contract_hash(); let withdraw_bid_args = runtime_args! { - auction::ARG_PUBLIC_KEY => validator, - auction::ARG_AMOUNT => amount, + ARG_PUBLIC_KEY => validator, + ARG_AMOUNT => amount, }; let withdraw_bid_request = ExecuteRequestBuilder::contract_call_by_hash( sender, @@ -118,9 +118,9 @@ fn undelegate( ) { let auction = builder.get_auction_contract_hash(); let undelegate_args = runtime_args! { - auction::ARG_DELEGATOR => delegator, - auction::ARG_VALIDATOR => validator, - auction::ARG_AMOUNT => amount, + ARG_DELEGATOR => delegator, + ARG_VALIDATOR => validator, + ARG_AMOUNT => amount, }; let undelegate_request = ExecuteRequestBuilder::contract_call_by_hash( sender, @@ -256,7 +256,7 @@ fn should_distribute_delegation_rate_zero() { let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); let total_payout = builder.base_round_reward(None, protocol_version); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); @@ -524,7 +524,7 @@ fn should_withdraw_bids_after_distribute() { let total_payout = builder.base_round_reward(None, protocol_version); // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); let rate = builder.round_seigniorage_rate(None, protocol_version); let expected_total_reward = rate * initial_supply; @@ -830,7 +830,7 @@ fn should_distribute_rewards_after_restaking_delegated_funds() { let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); let initial_rate = builder.round_seigniorage_rate(None, protocol_version); let initial_round_reward = builder.base_round_reward(None, protocol_version); @@ -978,7 +978,7 @@ fn should_distribute_rewards_after_restaking_delegated_funds() { )); // Next round of rewards - let updated_supply = builder.total_supply(None, protocol_version); + let updated_supply = builder.total_supply(protocol_version, None); assert!(updated_supply > total_supply); total_supply = updated_supply; @@ -1151,7 +1151,7 @@ fn should_distribute_delegation_rate_half() { let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); let total_payout = builder.base_round_reward(None, protocol_version); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); @@ -1383,7 +1383,7 @@ fn should_distribute_delegation_rate_full() { let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); @@ -1565,7 +1565,7 @@ fn should_distribute_uneven_delegation_rate_zero() { let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); let total_payout = builder.base_round_reward(None, protocol_version); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); @@ -1868,7 +1868,7 @@ fn should_distribute_with_multiple_validators_and_delegators() { let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); let total_payout = builder.base_round_reward(None, protocol_version); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); @@ -2200,7 +2200,7 @@ fn should_distribute_with_multiple_validators_and_shared_delegator() { let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); let total_payout = builder.base_round_reward(None, protocol_version); let expected_total_reward = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward.to_integer(); @@ -2557,13 +2557,13 @@ fn should_increase_total_supply_after_distribute() { let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); } - let post_genesis_supply = builder.total_supply(None, protocol_version); + let post_genesis_supply = builder.total_supply(protocol_version, None); assert_eq!( initial_supply, post_genesis_supply, @@ -2576,7 +2576,7 @@ fn should_increase_total_supply_after_distribute() { timestamp_millis += TIMESTAMP_MILLIS_INCREMENT; } - let post_auction_supply = builder.total_supply(None, protocol_version); + let post_auction_supply = builder.total_supply(protocol_version, None); assert_eq!( initial_supply, post_auction_supply, "total supply should remain unchanged regardless of auction" @@ -2603,7 +2603,7 @@ fn should_increase_total_supply_after_distribute() { builder.exec(distribute_request).expect_success().commit(); - let post_distribute_supply = builder.total_supply(None, protocol_version); + let post_distribute_supply = builder.total_supply(protocol_version, None); assert!( initial_supply < post_distribute_supply, "total supply should increase after distribute ({} >= {})", @@ -2737,13 +2737,13 @@ fn should_not_create_purses_during_distribute() { let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); for request in post_genesis_requests { builder.exec(request).commit().expect_success(); } - let post_genesis_supply = builder.total_supply(None, protocol_version); + let post_genesis_supply = builder.total_supply(protocol_version, None); assert_eq!( initial_supply, post_genesis_supply, @@ -2756,7 +2756,7 @@ fn should_not_create_purses_during_distribute() { timestamp_millis += TIMESTAMP_MILLIS_INCREMENT; } - let post_auction_supply = builder.total_supply(None, protocol_version); + let post_auction_supply = builder.total_supply(protocol_version, None); assert_eq!( initial_supply, post_auction_supply, "total supply should remain unchanged regardless of auction" @@ -2789,7 +2789,7 @@ fn should_not_create_purses_during_distribute() { number_of_purses_before_distribute ); - let post_distribute_supply = builder.total_supply(None, protocol_version); + let post_distribute_supply = builder.total_supply(protocol_version, None); assert!( initial_supply < post_distribute_supply, "total supply should increase after distribute ({} >= {})", @@ -2899,7 +2899,7 @@ fn should_distribute_delegation_rate_full_after_upgrading() { let protocol_version = DEFAULT_PROTOCOL_VERSION; // initial token supply - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); let expected_total_reward_before = *GENESIS_ROUND_SEIGNIORAGE_RATE * initial_supply; let expected_total_reward_integer = expected_total_reward_before.to_integer(); @@ -2985,7 +2985,7 @@ fn should_distribute_delegation_rate_full_after_upgrading() { builder.upgrade(&mut upgrade_request); - let initial_supply = builder.total_supply(None, protocol_version); + let initial_supply = builder.total_supply(protocol_version, None); for _ in 0..5 { builder.advance_era(); diff --git a/execution_engine_testing/tests/src/test/system_contracts/genesis.rs b/execution_engine_testing/tests/src/test/system_contracts/genesis.rs index f0b5bebb7f..32e16308dc 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/genesis.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/genesis.rs @@ -151,7 +151,7 @@ fn should_track_total_token_supply_in_mint() { builder.run_genesis(genesis_request); - let total_supply = builder.total_supply(None, protocol_version); + let total_supply = builder.total_supply(protocol_version, None); let expected_balance: U512 = accounts.iter().map(|item| item.balance().value()).sum(); let expected_staked_amount: U512 = accounts diff --git a/execution_engine_testing/tests/src/test/system_contracts/mint.rs b/execution_engine_testing/tests/src/test/system_contracts/mint.rs index 521d90f0ed..98489d8b74 100644 --- a/execution_engine_testing/tests/src/test/system_contracts/mint.rs +++ b/execution_engine_testing/tests/src/test/system_contracts/mint.rs @@ -1,11 +1,12 @@ use casper_engine_test_support::{ - auction, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, + ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, LOCAL_GENESIS_REQUEST, }; use casper_types::{runtime_args, ProtocolVersion, URef, U512}; +use casper_storage::data_access_layer::BalanceIdentifier; use tempfile::TempDir; -const TEST_DELEGATOR_INITIAL_ACCOUNT_BALANCE: u64 = 1_000_000 * 1_000_000_000; +// const TEST_DELEGATOR_INITIAL_ACCOUNT_BALANCE: u64 = 1_000_000 * 1_000_000_000; const CONTRACT_BURN: &str = "burn.wasm"; const CONTRACT_TRANSFER_TO_NAMED_PURSE: &str = "transfer_to_named_purse.wasm"; @@ -21,20 +22,22 @@ fn should_empty_purse_when_burning_above_balance() { let mut builder = LmdbWasmTestBuilder::new(data_dir.as_ref()); let source = *DEFAULT_ACCOUNT_ADDR; - let delegator_keys = auction::generate_public_keys(1); - let validator_keys = auction::generate_public_keys(1); - - auction::run_genesis_and_create_initial_accounts( - &mut builder, - &validator_keys, - delegator_keys - .iter() - .map(|public_key| public_key.to_account_hash()) - .collect::>(), - U512::from(TEST_DELEGATOR_INITIAL_ACCOUNT_BALANCE), - ); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + + // let delegator_keys = auction::generate_public_keys(1); + // let validator_keys = auction::generate_public_keys(1); + + // run_genesis_and_create_initial_accounts( + // &mut builder, + // &validator_keys, + // delegator_keys + // .iter() + // .map(|public_key| public_key.to_account_hash()) + // .collect::>(), + // U512::from(TEST_DELEGATOR_INITIAL_ACCOUNT_BALANCE), + // ); - let initial_supply = builder.total_supply(None); + let initial_supply = builder.total_supply(ProtocolVersion::V2_0_0, None); let purse_name = "purse"; let purse_amount = U512::from(10_000_000_000u64); @@ -64,8 +67,11 @@ fn should_empty_purse_when_burning_above_balance() { assert_eq!( builder - .get_purse_balance_result(ProtocolVersion::V2_0_0, purse_uref) - .motes() + .get_purse_balance_result_with_proofs( + ProtocolVersion::V2_0_0, + BalanceIdentifier::Purse(purse_uref) + ) + .total_balance() .cloned() .unwrap(), purse_amount @@ -89,8 +95,11 @@ fn should_empty_purse_when_burning_above_balance() { assert_eq!( builder - .get_purse_balance_result(ProtocolVersion::V2_0_0, purse_uref) - .motes() + .get_purse_balance_result_with_proofs( + ProtocolVersion::V2_0_0, + BalanceIdentifier::Purse(purse_uref) + ) + .total_balance() .cloned() .unwrap(), num_of_tokens_after_burn @@ -114,14 +123,17 @@ fn should_empty_purse_when_burning_above_balance() { assert_eq!( builder - .get_purse_balance_result(ProtocolVersion::V2_0_0, purse_uref) - .motes() + .get_purse_balance_result_with_proofs( + ProtocolVersion::V2_0_0, + BalanceIdentifier::Purse(purse_uref) + ) + .total_balance() .cloned() .unwrap(), num_of_tokens_after_burn ); - let supply_after_burns = builder.total_supply(None); + let supply_after_burns = builder.total_supply(ProtocolVersion::V2_0_0, None); let expected_supply_after_burns = initial_supply - U512::from(10_000_000_000u64); assert_eq!(supply_after_burns, expected_supply_after_burns); @@ -134,20 +146,21 @@ fn should_not_burn_excess_tokens() { let mut builder = LmdbWasmTestBuilder::new(data_dir.as_ref()); let source = *DEFAULT_ACCOUNT_ADDR; - let delegator_keys = auction::generate_public_keys(1); - let validator_keys = auction::generate_public_keys(1); - - auction::run_genesis_and_create_initial_accounts( - &mut builder, - &validator_keys, - delegator_keys - .iter() - .map(|public_key| public_key.to_account_hash()) - .collect::>(), - U512::from(TEST_DELEGATOR_INITIAL_ACCOUNT_BALANCE), - ); - - let initial_supply = builder.total_supply(None); + builder.run_genesis(LOCAL_GENESIS_REQUEST.clone()); + // let delegator_keys = auction::generate_public_keys(1); + // let validator_keys = auction::generate_public_keys(1); + // + // run_genesis_and_create_initial_accounts( + // &mut builder, + // &validator_keys, + // delegator_keys + // .iter() + // .map(|public_key| public_key.to_account_hash()) + // .collect::>(), + // U512::from(TEST_DELEGATOR_INITIAL_ACCOUNT_BALANCE), + // ); + + let initial_supply = builder.total_supply(ProtocolVersion::V2_0_0, None); let purse_name = "purse"; let purse_amount = U512::from(10_000_000_000u64); @@ -177,8 +190,11 @@ fn should_not_burn_excess_tokens() { assert_eq!( builder - .get_purse_balance_result(ProtocolVersion::V2_0_0, purse_uref) - .motes() + .get_purse_balance_result_with_proofs( + ProtocolVersion::V2_0_0, + BalanceIdentifier::Purse(purse_uref) + ) + .total_balance() .cloned() .unwrap(), purse_amount @@ -202,14 +218,17 @@ fn should_not_burn_excess_tokens() { assert_eq!( builder - .get_purse_balance_result(ProtocolVersion::V2_0_0, purse_uref) - .motes() + .get_purse_balance_result_with_proofs( + ProtocolVersion::V2_0_0, + BalanceIdentifier::Purse(purse_uref) + ) + .total_balance() .cloned() .unwrap(), num_of_tokens_after_burn, ); - let supply_after_burns = builder.total_supply(None); + let supply_after_burns = builder.total_supply(ProtocolVersion::V2_0_0, None); let expected_supply_after_burns = initial_supply - U512::from(10_000_000_000u64); assert_eq!(supply_after_burns, expected_supply_after_burns); diff --git a/storage/src/global_state/state/mod.rs b/storage/src/global_state/state/mod.rs index 7f44420fae..823ea8df89 100644 --- a/storage/src/global_state/state/mod.rs +++ b/storage/src/global_state/state/mod.rs @@ -1332,7 +1332,7 @@ pub trait StateProvider { )); } }; - match runtime.burn(source_purse, burn_amount) { + match runtime.payment_burn(source_purse, burn_amount) { Ok(_) => Ok(burn_amount), Err(err) => Err(err), } @@ -1424,7 +1424,7 @@ pub trait StateProvider { Ok(value) => value, Err(tce) => return HandleFeeResult::Failure(tce), }; - runtime.burn(source_purse, amount) + runtime.payment_burn(source_purse, amount) } }; diff --git a/storage/src/system/handle_payment.rs b/storage/src/system/handle_payment.rs index c952d8fcfe..b9854da1ed 100644 --- a/storage/src/system/handle_payment.rs +++ b/storage/src/system/handle_payment.rs @@ -6,9 +6,10 @@ pub mod storage_provider; use casper_types::{ system::handle_payment::{Error, REFUND_PURSE_KEY}, - AccessRights, URef, U512, + AccessRights, PublicKey, URef, U512, }; use num_rational::Ratio; +use tracing::error; use crate::system::handle_payment::{ mint_provider::MintProvider, runtime_provider::RuntimeProvider, @@ -43,6 +44,11 @@ pub trait HandlePayment: MintProvider + RuntimeProvider + StorageProvider + Size /// Clear refund purse. fn clear_refund_purse(&mut self) -> Result<(), Error> { + if self.get_caller() != PublicKey::System.to_account_hash() { + error!("invalid caller to clear refund purse"); + return Err(Error::InvalidCaller); + } + self.remove_key(REFUND_PURSE_KEY) } @@ -57,6 +63,11 @@ pub trait HandlePayment: MintProvider + RuntimeProvider + StorageProvider + Size source_purse: URef, refund_ratio: Ratio, ) -> Result<(U512, U512), Error> { + if self.get_caller() != PublicKey::System.to_account_hash() { + error!("invalid caller to calculate overpayment and fee"); + return Err(Error::InvalidCaller); + } + let available_balance = match self.available_balance(source_purse)? { Some(balance) => balance, None => return Err(Error::PaymentPurseBalanceNotFound), @@ -77,11 +88,21 @@ pub trait HandlePayment: MintProvider + RuntimeProvider + StorageProvider + Size source_uref: URef, amount: Option, ) -> Result<(), Error> { + if self.get_caller() != PublicKey::System.to_account_hash() { + error!("invalid caller to distribute accumulated fee"); + return Err(Error::InvalidCaller); + } + internal::distribute_accumulated_fees(self, source_uref, amount) } /// Burns the imputed amount from the imputed purse. - fn burn(&mut self, source_uref: URef, amount: Option) -> Result<(), Error> { - internal::burn(self, source_uref, amount) + fn payment_burn(&mut self, source_uref: URef, amount: Option) -> Result<(), Error> { + if self.get_caller() != PublicKey::System.to_account_hash() { + error!("invalid caller to payment burn"); + return Err(Error::InvalidCaller); + } + + internal::payment_burn(self, source_uref, amount) } } diff --git a/storage/src/system/handle_payment/internal.rs b/storage/src/system/handle_payment/internal.rs index ef6313e159..b6dbf33dba 100644 --- a/storage/src/system/handle_payment/internal.rs +++ b/storage/src/system/handle_payment/internal.rs @@ -4,7 +4,7 @@ use super::{ }; use casper_types::{ system::handle_payment::{Error, PAYMENT_PURSE_KEY, REFUND_PURSE_KEY}, - Key, Phase, PublicKey, URef, U512, + Key, Phase, URef, U512, }; use num::CheckedMul; use num_rational::Ratio; @@ -112,23 +112,22 @@ pub fn calculate_overpayment_and_fee( Ok((adjusted_refund, fee)) } -pub fn burn( +pub fn payment_burn( provider: &mut P, purse: URef, amount: Option, ) -> Result<(), Error> { - // get the purse total balance (without holds) - let total_balance = match provider.available_balance(purse)? { + let available_balance = match provider.available_balance(purse)? { Some(balance) => balance, None => return Err(Error::PaymentPurseBalanceNotFound), }; - let burn_amount = amount.unwrap_or(total_balance); + let burn_amount = amount.unwrap_or(available_balance); if burn_amount.is_zero() { // nothing to burn == noop return Ok(()); } // Reduce the source purse and total supply by the refund amount - let adjusted_balance = total_balance + let adjusted_balance = available_balance .checked_sub(burn_amount) .ok_or(Error::ArithmeticOverflow)?; provider.write_balance(purse, adjusted_balance)?; @@ -152,10 +151,6 @@ where return Err(Error::IncompatiblePaymentSettings); } - if provider.get_caller() != PublicKey::System.to_account_hash() { - return Err(Error::SystemFunctionCalledByUserAccount); - } - let administrative_accounts = provider.administrative_accounts(); let reward_recipients = U512::from(administrative_accounts.len()); diff --git a/storage/src/system/mint.rs b/storage/src/system/mint.rs index 0e0b908453..a9c4387a72 100644 --- a/storage/src/system/mint.rs +++ b/storage/src/system/mint.rs @@ -55,27 +55,25 @@ pub trait Mint: RuntimeProvider + StorageProvider + SystemProvider { /// Burns native tokens. fn burn(&mut self, purse: URef, amount: U512) -> Result<(), Error> { if !purse.is_writeable() { - return Err(Error::ForgedReference); + return Err(Error::InvalidAccessRights); } if !self.is_valid_uref(&purse) { return Err(Error::ForgedReference); } - let source_balance: U512 = match self.balance(purse)? { + let source_available_balance: U512 = match self.balance(purse)? { Some(source_balance) => source_balance, None => return Err(Error::PurseNotFound), }; - let new_balance = match source_balance.checked_sub(amount) { + let new_balance = match source_available_balance.checked_sub(amount) { Some(value) => value, None => U512::zero(), }; - - // source_balance is >= than new_balance - // this should block user from reducing totaly supply beyond what they own - let burned_amount = source_balance - new_balance; - + // change balance self.write_balance(purse, new_balance)?; + // reduce total supply AFTER changing balance in case changing balance errors + let burned_amount = source_available_balance.saturating_sub(new_balance); detail::reduce_total_supply_unsafe(self, burned_amount) } diff --git a/storage/src/system/runtime_native.rs b/storage/src/system/runtime_native.rs index a29f320f43..36a96b1443 100644 --- a/storage/src/system/runtime_native.rs +++ b/storage/src/system/runtime_native.rs @@ -409,7 +409,7 @@ where &mut self.named_keys } - pub fn access_rights(&mut self) -> &ContextAccessRights { + pub fn access_rights(&self) -> &ContextAccessRights { &self.access_rights } diff --git a/types/src/system/handle_payment/error.rs b/types/src/system/handle_payment/error.rs index 7eb8ea5910..b31e509c05 100644 --- a/types/src/system/handle_payment/error.rs +++ b/types/src/system/handle_payment/error.rs @@ -156,13 +156,12 @@ pub enum Error { /// assert_eq!(21, Error::StakesDeserializationFailed as u8); /// ``` StakesDeserializationFailed = 21, - /// The invoked Handle Payment function can only be called by system contracts, but was called - /// by a user contract. + /// Raised when caller is not the system account. /// ``` /// # use casper_types::system::handle_payment::Error; - /// assert_eq!(22, Error::SystemFunctionCalledByUserAccount as u8); + /// assert_eq!(22, Error::InvalidCaller as u8); /// ``` - SystemFunctionCalledByUserAccount = 22, + InvalidCaller = 22, /// Internal error: while finalizing payment, the amount spent exceeded the amount available. /// ``` /// # use casper_types::system::handle_payment::Error; @@ -308,7 +307,7 @@ impl Display for Error { Error::StakesDeserializationFailed => { formatter.write_str("Failed to deserialize stake's balance") } - Error::SystemFunctionCalledByUserAccount => { + Error::InvalidCaller => { formatter.write_str("System function was called by user account") } Error::InsufficientPaymentForAmountSpent => { @@ -387,9 +386,7 @@ impl TryFrom for Error { v if v == Error::StakesDeserializationFailed as u8 => { Error::StakesDeserializationFailed } - v if v == Error::SystemFunctionCalledByUserAccount as u8 => { - Error::SystemFunctionCalledByUserAccount - } + v if v == Error::InvalidCaller as u8 => Error::InvalidCaller, v if v == Error::InsufficientPaymentForAmountSpent as u8 => { Error::InsufficientPaymentForAmountSpent } diff --git a/utils/global-state-update-gen/src/admins.rs b/utils/global-state-update-gen/src/admins.rs index 4a6e08f802..c6833f5be9 100644 --- a/utils/global-state-update-gen/src/admins.rs +++ b/utils/global-state-update-gen/src/admins.rs @@ -35,7 +35,7 @@ pub(crate) fn generate_admins(matches: &ArgMatches<'_>) { let admin_values = matches.values_of("admin").expect("at least one argument"); let protocol_version = DEFAULT_PROTOCOL_VERSION; - let mut total_supply = test_builder.total_supply(Some(post_state_hash), protocol_version); + let mut total_supply = test_builder.total_supply(protocol_version, Some(post_state_hash)); let total_supply_before = total_supply; for value in admin_values {