未验证 提交 d1b5dfd6 编写于 作者: W wanderingbort 提交者: GitHub

Merge pull request #1201 from EOSIO/eos-noon-symbol

Separated asset symbol into an independent class
......@@ -11,30 +11,15 @@ namespace eosio { namespace chain {
typedef boost::multiprecision::int128_t int128_t;
uint8_t asset::decimals()const {
auto a = (const char*)&symbol;
return a[0];
}
void asset::set_decimals(uint8_t d){
auto a = (char*)&symbol;
a[0] = d;
return sym.decimals();
}
string asset::symbol_name()const {
auto a = (const char*)&symbol;
assert( a[7] == 0 );
return &a[1];
return sym.name();
}
int64_t asset::precision()const {
static int64_t table[] = {
1, 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000ll,
1000000000ll, 10000000000ll,
100000000000ll, 1000000000000ll,
10000000000000ll, 100000000000000ll
};
return table[ decimals() ];
return sym.precision();
}
string asset::to_string()const {
......@@ -49,118 +34,35 @@ string asset::to_string()const {
asset asset::from_string(const string& from)
{
try
{
string s = fc::trim( from );
auto space_pos = s.find( " " );
auto dot_pos = s.find( "." );
try {
string s = fc::trim(from);
auto dot_pos = s.find(".");
FC_ASSERT(dot_pos != string::npos, "dot missing in asset from string");
auto space_pos = s.find(" ", dot_pos);
FC_ASSERT(space_pos != string::npos, "space missing in asset from string");
asset result;
result.symbol = uint64_t(0);
auto sy = (char*)&result.symbol;
*sy = (char) dot_pos; // Mask due to undefined architecture behavior
auto intpart = s.substr( 0, dot_pos );
auto intpart = s.substr(0, dot_pos);
result.amount = fc::to_int64(intpart);
string fractpart;
if( dot_pos != string::npos )
{
auto fractpart = "1" + s.substr( dot_pos + 1, space_pos - dot_pos - 1 );
result.set_decimals( fractpart.size() - 1 );
string symbol_part;
if (dot_pos != string::npos && space_pos != string::npos) {
symbol_part = eosio::chain::to_string(space_pos - dot_pos - 1);
symbol_part += ',';
symbol_part += s.substr(space_pos + 1);
}
result.sym = symbol::from_string(symbol_part);
if (dot_pos != string::npos) {
auto fractpart = "1" + s.substr(dot_pos + 1, space_pos - dot_pos - 1);
result.amount *= int64_t(result.precision());
result.amount += int64_t(fc::to_int64(fractpart));
result.amount -= int64_t(result.precision());
}
auto symbol = s.substr( space_pos + 1 );
if( symbol.size() )
memcpy( sy+1, symbol.c_str(), std::min(symbol.size(),size_t(6)) );
return result;
}
FC_CAPTURE_LOG_AND_RETHROW( (from) )
}
bool operator == ( const price& a, const price& b )
{
if( std::tie( a.base.symbol, a.quote.symbol ) != std::tie( b.base.symbol, b.quote.symbol ) )
return false;
const auto amult = uint128_t( b.quote.amount ) * uint128_t(a.base.amount);
const auto bmult = uint128_t( a.quote.amount ) * uint128_t(b.base.amount);
return amult == bmult;
}
bool operator < ( const price& a, const price& b )
{
if( a.base.symbol < b.base.symbol ) return true;
if( a.base.symbol > b.base.symbol ) return false;
if( a.quote.symbol < b.quote.symbol ) return true;
if( a.quote.symbol > b.quote.symbol ) return false;
const auto amult = uint128_t( b.quote.amount ) * uint128_t(a.base.amount);
const auto bmult = uint128_t( a.quote.amount ) * uint128_t(b.base.amount);
return amult < bmult;
}
bool operator <= ( const price& a, const price& b )
{
return (a == b) || (a < b);
}
bool operator != ( const price& a, const price& b )
{
return !(a == b);
}
bool operator > ( const price& a, const price& b )
{
return !(a <= b);
}
bool operator >= ( const price& a, const price& b )
{
return !(a < b);
}
asset operator * ( const asset& a, const price& b )
{
if( a.symbol_name() == b.base.symbol_name() )
{
FC_ASSERT( static_cast<int64_t>(b.base.amount) > 0 );
auto result = (uint128_t(a.amount) * uint128_t(b.quote.amount))/uint128_t(b.base.amount);
return asset( int64_t(result), b.quote.symbol );
}
else if( a.symbol_name() == b.quote.symbol_name() )
{
FC_ASSERT( static_cast<int64_t>(b.quote.amount) > 0 );
auto result = (uint128_t(a.amount) *uint128_t(b.base.amount))/uint128_t(b.quote.amount);
return asset( int64_t(result), b.base.symbol );
}
FC_THROW_EXCEPTION( fc::assert_exception, "invalid asset * price", ("asset",a)("price",b) );
}
price operator / ( const asset& base, const asset& quote )
try {
FC_ASSERT( base.symbol_name() != quote.symbol_name() );
return price{ base, quote };
} FC_CAPTURE_AND_RETHROW( (base)(quote) )
price price::max( asset_symbol base, asset_symbol quote ) { return asset( share_type(EOS_MAX_SHARE_SUPPLY), base ) / asset( share_type(1), quote); }
price price::min( asset_symbol base, asset_symbol quote ) { return asset( 1, base ) / asset( EOS_MAX_SHARE_SUPPLY, quote); }
bool price::is_null() const { return *this == price(); }
void price::validate() const
try {
FC_ASSERT( base.amount > share_type(0) );
FC_ASSERT( quote.amount > share_type(0) );
FC_ASSERT( base.symbol_name() != quote.symbol_name() );
} FC_CAPTURE_AND_RETHROW( (base)(quote) )
} } // eosio::types
\ No newline at end of file
} } // eosio::types
......@@ -52,9 +52,11 @@ namespace eosio { namespace chain { namespace contracts {
//public_key.hpp
built_in_types.emplace("public_key", pack_unpack<public_key_type>());
//symbol.hpp
built_in_types.emplace("symbol", pack_unpack<symbol>());
//asset.hpp
built_in_types.emplace("asset", pack_unpack<asset>());
built_in_types.emplace("price", pack_unpack<price>());
//native.hpp
built_in_types.emplace("string", pack_unpack<string>());
......
......@@ -312,7 +312,7 @@ std::vector<action> chain_initializer::prepare_database( chain_controller& chain
messages_to_process.emplace_back(move(message));
if (acct.liquid_balance > 0) {
if (acct.liquid_balance > asset(0)) {
message = action( {{config::system_account_name, config::active_name}},
transfer{ .from = config::system_account_name, .to = acct.name,
.amount = acct.liquid_balance.amount, .memo = "Genesis Allocation"});
......
......@@ -5,58 +5,68 @@
#pragma once
#include <fc/exception/exception.hpp>
#include <eosio/chain/types.hpp>
#include <eosio/chain/symbol.hpp>
/// eos with 8 digits of precision
#define EOS_SYMBOL (int64_t(4) | (uint64_t('E') << 8) | (uint64_t('O') << 16) | (uint64_t('S') << 24))
#define EOS_SYMBOL_VALUE (int64_t(4) | (uint64_t('E') << 8) | (uint64_t('O') << 16) | (uint64_t('S') << 24))
static const eosio::chain::symbol EOS_SYMBOL(EOS_SYMBOL_VALUE);
/// Defined to be largest power of 10 that fits in 53 bits of precision
#define EOS_MAX_SHARE_SUPPLY int64_t(1'000'000'000'000'000ll)
namespace eosio { namespace chain {
using asset_symbol = uint64_t;
/**
asset includes amount and currency symbol
asset::from_string takes a string of the form "10.0000 CUR" and constructs an asset
with amount = 10 and symbol(4,"CUR")
*/
struct asset
{
asset(share_type a = 0, asset_symbol id = EOS_SYMBOL)
:amount(a),symbol(id){}
explicit asset(share_type a = 0, symbol id = EOS_SYMBOL)
:amount(a), sym(id){}
share_type amount;
asset_symbol symbol;
share_type amount;
symbol sym;
double to_real()const { return static_cast<double>(amount) / precision(); }
uint8_t decimals()const;
string symbol_name()const;
int64_t precision()const;
void set_decimals(uint8_t d);
const symbol& symbol() const { return sym; }
static asset from_string(const string& from);
string to_string()const;
asset& operator += (const asset& o)
{
FC_ASSERT(symbol == o.symbol);
FC_ASSERT(symbol() == o.symbol());
amount += o.amount;
return *this;
}
asset& operator -= (const asset& o)
{
FC_ASSERT(symbol == o.symbol);
FC_ASSERT(symbol() == o.symbol());
amount -= o.amount;
return *this;
}
asset operator -()const { return asset(-amount, symbol); }
asset operator -()const { return asset(-amount, symbol()); }
friend bool operator == (const asset& a, const asset& b)
{
return std::tie(a.symbol, a.amount) == std::tie(b.symbol, b.amount);
return std::tie(a.symbol(), a.amount) == std::tie(b.symbol(), b.amount);
}
friend bool operator < (const asset& a, const asset& b)
{
FC_ASSERT(a.symbol == b.symbol);
return std::tie(a.amount,a.symbol) < std::tie(b.amount,b.symbol);
FC_ASSERT(a.symbol() == b.symbol());
return std::tie(a.amount,a.symbol()) < std::tie(b.amount,b.symbol());
}
friend bool operator <= (const asset& a, const asset& b) { return (a == b) || (a < b); }
friend bool operator != (const asset& a, const asset& b) { return !(a == b); }
......@@ -64,51 +74,21 @@ struct asset
friend bool operator >= (const asset& a, const asset& b) { return !(a < b); }
friend asset operator - (const asset& a, const asset& b) {
FC_ASSERT(a.symbol == b.symbol);
return asset(a.amount - b.amount, a.symbol);
FC_ASSERT(a.symbol() == b.symbol());
return asset(a.amount - b.amount, a.symbol());
}
friend asset operator + (const asset& a, const asset& b) {
FC_ASSERT(a.symbol == b.symbol);
return asset(a.amount + b.amount, a.symbol);
FC_ASSERT(a.symbol() == b.symbol());
return asset(a.amount + b.amount, a.symbol());
}
friend std::ostream& operator << (std::ostream& out, const asset& a) { return out << a.to_string(); }
};
struct price
{
asset base;
asset quote;
price(const asset& base = asset(), const asset quote = asset())
:base(base),quote(quote){}
static price max(asset_symbol base, asset_symbol quote);
static price min(asset_symbol base, asset_symbol quote);
price max()const { return price::max(base.symbol, quote.symbol); }
price min()const { return price::min(base.symbol, quote.symbol); }
double to_real()const { return base.to_real() / quote.to_real(); }
bool is_null()const;
void validate()const;
};
price operator / (const asset& base, const asset& quote);
inline price operator~(const price& p) { return price{p.quote,p.base}; }
bool operator < (const asset& a, const asset& b);
bool operator <= (const asset& a, const asset& b);
bool operator < (const price& a, const price& b);
bool operator <= (const price& a, const price& b);
bool operator > (const price& a, const price& b);
bool operator >= (const price& a, const price& b);
bool operator == (const price& a, const price& b);
bool operator != (const price& a, const price& b);
asset operator * (const asset& a, const price& b);
}} // namespace eosio::chain
......@@ -119,5 +99,4 @@ inline void from_variant(const fc::variant& var, eosio::chain::asset& vo) {
}
}
FC_REFLECT(eosio::chain::asset, (amount)(symbol))
FC_REFLECT(eosio::chain::price, (base)(quote))
FC_REFLECT(eosio::chain::asset, (amount)(sym))
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <fc/exception/exception.hpp>
#include <eosio/chain/types.hpp>
#include <string>
#include <functional>
namespace eosio {
namespace chain {
/**
class symbol represents a token and contains precision and name.
When encoded as a uint64_t, first byte represents the number of decimals, remaining bytes
represent token name.
Name must only include upper case alphabets.
from_string constructs a symbol from an input a string of the form "4,EOS"
where the integer represents number of decimals. Number of decimals must be larger than zero.
*/
static constexpr uint64_t string_to_symbol_c(uint8_t precision, const char* str) {
uint32_t len = 0;
while (str[len]) ++len;
uint64_t result = 0;
// No validation is done at compile time
for (uint32_t i = 0; i < len; ++i) {
result |= (uint64_t(str[i]) << (8*(1+i)));
}
result |= uint64_t(precision);
return result;
}
#define SY(P,X) ::eosio::chain::string_to_symbol_c(P,#X)
static uint64_t string_to_symbol(uint8_t precision, const char* str) {
try {
uint32_t len = 0;
while(str[len]) ++len;
uint64_t result = 0;
for (uint32_t i = 0; i < len; ++i) {
// All characters must be upper case alaphabets
FC_ASSERT (str[i] >= 'A' && str[i] <= 'Z', "invalid character in symbol name");
result |= (uint64_t(str[i]) << (8*(i+1)));
}
result |= uint64_t(precision);
return result;
} FC_CAPTURE_LOG_AND_RETHROW((str))
}
class symbol {
public:
explicit symbol(uint8_t p, const char* s): m_value(string_to_symbol(p, s)) { }
explicit symbol(uint64_t v = SY(4, EOS)): m_value(v) { }
static symbol from_string(const string& from)
{
try {
string s = fc::trim(from);
FC_ASSERT(!s.empty(), "creating symbol from empty string");
auto comma_pos = s.find(',');
FC_ASSERT(comma_pos != string::npos, "missing comma in symbol");
auto prec_part = s.substr(0, comma_pos);
uint8_t p = fc::to_int64(prec_part);
FC_ASSERT(p > 0, "zero decimals in symbol");
string name_part = s.substr(comma_pos + 1);
return symbol(string_to_symbol(p, name_part.c_str()));
} FC_CAPTURE_LOG_AND_RETHROW((from))
}
uint64_t value() const { return m_value; }
bool valid() const
{
if (decimals() == 0) return false;
const auto& s = name();
return valid_name(s);
}
static bool valid_name(const string& name)
{
return all_of(name.begin(), name.end(), [](char c)->bool { return (c >= 'A' && c <= 'Z'); });
}
uint8_t decimals() const { return m_value & 0xFF; }
uint64_t precision() const
{
static int64_t table[] = {
1, 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000ll,
1000000000ll, 10000000000ll,
100000000000ll, 1000000000000ll,
10000000000000ll, 100000000000000ll
};
return table[ decimals() ];
}
string name() const
{
uint64_t v = m_value;
v >>= 8;
string result;
while (v > 0) {
char c = v & 0xFF;
result += c;
v >>= 8;
}
return result;
}
explicit operator string() const
{
uint64_t v = m_value;
uint8_t p = v & 0xFF;
string ret = eosio::chain::to_string(p);
ret += ',';
ret += name();
return ret;
}
string to_string() const { return string(*this); }
template <typename DataStream>
friend DataStream& operator<< (DataStream& ds, const symbol& s)
{
return ds << s.to_string();
}
private:
uint64_t m_value;
friend struct fc::reflector<symbol>;
}; // class symbol
inline bool operator== (const symbol& lhs, const symbol& rhs)
{
return lhs.value() == rhs.value();
}
inline bool operator!= (const symbol& lhs, const symbol& rhs)
{
return lhs.value() != rhs.value();
}
inline bool operator< (const symbol& lhs, const symbol& rhs)
{
return lhs.value() < rhs.value();
}
inline bool operator> (const symbol& lhs, const symbol& rhs)
{
return lhs.value() > rhs.value();
}
} // namespace chain
} // namespace eosio
namespace fc {
inline void to_variant(const eosio::chain::symbol& var, fc::variant& vo) { vo = var.to_string(); }
inline void from_variant(const fc::variant& var, eosio::chain::symbol& vo) {
vo = eosio::chain::symbol::from_string(var.get_string());
}
}
FC_REFLECT(eosio::chain::symbol, (m_value))
......@@ -61,6 +61,8 @@ namespace eosio { namespace chain {
using std::make_pair;
using std::move;
using std::forward;
using std::to_string;
using std::all_of;
using fc::path;
using fc::smart_ref;
......
......@@ -59,7 +59,7 @@ namespace eosio { namespace testing {
share_type get_balance( const account_name& account ) const;
asset get_currency_balance( const account_name& contract,
const asset_symbol& symbol,
const symbol& asset_symbol,
const account_name& account ) const;
private:
......
......@@ -252,21 +252,21 @@ namespace eosio { namespace testing {
* Reads balance as stored by generic_currency contract
*/
asset tester::get_currency_balance( const account_name& code,
const asset_symbol& symbol,
const account_name& account ) const {
const symbol& asset_symbol,
const account_name& account ) const {
const auto& db = control->get_database();
const auto* tbl = db.find<contracts::table_id_object, contracts::by_scope_code_table>(boost::make_tuple(account, code, N(account)));
share_type result = 0;
// the balance is implied to be 0 if either the table or row does not exist
if (tbl) {
const auto *obj = db.find<contracts::key_value_object, contracts::by_scope_primary>(boost::make_tuple(tbl->id, symbol));
const auto *obj = db.find<contracts::key_value_object, contracts::by_scope_primary>(boost::make_tuple(tbl->id, asset_symbol.value()));
if (obj) {
fc::datastream<const char *> ds(obj->value.data(), obj->value.size());
fc::raw::unpack(ds, result);
}
}
return asset(result, symbol);
return asset(result, asset_symbol);
}
......
......@@ -337,10 +337,10 @@ vector<asset> read_only::get_currency_balance( const read_only::get_currency_bal
share_type balance;
fc::datastream<const char *> ds(obj.value.data(), obj.value.size());
fc::raw::unpack(ds, balance);
auto cursor = asset(balance, obj.primary_key);
auto cursor = asset(balance, symbol(obj.primary_key));
if (p.symbol || cursor.symbol_name().compare(*p.symbol) == 0) {
results.emplace_back(balance, obj.primary_key);
results.emplace_back(balance, symbol(obj.primary_key));
}
// return false if we are looking for one and found it, true otherwise
......@@ -356,7 +356,7 @@ fc::variant read_only::get_currency_stats( const read_only::get_currency_stats_p
share_type balance;
fc::datastream<const char *> ds(obj.value.data(), obj.value.size());
fc::raw::unpack(ds, balance);
auto cursor = asset(balance, obj.primary_key);
auto cursor = asset(balance, symbol(obj.primary_key));
read_only::get_currency_stats_result result;
result.supply = cursor;
......
......@@ -222,7 +222,7 @@ struct faucet_testnet_plugin_impl {
auto& plugin = _app.get_plugin<chain_plugin>();
plugin.get_chain_id(chainid);
chain_controller& cc = plugin.chain();
const uint64_t deposit = 1;
const asset deposit(1);
signed_transaction trx;
auto memo = fc::variant(fc::time_point::now()).as_string() + " " + fc::variant(fc::time_point::now().time_since_epoch()).as_string();
......
......@@ -62,7 +62,7 @@ struct txn_test_gen_plugin_impl {
chain_controller& cc = app().get_plugin<chain_plugin>().chain();
chain::chain_id_type chainid;
app().get_plugin<chain_plugin>().get_chain_id(chainid);
uint64_t stake = 10000;
asset stake(10000);
fc::crypto::private_key txn_test_receiver_A_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'a')));
fc::crypto::private_key txn_test_receiver_B_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'b')));
......
......@@ -291,7 +291,7 @@ void create_account(name creator, name newaccount, public_key_type owner, public
auto active_auth = eosio::chain::authority{1, {{active, 1}}, {}};
auto recovery_auth = eosio::chain::authority{1, {}, {{{creator, "active"}, 1}}};
uint64_t deposit = staked_deposit;
asset deposit(staked_deposit);
signed_transaction trx;
trx.actions.emplace_back( vector<chain::permission_level>{{creator,"active"}},
......@@ -1030,7 +1030,7 @@ int main( int argc, char** argv ) {
auto active_auth = eosio::chain::authority{1, {{active, 1}}, {}};
auto recovery_auth = eosio::chain::authority{1, {}, {{{creator, "active"}, 1}}};
uint64_t deposit = 1;
asset deposit(1);
signed_transaction trx;
trx.actions.emplace_back( vector<chain::permission_level>{{creator,"active"}},
......
......@@ -21,14 +21,14 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
test.transfer( N(inita), N(dan), "10.0000 EOS", "memo" );
{
const auto& dans_balance = test.get_balance( N(dan) );
const asset dans_balance( test.get_balance( N(dan) ) );
FC_ASSERT( dans_balance == asset::from_string("10.0000 EOS") );
}
test.produce_block();
{
const auto& dans_balance = test.get_balance( N(dan) );
const asset dans_balance( test.get_balance( N(dan) ) );
FC_ASSERT( dans_balance == asset::from_string("10.0000 EOS") );
}
......@@ -40,12 +40,12 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
/// verify that bart now has 10.000
const auto& barts_balance = test.get_balance( N(bart) );
const asset barts_balance( test.get_balance( N(bart) ) );
FC_ASSERT( barts_balance == asset::from_string("10.0000 EOS") );
{
/// verify that dan now has 0.000
const auto& dans_balance = test.get_balance( N(dan) );
const asset dans_balance( test.get_balance( N(dan) ) );
FC_ASSERT( dans_balance == asset::from_string("0.0000 EOS") );
}
......
......@@ -67,12 +67,6 @@ const char* my_abi = R"=====(
},{
"name": "asset_arr",
"type": "asset[]"
},{
"name": "price",
"type": "price"
},{
"name": "price_arr",
"type": "price[]"
}]
},{
"name": "NativeTypes",
......@@ -488,7 +482,6 @@ BOOST_AUTO_TEST_CASE(generator)
nonce field40;
public_key field41;
asset field42;
price field43;
};
)=====";
......@@ -624,9 +617,6 @@ BOOST_AUTO_TEST_CASE(generator)
},{
"name": "field42",
"type": "asset"
},{
"name": "field43",
"type": "price"
}]
}],
"actions": [{
......@@ -1308,8 +1298,6 @@ BOOST_AUTO_TEST_CASE(general)
"publickey_arr" : ["EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV","EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV","EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"],
"asset" : "100.00 EOS",
"asset_arr" : ["100.00 EOS","100.00 EOS"],
"price" : { "base" : "100.00 EOS", "quote" : "200.00 BTC" },
"price_arr" : [{ "base" : "100.00 EOS", "quote" : "200.00 BTC" },{ "base" : "100.00 EOS", "quote" : "200.00 BTC" }],
"string" : "ola ke ase",
"string_arr" : ["ola ke ase","ola ke desi"],
......@@ -2067,7 +2055,7 @@ BOOST_AUTO_TEST_CASE(newaccount)
BOOST_TEST(53405u == newaccount.recovery.accounts[1].weight);
BOOST_TEST(-900000000000 == newaccount.deposit.amount);
BOOST_TEST(EOS_SYMBOL == newaccount.deposit.symbol);
BOOST_TEST(symbol(EOS_SYMBOL) == newaccount.deposit.symbol());
auto var2 = verify_round_trip_conversion( abis, "newaccount", var );
auto newaccount2 = var2.as<contracts::newaccount>();
......@@ -2123,7 +2111,7 @@ BOOST_AUTO_TEST_CASE(newaccount)
BOOST_TEST(newaccount.recovery.accounts[1].weight == newaccount2.recovery.accounts[1].weight);
BOOST_TEST(newaccount.deposit.amount == newaccount2.deposit.amount);
BOOST_TEST(newaccount.deposit.symbol == newaccount2.deposit.symbol);
BOOST_TEST(newaccount.deposit.symbol() == newaccount2.deposit.symbol());
} FC_LOG_AND_RETHROW() }
......
......@@ -51,7 +51,7 @@ BOOST_FIXTURE_TEST_CASE( test_generic_currency, tester ) try {
std::cerr << act.console << "\n";
produce_block();
auto actual = get_currency_balance(N(currency), expected.symbol, N(usera));
auto actual = get_currency_balance(N(currency), expected.symbol(), N(usera));
BOOST_REQUIRE_EQUAL(expected, actual);
}
......@@ -93,7 +93,7 @@ BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol, N(currency)), asset::from_string( "1000000.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol(), N(currency)), asset::from_string( "1000000.0000 CUR" ));
}
// make a transfer from the contract to a user
......@@ -117,7 +117,7 @@ BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol, N(alice)), asset::from_string( "100.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol(), N(alice)), asset::from_string( "100.0000 CUR" ));
}
// Overspend!
......@@ -141,8 +141,8 @@ BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
produce_block();
BOOST_REQUIRE_EQUAL(false, chain_has_transaction(trx.id()));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol, N(alice)), asset::from_string( "100.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol, N(bob)), asset::from_string( "0.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol(), N(alice)), asset::from_string( "100.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol(), N(bob)), asset::from_string( "0.0000 CUR" ));
}
// Full spend
......@@ -166,10 +166,84 @@ BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol, N(alice)), asset::from_string( "0.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol, N(bob)), asset::from_string( "100.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol(), N(alice)), asset::from_string( "0.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.symbol(), N(bob)), asset::from_string( "100.0000 CUR" ));
}
} FC_LOG_AND_RETHROW() /// test_currency
BOOST_FIXTURE_TEST_CASE(test_symbol, 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 eos(4, "EOS");
BOOST_REQUIRE_EQUAL(EOS_SYMBOL_VALUE, eos.value());
BOOST_REQUIRE_EQUAL("4,EOS", eos.to_string());
BOOST_REQUIRE_EQUAL("EOS", eos.name());
BOOST_REQUIRE_EQUAL(4, eos.decimals());
}
// default is "4,EOS"
{
symbol def;
BOOST_REQUIRE_EQUAL(4, def.decimals());
BOOST_REQUIRE_EQUAL("EOS", 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(""),
fc::assert_exception, assert_message_is("creating symbol from empty string"));
}
// precision part missing
{
BOOST_CHECK_EXCEPTION(symbol::from_string("RND"),
fc::assert_exception, assert_message_is("missing comma in symbol"));
}
// precision part missing
{
BOOST_CHECK_EXCEPTION(symbol::from_string("0,EURO"),
fc::assert_exception, assert_message_is("zero decimals in symbol"));
}
// invalid - contains lower case characters, no validation
{
symbol malformed(SY(6,EoS));
BOOST_REQUIRE_EQUAL(false, malformed.valid());
BOOST_REQUIRE_EQUAL("EoS", malformed.name());
BOOST_REQUIRE_EQUAL(6, malformed.decimals());
}
// invalid - contains lower case characters, exception thrown
{
BOOST_CHECK_EXCEPTION(symbol(5,"EoS"),
fc::assert_exception, assert_message_is("invalid character in symbol name"));
}
// invalid - missing decimal point
{
BOOST_CHECK_EXCEPTION(asset::from_string("10 CUR"),
fc::assert_exception, assert_message_is("dot missing in asset from string"));
}
} FC_LOG_AND_RETHROW() /// test_symbol
BOOST_AUTO_TEST_SUITE_END()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册