From a451ca4205671ad9983385bfd62795108490d99e Mon Sep 17 00:00:00 2001 From: Denis Carriere Date: Mon, 8 Apr 2024 23:48:08 +0200 Subject: [PATCH] Implement setmaxsupply ref: https://github.com/eosnetworkfoundation/eos-system-contracts/issues/125 --- .../include/eosio.token/eosio.token.hpp | 9 ++++ .../ricardian/eosio.token.contracts.md.in | 13 +++++ contracts/eosio.token/src/eosio.token.cpp | 19 +++++++ tests/eosio.token_tests.cpp | 49 +++++++++++++++++-- 4 files changed, 87 insertions(+), 3 deletions(-) diff --git a/contracts/eosio.token/include/eosio.token/eosio.token.hpp b/contracts/eosio.token/include/eosio.token/eosio.token.hpp index 8fa49a40..c248e0ad 100644 --- a/contracts/eosio.token/include/eosio.token/eosio.token.hpp +++ b/contracts/eosio.token/include/eosio.token/eosio.token.hpp @@ -60,6 +60,15 @@ namespace eosio { [[eosio::action]] void issuefixed( const name& to, const asset& supply, const string& memo ); + /** + * Set the maximum supply of the token. + * + * @param issuer - the issuer account setting the maximum supply. + * @param maximum_supply - the maximum supply of the token. + */ + [[eosio::action]] + void setmaxsupply( const name& issuer, const asset& maximum_supply ); + /** * The opposite for create action, if all validations succeed, * it debits the statstable.supply amount. diff --git a/contracts/eosio.token/ricardian/eosio.token.contracts.md.in b/contracts/eosio.token/ricardian/eosio.token.contracts.md.in index 2d331bb9..dc857fc1 100644 --- a/contracts/eosio.token/ricardian/eosio.token.contracts.md.in +++ b/contracts/eosio.token/ricardian/eosio.token.contracts.md.in @@ -28,6 +28,19 @@ This action will not result any any tokens being issued into circulation. RAM will deducted from {{$action.account}}’s resources to create the necessary records. +

setmaxsupply

+ +--- +spec_version: "0.2.0" +title: Set Max Supply +summary: 'Set max supply for token' +icon: @ICON_BASE_URL@/@TOKEN_ICON_URI@ +--- + +{{issuer}} will be allowed to issue tokens into circulation, up to a maximum supply of {{maximum_supply}}. + +This action will not result any any tokens being issued into circulation. +

issue

--- diff --git a/contracts/eosio.token/src/eosio.token.cpp b/contracts/eosio.token/src/eosio.token.cpp index 5aa6ec90..e0f73123 100644 --- a/contracts/eosio.token/src/eosio.token.cpp +++ b/contracts/eosio.token/src/eosio.token.cpp @@ -56,6 +56,25 @@ void token::issuefixed( const name& to, const asset& supply, const string& memo issue( to, quantity, memo ); } +void token::setmaxsupply( const name& issuer, const asset& maximum_supply ) +{ + auto sym = maximum_supply.symbol; + check( maximum_supply.is_valid(), "invalid supply"); + check( maximum_supply.amount > 0, "max-supply must be positive"); + + stats statstable( get_self(), sym.code().raw() ); + auto & st = statstable.get( sym.code().raw(), "token supply does not exist" ); + check( issuer == st.issuer, "only issuer can set token maximum supply" ); + require_auth( st.issuer ); + + check( maximum_supply.symbol == st.supply.symbol, "symbol precision mismatch" ); + check( maximum_supply.amount >= st.supply.amount, "max supply is less than available supply"); + + statstable.modify( st, same_payer, [&]( auto& s ) { + s.max_supply = maximum_supply; + }); +} + void token::retire( const asset& quantity, const string& memo ) { auto sym = quantity.symbol; diff --git a/tests/eosio.token_tests.cpp b/tests/eosio.token_tests.cpp index 506501ca..bc1f3266 100644 --- a/tests/eosio.token_tests.cpp +++ b/tests/eosio.token_tests.cpp @@ -78,14 +78,21 @@ class eosio_token_tester : public tester { ); } - action_result issuefixed( account_name issuer, asset supply, string memo ) { - return push_action( issuer, "issuefixed"_n, mvo() - ( "to", issuer) + action_result issuefixed( account_name to, asset supply, string memo ) { + return push_action( to, "issuefixed"_n, mvo() + ( "to", to) ( "supply", supply) ( "memo", memo) ); } + action_result setmaxsupply( account_name issuer, asset maximum_supply ) { + return push_action( issuer, "setmaxsupply"_n, mvo() + ( "issuer", issuer) + ( "maximum_supply", maximum_supply) + ); + } + action_result retire( account_name issuer, asset quantity, string memo ) { return push_action( issuer, "retire"_n, mvo() ( "quantity", quantity) @@ -270,6 +277,42 @@ BOOST_FIXTURE_TEST_CASE( issuefixed_tests, eosio_token_tester ) try { } FC_LOG_AND_RETHROW() +BOOST_FIXTURE_TEST_CASE( setmaxsupply_tests, eosio_token_tester ) try { + + auto token = create( "alice"_n, asset::from_string("1000.000 TKN")); + produce_blocks(1); + + issue( "alice"_n, asset::from_string("1000.000 TKN"), "issue active supply" ); + + BOOST_REQUIRE_EQUAL( wasm_assert_msg( "quantity exceeds available supply" ), + issue( "alice"_n, asset::from_string("1000.000 TKN"), "quantity exceeds available supply" ) + ); + + setmaxsupply( "alice"_n, asset::from_string("2000.000 TKN") ); + + issue( "alice"_n, asset::from_string("1000.000 TKN"), "issue active supply" ); + + auto stats = get_stats("3,TKN"); + // REQUIRE_MATCHING_OBJECT( stats, mvo() + // ("supply", "2000.000 TKN") + // ("max_supply", "2000.000 TKN") + // ("issuer", "alice") + // ); + + BOOST_REQUIRE_EQUAL( wasm_assert_msg( "symbol precision mismatch" ), + setmaxsupply( "alice"_n, asset::from_string("3000 TKN") ) + ); + + BOOST_REQUIRE_EQUAL( wasm_assert_msg( "only issuer can set token maximum supply" ), + setmaxsupply( "bob"_n, asset::from_string("1000.000 TKN") ) + ); + + BOOST_REQUIRE_EQUAL( wasm_assert_msg( "max supply is less than available supply" ), + setmaxsupply( "alice"_n, asset::from_string("1000.000 TKN") ) + ); + +} FC_LOG_AND_RETHROW() + BOOST_FIXTURE_TEST_CASE( retire_tests, eosio_token_tester ) try { auto token = create( "alice"_n, asset::from_string("1000.000 TKN"));