Skip to content

Commit faafca2

Browse files
committed
Ensure roundLength can be increased/decreased. Refactored RoundsManager unit test
1 parent ab92259 commit faafca2

File tree

6 files changed

+291
-133
lines changed

6 files changed

+291
-133
lines changed

.gitattributes

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.sol linguist-language=Solidity

contracts/rounds/IRoundsManager.sol

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
pragma solidity ^0.4.17;
22

33

4-
/*
5-
* @title Interface for RoundsManager
4+
/**
5+
* @title RoundsManager interface
66
*/
7-
contract IRoundsManager {
7+
interface IRoundsManager {
8+
// Events
89
event NewRound(uint256 round);
910

1011
// External functions

contracts/rounds/RoundsManager.sol

+61-34
Original file line numberDiff line numberDiff line change
@@ -9,52 +9,69 @@ import "../libraries/MathUtils.sol";
99
import "zeppelin-solidity/contracts/math/SafeMath.sol";
1010

1111

12+
/**
13+
* @title RoundsManager
14+
* @dev Manages round progression and other blockchain time related operations of the Livepeer protocol
15+
*/
1216
contract RoundsManager is ManagerProxyTarget, IRoundsManager {
1317
using SafeMath for uint256;
1418

1519
// Round length in blocks
1620
uint256 public roundLength;
17-
1821
// Lock period of a round as a % of round length
1922
// Transcoders cannot join the transcoder pool or change their rates during the lock period at the end of a round
2023
// The lock period provides delegators time to review transcoder information without changes
2124
// # of blocks in the lock period = (roundLength * roundLockAmount) / PERC_DIVISOR
2225
uint256 public roundLockAmount;
23-
2426
// Last initialized round. After first round, this is the last round during which initializeRound() was called
2527
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+
*/
2737
function RoundsManager(address _controller) public Manager(_controller) {}
2838

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
3141
* @param _roundLength Round length in blocks
3242
*/
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;
4259
}
4360

44-
ParameterUpdate("all");
61+
ParameterUpdate("roundLength");
4562
}
4663

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
5067
*/
51-
function setRoundLength(uint256 _roundLength) external onlyControllerOwner {
52-
roundLength = _roundLength;
68+
function setRoundLockAmount(uint256 _roundLockAmount) external onlyControllerOwner {
69+
roundLockAmount = _roundLockAmount;
5370

54-
ParameterUpdate("roundLength");
71+
ParameterUpdate("roundLockAmount");
5572
}
5673

57-
/*
74+
/**
5875
* @dev Initialize the current round. Called once at the start of any round
5976
*/
6077
function initializeRound() external whenSystemNotPaused {
@@ -65,21 +82,22 @@ contract RoundsManager is ManagerProxyTarget, IRoundsManager {
6582

6683
// Set current round as initialized
6784
lastInitializedRound = currRound;
68-
85+
// Set active transcoders for the round
6986
bondingManager().setActiveTranscoders();
87+
// Set mintable rewards for the round
7088
minter().setCurrentRewardTokens();
7189

7290
NewRound(currRound);
7391
}
7492

75-
/*
93+
/**
7694
* @dev Return current block number
7795
*/
7896
function blockNum() public view returns (uint256) {
7997
return block.number;
8098
}
8199

82-
/*
100+
/**
83101
* @dev Return blockhash for a block
84102
*/
85103
function blockHash(uint256 _block) public view returns (bytes32) {
@@ -92,42 +110,51 @@ contract RoundsManager is ManagerProxyTarget, IRoundsManager {
92110
return block.blockhash(_block);
93111
}
94112

95-
/*
113+
/**
96114
* @dev Return current round
97115
*/
98116
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);
100121
}
101122

102-
/*
123+
/**
103124
* @dev Return start block of current round
104125
*/
105126
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));
107131
}
108132

109-
/*
110-
* @dev Check if current round is initialized i.e. block.number / roundLength == lastInitializedRound
133+
/**
134+
* @dev Check if current round is initialized
111135
*/
112136
function currentRoundInitialized() public view returns (bool) {
113137
return lastInitializedRound == currentRound();
114138
}
115139

116-
/*
140+
/**
117141
* @dev Check if we are in the lock period of the current round
118142
*/
119143
function currentRoundLocked() public view returns (bool) {
120144
uint256 lockedBlocks = MathUtils.percOf(roundLength, roundLockAmount);
121145
return blockNum().sub(currentRoundStartBlock()) >= roundLength.sub(lockedBlocks);
122146
}
123147

124-
/*
125-
* @dev Return BondingManager contract (interface)
148+
/**
149+
* @dev Return BondingManager interface
126150
*/
127151
function bondingManager() internal view returns (IBondingManager) {
128152
return IBondingManager(controller.getContract(keccak256("BondingManager")));
129153
}
130154

155+
/**
156+
* @dev Return Minter interface
157+
*/
131158
function minter() internal view returns (IMinter) {
132159
return IMinter(controller.getContract(keccak256("Minter")));
133160
}

migrations/3_deploy_contracts.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ module.exports = function(deployer, network) {
4545
config.jobsManager.doubleClaimSegmentSlashAmount,
4646
config.jobsManager.finderFee
4747
)
48-
await roundsManager.setParameters(config.roundsManager.roundLength, config.roundsManager.roundLockAmount)
48+
49+
// Set RoundsManager parameters
50+
await roundsManager.setRoundLength(config.roundsManager.roundLength)
51+
await roundsManager.setRoundLockAmount(config.roundsManager.roundLockAmount)
4952
})
5053
}

0 commit comments

Comments
 (0)