-
Notifications
You must be signed in to change notification settings - Fork 0
/
TokenMinter.sol
168 lines (130 loc) · 5.08 KB
/
TokenMinter.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
pragma solidity 0.5.10;
interface IToken {
function claimTokens(address _token, address payable _to) external;
function mint(address _to, uint256 _amount) external returns (bool);
function setBridgeContract(address _bridgeContract) external;
function transferOwnership(address _newOwner) external;
}
/// @dev Used when we need to have an ability to mint POSDAO tokens not only by the bridge,
/// but also by the BlockRewardAuRa contract if the staking token contract doesn't support
/// the `mintReward` function.
contract TokenMinter {
address public owner;
address public blockRewardContract;
IToken public tokenContract;
address public constant F_ADDR = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF;
uint256 internal constant MAX_MINTERS = 50;
mapping(address => address) public minterPointers;
uint256 public minterCount;
event BlockRewardContractSet(address blockRewardContractAddress);
event MinterAdded(address indexed minter);
event MinterRemoved(address indexed minter);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
modifier onlyBlockRewardContract() {
require(msg.sender == blockRewardContract);
_;
}
modifier onlyMinter() {
require(isMinter(msg.sender));
_;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
constructor(
address _owner,
address _blockRewardContract,
address _bridgeContract,
IToken _tokenContract
) public {
_transferOwnership(_owner);
_setBlockRewardContract(_blockRewardContract);
minterPointers[F_ADDR] = F_ADDR; // initially empty minter list
_addMinter(_bridgeContract);
require(_isContract(address(_tokenContract)));
tokenContract = _tokenContract;
}
function addMinter(address _minter) external onlyOwner {
_addMinter(_minter);
}
function removeMinter(address _minter) external onlyOwner {
require(isMinter(_minter));
address nextMinter = minterPointers[_minter];
address index = F_ADDR;
address next = minterPointers[index];
require(next != address(0));
while (next != _minter) {
index = next;
next = minterPointers[index];
require(next != F_ADDR && next != address(0));
}
minterPointers[index] = nextMinter;
delete minterPointers[_minter];
minterCount--;
emit MinterRemoved(_minter);
}
function claimTokens(address _token, address payable _to) external onlyOwner {
tokenContract.claimTokens(_token, _to);
}
function mint(address _to, uint256 _amount) external onlyMinter returns (bool) {
return tokenContract.mint(_to, _amount);
}
function mintReward(uint256 _amount) external onlyBlockRewardContract {
if (_amount == 0) return;
tokenContract.mint(blockRewardContract, _amount);
}
function setBlockRewardContract(address _blockRewardContract) external onlyOwner {
_setBlockRewardContract(_blockRewardContract);
}
function setBridgeContract(address _bridgeContract) external onlyOwner {
tokenContract.setBridgeContract(_bridgeContract);
}
function transferOwnership(address _newOwner) external onlyOwner {
_transferOwnership(_newOwner);
}
function transferTokenOwnership(address _newOwner) external onlyOwner {
tokenContract.transferOwnership(_newOwner);
}
function isMinter(address _address) public view returns (bool) {
return _address != F_ADDR && minterPointers[_address] != address(0);
}
function minterList() external view returns (address[] memory list) {
list = new address[](minterCount);
uint256 counter = 0;
address nextMinter = minterPointers[F_ADDR];
require(nextMinter != address(0));
while (nextMinter != F_ADDR) {
list[counter] = nextMinter;
nextMinter = minterPointers[nextMinter];
counter++;
require(nextMinter != address(0));
}
return list;
}
function _addMinter(address _minter) private {
require(minterCount < MAX_MINTERS);
require(!isMinter(_minter));
address firstMinter = minterPointers[F_ADDR];
require(firstMinter != address(0));
minterPointers[F_ADDR] = _minter;
minterPointers[_minter] = firstMinter;
minterCount++;
emit MinterAdded(_minter);
}
function _setBlockRewardContract(address _blockRewardContract) private {
require(_isContract(_blockRewardContract));
blockRewardContract = _blockRewardContract;
emit BlockRewardContractSet(_blockRewardContract);
}
function _transferOwnership(address _newOwner) private {
require(_newOwner != address(0));
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
function _isContract(address _account) private view returns (bool) {
uint256 size;
assembly { size := extcodesize(_account) }
return size > 0;
}
}