594 lines
21 KiB
C++
594 lines
21 KiB
C++
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
|
#include <boost/test/unit_test.hpp>
|
|
#pragma GCC diagnostic pop
|
|
#include <boost/algorithm/string/predicate.hpp>
|
|
#include <eosio/testing/tester.hpp>
|
|
#include <eosio/chain/abi_serializer.hpp>
|
|
#include <eosio/chain/generated_transaction_object.hpp>
|
|
|
|
#include <fc/variant_object.hpp>
|
|
#include <fc/io/json.hpp>
|
|
|
|
#include <contracts.hpp>
|
|
#include <test_contracts.hpp>
|
|
|
|
using namespace eosio;
|
|
using namespace eosio::chain;
|
|
using namespace eosio::testing;
|
|
using namespace fc;
|
|
|
|
class currency_tester : public validating_tester {
|
|
public:
|
|
|
|
auto push_action(const account_name& signer, const action_name &name, const variant_object &data ) {
|
|
string action_type_name = abi_ser.get_action_type(name);
|
|
|
|
action act;
|
|
act.account = "eosio.token"_n;
|
|
act.name = name;
|
|
act.authorization = vector<permission_level>{{signer, config::active_name}};
|
|
act.data = abi_ser.variant_to_binary(action_type_name, data, abi_serializer::create_yield_function( abi_serializer_max_time ));
|
|
|
|
signed_transaction trx;
|
|
trx.actions.emplace_back(std::move(act));
|
|
|
|
set_transaction_headers(trx);
|
|
trx.sign(get_private_key(signer, "active"), control->get_chain_id());
|
|
return push_transaction(trx);
|
|
}
|
|
|
|
asset get_balance(const account_name& account) const {
|
|
return get_currency_balance("eosio.token"_n, symbol(SY(4,CUR)), account);
|
|
}
|
|
|
|
auto transfer(const account_name& from, const account_name& to, const std::string& quantity, const std::string& memo = "") {
|
|
auto trace = push_action(from, "transfer"_n, mutable_variant_object()
|
|
("from", from)
|
|
("to", to)
|
|
("quantity", quantity)
|
|
("memo", memo)
|
|
);
|
|
produce_block();
|
|
return trace;
|
|
}
|
|
|
|
auto issue(const account_name& to, const std::string& quantity, const std::string& memo = "") {
|
|
auto trace = push_action("eosio.token"_n, "issue"_n, mutable_variant_object()
|
|
("to", to)
|
|
("quantity", quantity)
|
|
("memo", memo)
|
|
);
|
|
produce_block();
|
|
return trace;
|
|
}
|
|
|
|
currency_tester(setup_policy p = setup_policy::full)
|
|
:validating_tester({}, nullptr, p), abi_ser(json::from_string(test_contracts::eosio_token_abi()).as<abi_def>(), abi_serializer::create_yield_function( abi_serializer_max_time ))
|
|
{
|
|
create_account( "eosio.token"_n);
|
|
set_code( "eosio.token"_n, test_contracts::eosio_token_wasm() );
|
|
|
|
auto result = push_action("eosio.token"_n, "create"_n, mutable_variant_object()
|
|
("issuer", eosio_token)
|
|
("maximum_supply", "1000000000.0000 CUR")
|
|
("can_freeze", 0)
|
|
("can_recall", 0)
|
|
("can_whitelist", 0)
|
|
);
|
|
wdump((result));
|
|
|
|
result = push_action("eosio.token"_n, "issue"_n, mutable_variant_object()
|
|
("to", eosio_token)
|
|
("quantity", "1000000.0000 CUR")
|
|
("memo", "gggggggggggg")
|
|
);
|
|
wdump((result));
|
|
produce_block();
|
|
}
|
|
|
|
abi_serializer abi_ser;
|
|
static const name eosio_token;
|
|
};
|
|
|
|
class pre_disable_deferred_trx_currency_tester : public currency_tester {
|
|
public:
|
|
pre_disable_deferred_trx_currency_tester() : currency_tester(setup_policy::full_except_do_not_disable_deferred_trx) {}
|
|
};
|
|
|
|
const name currency_tester::eosio_token = "eosio.token"_n;
|
|
|
|
BOOST_AUTO_TEST_SUITE(currency_tests)
|
|
|
|
BOOST_AUTO_TEST_CASE( bootstrap ) try {
|
|
auto expected = asset::from_string( "1000000.0000 CUR" );
|
|
currency_tester t;
|
|
auto actual = t.get_currency_balance("eosio.token"_n, expected.get_symbol(), "eosio.token"_n);
|
|
BOOST_REQUIRE_EQUAL(expected, actual);
|
|
} FC_LOG_AND_RETHROW() /// test_api_bootstrap
|
|
|
|
BOOST_FIXTURE_TEST_CASE( test_transfer, currency_tester ) try {
|
|
create_accounts( {"alice"_n} );
|
|
|
|
// make a transfer from the contract to a user
|
|
{
|
|
auto trace = push_action("eosio.token"_n, "transfer"_n, mutable_variant_object()
|
|
("from", eosio_token)
|
|
("to", "alice")
|
|
("quantity", "100.0000 CUR")
|
|
("memo", "fund Alice")
|
|
);
|
|
|
|
produce_block();
|
|
|
|
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
|
|
BOOST_REQUIRE_EQUAL(get_balance("alice"_n), asset::from_string( "100.0000 CUR" ) );
|
|
}
|
|
} FC_LOG_AND_RETHROW() /// test_transfer
|
|
|
|
BOOST_FIXTURE_TEST_CASE( test_duplicate_transfer, currency_tester ) {
|
|
create_accounts( {"alice"_n} );
|
|
|
|
auto trace = push_action("eosio.token"_n, "transfer"_n, mutable_variant_object()
|
|
("from", eosio_token)
|
|
("to", "alice")
|
|
("quantity", "100.0000 CUR")
|
|
("memo", "fund Alice")
|
|
);
|
|
|
|
BOOST_REQUIRE_THROW(push_action("eosio.token"_n, "transfer"_n, mutable_variant_object()
|
|
("from", eosio_token)
|
|
("to", "alice")
|
|
("quantity", "100.0000 CUR")
|
|
("memo", "fund Alice")),
|
|
tx_duplicate);
|
|
|
|
produce_block();
|
|
|
|
BOOST_CHECK_EQUAL(true, chain_has_transaction(trace->id));
|
|
BOOST_CHECK_EQUAL(get_balance("alice"_n), asset::from_string( "100.0000 CUR" ) );
|
|
}
|
|
|
|
BOOST_FIXTURE_TEST_CASE( test_addtransfer, currency_tester ) try {
|
|
create_accounts( {"alice"_n} );
|
|
|
|
// make a transfer from the contract to a user
|
|
{
|
|
auto trace = push_action("eosio.token"_n, "transfer"_n, mutable_variant_object()
|
|
("from", eosio_token)
|
|
("to", "alice")
|
|
("quantity", "100.0000 CUR")
|
|
("memo", "fund Alice")
|
|
);
|
|
|
|
produce_block();
|
|
|
|
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
|
|
BOOST_REQUIRE_EQUAL(get_balance("alice"_n), asset::from_string( "100.0000 CUR" ));
|
|
}
|
|
|
|
// make a transfer from the contract to a user
|
|
{
|
|
auto trace = push_action("eosio.token"_n, "transfer"_n, mutable_variant_object()
|
|
("from", eosio_token)
|
|
("to", "alice")
|
|
("quantity", "10.0000 CUR")
|
|
("memo", "add Alice")
|
|
);
|
|
|
|
produce_block();
|
|
|
|
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
|
|
BOOST_REQUIRE_EQUAL(get_balance("alice"_n), asset::from_string( "110.0000 CUR" ));
|
|
}
|
|
} FC_LOG_AND_RETHROW() /// test_transfer
|
|
|
|
|
|
BOOST_FIXTURE_TEST_CASE( test_overspend, currency_tester ) try {
|
|
create_accounts( {"alice"_n, "bob"_n} );
|
|
|
|
// make a transfer from the contract to a user
|
|
{
|
|
auto trace = push_action("eosio.token"_n, "transfer"_n, mutable_variant_object()
|
|
("from", eosio_token)
|
|
("to", "alice")
|
|
("quantity", "100.0000 CUR")
|
|
("memo", "fund Alice")
|
|
);
|
|
|
|
produce_block();
|
|
|
|
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
|
|
BOOST_REQUIRE_EQUAL(get_balance("alice"_n), asset::from_string( "100.0000 CUR" ));
|
|
}
|
|
|
|
// Overspend!
|
|
{
|
|
variant_object data = mutable_variant_object()
|
|
("from", "alice")
|
|
("to", "bob")
|
|
("quantity", "101.0000 CUR")
|
|
("memo", "overspend! Alice");
|
|
|
|
BOOST_CHECK_EXCEPTION( push_action("alice"_n, "transfer"_n, data),
|
|
eosio_assert_message_exception, eosio_assert_message_is("overdrawn balance") );
|
|
produce_block();
|
|
|
|
BOOST_REQUIRE_EQUAL(get_balance("alice"_n), asset::from_string( "100.0000 CUR" ));
|
|
BOOST_REQUIRE_EQUAL(get_balance("bob"_n), asset::from_string( "0.0000 CUR" ));
|
|
}
|
|
} FC_LOG_AND_RETHROW() /// test_overspend
|
|
|
|
BOOST_FIXTURE_TEST_CASE( test_fullspend, currency_tester ) try {
|
|
create_accounts( {"alice"_n, "bob"_n} );
|
|
|
|
// make a transfer from the contract to a user
|
|
{
|
|
auto trace = push_action("eosio.token"_n, "transfer"_n, mutable_variant_object()
|
|
("from", eosio_token)
|
|
("to", "alice")
|
|
("quantity", "100.0000 CUR")
|
|
("memo", "fund Alice")
|
|
);
|
|
|
|
produce_block();
|
|
|
|
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
|
|
BOOST_REQUIRE_EQUAL(get_balance("alice"_n), asset::from_string( "100.0000 CUR" ));
|
|
}
|
|
|
|
// Full spend
|
|
{
|
|
variant_object data = mutable_variant_object()
|
|
("from", "alice")
|
|
("to", "bob")
|
|
("quantity", "100.0000 CUR")
|
|
("memo", "all in! Alice");
|
|
|
|
auto trace = push_action("alice"_n, "transfer"_n, data);
|
|
produce_block();
|
|
|
|
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace->id));
|
|
BOOST_REQUIRE_EQUAL(get_balance("alice"_n), asset::from_string( "0.0000 CUR" ));
|
|
BOOST_REQUIRE_EQUAL(get_balance("bob"_n), asset::from_string( "100.0000 CUR" ));
|
|
}
|
|
|
|
} FC_LOG_AND_RETHROW() /// test_fullspend
|
|
|
|
|
|
|
|
BOOST_FIXTURE_TEST_CASE(test_symbol, validating_tester) try {
|
|
|
|
{
|
|
symbol dollar(2, "DLLR");
|
|
BOOST_REQUIRE_EQUAL(SY(2, DLLR), dollar.value());
|
|
BOOST_REQUIRE_EQUAL(2, dollar.decimals());
|
|
BOOST_REQUIRE_EQUAL(100, dollar.precision());
|
|
BOOST_REQUIRE_EQUAL("DLLR", dollar.name());
|
|
BOOST_REQUIRE_EQUAL(true, dollar.valid());
|
|
}
|
|
|
|
{
|
|
symbol sys(4, "SYS");
|
|
BOOST_REQUIRE_EQUAL(SY(4,SYS), sys.value());
|
|
BOOST_REQUIRE_EQUAL("4,SYS", sys.to_string());
|
|
BOOST_REQUIRE_EQUAL("SYS", sys.name());
|
|
BOOST_REQUIRE_EQUAL(4, sys.decimals());
|
|
}
|
|
|
|
// default is "4,${CORE_SYMBOL_NAME}"
|
|
{
|
|
symbol def;
|
|
BOOST_REQUIRE_EQUAL(4, def.decimals());
|
|
BOOST_REQUIRE_EQUAL(CORE_SYMBOL_NAME, def.name());
|
|
}
|
|
// from string
|
|
{
|
|
symbol y = symbol::from_string("3,YEN");
|
|
BOOST_REQUIRE_EQUAL(3, y.decimals());
|
|
BOOST_REQUIRE_EQUAL("YEN", y.name());
|
|
}
|
|
|
|
// from empty string
|
|
{
|
|
BOOST_CHECK_EXCEPTION(symbol::from_string(""),
|
|
symbol_type_exception, fc_exception_message_is("creating symbol from empty string"));
|
|
}
|
|
|
|
// precision part missing
|
|
{
|
|
BOOST_CHECK_EXCEPTION(symbol::from_string("RND"),
|
|
symbol_type_exception, fc_exception_message_is("missing comma in symbol"));
|
|
}
|
|
|
|
// 0 decimals part
|
|
{
|
|
symbol sym = symbol::from_string("0,EURO");
|
|
BOOST_REQUIRE_EQUAL(0, sym.decimals());
|
|
BOOST_REQUIRE_EQUAL("EURO", sym.name());
|
|
}
|
|
|
|
// invalid - contains lower case characters, no validation
|
|
{
|
|
BOOST_CHECK_EXCEPTION(symbol malformed(SY(6,EoS)),
|
|
symbol_type_exception, fc_exception_message_is("invalid symbol: EoS"));
|
|
}
|
|
|
|
// invalid - contains lower case characters, exception thrown
|
|
{
|
|
BOOST_CHECK_EXCEPTION(symbol(5,"EoS"),
|
|
symbol_type_exception, fc_exception_message_is("invalid character in symbol name"));
|
|
}
|
|
|
|
// Missing decimal point, should create asset with 0 decimals
|
|
{
|
|
asset a = asset::from_string("10 CUR");
|
|
BOOST_REQUIRE_EQUAL(a.get_amount(), 10);
|
|
BOOST_REQUIRE_EQUAL(a.precision(), 1);
|
|
BOOST_REQUIRE_EQUAL(a.decimals(), 0);
|
|
BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
|
|
}
|
|
|
|
// Missing space
|
|
{
|
|
BOOST_CHECK_EXCEPTION(asset::from_string("10CUR"),
|
|
asset_type_exception, fc_exception_message_is("Asset's amount and symbol should be separated with space"));
|
|
}
|
|
|
|
// Precision is not specified when decimal separator is introduced
|
|
{
|
|
BOOST_CHECK_EXCEPTION(asset::from_string("10. CUR"),
|
|
asset_type_exception, fc_exception_message_is("Missing decimal fraction after decimal point"));
|
|
}
|
|
|
|
// Missing symbol
|
|
{
|
|
BOOST_CHECK_EXCEPTION(asset::from_string("10"),
|
|
asset_type_exception, fc_exception_message_is("Asset's amount and symbol should be separated with space"));
|
|
}
|
|
|
|
// Multiple spaces
|
|
{
|
|
asset a = asset::from_string("1000000000.00000 CUR");
|
|
BOOST_REQUIRE_EQUAL(a.get_amount(), 100000000000000);
|
|
BOOST_REQUIRE_EQUAL(a.decimals(), 5);
|
|
BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
|
|
BOOST_REQUIRE_EQUAL(a.to_string(), "1000000000.00000 CUR");
|
|
}
|
|
|
|
// Valid asset
|
|
{
|
|
asset a = asset::from_string("1000000000.00000 CUR");
|
|
BOOST_REQUIRE_EQUAL(a.get_amount(), 100000000000000);
|
|
BOOST_REQUIRE_EQUAL(a.decimals(), 5);
|
|
BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
|
|
BOOST_REQUIRE_EQUAL(a.to_string(), "1000000000.00000 CUR");
|
|
}
|
|
|
|
// Negative asset
|
|
{
|
|
asset a = asset::from_string("-001000000.00010 CUR");
|
|
BOOST_REQUIRE_EQUAL(a.get_amount(), -100000000010);
|
|
BOOST_REQUIRE_EQUAL(a.decimals(), 5);
|
|
BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
|
|
BOOST_REQUIRE_EQUAL(a.to_string(), "-1000000.00010 CUR");
|
|
}
|
|
|
|
// Negative asset below 1
|
|
{
|
|
asset a = asset::from_string("-000000000.00100 CUR");
|
|
BOOST_REQUIRE_EQUAL(a.get_amount(), -100);
|
|
BOOST_REQUIRE_EQUAL(a.decimals(), 5);
|
|
BOOST_REQUIRE_EQUAL(a.symbol_name(), "CUR");
|
|
BOOST_REQUIRE_EQUAL(a.to_string(), "-0.00100 CUR");
|
|
}
|
|
|
|
// Negative asset below 1
|
|
{
|
|
asset a = asset::from_string("-0.0001 PPP");
|
|
BOOST_REQUIRE_EQUAL(a.get_amount(), -1);
|
|
BOOST_REQUIRE_EQUAL(a.decimals(), 4);
|
|
BOOST_REQUIRE_EQUAL(a.symbol_name(), "PPP");
|
|
BOOST_REQUIRE_EQUAL(a.to_string(), "-0.0001 PPP");
|
|
}
|
|
|
|
} FC_LOG_AND_RETHROW() /// test_symbol
|
|
|
|
BOOST_FIXTURE_TEST_CASE( test_proxy_deferred, pre_disable_deferred_trx_currency_tester ) try {
|
|
produce_blocks(2);
|
|
|
|
create_accounts( {"alice"_n, "proxy"_n} );
|
|
produce_block();
|
|
|
|
set_code("proxy"_n, test_contracts::proxy_wasm());
|
|
produce_blocks(1);
|
|
|
|
abi_serializer proxy_abi_ser(json::from_string(test_contracts::proxy_abi()).as<abi_def>(), abi_serializer::create_yield_function( abi_serializer_max_time ));
|
|
|
|
// set up proxy owner
|
|
{
|
|
signed_transaction trx;
|
|
action setowner_act;
|
|
setowner_act.account = "proxy"_n;
|
|
setowner_act.name = "setowner"_n;
|
|
setowner_act.authorization = vector<permission_level>{{"proxy"_n, config::active_name}};
|
|
setowner_act.data = proxy_abi_ser.variant_to_binary("setowner", mutable_variant_object()
|
|
("owner", "alice")
|
|
("delay", 10),
|
|
abi_serializer::create_yield_function( abi_serializer_max_time )
|
|
);
|
|
trx.actions.emplace_back(std::move(setowner_act));
|
|
|
|
set_transaction_headers(trx);
|
|
trx.sign(get_private_key("proxy"_n, "active"), control->get_chain_id());
|
|
push_transaction(trx);
|
|
produce_block();
|
|
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
|
|
}
|
|
|
|
// for now wasm "time" is in seconds, so we have to truncate off any parts of a second that may have applied
|
|
fc::time_point expected_delivery(fc::seconds(control->head_block_time().sec_since_epoch()) + fc::seconds(10));
|
|
{
|
|
auto trace = push_action("eosio.token"_n, "transfer"_n, mutable_variant_object()
|
|
("from", eosio_token)
|
|
("to", "proxy")
|
|
("quantity", "5.0000 CUR")
|
|
("memo", "fund Proxy")
|
|
);
|
|
}
|
|
|
|
while(control->head_block_time() < expected_delivery) {
|
|
produce_block();
|
|
BOOST_REQUIRE_EQUAL(get_balance( "proxy"_n), asset::from_string("5.0000 CUR"));
|
|
BOOST_REQUIRE_EQUAL(get_balance( "alice"_n), asset::from_string("0.0000 CUR"));
|
|
}
|
|
|
|
produce_block();
|
|
BOOST_REQUIRE_EQUAL(get_balance( "proxy"_n), asset::from_string("0.0000 CUR"));
|
|
BOOST_REQUIRE_EQUAL(get_balance( "alice"_n), asset::from_string("5.0000 CUR"));
|
|
|
|
} FC_LOG_AND_RETHROW() /// test_proxy_deferred
|
|
|
|
BOOST_FIXTURE_TEST_CASE( test_deferred_failure, pre_disable_deferred_trx_currency_tester ) try {
|
|
produce_blocks(2);
|
|
|
|
create_accounts( {"alice"_n, "bob"_n, "proxy"_n} );
|
|
produce_block();
|
|
|
|
set_code("proxy"_n, test_contracts::proxy_wasm());
|
|
set_code("bob"_n, test_contracts::proxy_wasm());
|
|
produce_blocks(1);
|
|
|
|
abi_serializer proxy_abi_ser(json::from_string(test_contracts::proxy_abi()).as<abi_def>(), abi_serializer::create_yield_function( abi_serializer_max_time ));
|
|
|
|
// set up proxy owner
|
|
{
|
|
signed_transaction trx;
|
|
action setowner_act;
|
|
setowner_act.account = "proxy"_n;
|
|
setowner_act.name = "setowner"_n;
|
|
setowner_act.authorization = vector<permission_level>{{"proxy"_n, config::active_name}};
|
|
setowner_act.data = proxy_abi_ser.variant_to_binary("setowner", mutable_variant_object()
|
|
("owner", "bob")
|
|
("delay", 10),
|
|
abi_serializer::create_yield_function( abi_serializer_max_time )
|
|
);
|
|
trx.actions.emplace_back(std::move(setowner_act));
|
|
|
|
set_transaction_headers(trx);
|
|
trx.sign(get_private_key("proxy"_n, "active"), control->get_chain_id());
|
|
push_transaction(trx);
|
|
produce_block();
|
|
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
|
|
}
|
|
const auto& index = control->db().get_index<generated_transaction_multi_index,by_trx_id>();
|
|
BOOST_REQUIRE_EQUAL(0, index.size());
|
|
|
|
auto trace = push_action("eosio.token"_n, "transfer"_n, mutable_variant_object()
|
|
("from", eosio_token)
|
|
("to", "proxy")
|
|
("quantity", "5.0000 CUR")
|
|
("memo", "fund Proxy")
|
|
);
|
|
fc::time_point expected_delivery = control->pending_block_time() + fc::seconds(10);
|
|
|
|
BOOST_REQUIRE_EQUAL(1, index.size());
|
|
auto deferred_id = index.begin()->trx_id;
|
|
BOOST_REQUIRE_EQUAL(false, chain_has_transaction(deferred_id));
|
|
|
|
while( control->pending_block_time() < expected_delivery ) {
|
|
produce_block();
|
|
BOOST_REQUIRE_EQUAL(get_balance( "proxy"_n), asset::from_string("5.0000 CUR"));
|
|
BOOST_REQUIRE_EQUAL(get_balance( "bob"_n), asset::from_string("0.0000 CUR"));
|
|
BOOST_REQUIRE_EQUAL(1, index.size());
|
|
BOOST_REQUIRE_EQUAL(false, chain_has_transaction(deferred_id));
|
|
}
|
|
|
|
fc::time_point expected_redelivery = control->pending_block_time() + fc::seconds(10);
|
|
// First deferred transaction should be retired in this block.
|
|
// It will fail, and its onerror handler will reschedule the transaction for 10 seconds later.
|
|
produce_block();
|
|
BOOST_REQUIRE_EQUAL(1, index.size()); // Still one because the first deferred transaction retires but the second is created at the same time.
|
|
BOOST_REQUIRE_EQUAL(get_transaction_receipt(deferred_id).status, transaction_receipt::soft_fail);
|
|
auto deferred2_id = index.begin()->trx_id;
|
|
|
|
// set up alice owner
|
|
{
|
|
signed_transaction trx;
|
|
action setowner_act;
|
|
setowner_act.account = "bob"_n;
|
|
setowner_act.name = "setowner"_n;
|
|
setowner_act.authorization = vector<permission_level>{{"bob"_n, config::active_name}};
|
|
setowner_act.data = proxy_abi_ser.variant_to_binary("setowner", mutable_variant_object()
|
|
("owner", "alice")
|
|
("delay", 0),
|
|
abi_serializer::create_yield_function( abi_serializer_max_time )
|
|
);
|
|
trx.actions.emplace_back(std::move(setowner_act));
|
|
|
|
set_transaction_headers(trx);
|
|
trx.sign(get_private_key("bob"_n, "active"), control->get_chain_id());
|
|
push_transaction(trx);
|
|
produce_block();
|
|
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
|
|
}
|
|
|
|
while( control->pending_block_time() < expected_redelivery ) {
|
|
produce_block();
|
|
BOOST_REQUIRE_EQUAL(get_balance( "proxy"_n), asset::from_string("5.0000 CUR"));
|
|
BOOST_REQUIRE_EQUAL(get_balance( "alice"_n), asset::from_string("0.0000 CUR"));
|
|
BOOST_REQUIRE_EQUAL(get_balance( "bob"_n), asset::from_string("0.0000 CUR"));
|
|
BOOST_REQUIRE_EQUAL(1, index.size());
|
|
BOOST_REQUIRE_EQUAL(false, chain_has_transaction(deferred2_id));
|
|
}
|
|
|
|
BOOST_REQUIRE_EQUAL(1, index.size());
|
|
|
|
// Second deferred transaction should be retired in this block and should succeed,
|
|
// which should move tokens from the proxy contract to the bob contract, thereby trigger the bob contract to
|
|
// schedule a third deferred transaction with no delay.
|
|
// That third deferred transaction (which moves tokens from the bob contract to account alice) should be executed immediately
|
|
// after in the same block (note that this is the current deferred transaction scheduling policy in tester and it may change).
|
|
produce_block();
|
|
BOOST_REQUIRE_EQUAL(0, index.size());
|
|
BOOST_REQUIRE_EQUAL(get_transaction_receipt(deferred2_id).status, transaction_receipt::executed);
|
|
|
|
BOOST_REQUIRE_EQUAL(get_balance( "proxy"_n), asset::from_string("0.0000 CUR"));
|
|
BOOST_REQUIRE_EQUAL(get_balance( "alice"_n), asset::from_string("5.0000 CUR"));
|
|
BOOST_REQUIRE_EQUAL(get_balance( "bob"_n), asset::from_string("0.0000 CUR"));
|
|
|
|
} FC_LOG_AND_RETHROW() /// test_currency
|
|
|
|
BOOST_FIXTURE_TEST_CASE( test_input_quantity, currency_tester ) try {
|
|
|
|
produce_blocks(2);
|
|
|
|
create_accounts( {"alice"_n, "bob"_n, "carl"_n} );
|
|
|
|
// transfer to alice using right precision
|
|
{
|
|
auto trace = transfer(eosio_token, "alice"_n, "100.0000 CUR");
|
|
|
|
BOOST_CHECK_EQUAL(true, chain_has_transaction(trace->id));
|
|
BOOST_CHECK_EQUAL(asset::from_string( "100.0000 CUR"), get_balance("alice"_n));
|
|
BOOST_CHECK_EQUAL(1000000, get_balance("alice"_n).get_amount());
|
|
}
|
|
|
|
// transfer using different symbol name fails
|
|
{
|
|
BOOST_REQUIRE_THROW(transfer("alice"_n, "carl"_n, "20.50 USD"), eosio_assert_message_exception);
|
|
}
|
|
|
|
// issue to alice using right precision
|
|
{
|
|
auto trace = issue("alice"_n, "25.0256 CUR");
|
|
|
|
BOOST_CHECK_EQUAL(true, chain_has_transaction(trace->id));
|
|
BOOST_CHECK_EQUAL(asset::from_string("125.0256 CUR"), get_balance("alice"_n));
|
|
}
|
|
|
|
|
|
} FC_LOG_AND_RETHROW() /// test_currency
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|