-
Notifications
You must be signed in to change notification settings - Fork 0
/
vGlobalMinter.sol
138 lines (124 loc) · 4.39 KB
/
vGlobalMinter.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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/utils/math/Math.sol';
import './libraries/EmissionMath.sol';
import './interfaces/IvGlobalMinter.sol';
import './vVestingWallet.sol';
import './Vrsw.sol';
import './GVrsw.sol';
/**
* @title vGlobalMinter
* @dev This contract is responsible for minting and distributing VRSW and gVrsw
* tokens.
*/
contract vGlobalMinter is IvGlobalMinter, Ownable {
address[] public vestingWallets;
Vrsw public vrsw;
GVrsw public gVrsw;
uint256 public startEpochTime;
uint256 public epochDuration;
uint256 public epochPreparationTime;
uint256 public nextEpochDuration;
uint256 public nextEpochPreparationTime;
uint256 public unlockedBalance;
uint256 public immutable emissionStartTs;
/**
* @dev Constructor function
* @param _emissionStartTs Timestamp of the start of emission
*/
constructor(uint256 _emissionStartTs) {
emissionStartTs = _emissionStartTs;
unlockedBalance = 5e8 * 1e18;
epochDuration = 4 weeks;
epochPreparationTime = 1 weeks;
startEpochTime = _emissionStartTs - epochDuration;
vrsw = new Vrsw(address(this));
gVrsw = new GVrsw(address(this));
}
/// @inheritdoc IvGlobalMinter
function addChainMinter() external override onlyOwner {
gVrsw.mint(msg.sender, 1e9 * 1e18);
}
/// @inheritdoc IvGlobalMinter
function newVesting(
address beneficiary,
uint256 startTs,
uint256 duration,
uint256 amount
) external override onlyOwner returns (address vestingWallet) {
require(block.timestamp >= emissionStartTs, 'too early');
require(amount <= unlockedBalance, 'not enough unlocked tokens');
vestingWallet = address(
new vVestingWallet(
beneficiary,
address(vrsw),
uint64(startTs),
uint64(duration)
)
);
vestingWallets.push(vestingWallet);
SafeERC20.safeTransfer(IERC20(vrsw), vestingWallet, amount);
emit NewVesting(vestingWallet, beneficiary, startTs, duration);
}
/// @inheritdoc IvGlobalMinter
function arbitraryTransfer(
address to,
uint256 amount
) external override onlyOwner {
require(block.timestamp >= emissionStartTs, 'too early');
require(amount <= unlockedBalance, 'not enough unlocked tokens');
SafeERC20.safeTransfer(IERC20(vrsw), to, amount);
}
/// @inheritdoc IvGlobalMinter
function nextEpochTransfer() external override onlyOwner {
uint256 currentEpochEnd = startEpochTime + epochDuration;
if (block.timestamp >= currentEpochEnd) {
_epochTransition();
currentEpochEnd = startEpochTime + epochDuration;
}
require(
block.timestamp + epochPreparationTime >= currentEpochEnd,
'Too early'
);
uint256 amountToTransfer = EmissionMath.calculateAlgorithmicEmission(
currentEpochEnd - emissionStartTs,
currentEpochEnd +
(nextEpochDuration > 0 ? nextEpochDuration : epochDuration) -
emissionStartTs
);
SafeERC20.safeTransfer(IERC20(vrsw), msg.sender, amountToTransfer);
}
/// @inheritdoc IvGlobalMinter
function setEpochParams(
uint256 _epochDuration,
uint256 _epochPreparationTime
) external override onlyOwner {
require(
_epochPreparationTime > 0 && _epochDuration > 0,
'must be greater than zero'
);
require(
_epochPreparationTime < _epochDuration,
'preparationTime >= epochDuration'
);
if (block.timestamp >= startEpochTime + epochDuration)
_epochTransition();
(nextEpochPreparationTime, nextEpochDuration) = (
_epochPreparationTime,
_epochDuration
);
}
function _epochTransition() private {
startEpochTime += epochDuration;
if (nextEpochDuration > 0) {
epochDuration = nextEpochDuration;
nextEpochDuration = 0;
}
if (nextEpochPreparationTime > 0) {
epochPreparationTime = nextEpochPreparationTime;
nextEpochPreparationTime = 0;
}
}
}