-
Notifications
You must be signed in to change notification settings - Fork 2
/
token.sol
169 lines (139 loc) · 5.45 KB
/
token.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
pragma solidity ^0.4.21;
/**
* @title SafeMath
* @dev Math operations with necessary safety checks.
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws an error on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
// Gas optimization: using 'if' is cheaper than asserting 'a' not being zero.
// See https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Division of two integers, truncating the quotient.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Subtracts two numbers, throws on overflow if subtracted is greater than the number.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws an error on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
}
/**
* @title Token
* @dev A minimal lockable token.
*/
contract Token {
using SafeMath for uint256;
// A map of client addresses to their total amount of tokens (locked + available)
mapping (address => uint256) public totalTokens;
// A map of client addresses to the amout of locked tokens.
mapping (address => uint256) public lockedTokens;
// A map of client addresses to times (unix time) when the client locked funds.
mapping (address => uint256[]) public lockingTimes;
// A map of client addresses to the amount of tokens locked.
// These amounts correspond to the times stored in lockingTimes.
mapping (address => uint256[]) public lockingAmounts;
// Interest multiplier, where locking 1 token produces M new tokens.
// We expect that M will be significantly lower than 1.
uint256 public M;
// The duration that tokens will be locked, in unix time.
uint256 public LT;
function Token(address _client, uint256 _clientTokens,
uint256 _lockingDuration, uint256 _multiplier) public {
totalTokens[_client] = _clientTokens;
LT = _lockingDuration;
M = _multiplier;
}
/**
* @dev Lock the tokens (A_lock) for a specified time period
* from the recipient's address by an owner,
* and apply a prepaid interest ('M')
*/
function lock(address _from, address _to, uint256 A_lock, uint256 A_spend) public {
// Calculating the lock time for the tokens.
uint256 lockUntil = (now).add(LT);
// Substracting the A_spend from client's (_from) balance.
totalTokens[_from] = totalTokens[_from].sub(A_spend);
// Add the tokens to the "lockedTokens" array.
lockedTokens[_from] = lockedTokens[_from].add(A_lock);
// Calculating the prepaid interest
uint256 reward = (M.mul(A_lock)).add(A_spend);
// Adding the interest/reward to the recipient's address.
totalTokens[_to] = totalTokens[_to].add(reward);
// Storing the time when the locked tokens may be used by _from again.
lockingTimes[_from].push(lockUntil);
lockingAmounts[_from].push(A_lock);
}
/**
* @dev Regains the tokens previously locked from the recipient,
* after the elapse of time period -- 'LT'.
*/
function unlock(address _client) public {
uint256 i = 0;
// Unlock all tokens that have passed their locking period.
while(i < lockingTimes[_client].length && now > lockingTimes[_client][i]){
uint256 amt = lockingAmounts[_client][i];
lockedTokens[_client] = lockedTokens[_client].sub(amt);
i++;
}
// Removing elapsed locking time periods and tokens.
uint256[] remainingLockingTimes;
uint256[] remainingLockingAmounts;
while(i < lockingTimes[_client].length) {
remainingLockingTimes.push(lockingTimes[_client][i]);
remainingLockingAmounts.push(lockingAmounts[_client][i]);
i++;
}
// Re-assigning the remaining locking times and amounts.
lockingTimes[_client] = remainingLockingTimes;
lockingAmounts[_client] = remainingLockingAmounts;
}
/**
* @dev Get the total amount of tokens (locked + availableTokens).
*/
function getTotalTokens(address _client) public view returns (uint256) {
// The total client balance initialized before deploying the contract.
return totalTokens[_client];
}
/**
* @dev Get the locking times associated to the client address.
*/
function getLockingTimes(address _client) public view returns (uint256) {
return lockingTimes[_client][0];
}
/**
* @dev Get the available tokens to spend after the locked tokens are deducted.
*/
function getAvailableTokens(address _client) public view returns (uint256) {
// Calculating the availableTokens owned by a client after deducting the locked tokens.
return totalTokens[_client].sub(lockedTokens[_client]);
}
/**
* @dev Get the specified amount of locked tokens.
*/
function getLockedTokens(address _client) public view returns (uint256) {
// Returns the number of locked tokens owned by a client.
return lockedTokens[_client];
}
}