Skip to content

Commit bac2da6

Browse files
authored
Create test_token.py
1 parent 17bf914 commit bac2da6

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed

tests/test_token.py

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
import pytest
2+
from web3 import Web3
3+
from solcx import compile_source
4+
5+
# Sample Solidity code for the Token contract
6+
TOKEN_CONTRACT_SOURCE = '''
7+
// SPDX-License-Identifier: MIT
8+
pragma solidity ^0.8.0;
9+
10+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
11+
import "@openzeppelin/contracts/access/Ownable.sol";
12+
13+
contract Token is ERC20, Ownable {
14+
mapping(address => bool) public minters;
15+
16+
event MinterAdded(address indexed account);
17+
event MinterRemoved(address indexed account);
18+
19+
constructor(string memory name, string memory symbol) ERC20(name, symbol) {}
20+
21+
modifier onlyMinter() {
22+
require(minters[msg.sender], "Caller is not a minter");
23+
_;
24+
}
25+
26+
function addMinter(address account) external onlyOwner {
27+
minters[account] = true;
28+
emit MinterAdded(account);
29+
}
30+
31+
function removeMinter(address account) external onlyOwner {
32+
minters[account] = false;
33+
emit MinterRemoved(account);
34+
}
35+
36+
function mint(address to, uint256 amount) external onlyMinter {
37+
_mint(to, amount);
38+
}
39+
40+
function burn(uint256 amount) external {
41+
_burn(msg.sender, amount);
42+
}
43+
}
44+
'''
45+
46+
@pytest.fixture
47+
def token_contract(web3):
48+
# Compile the contract
49+
compiled_sol = compile_source(TOKEN_CONTRACT_SOURCE)
50+
contract_interface = compiled_sol['<stdin>:Token']
51+
52+
# Deploy the contract
53+
TokenContract = web3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin'])
54+
tx_hash = TokenContract.constructor("Stable Pi Token", "SPT").transact({'from': web3.eth.accounts[0]})
55+
tx_receipt = web3.eth.waitForTransactionReceipt(tx_hash)
56+
57+
return web3.eth.contract(address=tx_receipt.contractAddress, abi=contract_interface['abi'])
58+
59+
def test_initial_supply(token_contract):
60+
# Assert initial supply is zero
61+
assert token_contract.functions.totalSupply().call() == 0
62+
63+
def test_minting(token_contract):
64+
# Arrange
65+
owner = token_contract.functions.owner().call()
66+
token_contract.functions.addMinter(web3.eth.accounts[1]).transact({'from': owner})
67+
68+
# Act
69+
tx_hash = token_contract.functions.mint(web3.eth.accounts[2], 100).transact({'from': web3.eth.accounts[1]})
70+
web3.eth.waitForTransactionReceipt(tx_hash)
71+
72+
# Assert
73+
assert token_contract.functions.balanceOf(web3.eth.accounts[2]).call() == 100
74+
assert token_contract.functions.totalSupply().call() == 100
75+
76+
def test_burning(token_contract):
77+
# Arrange
78+
owner = token_contract.functions.owner().call()
79+
token_contract.functions.addMinter(web3.eth.accounts[1]).transact({'from': owner})
80+
token_contract.functions.mint(web3.eth.accounts[2], 100).transact({'from': web3.eth.accounts[1]})
81+
82+
# Act
83+
tx_hash = token_contract.functions.burn(50).transact({'from': web3.eth.accounts[2]})
84+
web3.eth.waitForTransactionReceipt(tx_hash)
85+
86+
# Assert
87+
assert token_contract.functions.balanceOf(web3.eth.accounts[2]).call() == 50
88+
assert token_contract.functions.totalSupply().call() == 50
89+
90+
def test_add_minter(token_contract):
91+
# Arrange
92+
owner = token_contract.functions.owner().call()
93+
94+
# Act
95+
tx_hash = token_contract.functions.addMinter(web3.eth.accounts[1]).transact({'from': owner})
96+
web3.eth.waitForTransactionReceipt(tx_hash)
97+
98+
# Assert
99+
assert token_contract.functions.minters(web3.eth.accounts[1]).call() is True
100+
101+
def test_remove_minter(token_contract):
102+
# Arrange
103+
owner = token_contract.functions.owner().call()
104+
token_contract.functions.addMinter(web3.eth.accounts[1]).transact({'from': owner})
105+
106+
# Act
107+
tx_hash = token_contract.functions.removeMinter(web3.eth.accounts[1]).transact({'from': owner})
108+
web3.eth.waitForTransactionReceipt(tx_hash)
109+
110+
# Assert
111+
assert token_contract.functions.minters(web3.eth.accounts[1]).call() is False
112+
113+
def test_minting_without_permission(token_contract):
114+
# Act & Assert
115+
with pytest.raises(Exception):
116+
token_contract.functions.mint(web3.eth.accounts[2], 100).transact({'from': web3.eth.accounts[3]})
117+
118+
def test_burn_more_than_balance(token_contract):
119+
# Arrange
120+
owner = token_contract.functions.owner().call()
121+
token_contract.functions.addMinter(web3.eth.accounts[1]).transact({'from': owner})
122+
token_contract.functions.mint(web3.eth.accounts[2], 100).transact({'from': web3.eth.accounts[1]})
123+
124+
# Act & Assert
125+
with pytest.raises(Exception):
126+
token_contract.functions.burn(200).transact({'from': web3.eth .accounts[2]})
127+
128+
def test_burn_without_balance(token_contract):
129+
# Act & Assert
130+
with pytest.raises(Exception):
131+
token_contract.functions.burn(50).transact({'from': web3.eth.accounts[3]})
132+
133+
def test_transfer(token_contract):
134+
# Arrange
135+
owner = token_contract.functions.owner().call()
136+
token_contract.functions.addMinter(web3.eth.accounts[1]).transact({'from': owner})
137+
token_contract.functions.mint(web3.eth.accounts[2], 100).transact({'from': web3.eth.accounts[1]})
138+
139+
# Act
140+
tx_hash = token_contract.functions.transfer(web3.eth.accounts[3], 50).transact({'from': web3.eth.accounts[2]})
141+
web3.eth.waitForTransactionReceipt(tx_hash)
142+
143+
# Assert
144+
assert token_contract.functions.balanceOf(web3.eth.accounts[2]).call() == 50
145+
assert token_contract.functions.balanceOf(web3.eth.accounts[3]).call() == 50
146+
147+
def test_transfer_more_than_balance(token_contract):
148+
# Arrange
149+
owner = token_contract.functions.owner().call()
150+
token_contract.functions.addMinter(web3.eth.accounts[1]).transact({'from': owner})
151+
token_contract.functions.mint(web3.eth.accounts[2], 100).transact({'from': web3.eth.accounts[1]})
152+
153+
# Act & Assert
154+
with pytest.raises(Exception):
155+
token_contract.functions.transfer(web3.eth.accounts[3], 200).transact({'from': web3.eth.accounts[2]})
156+
157+
def test_approve_and_transfer_from(token_contract):
158+
# Arrange
159+
owner = token_contract.functions.owner().call()
160+
token_contract.functions.addMinter(web3.eth.accounts[1]).transact({'from': owner})
161+
token_contract.functions.mint(web3.eth.accounts[2], 100).transact({'from': web3.eth.accounts[1]})
162+
163+
# Act
164+
tx_hash = token_contract.functions.approve(web3.eth.accounts[3], 50).transact({'from': web3.eth.accounts[2]})
165+
web3.eth.waitForTransactionReceipt(tx_hash)
166+
167+
# Transfer from
168+
tx_hash = token_contract.functions.transferFrom(web3.eth.accounts[2], web3.eth.accounts[4], 50).transact({'from': web3.eth.accounts[3]})
169+
web3.eth.waitForTransactionReceipt(tx_hash)
170+
171+
# Assert
172+
assert token_contract.functions.balanceOf(web3.eth.accounts[2]).call() == 50
173+
assert token_contract.functions.balanceOf(web3.eth.accounts[4]).call() == 50
174+
175+
def test_transfer_from_without_approval(token_contract):
176+
# Arrange
177+
owner = token_contract.functions.owner().call()
178+
token_contract.functions.addMinter(web3.eth.accounts[1]).transact({'from': owner})
179+
token_contract.functions.mint(web3.eth.accounts[2], 100).transact({'from': web3.eth.accounts[1]})
180+
181+
# Act & Assert
182+
with pytest.raises(Exception):
183+
token_contract.functions.transferFrom(web3.eth.accounts[2], web3.eth.accounts[4], 50).transact({'from': web3.eth.accounts[3]})
184+
185+
def test_approve_more_than_balance(token_contract):
186+
# Arrange
187+
owner = token_contract.functions.owner().call()
188+
token_contract.functions.addMinter(web3.eth.accounts[1]).transact({'from': owner})
189+
token_contract.functions.mint(web3.eth.accounts[2], 100).transact({'from': web3.eth.accounts[1]})
190+
191+
# Act
192+
tx_hash = token_contract.functions.approve(web3.eth.accounts[3], 150).transact({'from': web3.eth.accounts[2]})
193+
web3.eth.waitForTransactionReceipt(tx_hash)
194+
195+
# Assert
196+
assert token_contract.functions.allowance(web3.eth.accounts[2], web3.eth.accounts[3]).call() == 150

0 commit comments

Comments
 (0)