@@ -9,52 +9,69 @@ import "../libraries/MathUtils.sol";
9
9
import "zeppelin-solidity/contracts/math/SafeMath.sol " ;
10
10
11
11
12
+ /**
13
+ * @title RoundsManager
14
+ * @dev Manages round progression and other blockchain time related operations of the Livepeer protocol
15
+ */
12
16
contract RoundsManager is ManagerProxyTarget , IRoundsManager {
13
17
using SafeMath for uint256 ;
14
18
15
19
// Round length in blocks
16
20
uint256 public roundLength;
17
-
18
21
// Lock period of a round as a % of round length
19
22
// Transcoders cannot join the transcoder pool or change their rates during the lock period at the end of a round
20
23
// The lock period provides delegators time to review transcoder information without changes
21
24
// # of blocks in the lock period = (roundLength * roundLockAmount) / PERC_DIVISOR
22
25
uint256 public roundLockAmount;
23
-
24
26
// Last initialized round. After first round, this is the last round during which initializeRound() was called
25
27
uint256 public lastInitializedRound;
26
-
28
+ // Round in which roundLength was last updated
29
+ uint256 public lastRoundLengthUpdateRound;
30
+ // Start block of the round in which roundLength was last updated
31
+ uint256 public lastRoundLengthUpdateStartBlock;
32
+
33
+ /**
34
+ * @dev RoundsManager constructor. Only invokes constructor of base Manager contract with provided Controller address
35
+ * @param _controller Address of Controller that this contract will be registered with
36
+ */
27
37
function RoundsManager (address _controller ) public Manager (_controller) {}
28
38
29
- /*
30
- * @dev Batch set protocol parameters . Only callable by the controller owner
39
+ /**
40
+ * @dev Set round length . Only callable by the controller owner
31
41
* @param _roundLength Round length in blocks
32
42
*/
33
- function setParameters (uint256 _roundLength , uint256 _roundLockAmount ) external onlyControllerOwner {
34
- // Must be a valid percentage
35
- require (MathUtils.validPerc (_roundLockAmount));
36
-
37
- roundLength = _roundLength;
38
- roundLockAmount = _roundLockAmount;
39
-
40
- if (lastInitializedRound == 0 ) {
41
- lastInitializedRound = currentRound ();
43
+ function setRoundLength (uint256 _roundLength ) external onlyControllerOwner {
44
+ // Round length cannot be 0
45
+ require (_roundLength > 0 );
46
+
47
+ if (roundLength == 0 ) {
48
+ // If first time initializing roundLength, set roundLength before
49
+ // lastRoundLengthUpdateRound and lastRoundLengthUpdateStartBlock
50
+ roundLength = _roundLength;
51
+ lastRoundLengthUpdateRound = currentRound ();
52
+ lastRoundLengthUpdateStartBlock = lastRoundLengthUpdateRound.mul (roundLength);
53
+ } else {
54
+ // If updating roundLength, set roundLength after
55
+ // lastRoundLengthUpdateRound and lastRoundLengthUpdateStartBlock
56
+ lastRoundLengthUpdateRound = currentRound ();
57
+ lastRoundLengthUpdateStartBlock = lastRoundLengthUpdateRound.mul (roundLength);
58
+ roundLength = _roundLength;
42
59
}
43
60
44
- ParameterUpdate ("all " );
61
+ ParameterUpdate ("roundLength " );
45
62
}
46
63
47
- /*
48
- * @dev Set round length . Only callable by the controller owner
49
- * @param _roundLength Round length in blocks
64
+ /**
65
+ * @dev Set round lock amount . Only callable by the controller owner
66
+ * @param _roundLockAmount Round lock amount as a % of the number of blocks in a round
50
67
*/
51
- function setRoundLength (uint256 _roundLength ) external onlyControllerOwner {
52
- roundLength = _roundLength ;
68
+ function setRoundLockAmount (uint256 _roundLockAmount ) external onlyControllerOwner {
69
+ roundLockAmount = _roundLockAmount ;
53
70
54
- ParameterUpdate ("roundLength " );
71
+ ParameterUpdate ("roundLockAmount " );
55
72
}
56
73
57
- /*
74
+ /**
58
75
* @dev Initialize the current round. Called once at the start of any round
59
76
*/
60
77
function initializeRound () external whenSystemNotPaused {
@@ -65,21 +82,22 @@ contract RoundsManager is ManagerProxyTarget, IRoundsManager {
65
82
66
83
// Set current round as initialized
67
84
lastInitializedRound = currRound;
68
-
85
+ // Set active transcoders for the round
69
86
bondingManager ().setActiveTranscoders ();
87
+ // Set mintable rewards for the round
70
88
minter ().setCurrentRewardTokens ();
71
89
72
90
NewRound (currRound);
73
91
}
74
92
75
- /*
93
+ /**
76
94
* @dev Return current block number
77
95
*/
78
96
function blockNum () public view returns (uint256 ) {
79
97
return block .number ;
80
98
}
81
99
82
- /*
100
+ /**
83
101
* @dev Return blockhash for a block
84
102
*/
85
103
function blockHash (uint256 _block ) public view returns (bytes32 ) {
@@ -92,42 +110,51 @@ contract RoundsManager is ManagerProxyTarget, IRoundsManager {
92
110
return block .blockhash (_block);
93
111
}
94
112
95
- /*
113
+ /**
96
114
* @dev Return current round
97
115
*/
98
116
function currentRound () public view returns (uint256 ) {
99
- return blockNum ().div (roundLength);
117
+ // Compute # of rounds since roundLength was last updated
118
+ uint256 roundsSinceUpdate = blockNum ().sub (lastRoundLengthUpdateStartBlock).div (roundLength);
119
+ // Current round = round that roundLength was last updated + # of rounds since roundLength was last updated
120
+ return lastRoundLengthUpdateRound.add (roundsSinceUpdate);
100
121
}
101
122
102
- /*
123
+ /**
103
124
* @dev Return start block of current round
104
125
*/
105
126
function currentRoundStartBlock () public view returns (uint256 ) {
106
- return currentRound ().mul (roundLength);
127
+ // Compute # of rounds since roundLength was last updated
128
+ uint256 roundsSinceUpdate = blockNum ().sub (lastRoundLengthUpdateStartBlock).div (roundLength);
129
+ // Current round start block = start block of round that roundLength was last updated + (# of rounds since roundLenght was last updated * roundLength)
130
+ return lastRoundLengthUpdateStartBlock.add (roundsSinceUpdate.mul (roundLength));
107
131
}
108
132
109
- /*
110
- * @dev Check if current round is initialized i.e. block.number / roundLength == lastInitializedRound
133
+ /**
134
+ * @dev Check if current round is initialized
111
135
*/
112
136
function currentRoundInitialized () public view returns (bool ) {
113
137
return lastInitializedRound == currentRound ();
114
138
}
115
139
116
- /*
140
+ /**
117
141
* @dev Check if we are in the lock period of the current round
118
142
*/
119
143
function currentRoundLocked () public view returns (bool ) {
120
144
uint256 lockedBlocks = MathUtils.percOf (roundLength, roundLockAmount);
121
145
return blockNum ().sub (currentRoundStartBlock ()) >= roundLength.sub (lockedBlocks);
122
146
}
123
147
124
- /*
125
- * @dev Return BondingManager contract ( interface)
148
+ /**
149
+ * @dev Return BondingManager interface
126
150
*/
127
151
function bondingManager () internal view returns (IBondingManager) {
128
152
return IBondingManager (controller.getContract (keccak256 ("BondingManager " )));
129
153
}
130
154
155
+ /**
156
+ * @dev Return Minter interface
157
+ */
131
158
function minter () internal view returns (IMinter) {
132
159
return IMinter (controller.getContract (keccak256 ("Minter " )));
133
160
}
0 commit comments