-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathICO.sol
More file actions
184 lines (144 loc) · 6.82 KB
/
ICO.sol
File metadata and controls
184 lines (144 loc) · 6.82 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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
//SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.5.0 <0.9.0; // ---------------------------------------------------------------------------- // EIP-20: ERC-20 Token Standard // https://eips.ethereum.org/EIPS/eip-20 // -----------------------------------------
//Unlike ETH (Ethereum’s native cryptocurrency), ERC-20 tokens aren’t held by accounts. The tokens only exist inside a contract, which is like a self-contained database. It specifies the rules for the tokens (i.e., name, symbol, divisibility) and keeps a list that maps users’ balances to their Ethereum addresses.
interface ERC20Interface {
function totalSupply() external view returns (uint);
function balanceOf(address tokenOwner) external view returns (uint balance);
function transfer(address to, uint tokens) external returns (bool success);
function approve(address spender, uint tokens) external returns (bool success);
function allowance(address tokenOwner, address spender) external view returns (uint remaining);
function transferFrom(address from, address to, uint tokens) external returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
contract Block is ERC20Interface {
string public name = 'Block';
string public symbol = 'BLK';
string public decimal = 0;
uint public override totalSupply; // to override interface beloged function
address public founder;
mapping(address => uint) public balances; // track perticular user balances - default 0
mapping(address=>mapping(address=>uint)) allowed;
constructor() {
totalSupply = 1000000;
founder = msg.sender; // who deployed contract - add0
balances[founder] = totalSupply; // founder has all supply
}
// to override interface beloged function - perticular user balance check
function balanceOf(address tokenOwner) public view override returns(uint balance) {
return balances[tokenOwner];
}
// send tokens - how much/amount-> bool status (zaree TAKA dilam koto & amr roilo koto tar record -> amount)
// founder add0 r 1000000 tokens theke addB user k 1000 tokens dilam
function transfer(address to, uint tokens) public override virtual returns (bool success) {
require (balances[msg.sender] >= tokens);
balances[to]+=tokens; //balances[to] = balances[to] + tokens
balances[msg.sender] -= tokens;
emit Transfer(msg.sender, to, tokens);
return true;
}
//approve is another useful function from a programmability standpoint. With this function, you can limit the number of tokens that a smart contract can withdraw from your balance. Without it, you run the risk of the contract malfunctioning (or being exploited) and stealing all of your funds.
// addB abr tar 1000 tokens theke addC k 100 tokens dilo -> set a limit of 100 tokens
//msg.sender allowed spender to use <tokens> (ami z Taka dilam ata amar record & zare dilm tr record -> address)
function approve(address spender, uint tokens) public override returns (bool success) {
require (balances[msg.sender] >= tokens); // @param = uint tokens
require(tokens > 0);
// addB abr tar 1000 tokens theke addC k 100 tokens dilo approval use r jnno
allowed[msg.sender][spender] = tokens; // msg.sender allowed spender to use this much <tokens>
emit Approval(msg.sender, spender, tokens);
return true;
}
// tokenOwner approved this amount to spender for taking - approval check kore allowance
// addB owner age addC k koto dise check -> 100 dise age
function allowance(address tokenOwner, address spender) external view returns (uint noOfToken) {
return allowed[tokenOwner][spender]; // -> approve() fun e record kora hoise
}
//Like transfer, transferFrom used to move tokens, but those tokens don’t necessarily need to belong to the person/add0/founder who calling the contract.
// addA has given 100 tokens allowance to addB, now addB can recv 100 or lower than 100
// addA akohn addB k 90 tokens dibe cox addB 90 chaise
function transferFrom(address from, address to, uint tokens) public override virtual returns (bool success) {
require(allowed[from][to] >= tokens); // 100 >= 90 (100 >= @token=90)
require(balances[from] >= tokens);
balances[from] -= tokens;
balances[to] += tokens;
return true;
}
}
// ICO
contract ICO is Block {
address public manager;
address payable public deposit;
uint tokenPrice = 0.1 ether;
uint public cap = 300 ether;
uint public raisedAmount;
uint public icoStart = block.timestamp;
uint public icoEnd = block.timestamp + 3600;
uint public tokenTradeTime = icoEnd+3600;
uint public maxInvest = 10 ether;
uint public minInvest = 0.1 ether;
enum State{ beforeStart, afterEnd, halted }
State public icoState;
event Invest(address investor, uint value, uint token);
constructor(address payable _deposit) {
deposit = _deposit;
manager = msg.sender;
icoState = State.beforeStart;
}
modifier onlyManager() {
require(msg.sender == manager);
_;
}
function halt() public onlyManger{
icoState=State.halted;
}
function resume() public onlyManger{
icoState=State.running;
}
function changeDepositAddr(address payable newDeposit) public onlyManger{
deposit=newDeposit;
}
function getState() public view returns(State){
if(icoState==State.halted){
return State.halted;
}else if(block.timestamp<icoStart){
return State.beforeStart;
}else if(block.timestamp>=icoStart && block.timestamp<=icoEnd){
return State.running;
}else{
return State.afterEnd;
}
}
function invest() payable public returns(bool) {
icoState = getState();
require(icoState == State.running);
require(msg.value >= minInvest && msg.value <= maxInvest);
raisedAmount += msg.value;
require(raisedAmount <= cap);
uint tokens = msg.value/tokenPrice; // 0.1 eth e token pai 1 ta, 1 e koto, 10 e koto (10/0.1=100)
balances[msg.sender] += tokens; //Block contact theke balances
balances[founder] -= tokens;
deposit.transfer(msg.value);
emit Invest(msg.sender, msg.value, tokens);
return true;
}
function burn() public returns(bool){
icoState=getState();
require(icoState==State.afterEnd);
balances[founder]=0;
return true;
}
// override interface ERC20 of Block
function transfer(address to,uint tokens) public override returns(bool success){
require(block.timestamp>tokenTradeTime);
super.transfer(to,tokens); //super means transfer() fun will be called from parent, otherwise infinite loop
return true;
}
function transferFrom(address from,address to,uint tokens) public override returns(bool success){
require(block.timestamp>tokenTradeTime);
Block.transferFrom(from,to,tokens); // can use super as OOP keyword
return true;
}
receive() external payable{
invest();
}
}