-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtoken.sol
More file actions
164 lines (139 loc) · 4.65 KB
/
token.sol
File metadata and controls
164 lines (139 loc) · 4.65 KB
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
159
160
161
162
163
164
// Token - ERC20-style fungible token
// Demonstrates mappings, events, and transfers
contract Token {
// Token metadata
string public name;
string public symbol;
uint8 public decimals = 9;
// Token state
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
// Ownership
address public owner;
bool public paused;
// Events
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event Mint(address indexed to, uint256 amount);
event Burn(address indexed from, uint256 amount);
event Paused(address account);
event Unpaused(address account);
// Errors
error InsufficientBalance(uint256 available, uint256 required);
error InsufficientAllowance(uint256 available, uint256 required);
error ContractPaused();
error Unauthorized();
error InvalidAddress();
// Modifiers
modifier onlyOwner() {
if (msg.sender != owner) revert Unauthorized();
_;
}
modifier whenNotPaused() {
if (paused) revert ContractPaused();
_;
}
modifier validAddress(address addr) {
if (addr == address(0)) revert InvalidAddress();
_;
}
// Constructor
constructor(string memory _name, string memory _symbol, uint256 _initialSupply) {
name = _name;
symbol = _symbol;
owner = msg.sender;
if (_initialSupply > 0) {
_mint(msg.sender, _initialSupply);
}
}
// Transfer tokens
function transfer(address to, uint256 amount)
public
whenNotPaused
validAddress(to)
returns (bool)
{
_transfer(msg.sender, to, amount);
return true;
}
// Approve spender
function approve(address spender, uint256 amount)
public
validAddress(spender)
returns (bool)
{
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
// Transfer from (using allowance)
function transferFrom(address from, address to, uint256 amount)
public
whenNotPaused
validAddress(to)
returns (bool)
{
uint256 currentAllowance = allowance[from][msg.sender];
if (currentAllowance < amount) {
revert InsufficientAllowance(currentAllowance, amount);
}
allowance[from][msg.sender] = currentAllowance - amount;
_transfer(from, to, amount);
return true;
}
// Mint new tokens (owner only)
function mint(address to, uint256 amount) public onlyOwner validAddress(to) {
_mint(to, amount);
emit Mint(to, amount);
}
// Burn tokens
function burn(uint256 amount) public {
if (balanceOf[msg.sender] < amount) {
revert InsufficientBalance(balanceOf[msg.sender], amount);
}
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
emit Burn(msg.sender, amount);
emit Transfer(msg.sender, address(0), amount);
}
// Pause transfers (owner only)
function pause() public onlyOwner {
paused = true;
emit Paused(msg.sender);
}
// Unpause transfers (owner only)
function unpause() public onlyOwner {
paused = false;
emit Unpaused(msg.sender);
}
// Increase allowance
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
allowance[msg.sender][spender] += addedValue;
emit Approval(msg.sender, spender, allowance[msg.sender][spender]);
return true;
}
// Decrease allowance
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
uint256 currentAllowance = allowance[msg.sender][spender];
require(currentAllowance >= subtractedValue, "Decreased below zero");
allowance[msg.sender][spender] = currentAllowance - subtractedValue;
emit Approval(msg.sender, spender, allowance[msg.sender][spender]);
return true;
}
// Internal transfer
function _transfer(address from, address to, uint256 amount) internal {
if (balanceOf[from] < amount) {
revert InsufficientBalance(balanceOf[from], amount);
}
balanceOf[from] -= amount;
balanceOf[to] += amount;
emit Transfer(from, to, amount);
}
// Internal mint
function _mint(address to, uint256 amount) internal {
totalSupply += amount;
balanceOf[to] += amount;
emit Transfer(address(0), to, amount);
}
}