-
Notifications
You must be signed in to change notification settings - Fork 132
/
test_token.py
158 lines (112 loc) · 5.78 KB
/
test_token.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
"""Mock token deployment."""
import pytest
from eth_tester.exceptions import TransactionFailed
from web3 import Web3, EthereumTesterProvider
from eth_defi.deploy import deploy_contract, get_registered_contract
from eth_defi.token import create_token, fetch_erc20_details, TokenDetailError, TokenDetails, DEFAULT_TOKEN_CACHE, reset_default_token_cache
@pytest.fixture
def tester_provider():
# https://web3py.readthedocs.io/en/stable/examples.html#contract-unit-tests-in-python
return EthereumTesterProvider()
@pytest.fixture
def eth_tester(tester_provider):
# https://web3py.readthedocs.io/en/stable/examples.html#contract-unit-tests-in-python
return tester_provider.ethereum_tester
@pytest.fixture
def web3(tester_provider):
"""Set up a local unit testing blockchain."""
# This test does not work with token cache
reset_default_token_cache()
# https://web3py.readthedocs.io/en/stable/examples.html#contract-unit-tests-in-python
return Web3(tester_provider)
@pytest.fixture()
def deployer(web3) -> str:
"""Deploy account.
Do some account allocation for tests.
"""
return web3.eth.accounts[0]
@pytest.fixture()
def user_1(web3) -> str:
"""User account.
Do some account allocation for tests.
"""
return web3.eth.accounts[1]
@pytest.fixture()
def user_2(web3) -> str:
"""User account.
Do some account allocation for tests.
"""
return web3.eth.accounts[2]
def test_deploy_token(web3: Web3, deployer: str):
"""Deploy mock ERC-20."""
token = create_token(web3, deployer, "Hentai books token", "HENTAI", 100_000 * 10**18, 6)
# https://web3py.readthedocs.io/en/stable/contracts.html#contract-deployment-example
assert token.functions.name().call() == "Hentai books token"
assert token.functions.symbol().call() == "HENTAI"
assert token.functions.totalSupply().call() == 100_000 * 10**18
assert token.functions.decimals().call() == 6
registered_contract = get_registered_contract(web3, token.address)
assert registered_contract.name == "ERC20MockDecimals"
def test_tranfer_tokens_between_users(web3: Web3, deployer: str, user_1, user_2):
"""Transfer tokens between users."""
token = create_token(web3, deployer, "Telos EVM rocks", "TELOS", 100_000 * 10**18)
# Move 10 tokens from deployer to user1
token.functions.transfer(user_1, 10 * 10**18).transact({"from": deployer})
assert token.functions.balanceOf(user_1).call() == 10 * 10**18
# Move 10 tokens from deployer to user1
token.functions.transfer(user_2, 6 * 10**18).transact({"from": user_1})
assert token.functions.balanceOf(user_1).call() == 4 * 10**18
assert token.functions.balanceOf(user_2).call() == 6 * 10**18
def test_tranfer_too_much(web3: Web3, deployer: str, user_1, user_2):
"""Attempt to transfer more tokens than an account has."""
token = create_token(web3, deployer, "Telos EVM rocks", "TELOS", 100_000 * 10**18)
# Move 10 tokens from deployer to user1
token.functions.transfer(user_1, 10 * 10**18).transact({"from": deployer})
assert token.functions.balanceOf(user_1).call() == 10 * 10**18
# Attempt to move 11 tokens from deployer to user1
with pytest.raises(TransactionFailed) as excinfo:
token.functions.transfer(user_1, 11 * 10**18).transact({"from": user_1})
assert str(excinfo.value) == "execution reverted: ERC20: transfer amount exceeds balance"
def test_fetch_token_details(web3: Web3, deployer: str):
"""Get details of a token."""
token = create_token(web3, deployer, "Hentai books token", "HENTAI", 100_000 * 10**18, 6)
details = fetch_erc20_details(web3, token.address)
assert details.name == "Hentai books token"
assert details.decimals == 6
def test_fetch_token_details_broken_silent(web3: Web3, deployer: str):
"""Get details of a token that does not conform ERC-20 guidelines."""
malformed_token = deploy_contract(web3, "MalformedERC20.json", deployer)
details = fetch_erc20_details(web3, malformed_token.address, raise_on_error=False)
assert details.symbol == ""
assert details.decimals == 0
assert details.total_supply is None
def test_fetch_token_details_broken_load(web3: Web3, deployer: str):
"""Get an error if trying to read malformed token."""
malformed_token = deploy_contract(web3, "MalformedERC20.json", deployer)
with pytest.raises(TokenDetailError):
fetch_erc20_details(web3, malformed_token.address, cache=None)
def test_compare_token(web3: Web3, deployer: str):
"""token __eq__ works by chain id and address"""
token_1_contract = create_token(web3, deployer, "Hentai books token", "HENTAI", 100_000 * 10**18, 6)
token_2_contract = create_token(web3, deployer, "Animu token", "ANIMU", 100_000 * 10**18, 6)
token_1 = fetch_erc20_details(web3, token_1_contract.address)
token_2 = fetch_erc20_details(web3, token_2_contract.address)
token_1_again = fetch_erc20_details(web3, token_1.address)
assert token_1 == token_1_again
assert token_2 != token_1
assert hash(token_1) == hash(token_1_again)
def test_cache_erc_20_details(web3: Web3, deployer: str):
"""Token details are cached."""
token = create_token(web3, deployer, "Hentai books token", "HENTAI", 100_000 * 10**18, 6)
fetch_erc20_details(web3, token.address)
cache_key = TokenDetails.generate_cache_key(web3.eth.chain_id, token.address)
assert cache_key in DEFAULT_TOKEN_CACHE
def test_cache_reset_erc_20_details(web3: Web3, deployer: str):
"""Token cache can be reset."""
token = create_token(web3, deployer, "Hentai books token", "HENTAI", 100_000 * 10**18, 6)
fetch_erc20_details(web3, token.address)
assert len(DEFAULT_TOKEN_CACHE) == 1
reset_default_token_cache()
assert len(DEFAULT_TOKEN_CACHE) == 0
fetch_erc20_details(web3, token.address)
assert len(DEFAULT_TOKEN_CACHE) == 1