-
Notifications
You must be signed in to change notification settings - Fork 11
/
stock.sol
186 lines (143 loc) · 6.3 KB
/
stock.sol
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.3;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
}
contract ERC20Token is IERC20 {
using SafeMath for uint256;
string private m_name;
string private m_symbol;
uint256 private m_totalSupply;
mapping(address => uint) m_balances;
mapping(address => mapping(address => uint)) m_allowed;
address public m_token;
address public m_owner;
event Mint(address indexed sender, uint lpAmount, uint tokenAmount);
event Burn(address indexed sender, uint lpAmount, uint tokenAmount);
constructor(address token) {
m_token = token;
m_name = "LP Token";
m_symbol = "LP";
m_totalSupply = 0;
m_owner = msg.sender;
}
function totalToken() public view returns(uint) {
return IERC20(m_token).balanceOf(address(this));
}
function mint(uint tokenAmount) public {
require(tokenAmount > 0, "invalid tokenAmount");
uint lpAmount = 0;
if (m_totalSupply == 0 || totalToken() == 0) {
lpAmount = tokenAmount;
m_balances[msg.sender] = lpAmount;
m_totalSupply = lpAmount;
}else {
lpAmount = m_totalSupply.mul(tokenAmount).div(totalToken());
m_balances[msg.sender] = m_balances[msg.sender].add(lpAmount);
m_totalSupply = m_totalSupply.add(lpAmount);
}
require(IERC20(m_token).transferFrom(msg.sender, address(this), tokenAmount), "failed to Transfer token");
emit Transfer(address(0), msg.sender, lpAmount);
emit Mint(msg.sender, lpAmount, tokenAmount);
}
function burn(uint lpAmount) public {
require(lpAmount > 0, "invalid lpAmount");
require(lpAmount <= m_balances[msg.sender], "lpAmount exceed range");
uint tokenAmount = totalToken().mul(lpAmount).div(m_totalSupply);
m_balances[msg.sender] = m_balances[msg.sender].sub(lpAmount);
m_totalSupply = m_totalSupply.sub(lpAmount);
require(IERC20(m_token).transfer(msg.sender, tokenAmount), "failed to Transfer token");
emit Transfer(msg.sender, address(0), lpAmount);
emit Burn(msg.sender, lpAmount, tokenAmount);
}
function name() public view override returns (string memory) {
return m_name;
}
function symbol() public view override returns (string memory) {
return m_symbol;
}
function decimals() public view override returns (uint8) {
return IERC20(m_token).decimals();
}
function totalSupply() public view override returns (uint256) {
return m_totalSupply;
}
function balanceOf(address tokenOwner) public view override returns (uint balance) {
return m_balances[tokenOwner];
}
function allowance(address tokenOwner, address spender) public view override returns (uint remaining) {
return m_allowed[tokenOwner][spender];
}
function approve(address spender, uint tokens) public override returns (bool success) {
require(spender != address(0));
m_allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
return true;
}
function transfer(address to, uint tokens) public override returns (bool success) {
require(to != address(0));
m_balances[msg.sender] = m_balances[msg.sender].sub(tokens);
m_balances[to] = m_balances[to].add(tokens);
emit Transfer(msg.sender, to, tokens);
return true;
}
function transferFrom(address from, address to, uint tokens) public override returns (bool success) {
m_balances[from] = m_balances[from].sub(tokens);
m_allowed[from][msg.sender] = m_allowed[from][msg.sender].sub(tokens);
m_balances[to] = m_balances[to].add(tokens);
emit Transfer(from, to, tokens);
return true;
}
}