-
Notifications
You must be signed in to change notification settings - Fork 3
/
QiibeeToken.sol
180 lines (158 loc) · 6.09 KB
/
QiibeeToken.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
pragma solidity ^0.4.11;
import "zeppelin-solidity/contracts/token/PausableToken.sol";
import "zeppelin-solidity/contracts/token/MintableToken.sol";
import "zeppelin-solidity/contracts/token/BurnableToken.sol";
import "zeppelin-solidity/contracts/token/VestedToken.sol";
// @dev Migration Agent interface
contract MigrationAgentInterface {
function migrateFrom(address _from, uint256 _value);
function setSourceToken(address _qbxSourceToken);
function updateSupply();
function qbxSourceToken() returns (address);
}
/**
@title QBX, the qiibee token
Implementation of QBX, an ERC20 token for the qiibee ecosystem. The smallest unit of a qbx is
the atto. The token call be migrated to a new token by calling the `migrate()` function.
*/
contract QiibeeToken is BurnableToken, PausableToken, VestedToken, MintableToken {
using SafeMath for uint256;
string public constant symbol = "QBX";
string public constant name = "qiibeeCoin";
uint8 public constant decimals = 18;
// migration vars
uint256 public totalMigrated;
uint256 public newTokens; // amount of tokens minted after migrationAgent has been set
uint256 public burntTokens; // amount of tokens burnt after migrationAgent has been set
address public migrationAgent;
address public migrationMaster;
event Migrate(address indexed _from, address indexed _to, uint256 _value);
event NewVestedToken(address indexed from, address indexed to, uint256 value, uint256 grantId);
modifier onlyMigrationMaster {
require(msg.sender == migrationMaster);
_;
}
/*
* Constructor.
*/
function QiibeeToken(address _migrationMaster) {
require(_migrationMaster != address(0));
migrationMaster = _migrationMaster;
}
/**
@dev Similar to grantVestedTokens but minting tokens instead of transferring.
*/
function mintVestedTokens (
address _to,
uint256 _value,
uint64 _start,
uint64 _cliff,
uint64 _vesting,
bool _revokable,
bool _burnsOnRevoke,
address _wallet
) onlyOwner public returns (bool) {
// Check for date inconsistencies that may cause unexpected behavior
require(_cliff >= _start && _vesting >= _cliff);
require(tokenGrantsCount(_to) < MAX_GRANTS_PER_ADDRESS); // To prevent a user being spammed and have his balance locked (out of gas attack when calculating vesting).
uint256 count = grants[_to].push(
TokenGrant(
_revokable ? _wallet : 0, // avoid storing an extra 20 bytes when it is non-revokable
_value,
_cliff,
_vesting,
_start,
_revokable,
_burnsOnRevoke
)
);
NewVestedToken(msg.sender, _to, _value, count - 1);
return mint(_to, _value); //mint tokens
}
/**
@dev Overrides VestedToken#grantVestedTokens(). Only owner can call it.
*/
function grantVestedTokens (
address _to,
uint256 _value,
uint64 _start,
uint64 _cliff,
uint64 _vesting,
bool _revokable,
bool _burnsOnRevoke
) onlyOwner public {
super.grantVestedTokens(_to, _value, _start, _cliff, _vesting, _revokable, _burnsOnRevoke);
}
/**
@dev Set address of migration agent contract and enable migration process.
@param _agent The address of the MigrationAgent contract
*/
function setMigrationAgent(address _agent) public onlyMigrationMaster {
require(MigrationAgentInterface(_agent).qbxSourceToken() == address(this));
require(migrationAgent == address(0));
require(_agent != address(0));
migrationAgent = _agent;
}
/**
@dev Migrates the tokens to the target token through the MigrationAgent.
@param _value The amount of tokens (in atto) to be migrated.
*/
function migrate(uint256 _value) public whenNotPaused {
require(migrationAgent != address(0));
require(_value != 0);
require(_value <= balances[msg.sender]);
require(_value <= transferableTokens(msg.sender, uint64(now)));
balances[msg.sender] = balances[msg.sender].sub(_value);
totalSupply = totalSupply.sub(_value);
totalMigrated = totalMigrated.add(_value);
MigrationAgentInterface(migrationAgent).migrateFrom(msg.sender, _value);
Migrate(msg.sender, migrationAgent, _value);
}
/**
* @dev Overrides mint() function so as to keep track of the tokens minted after the
* migrationAgent has been set. This is to ensure that the migration agent has always the
* totalTokens variable up to date. This prevents the failure of the safetyInvariantCheck().
* @param _to The address that will receive the minted tokens.
* @param _amount The amount of tokens to mint.
* @return A boolean that indicates if the operation was successful.
*/
function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
bool mint = super.mint(_to, _amount);
if (mint && migrationAgent != address(0)) {
newTokens = newTokens.add(_amount);
}
return mint;
}
/*
* @dev Changes the migration master.
* @param _master The address of the migration master.
*/
function setMigrationMaster(address _master) public onlyMigrationMaster {
require(_master != address(0));
migrationMaster = _master;
}
/*
* @dev Resets newTokens to zero. Can only be called by the migrationAgent
*/
function resetNewTokens() {
require(msg.sender == migrationAgent);
newTokens = 0;
}
/*
* @dev Resets burntTokens to zero. Can only be called by the migrationAgent
*/
function resetBurntTokens() {
require(msg.sender == migrationAgent);
burntTokens = 0;
}
/*
* @dev Burns a specific amount of tokens.
* @param _value The amount of tokens to be burnt.
*/
function burn(uint256 _value) whenNotPaused onlyOwner public {
super.burn(_value);
if (migrationAgent != address(0)) {
burntTokens = burntTokens.add(_value);
}
}
}