Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
0ca7d7a2
Y
YTBP
项目概览
YottaChain
/
YTBP
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Y
YTBP
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
0ca7d7a2
编写于
4月 17, 2018
作者:
W
wanderingbort
提交者:
GitHub
4月 17, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #2300 from EOSIO/fix-eosio.token
Fix eosio.token
上级
4ec2c52b
14d714c7
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
326 addition
and
23 deletion
+326
-23
contracts/eosio.token/eosio.token.abi
contracts/eosio.token/eosio.token.abi
+12
-5
contracts/eosio.token/eosio.token.cpp
contracts/eosio.token/eosio.token.cpp
+8
-5
contracts/eosio.token/eosio.token.hpp
contracts/eosio.token/eosio.token.hpp
+1
-1
contracts/eosiolib/currency.hpp
contracts/eosiolib/currency.hpp
+3
-3
libraries/chain/include/eosio/chain/symbol.hpp
libraries/chain/include/eosio/chain/symbol.hpp
+6
-8
libraries/testing/tester.cpp
libraries/testing/tester.cpp
+1
-1
tests/wasm_tests/eosio.token_tests.cpp
tests/wasm_tests/eosio.token_tests.cpp
+295
-0
未找到文件。
contracts/eosio.token/eosio.token.abi
浏览文件 @
0ca7d7a2
...
...
@@ -31,15 +31,22 @@
"name": "account",
"base": "",
"fields": [
{"name":"currency", "type":"uint64"},
{"name":"balance", "type":"uint64"}
{"name":"balance", "type":"asset"},
{"name":"frozen", "type":"uint8"},
{"name":"whitelist", "type":"uint8"}
]
},{
"name": "currency_stats",
"base": "",
"fields": [
{"name":"currency", "type":"uint64"},
{"name":"supply", "type":"uint64"}
{"name":"supply", "type":"asset"},
{"name":"max_supply", "type":"asset"},
{"name":"issuer", "type":"account_name"},
{"name":"can_freeze", "type":"uint8"},
{"name":"can_recall", "type":"uint8"},
{"name":"can_whitelist", "type":"uint8"},
{"name":"is_frozen", "type":"uint8"},
{"name":"enforce_whitelist", "type":"uint8"}
]
}
],
...
...
@@ -59,7 +66,7 @@
],
"tables": [{
"name": "account",
"name": "account
s
",
"type": "account",
"index_type": "i64",
"key_names" : ["currency"],
...
...
contracts/eosio.token/eosio.token.cpp
浏览文件 @
0ca7d7a2
...
...
@@ -17,6 +17,8 @@ void token::create( account_name issuer,
auto
sym
=
maximum_supply
.
symbol
;
eosio_assert
(
sym
.
is_valid
(),
"invalid symbol name"
);
eosio_assert
(
maximum_supply
.
is_valid
(),
"invalid supply"
);
eosio_assert
(
maximum_supply
.
amount
>
0
,
"max-supply must be positive"
);
stats
statstable
(
_self
,
sym
.
name
()
);
auto
existing
=
statstable
.
find
(
sym
.
name
()
);
...
...
@@ -43,9 +45,10 @@ void token::issue( account_name to, asset quantity, string memo )
require_auth
(
st
.
issuer
);
eosio_assert
(
quantity
.
is_valid
(),
"invalid quantity"
);
eosio_assert
(
quantity
.
amount
>
0
,
"must issue positive quantity"
);
eosio_assert
(
quantity
<=
st
.
max_supply
-
st
.
supply
,
"quantity exceeds available supply"
);
statstable
.
modify
(
st
,
0
,
[
&
](
auto
&
s
)
{
s
.
supply
.
amount
+=
quantity
.
amount
;
s
.
supply
+=
quantity
;
});
add_balance
(
st
.
issuer
,
quantity
,
st
,
st
.
issuer
);
...
...
@@ -81,7 +84,7 @@ void token::transfer( account_name from,
void
token
::
sub_balance
(
account_name
owner
,
asset
value
,
const
currency_stats
&
st
)
{
accounts
from_acnts
(
_self
,
owner
);
const
auto
&
from
=
from_acnts
.
get
(
value
.
symbol
);
const
auto
&
from
=
from_acnts
.
get
(
value
.
symbol
.
name
()
);
eosio_assert
(
from
.
balance
.
amount
>=
value
.
amount
,
"overdrawn balance"
);
if
(
has_auth
(
owner
)
)
{
...
...
@@ -95,14 +98,14 @@ void token::sub_balance( account_name owner, asset value, const currency_stats&
}
from_acnts
.
modify
(
from
,
owner
,
[
&
](
auto
&
a
)
{
a
.
balance
.
amount
-=
value
.
amount
;
a
.
balance
-=
value
;
});
}
void
token
::
add_balance
(
account_name
owner
,
asset
value
,
const
currency_stats
&
st
,
account_name
ram_payer
)
{
accounts
to_acnts
(
_self
,
owner
);
auto
to
=
to_acnts
.
find
(
value
.
symbol
);
auto
to
=
to_acnts
.
find
(
value
.
symbol
.
name
()
);
if
(
to
==
to_acnts
.
end
()
)
{
eosio_assert
(
!
st
.
enforce_whitelist
,
"can only transfer to white listed accounts"
);
to_acnts
.
emplace
(
ram_payer
,
[
&
](
auto
&
a
){
...
...
@@ -111,7 +114,7 @@ void token::add_balance( account_name owner, asset value, const currency_stats&
}
else
{
eosio_assert
(
!
st
.
enforce_whitelist
||
to
->
whitelist
,
"receiver requires whitelist by issuer"
);
to_acnts
.
modify
(
to
,
0
,
[
&
](
auto
&
a
)
{
a
.
balance
.
amount
+=
value
.
amount
;
a
.
balance
+=
value
;
});
}
}
...
...
contracts/eosio.token/eosio.token.hpp
浏览文件 @
0ca7d7a2
...
...
@@ -36,7 +36,7 @@ namespace eosio {
bool
frozen
=
false
;
bool
whitelist
=
true
;
uint64_t
primary_key
()
const
{
return
balance
.
symbol
;
}
uint64_t
primary_key
()
const
{
return
balance
.
symbol
.
name
()
;
}
};
struct
currency_stats
{
...
...
contracts/eosiolib/currency.hpp
浏览文件 @
0ca7d7a2
...
...
@@ -58,7 +58,7 @@ namespace eosio {
bool
frozen
=
false
;
bool
whitelist
=
true
;
uint64_t
primary_key
()
const
{
return
balance
.
symbol
;
}
uint64_t
primary_key
()
const
{
return
balance
.
symbol
.
name
()
;
}
EOSLIB_SERIALIZE
(
account
,
(
balance
)(
frozen
)(
whitelist
)
)
};
...
...
@@ -211,7 +211,7 @@ namespace eosio {
void
sub_balance
(
account_name
owner
,
asset
value
,
const
currency_stats
&
st
)
{
accounts
from_acnts
(
_contract
,
owner
);
const
auto
&
from
=
from_acnts
.
get
(
value
.
symbol
);
const
auto
&
from
=
from_acnts
.
get
(
value
.
symbol
.
name
()
);
eosio_assert
(
from
.
balance
.
amount
>=
value
.
amount
,
"overdrawn balance"
);
if
(
has_auth
(
owner
)
)
{
...
...
@@ -232,7 +232,7 @@ namespace eosio {
void
add_balance
(
account_name
owner
,
asset
value
,
const
currency_stats
&
st
,
account_name
ram_payer
)
{
accounts
to_acnts
(
_contract
,
owner
);
auto
to
=
to_acnts
.
find
(
value
.
symbol
);
auto
to
=
to_acnts
.
find
(
value
.
symbol
.
name
()
);
if
(
to
==
to_acnts
.
end
()
)
{
eosio_assert
(
!
st
.
enforce_whitelist
,
"can only transfer to white listed accounts"
);
to_acnts
.
emplace
(
ram_payer
,
[
&
](
auto
&
a
){
...
...
libraries/chain/include/eosio/chain/symbol.hpp
浏览文件 @
0ca7d7a2
...
...
@@ -86,14 +86,12 @@ namespace eosio {
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
()
];
uint64_t
p10
=
1
;
uint64_t
p
=
decimals
();
while
(
p
>
0
)
{
p10
*=
10
;
--
p
;
}
return
p10
;
}
string
name
()
const
{
...
...
libraries/testing/tester.cpp
浏览文件 @
0ca7d7a2
...
...
@@ -520,7 +520,7 @@ namespace eosio { namespace testing {
// the balance is implied to be 0 if either the table or row does not exist
if
(
tbl
)
{
const
auto
*
obj
=
db
.
template
find
<
contracts
::
key_value_object
,
contracts
::
by_scope_primary
>(
boost
::
make_tuple
(
tbl
->
id
,
asset_symbol
.
value
()
));
const
auto
*
obj
=
db
.
template
find
<
contracts
::
key_value_object
,
contracts
::
by_scope_primary
>(
boost
::
make_tuple
(
tbl
->
id
,
asset_symbol
.
to_symbol_code
().
value
));
if
(
obj
)
{
//balance is the second field after symbol, so skip the symbol
fc
::
datastream
<
const
char
*>
ds
(
obj
->
value
.
data
(),
obj
->
value
.
size
());
...
...
tests/wasm_tests/eosio.token_tests.cpp
0 → 100644
浏览文件 @
0ca7d7a2
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
#include <eosio/chain_plugin/chain_plugin.hpp>
#include <eosio.token/eosio.token.wast.hpp>
#include <eosio.token/eosio.token.abi.hpp>
#include <Runtime/Runtime.h>
#include <fc/variant_object.hpp>
using
namespace
eosio
::
testing
;
using
namespace
eosio
;
using
namespace
eosio
::
chain
;
using
namespace
eosio
::
chain
::
contracts
;
using
namespace
eosio
::
chain_apis
;
using
namespace
eosio
::
testing
;
using
namespace
fc
;
using
namespace
std
;
using
mvo
=
fc
::
mutable_variant_object
;
class
eosio_token_tester
:
public
tester
{
public:
eosio_token_tester
()
{
produce_blocks
(
2
);
create_accounts
(
{
N
(
alice
),
N
(
bob
),
N
(
carol
),
N
(
eosio
.
token
)
}
);
produce_blocks
(
2
);
set_code
(
N
(
eosio
.
token
),
eosio_token_wast
);
set_abi
(
N
(
eosio
.
token
),
eosio_token_abi
);
produce_blocks
();
const
auto
&
accnt
=
control
->
get_database
().
get
<
account_object
,
by_name
>
(
N
(
eosio
.
token
)
);
abi_def
abi
;
BOOST_REQUIRE_EQUAL
(
abi_serializer
::
to_abi
(
accnt
.
abi
,
abi
),
true
);
abi_ser
.
set_abi
(
abi
);
}
action_result
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
=
N
(
eosio
.
token
);
act
.
name
=
name
;
act
.
data
=
abi_ser
.
variant_to_binary
(
action_type_name
,
data
);
return
base_tester
::
push_action
(
std
::
move
(
act
),
uint64_t
(
signer
));
}
fc
::
variant
get_stats
(
const
string
&
symbolname
)
{
auto
symb
=
eosio
::
chain
::
symbol
::
from_string
(
symbolname
);
auto
symbol_code
=
symb
.
to_symbol_code
().
value
;
vector
<
char
>
data
=
get_row_by_account
(
N
(
eosio
.
token
),
symbol_code
,
N
(
stat
),
symbol_code
);
return
data
.
empty
()
?
fc
::
variant
()
:
abi_ser
.
binary_to_variant
(
"currency_stats"
,
data
);
}
fc
::
variant
get_account
(
account_name
acc
,
const
string
&
symbolname
)
{
auto
symb
=
eosio
::
chain
::
symbol
::
from_string
(
symbolname
);
auto
symbol_code
=
symb
.
to_symbol_code
().
value
;
vector
<
char
>
data
=
get_row_by_account
(
N
(
eosio
.
token
),
acc
,
N
(
accounts
),
symbol_code
);
return
data
.
empty
()
?
fc
::
variant
()
:
abi_ser
.
binary_to_variant
(
"account"
,
data
);
}
action_result
create
(
account_name
issuer
,
asset
maximum_supply
,
uint8_t
issuer_can_freeze
,
uint8_t
issuer_can_recall
,
uint8_t
issuer_can_whitelist
)
{
return
push_action
(
N
(
eosio
.
token
),
N
(
create
),
mvo
()
(
"issuer"
,
issuer
)
(
"maximum_supply"
,
maximum_supply
)
(
"can_freeze"
,
issuer_can_freeze
)
(
"can_recall"
,
issuer_can_recall
)
(
"can_whitelist"
,
issuer_can_whitelist
)
);
}
action_result
issue
(
account_name
issuer
,
account_name
to
,
asset
quantity
,
string
memo
)
{
return
push_action
(
issuer
,
N
(
issue
),
mvo
()
(
"to"
,
to
)
(
"quantity"
,
quantity
)
(
"memo"
,
memo
)
);
}
action_result
transfer
(
account_name
from
,
account_name
to
,
asset
quantity
,
string
memo
)
{
return
push_action
(
from
,
N
(
transfer
),
mvo
()
(
"from"
,
from
)
(
"to"
,
to
)
(
"quantity"
,
quantity
)
(
"memo"
,
memo
)
);
}
abi_serializer
abi_ser
;
};
BOOST_AUTO_TEST_SUITE
(
eosio_token_tests
)
BOOST_FIXTURE_TEST_CASE
(
create_tests
,
eosio_token_tester
)
try
{
auto
token
=
create
(
N
(
alice
),
asset
::
from_string
(
"1000.000 TKN"
),
false
,
false
,
false
);
auto
stats
=
get_stats
(
"3,TKN"
);
REQUIRE_MATCHING_OBJECT
(
stats
,
mvo
()
(
"supply"
,
"0.000 TKN"
)
(
"max_supply"
,
"1000.000 TKN"
)
(
"issuer"
,
"alice"
)
(
"can_freeze"
,
0
)
(
"can_recall"
,
0
)
(
"can_whitelist"
,
0
)
(
"is_frozen"
,
false
)
(
"enforce_whitelist"
,
false
)
);
produce_blocks
(
1
);
}
FC_LOG_AND_RETHROW
()
BOOST_FIXTURE_TEST_CASE
(
create_negative_max_supply
,
eosio_token_tester
)
try
{
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: max-supply must be positive"
),
create
(
N
(
alice
),
asset
::
from_string
(
"-1000.000 TKN"
),
false
,
false
,
false
)
);
}
FC_LOG_AND_RETHROW
()
BOOST_FIXTURE_TEST_CASE
(
create_max_supply
,
eosio_token_tester
)
try
{
auto
token
=
create
(
N
(
alice
),
asset
::
from_string
(
"4611686018427387903 TKN"
),
true
,
false
,
false
);
auto
stats
=
get_stats
(
"0,TKN"
);
REQUIRE_MATCHING_OBJECT
(
stats
,
mvo
()
(
"supply"
,
"0 TKN"
)
(
"max_supply"
,
"4611686018427387903 TKN"
)
(
"issuer"
,
"alice"
)
(
"can_freeze"
,
1
)
(
"can_recall"
,
0
)
(
"can_whitelist"
,
0
)
(
"is_frozen"
,
false
)
(
"enforce_whitelist"
,
false
)
);
produce_blocks
(
1
);
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: invalid supply"
),
create
(
N
(
alice
),
asset
::
from_string
(
"4611686018427387904 TKN"
),
true
,
false
,
false
)
);
}
FC_LOG_AND_RETHROW
()
BOOST_FIXTURE_TEST_CASE
(
create_max_decimals
,
eosio_token_tester
)
try
{
auto
token
=
create
(
N
(
alice
),
asset
::
from_string
(
"1.000000000000000000 TKN"
),
true
,
false
,
false
);
auto
stats
=
get_stats
(
"18,TKN"
);
REQUIRE_MATCHING_OBJECT
(
stats
,
mvo
()
(
"supply"
,
"0.000000000000000000 TKN"
)
(
"max_supply"
,
"1.000000000000000000 TKN"
)
(
"issuer"
,
"alice"
)
(
"can_freeze"
,
1
)
(
"can_recall"
,
0
)
(
"can_whitelist"
,
0
)
(
"is_frozen"
,
false
)
(
"enforce_whitelist"
,
false
)
);
produce_blocks
(
1
);
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: invalid supply"
),
create
(
N
(
alice
),
asset
::
from_string
(
"4.611686018427387904 TKN"
),
true
,
false
,
false
)
);
//1.0000000000000000000 => 0x8ac7230489e80000L
//TODO: Better error message
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: max-supply must be positive"
),
create
(
N
(
alice
),
asset
::
from_string
(
"1.0000000000000000000 TKN"
),
true
,
false
,
false
)
);
}
FC_LOG_AND_RETHROW
()
BOOST_FIXTURE_TEST_CASE
(
issue_tests
,
eosio_token_tester
)
try
{
auto
token
=
create
(
N
(
alice
),
asset
::
from_string
(
"1000.000 TKN"
),
false
,
false
,
false
);
produce_blocks
(
1
);
issue
(
N
(
alice
),
N
(
alice
),
asset
::
from_string
(
"500.000 TKN"
),
"hola"
);
auto
stats
=
get_stats
(
"3,TKN"
);
REQUIRE_MATCHING_OBJECT
(
stats
,
mvo
()
(
"supply"
,
"500.000 TKN"
)
(
"max_supply"
,
"1000.000 TKN"
)
(
"issuer"
,
"alice"
)
(
"can_freeze"
,
0
)
(
"can_recall"
,
0
)
(
"can_whitelist"
,
0
)
(
"is_frozen"
,
false
)
(
"enforce_whitelist"
,
false
)
);
auto
alice_balance
=
get_account
(
N
(
alice
),
"3,TKN"
);
REQUIRE_MATCHING_OBJECT
(
alice_balance
,
mvo
()
(
"balance"
,
"500.000 TKN"
)
(
"frozen"
,
0
)
(
"whitelist"
,
1
)
);
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: quantity exceeds available supply"
),
issue
(
N
(
alice
),
N
(
alice
),
asset
::
from_string
(
"500.001 TKN"
),
"hola"
)
);
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: invalid quantity"
),
issue
(
N
(
alice
),
N
(
alice
),
asset
::
from_string
(
"4611686018427387.904 TKN"
),
"hola"
)
);
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: must issue positive quantity"
),
issue
(
N
(
alice
),
N
(
alice
),
asset
::
from_string
(
"-1.000 TKN"
),
"hola"
)
);
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: comparison of assets with different symbols is not allowed"
),
issue
(
N
(
alice
),
N
(
alice
),
asset
::
from_string
(
"1.00 TKN"
),
"hola"
)
);
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: comparison of assets with different symbols is not allowed"
),
issue
(
N
(
alice
),
N
(
alice
),
asset
::
from_string
(
"1.0000 TKN"
),
"hola"
)
);
}
FC_LOG_AND_RETHROW
()
BOOST_FIXTURE_TEST_CASE
(
transfer_tests
,
eosio_token_tester
)
try
{
auto
token
=
create
(
N
(
alice
),
asset
::
from_string
(
"1000 CERO"
),
false
,
false
,
false
);
produce_blocks
(
1
);
issue
(
N
(
alice
),
N
(
alice
),
asset
::
from_string
(
"1000 CERO"
),
"hola"
);
auto
stats
=
get_stats
(
"0,CERO"
);
REQUIRE_MATCHING_OBJECT
(
stats
,
mvo
()
(
"supply"
,
"1000 CERO"
)
(
"max_supply"
,
"1000 CERO"
)
(
"issuer"
,
"alice"
)
(
"can_freeze"
,
0
)
(
"can_recall"
,
0
)
(
"can_whitelist"
,
0
)
(
"is_frozen"
,
false
)
(
"enforce_whitelist"
,
false
)
);
auto
alice_balance
=
get_account
(
N
(
alice
),
"0,CERO"
);
REQUIRE_MATCHING_OBJECT
(
alice_balance
,
mvo
()
(
"balance"
,
"1000 CERO"
)
(
"frozen"
,
0
)
(
"whitelist"
,
1
)
);
transfer
(
N
(
alice
),
N
(
bob
),
asset
::
from_string
(
"300 CERO"
),
"hola"
);
alice_balance
=
get_account
(
N
(
alice
),
"0,CERO"
);
REQUIRE_MATCHING_OBJECT
(
alice_balance
,
mvo
()
(
"balance"
,
"700 CERO"
)
(
"frozen"
,
0
)
(
"whitelist"
,
1
)
);
auto
bob_balance
=
get_account
(
N
(
bob
),
"0,CERO"
);
REQUIRE_MATCHING_OBJECT
(
bob_balance
,
mvo
()
(
"balance"
,
"300 CERO"
)
(
"frozen"
,
0
)
(
"whitelist"
,
1
)
);
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: overdrawn balance"
),
transfer
(
N
(
alice
),
N
(
bob
),
asset
::
from_string
(
"701 CERO"
),
"hola"
)
);
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: invalid quantity"
),
transfer
(
N
(
alice
),
N
(
alice
),
asset
::
from_string
(
"4611686018427387904 CERO"
),
"hola"
)
);
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: must transfer positive quantity"
),
transfer
(
N
(
alice
),
N
(
alice
),
asset
::
from_string
(
"-1000 CERO"
),
"hola"
)
);
BOOST_REQUIRE_EQUAL
(
error
(
"condition: assertion failed: attempt to subtract asset with different symbol"
),
transfer
(
N
(
alice
),
N
(
alice
),
asset
::
from_string
(
"1.0 CERO"
),
"hola"
)
);
}
FC_LOG_AND_RETHROW
()
BOOST_AUTO_TEST_SUITE_END
()
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录