forked from serial-coder/RTHB-ThaiBahtCoin
-
Notifications
You must be signed in to change notification settings - Fork 3
/
BahtCoin.sol
225 lines (185 loc) · 6.85 KB
/
BahtCoin.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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
* Copyright (c) 2018, Phuwanai Thummavet (serial-coder). All rights reserved.
* Github: https://github.com/serial-coder
* Contact us: mr[dot]thummavet[at]gmail[dot]com
*/
pragma solidity ^0.4.24;
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
contract Owned {
address public owner;
constructor() public {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
}
/*
Thai Baht Stable Coin developed for running on RootStock (RSK)
smart contract platform and also Ethereum platform
*/
contract BahtCoin is Owned {
using SafeMath for uint256;
string public constant name = "RSK-Thai-Baht";
string public constant symbol = "RTHB";
uint8 public constant decimals = 18;
uint256 private _totalSupply;
mapping(address => uint256) private balances;
struct RTHBContract {
address owner; // A user who invokes issue()
uint256 RBTC; // RSK BTC
uint256 RTHB; // RSK Thai Baht
uint256 rate; // Current rate at a contract issue time
// Threshold value which allows the public to take over
// this contract in order to take away the collateralized RBTC.
// This will happen if RBTC price on a specific RTHB contract
// is less than or equal to this threshold variable.
uint256 dropThreshold;
address takeoverAddr; // A user who invokes publicTakeover()
// This variable would be set to true if there is an invocation
// either on claim() or publicTakeover() against this contract
bool invalidContract;
}
RTHBContract[] private contracts;
uint256 public collateralRate;
uint256 public thresholdRate;
uint256 public currentRate;
event Transfer(address indexed from, address indexed to, uint tokens);
constructor(
uint256 _collateralRate,
uint256 _thresholdRate,
uint256 _currentRate
) public {
collateralRate = _collateralRate;
thresholdRate = _thresholdRate;
currentRate = _currentRate;
}
function getGlobalStatus() public view returns (
uint256 _contractLength,
uint256 _thresholdRate,
uint256 _collateralRate,
uint256 _currentRate
) {
return (
contracts.length,
thresholdRate,
collateralRate,
currentRate
);
}
function setCollateralRate(uint256 _collateralRate) public onlyOwner {
collateralRate = _collateralRate;
}
function setThresholdRate(uint256 _thresholdRate) public onlyOwner {
thresholdRate = _thresholdRate;
}
function setCurrentRate(uint256 _currentRate) public onlyOwner {
currentRate = _currentRate;
}
/*
A user issues RTHB contract which collateralizes
the input RBTC for minting RTHB
*/
function issue() public payable {
uint256 RBTC = msg.value;
require(RBTC != 0);
uint256 RTHB = RBTC.mul(100).mul(currentRate).div(collateralRate);
uint256 dropThreshold = RBTC.mul(100).mul(currentRate).div(thresholdRate);
RTHBContract memory newContract = RTHBContract({
owner: msg.sender,
RBTC: RBTC,
RTHB: RTHB,
rate: currentRate,
dropThreshold: dropThreshold,
takeoverAddr: address(0),
invalidContract: false
});
contracts.push(newContract);
balances[msg.sender] = balances[msg.sender].add(RTHB);
_totalSupply = _totalSupply.add(RTHB);
}
/*
An owner claims back the collateralized RBTC
on his/her RTHB contract
*/
function claim(uint256 contractIndex) public payable {
require(contractIndex < contractLength());
RTHBContract storage targetContract = contracts[contractIndex];
require(targetContract.owner == msg.sender);
require(!targetContract.invalidContract);
// Burn RTHB
balances[msg.sender] = balances[msg.sender].sub(targetContract.RTHB);
_totalSupply = _totalSupply.sub(targetContract.RTHB);
// Mark the target contract to be invalid
targetContract.invalidContract = true;
// Transfer RBTC back to its owner
msg.sender.transfer(targetContract.RBTC);
}
/*
In case RBTC price on a specific RTHB contract is less than
or equal to the pre-determined "dropThreshold" variable,
that contract is open for the public to take over.
To take over the contract, an invoker has to spend
his/her own RTHB to take away the taken over contract's
collateralized RBTC.
*/
function publicTakeover(uint256 _contractIndex) public payable {
require(_contractIndex < contractLength());
RTHBContract storage targetContract = contracts[_contractIndex];
require(targetContract.owner != msg.sender);
require(!targetContract.invalidContract);
require(balances[msg.sender] >= targetContract.RTHB);
require(targetContract.RBTC.mul(currentRate) <= targetContract.dropThreshold);
// Burn RTHB
balances[msg.sender] = balances[msg.sender].sub(targetContract.RTHB);
_totalSupply = _totalSupply.sub(targetContract.RTHB);
// Set the takeover address
targetContract.takeoverAddr = msg.sender;
// Mark the target contract to be invalid
targetContract.invalidContract = true;
// Transfer RBTC to the invoker
msg.sender.transfer(targetContract.RBTC);
}
// Transfer the RTHB balance from owner's account to another account
function transfer(address to, uint tokens) public returns (bool success) {
balances[msg.sender] = balances[msg.sender].sub(tokens);
balances[to] = balances[to].add(tokens);
emit Transfer(msg.sender, to, tokens);
return true;
}
function balanceOf(address tokenOwner)
public view
returns (uint256 balance) {
return balances[tokenOwner];
}
function contractLength() public view returns (uint256) {
return contracts.length;
}
function getContractInfo(uint256 _contractIndex)
public view
returns (
address owner,
uint256 RBTC,
uint256 RTHB,
uint256 rate,
uint256 dropThreshold,
address takeoverAddr,
bool invalidContract
) {
return (
contracts[_contractIndex].owner,
contracts[_contractIndex].RBTC,
contracts[_contractIndex].RTHB,
contracts[_contractIndex].rate,
contracts[_contractIndex].dropThreshold,
contracts[_contractIndex].takeoverAddr,
contracts[_contractIndex].invalidContract
);
}
function convertToRTHB(uint256 _RBTC)
public view
returns (uint256 _RTHB) {
return _RBTC.mul(100).mul(currentRate).div(collateralRate);
}
}