Skip to content
Closed
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
6 changes: 6 additions & 0 deletions libraries/chain/asset_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,12 @@ void_result asset_update_evaluator::do_evaluate(const asset_update_operation& o)
FC_ASSERT(!((o.new_options.flags ^ a.options.flags) & ~a.options.issuer_permissions),
"Flag change is forbidden by issuer permissions");

// TODO HARDFORKCHECK
// maximum supply can only be changed if the disable_modify_max_supply flag is 0
FC_ASSERT( ( a.options.max_supply == o.new_options.max_supply
|| ( a.options.flags & disable_modify_max_supply ) == 0 ),
"Modification of the maximum supply is forbidden" );

asset_to_update = &a;
FC_ASSERT( o.issuer == a.issuer,
"Incorrect issuer for asset! (${o.issuer} != ${a.issuer})",
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/include/graphene/chain/asset_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ namespace graphene { namespace chain {
bool is_transfer_restricted()const { return options.flags & transfer_restricted; }
bool can_override()const { return options.flags & override_authority; }
bool allow_confidential()const { return !(options.flags & asset_issuer_permission_flags::disable_confidential); }
/// @return true if this asset can modify the max supply
bool can_modify_max_supply() const { return !(options.flags & asset_issuer_permission_flags::disable_modify_max_supply); }

/// Helper function to get an asset object with the given amount in this asset's type
asset amount(share_type a)const { return asset(a, id); }
Expand Down
8 changes: 5 additions & 3 deletions libraries/chain/include/graphene/chain/protocol/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,12 @@ namespace graphene { namespace chain {
global_settle = 0x20, /**< allow the bitasset issuer to force a global settling -- this may be set in permissions, but not flags */
disable_confidential = 0x40, /**< allow the asset to be used with confidential transactions */
witness_fed_asset = 0x80, /**< allow the asset to be fed by witnesses */
committee_fed_asset = 0x100 /**< allow the asset to be fed by the committee */
committee_fed_asset = 0x100,/**< allow the asset to be fed by the committee */
disable_modify_max_supply = 0x200 /**< disable the modification of the maximum supply; can only be activated once */
};
const static uint32_t ASSET_ISSUER_PERMISSION_MASK = charge_market_fee|white_list|override_authority|transfer_restricted|disable_force_settle|global_settle|disable_confidential
|witness_fed_asset|committee_fed_asset;
const static uint32_t UIA_ASSET_ISSUER_PERMISSION_MASK = charge_market_fee|white_list|override_authority|transfer_restricted|disable_confidential;
|witness_fed_asset|committee_fed_asset|disable_modify_max_supply;
const static uint32_t UIA_ASSET_ISSUER_PERMISSION_MASK = charge_market_fee|white_list|override_authority|transfer_restricted|disable_confidential|disable_modify_max_supply;

enum reserved_spaces
{
Expand Down Expand Up @@ -417,4 +418,5 @@ FC_REFLECT_ENUM( graphene::chain::asset_issuer_permission_flags,
(disable_confidential)
(witness_fed_asset)
(committee_fed_asset)
(disable_modify_max_supply)
)
127 changes: 127 additions & 0 deletions tests/tests/operation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2357,6 +2357,133 @@ BOOST_AUTO_TEST_CASE( vesting_balance_withdraw_test )
// TODO: Test with non-core asset and Bob account
} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_CASE( disable_modify_max_supply_flag_test )
{
// latest hf
// generate_blocks( HARDFORK_CORE_942_TIME );

ACTOR( alice );
account_id_type committee_acc;
transfer( committee_acc, alice_id, asset(100000000) );

signed_transaction trx;
string SYMBOL = "TEST";
asset_object test_asset;
asset_id_type test_asset_id;

edump( ("Creating an asset disable_modify_max_supply_flag == 0") );
{
asset_options a_opt;
a_opt.max_supply = 1000;
a_opt.core_exchange_rate = price( asset( 4, asset_id_type(1) ), asset( 4, asset_id_type() ) );

asset_create_operation acop;
acop.issuer = alice_id;
acop.symbol = SYMBOL;
acop.common_options = a_opt;

set_expiration(db, trx);
trx.operations.push_back( acop );
PUSH_TX( db, trx, ~0 );

// getting asset_obj from db
const auto& idx = db.get_index_type<asset_index>();
idx.inspect_all_objects( [&](const object& obj){
const asset_object& ao = static_cast<const asset_object&>(obj);
if(ao.symbol == SYMBOL){
test_asset = ao;
test_asset_id = ao.id;
}
} );

BOOST_CHECK( test_asset.can_modify_max_supply() );
}

edump( ( "Modifying the maximum supply. disable_modify_max_supply flag == 0" ) );
{
asset_options a_opt;
a_opt.max_supply = 2000;
a_opt.core_exchange_rate = price( asset(4, asset_id_type(2) ), asset(4, asset_id_type(0) ) );

asset_update_operation auop;
auop.fee = asset(0);
auop.issuer = alice_id;
auop.asset_to_update = test_asset_id;
auop.new_options = a_opt;

trx = signed_transaction();
set_expiration(db, trx);
trx.operations.push_back( auop );
PUSH_TX( db, trx, ~0 );

test_asset = db.get(test_asset_id);
BOOST_CHECK( test_asset.options.max_supply == 2000 );
}

edump( ( "Setting disable_modify_max_supply_flag. disable_modify_max_supply flag == 0x200" ) );
{
asset_options a_opt;
a_opt.max_supply = 2000;
a_opt.core_exchange_rate = price( asset(4, asset_id_type(2) ), asset(4, asset_id_type(0) ) );
a_opt.flags = asset_issuer_permission_flags::disable_modify_max_supply;

asset_update_operation auop;
auop.fee = asset(0);
auop.issuer = alice_id;
auop.asset_to_update = test_asset_id;
auop.new_options = a_opt;

trx = signed_transaction();
set_expiration(db, trx);
trx.operations.push_back( auop );
PUSH_TX( db, trx, ~0 );

test_asset = db.get(test_asset_id);
BOOST_CHECK( ( test_asset.options.flags)// & asset_issuer_permission_flags::disable_modify_max_supply )
== asset_issuer_permission_flags::disable_modify_max_supply );
BOOST_CHECK( !test_asset.can_modify_max_supply() );
}

edump( ( "Trying to disable the disable_modify_max_supply_flag.") );
{
asset_options a_opt;
a_opt.max_supply = 2000;
a_opt.core_exchange_rate = price( asset(4, asset_id_type(2) ), asset(4, asset_id_type(0) ) );
a_opt.flags = 0;

asset_update_operation auop;
auop.fee = asset(0);
auop.issuer = alice_id;
auop.asset_to_update = test_asset.get_id();
auop.new_options = a_opt;

trx = signed_transaction();
set_expiration(db, trx);
trx.operations.push_back( auop );

GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx, ~0 ), fc::exception );
}

edump( ( "Trying to change the maximum supply." ) );
{
asset_options a_opt;
a_opt.max_supply = 1000;
a_opt.core_exchange_rate = price( asset(4, asset_id_type(2) ), asset(4, asset_id_type(0) ) );
a_opt.flags = asset_issuer_permission_flags::disable_modify_max_supply;

asset_update_operation auop;
auop.fee = asset(0);
auop.issuer = alice_id;
auop.asset_to_update = test_asset.get_id();
auop.new_options = a_opt;

trx = signed_transaction();
set_expiration(db, trx);
trx.operations.push_back( auop );

GRAPHENE_REQUIRE_THROW( PUSH_TX( db, trx, ~0 ), fc::exception );
}
}
// TODO: Write linear VBO tests

BOOST_AUTO_TEST_SUITE_END()