forked from m10io/tokeninc-smart-contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTokenIOCurrencyAuthority.sol
283 lines (257 loc) · 12.4 KB
/
TokenIOCurrencyAuthority.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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
pragma solidity 0.4.24;
import "./Ownable.sol";
import "./TokenIOStorage.sol";
import "./TokenIOLib.sol";
/*
COPYRIGHT 2018 Token, Inc.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@title TokenIOCurrencyAuthority - Currency Authority Smart Contract for Token, Inc.
@author Ryan Tate <[email protected]>, Sean Pollock <[email protected]>
@notice Contract uses generalized storage contract, `TokenIOStorage`, for
upgradeability of interface contract.
*/
contract TokenIOCurrencyAuthority is Ownable {
/// @dev Set reference to TokenIOLib interface which proxies to TokenIOStorage */
using TokenIOLib for TokenIOLib.Data;
TokenIOLib.Data lib;
/**
* @notice Constructor method for CurrencyAuthority contract
* @param _storageContract Address of TokenIOStorage contract
*/
constructor(address _storageContract) public {
/**
* @notice Set the storage contract for the interface
* @dev This contract will be unable to use the storage constract until
* @dev Contract address is authorized with the storage contract
*/
lib.Storage = TokenIOStorage(_storageContract);
// @dev set owner to contract initiator
owner[msg.sender] = true;
}
/**
* @notice Gets balance of sepcified account for a given currency
* @param currency Currency symbol 'USDx'
* @param account Sepcified account address
* @return { "balance": "Returns account balance"}
*/
function getTokenBalance(string currency, address account) public view returns (uint balance) {
return lib.getTokenBalance(currency, account);
}
/**
* @notice Gets total supply of specified currency
* @param currency Currency symbol 'USDx'
* @return { "supply": "Returns total supply of currency"}
*/
function getTokenSupply(string currency) public view returns (uint supply) {
return lib.getTokenSupply(currency);
}
/**
* @notice Updates account status. false: frozen, true: un-frozen
* @param account Sepcified account address
* @param isAllowed Frozen status
* @param issuerFirm Name of the issuer firm with authority on account holder;
* @return { "success": "Returns true if successfully called from another contract"}
*/
function freezeAccount(address account, bool isAllowed, string issuerFirm) public onlyAuthority(issuerFirm, msg.sender) returns (bool success) {
// @notice updates account status
// @dev !!! mutates storage state
require(
lib.setAccountStatus(account, isAllowed, issuerFirm),
"Error: Unable to freeze account. Please check issuerFirm and firm authority are registered"
);
return true;
}
/**
* @notice Sets approval status of specified account
* @param account Sepcified account address
* @param isApproved Frozen status
* @param issuerFirm Name of the issuer firm with authority on account holder;
* @return { "success": "Returns true if successfully called from another contract"}
*/
function approveKYC(address account, bool isApproved, uint limit, string issuerFirm) public onlyAuthority(issuerFirm, msg.sender) returns (bool success) {
// @notice updates kyc approval status
// @dev !!! mutates storage state
require(
lib.setKYCApproval(account, isApproved, issuerFirm),
"Error: Unable to approve account. Please check issuerFirm and firm authority are registered"
);
// @notice updates account statuss
// @dev !!! mutates storage state
require(
lib.setAccountStatus(account, isApproved, issuerFirm),
"Error: Unable to set account status. Please check issuerFirm and firm authority are registered"
);
require(
lib.setAccountSpendingLimit(account, limit),
"Error: Unable to set initial spending limit for account. Please check issuerFirm and firm authority are registered"
);
require(
lib.setAccountSpendingPeriod(account, (now + 86400)),
"Error: Unable to set spending period for account. Please check issuerFirm and firm authority are registered"
);
return true;
}
/**
* @notice Approves account and deposits specified amount of given currency
* @param currency Currency symbol of amount to be deposited;
* @param account Ethereum address of account holder;
* @param amount Deposit amount for account holder;
* @param issuerFirm Name of the issuer firm with authority on account holder;
* @return { "success": "Returns true if successfully called from another contract"}
*/
function approveKYCAndDeposit(string currency, address account, uint amount, uint limit, string issuerFirm) public onlyAuthority(issuerFirm, msg.sender) returns (bool success) {
/// @notice updates kyc approval status
/// @dev !!! mutates storage state
require(
lib.setKYCApproval(account, true, issuerFirm),
"Error: Unable to approve account. Please check issuerFirm and firm authority are registered"
);
/// @notice updates kyc approval status
/// @dev !!! mutates storage state
require(
lib.setAccountStatus(account, true, issuerFirm),
"Error: Unable to set account status. Please check issuerFirm and firm authority are registered"
);
require(
lib.deposit(currency, account, amount, issuerFirm),
"Error: Unable to deposit funds. Please check issuerFirm and firm authority are registered"
);
require(
lib.setAccountSpendingLimit(account, limit),
"Error: Unable to set initial spending limit for account. Please check issuerFirm and firm authority are registered"
);
require(
lib.setAccountSpendingPeriod(account, (now + 86400)),
"Error: Unable to set spending period for account. Please check issuerFirm and firm authority are registered"
);
return true;
}
/**
* @notice Sets the spending limit for a given account
* @param account Ethereum address of account holder;
* @param limit Spending limit amount for account;
* @param issuerFirm Name of the issuer firm with authority on account holder;
* @return { "success": "Returns true if successfully called from another contract"}
*/
function setAccountSpendingLimit(address account, uint limit, string issuerFirm) public onlyAuthority(issuerFirm, msg.sender) returns (bool success) {
require(
lib.setAccountSpendingLimit(account, limit),
"Error: Unable to set initial spending limit for account. Please check issuerFirm and firm authority are registered"
);
return true;
}
/**
* @notice Returns the periodic remaining spending amount for an account
* @param account Ethereum address of account holder;
* @return {"spendingRemaining" : "Returns the remaining spending amount for the account"}
*/
function getAccountSpendingRemaining(address account) public view returns (uint spendingRemaining) {
return lib.getAccountSpendingRemaining(account);
}
/**
* @notice Return the spending limit for an account
* @param account Ethereum address of account holder
* @return {"spendingLimit" : "Returns the remaining daily spending limit of the account"}
*/
function getAccountSpendingLimit(address account) public view returns (uint spendingLimit) {
return lib.getAccountSpendingLimit(account);
}
/**
* @notice Set the foreign currency exchange rate to USD in basis points
* @dev NOTE: This value should always be relative to USD pair; e.g. JPY/USD, GBP/USD, etc.
* @param currency The TokenIO currency symbol (e.g. USDx, JPYx, GBPx)
* @param bpsRate Basis point rate of foreign currency exchange rate to USD
* @param issuerFirm Firm setting the foreign currency exchange
* @return { "success": "Returns true if successfully called from another contract"}
*/
function setFxBpsRate(string currency, uint bpsRate, string issuerFirm) public onlyAuthority(issuerFirm, msg.sender) returns (bool success) {
require(
lib.setFxUSDBPSRate(currency, bpsRate),
"Error: Unable to set FX USD basis points rate. Please ensure issuerFirm is authorized"
);
return true;
}
/**
* @notice Return the foreign currency USD exchanged amount
* @param currency The TokenIO currency symbol (e.g. USDx, JPYx, GBPx)
* @param fxAmount Amount of foreign currency to exchange into USD
* @return {"usdAmount" : "Returns the foreign currency amount in USD"}
*/
function getFxUSDAmount(string currency, uint fxAmount) public view returns (uint usdAmount) {
return lib.getFxUSDAmount(currency, fxAmount);
}
/**
* @notice Updates to new forwarded account
* @param originalAccount [address]
* @param updatedAccount [address]
* @param issuerFirm Name of the issuer firm with authority on account holder;
* @return { "success": "Returns true if successfully called from another contract"}
*/
function approveForwardedAccount(address originalAccount, address updatedAccount, string issuerFirm) public onlyAuthority(issuerFirm, msg.sender) returns (bool success) {
// @notice updatesa forwarded account
// @dev !!! mutates storage state
require(
lib.setForwardedAccount(originalAccount, updatedAccount),
"Error: Unable to set forwarded address for account. Please check issuerFirm and firm authority are registered"
);
return true;
}
/**
* @notice Issues a specified account to recipient account of a given currency
* @param currency [string] currency symbol
* @param amount [uint] issuance amount
* @param issuerFirm Name of the issuer firm with authority on account holder;
* @return { "success": "Returns true if successfully called from another contract"}
*/
function deposit(string currency, address account, uint amount, string issuerFirm) public onlyAuthority(issuerFirm, msg.sender) returns (bool success) {
require(
lib.verifyAccount(account),
"Error: Account is not verified!"
);
// @notice depositing tokens to account
// @dev !!! mutates storage state
require(
lib.deposit(currency, account, amount, issuerFirm),
"Error: Unable to deposit funds. Please check issuerFirm and firm authority are registered"
);
return true;
}
/**
* @notice Withdraws a specified amount of tokens of a given currency
* @param currency Currency symbol
* @param account Ethereum address of account holder
* @param amount Issuance amount
* @param issuerFirm Name of the issuer firm with authority on account holder
* @return { "success": "Returns true if successfully called from another contract"}
*/
function withdraw(string currency, address account, uint amount, string issuerFirm) public onlyAuthority(issuerFirm, msg.sender) returns (bool success) {
require(
lib.verifyAccount(account),
"Error: Account is not verified!"
);
// @notice withdrawing from account
// @dev !!! mutates storage state
require(
lib.withdraw(currency, account, amount, issuerFirm),
"Error: Unable to withdraw funds. Please check issuerFirm and firm authority are registered and have issued funds that can be withdrawn"
);
return true;
}
/**
* @notice Ensure only authorized currency firms and authorities can modify protected methods
* @dev authority must be registered to an authorized firm to use protected methods
*/
modifier onlyAuthority(string firmName, address authority) {
// @notice throws if authority account is not registred to the given firm
require(
lib.isRegisteredToFirm(firmName, authority),
"Error: issuerFirm and/or firm authority are not registered"
);
_;
}
}