Skip to content

Commit 469ad20

Browse files
authored
epochs: make epoch manager upgradeable (#256)
1 parent f07b62a commit 469ad20

File tree

11 files changed

+122
-49
lines changed

11 files changed

+122
-49
lines changed

contracts/curation/Curation.sol

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,15 @@ contract Curation is CurationV1Storage, ICuration, Governed {
7272
/**
7373
* @dev Initialize this contract.
7474
*/
75-
function initialize(address _token) external onlyGovernorOrInit {
75+
function initialize(
76+
address _token,
77+
uint32 _defaultReserveRatio,
78+
uint256 _minimumCurationStake
79+
) external onlyGovernorOrInit {
7680
BancorFormula._initialize();
7781
token = IGraphToken(_token);
82+
defaultReserveRatio = _defaultReserveRatio;
83+
minimumCurationStake = _minimumCurationStake;
7884
}
7985

8086
/**
@@ -84,7 +90,7 @@ contract Curation is CurationV1Storage, ICuration, Governed {
8490
* @param _defaultReserveRatio Reserve ratio to initialize the bonding curve of CurationPool
8591
* @param _minimumCurationStake Minimum amount of tokens that curators can stake
8692
*/
87-
function acceptUpgrade(
93+
function acceptProxy(
8894
GraphProxy _proxy,
8995
address _token,
9096
uint32 _defaultReserveRatio,
@@ -96,9 +102,7 @@ contract Curation is CurationV1Storage, ICuration, Governed {
96102
_proxy.acceptImplementation();
97103

98104
// Initialization
99-
Curation(address(_proxy)).initialize(_token);
100-
Curation(address(_proxy)).setDefaultReserveRatio(_defaultReserveRatio);
101-
Curation(address(_proxy)).setMinimumCurationStake(_minimumCurationStake);
105+
Curation(address(_proxy)).initialize(_token, _defaultReserveRatio, _minimumCurationStake);
102106
}
103107

104108
/**

contracts/EpochManager.sol renamed to contracts/epochs/EpochManager.sol

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,36 @@ pragma solidity ^0.6.4;
22

33
import "@openzeppelin/contracts/math/SafeMath.sol";
44

5-
import "./governance/Governed.sol";
5+
import "../governance/Governed.sol";
6+
import "../upgrades/GraphProxy.sol";
7+
8+
import "./EpochManagerStorage.sol";
9+
import "./IEpochManager.sol";
610

711
/**
812
* @title EpochManager contract
913
* @dev Tracks epochs based on its block duration to sync contracts in the protocol.
1014
*/
11-
contract EpochManager is Governed {
15+
contract EpochManager is EpochManagerV1Storage, IEpochManager, Governed {
1216
using SafeMath for uint256;
1317

14-
// -- State --
15-
16-
// Epoch length in blocks
17-
uint256 public epochLength;
18-
19-
// Epoch that was last run
20-
uint256 public lastRunEpoch;
21-
22-
// Block and epoch when epoch length was last updated
23-
uint256 public lastLengthUpdateEpoch;
24-
uint256 public lastLengthUpdateBlock;
25-
2618
// -- Events --
2719

2820
event EpochRun(uint256 indexed epoch, address caller);
2921
event EpochLengthUpdate(uint256 indexed epoch, uint256 epochLength);
3022

3123
/**
32-
* @dev Contract Constructor.
33-
* @param _epochLength Epoch length in blocks
24+
* @dev Check if the caller is the governor or initializing the implementation.
3425
*/
35-
constructor(uint256 _epochLength) public {
26+
modifier onlyGovernorOrInit {
27+
require(msg.sender == governor || msg.sender == implementation, "Only Governor can call");
28+
_;
29+
}
30+
31+
/**
32+
* @dev Initialize this contract.
33+
*/
34+
function initialize(uint256 _epochLength) external onlyGovernorOrInit {
3635
require(_epochLength > 0, "Epoch length cannot be 0");
3736

3837
lastLengthUpdateEpoch = 0;
@@ -42,12 +41,27 @@ contract EpochManager is Governed {
4241
emit EpochLengthUpdate(lastLengthUpdateEpoch, epochLength);
4342
}
4443

44+
/**
45+
* @dev Accept to be an implementation of proxy and run initializer.
46+
* @param _proxy Graph proxy delegate caller
47+
* @param _epochLength Epoch length in blocks
48+
*/
49+
function acceptProxy(GraphProxy _proxy, uint256 _epochLength) external {
50+
require(msg.sender == _proxy.governor(), "Only proxy governor can upgrade");
51+
52+
// Accept to be the implementation for this proxy
53+
_proxy.acceptImplementation();
54+
55+
// Initialization
56+
EpochManager(address(_proxy)).initialize(_epochLength);
57+
}
58+
4559
/**
4660
* @dev Set the epoch length.
4761
* @notice Set epoch length to `_epochLength` blocks
4862
* @param _epochLength Epoch length in blocks
4963
*/
50-
function setEpochLength(uint256 _epochLength) external onlyGovernor {
64+
function setEpochLength(uint256 _epochLength) external override onlyGovernor {
5165
require(_epochLength > 0, "Epoch length cannot be 0");
5266
require(_epochLength != epochLength, "Epoch length must be different to current");
5367

@@ -62,7 +76,7 @@ contract EpochManager is Governed {
6276
* @dev Run a new epoch, should be called once at the start of any epoch.
6377
* @notice Perform state changes for the current epoch
6478
*/
65-
function runEpoch() external {
79+
function runEpoch() external override {
6680
// Check if already called for the current epoch
6781
require(!isCurrentEpochRun(), "Current epoch already run");
6882

@@ -77,23 +91,23 @@ contract EpochManager is Governed {
7791
* @dev Return true if the current epoch has already run.
7892
* @return Return true if epoch has run
7993
*/
80-
function isCurrentEpochRun() public view returns (bool) {
94+
function isCurrentEpochRun() public override view returns (bool) {
8195
return lastRunEpoch == currentEpoch();
8296
}
8397

8498
/**
8599
* @dev Return current block number.
86100
* @return Block number
87101
*/
88-
function blockNum() public view returns (uint256) {
102+
function blockNum() public override view returns (uint256) {
89103
return block.number;
90104
}
91105

92106
/**
93107
* @dev Return blockhash for a block.
94108
* @return BlockHash for `_block` number
95109
*/
96-
function blockHash(uint256 _block) public view returns (bytes32) {
110+
function blockHash(uint256 _block) public override view returns (bytes32) {
97111
uint256 currentBlock = blockNum();
98112

99113
require(_block < currentBlock, "Can only retrieve past block hashes");
@@ -109,23 +123,23 @@ contract EpochManager is Governed {
109123
* @dev Return the current epoch, it may have not been run yet.
110124
* @return The current epoch based on epoch length
111125
*/
112-
function currentEpoch() public view returns (uint256) {
126+
function currentEpoch() public override view returns (uint256) {
113127
return lastLengthUpdateEpoch.add(epochsSinceUpdate());
114128
}
115129

116130
/**
117131
* @dev Return block where the current epoch started.
118132
* @return The block number when the current epoch started
119133
*/
120-
function currentEpochBlock() public view returns (uint256) {
134+
function currentEpochBlock() public override view returns (uint256) {
121135
return lastLengthUpdateBlock.add(epochsSinceUpdate().mul(epochLength));
122136
}
123137

124138
/**
125139
* @dev Return the number of blocks that passed since current epoch started.
126140
* @return Blocks that passed since start of epoch
127141
*/
128-
function currentEpochBlockSinceStart() public view returns (uint256) {
142+
function currentEpochBlockSinceStart() public override view returns (uint256) {
129143
return blockNum() - currentEpochBlock();
130144
}
131145

@@ -134,7 +148,7 @@ contract EpochManager is Governed {
134148
* @param _epoch Epoch to use as since epoch value
135149
* @return Number of epochs and current epoch
136150
*/
137-
function epochsSince(uint256 _epoch) public view returns (uint256) {
151+
function epochsSince(uint256 _epoch) public override view returns (uint256) {
138152
uint256 epoch = currentEpoch();
139153
return _epoch < epoch ? epoch.sub(_epoch) : 0;
140154
}
@@ -143,7 +157,7 @@ contract EpochManager is Governed {
143157
* @dev Return number of epochs passed since last epoch length update.
144158
* @return The number of epoch that passed since last epoch length update
145159
*/
146-
function epochsSinceUpdate() public view returns (uint256) {
160+
function epochsSinceUpdate() public override view returns (uint256) {
147161
return blockNum().sub(lastLengthUpdateBlock).div(epochLength);
148162
}
149163
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
pragma solidity ^0.6.4;
2+
3+
import "../upgrades/GraphProxyStorage.sol";
4+
5+
contract EpochManagerV1Storage is GraphProxyStorage {
6+
// -- State --
7+
8+
// Epoch length in blocks
9+
uint256 public epochLength;
10+
11+
// Epoch that was last run
12+
uint256 public lastRunEpoch;
13+
14+
// Block and epoch when epoch length was last updated
15+
uint256 public lastLengthUpdateEpoch;
16+
uint256 public lastLengthUpdateBlock;
17+
}

contracts/epochs/IEpochManager.sol

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
pragma solidity ^0.6.4;
2+
3+
interface IEpochManager {
4+
// -- Configuration --
5+
6+
function setEpochLength(uint256 _epochLength) external;
7+
8+
// -- Epochs
9+
10+
function runEpoch() external;
11+
12+
// -- Getters --
13+
14+
function isCurrentEpochRun() external view returns (bool);
15+
16+
function blockNum() external view returns (uint256);
17+
18+
function blockHash(uint256 _block) external view returns (bytes32);
19+
20+
function currentEpoch() external view returns (uint256);
21+
22+
function currentEpochBlock() external view returns (uint256);
23+
24+
function currentEpochBlockSinceStart() external view returns (uint256);
25+
26+
function epochsSince(uint256 _epoch) external view returns (uint256);
27+
28+
function epochsSinceUpdate() external view returns (uint256);
29+
}

contracts/staking/Staking.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ pragma experimental ABIEncoderV2;
33

44
import "@nomiclabs/buidler/console.sol";
55

6-
import "../EpochManager.sol";
76
import "../curation/ICuration.sol";
7+
import "../epochs/IEpochManager.sol";
88
import "../governance/Governed.sol";
99
import "../token/IGraphToken.sol";
1010
import "../upgrades/GraphProxy.sol";
@@ -205,7 +205,7 @@ contract Staking is StakingV1Storage, IStaking, Governed {
205205
*/
206206
function initialize(address _token, address _epochManager) external onlyGovernorOrInit {
207207
token = IGraphToken(_token);
208-
epochManager = EpochManager(_epochManager);
208+
epochManager = IEpochManager(_epochManager);
209209
}
210210

211211
/**
@@ -214,7 +214,7 @@ contract Staking is StakingV1Storage, IStaking, Governed {
214214
* @param _token Address of the Graph Protocol token
215215
* @param _epochManager Address of the EpochManager contract
216216
*/
217-
function acceptUpgrade(
217+
function acceptProxy(
218218
GraphProxy _proxy,
219219
address _token,
220220
address _epochManager

contracts/staking/StakingStorage.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pragma solidity ^0.6.4;
22

3-
import "../EpochManager.sol";
43
import "../curation/ICuration.sol";
4+
import "../epochs/IEpochManager.sol";
55
import "../staking/IStaking.sol";
66
import "../token/IGraphToken.sol";
77
import "../upgrades/GraphProxyStorage.sol";
@@ -68,6 +68,6 @@ contract StakingV1Storage is GraphProxyStorage {
6868
// -- Related contracts --
6969

7070
IGraphToken public token;
71-
EpochManager public epochManager;
71+
IEpochManager public epochManager;
7272
ICuration public curation;
7373
}

contracts/upgrades/GraphProxy.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ contract GraphProxy is GraphProxyStorage, Governed {
2727
* @dev Upgrades to a new implementation contract.
2828
* @param _newImplementation Address of implementation contract
2929
*/
30-
function upgradeTo(address _newImplementation) external onlyGovernor {
30+
function setImplementation(address _newImplementation) external onlyGovernor {
3131
address oldPendingImplementation = pendingImplementation;
3232
pendingImplementation = _newImplementation;
3333

graph.config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ contracts:
2020
slashingPercentage: 50000 # in basis points
2121
EpochManager:
2222
lengthInBlocks: 5760 # One day in blocks
23+
__proxy: true
2324
GNS:
2425
didRegistry: "0xdca7ef03e98e0dc2b855be647c39abe984fcf21b"
2526
GraphToken:

scripts/cli/commands/upgrade.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ export const upgrade = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise<vo
5959
// Upgrade to new implementation
6060
const pendingImplementation = (await proxy.functions['pendingImplementation']())[0]
6161
if (pendingImplementation != implAddress) {
62-
await sendTransaction(cli.wallet, proxy, 'upgradeTo', ...[implAddress])
62+
await sendTransaction(cli.wallet, proxy, 'setImplementation', ...[implAddress])
6363
}
6464

6565
// Accept upgrade from the implementation
6666
const contractArgs = initArgs ? initArgs.split(',') : []
67-
await sendTransaction(cli.wallet, contract, 'acceptUpgrade', ...[proxy.address, ...contractArgs])
67+
await sendTransaction(cli.wallet, contract, 'acceptProxy', ...[proxy.address, ...contractArgs])
6868

6969
// TODO
7070
// -- update entry

scripts/cli/deploy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,12 @@ export const deployContractWithProxyAndSave = async (
125125
// Deploy implementation
126126
const contract = await deployContractAndSave(name, [], wallet, addressBook)
127127
// Upgrade to implementation
128-
await sendTransaction(wallet, proxy, 'upgradeTo', contract.address)
128+
await sendTransaction(wallet, proxy, 'setImplementation', contract.address)
129129
// Implementation accepts upgrade
130130
await sendTransaction(
131131
wallet,
132132
contract,
133-
'acceptUpgrade',
133+
'acceptProxy',
134134
...[proxy.address, ...args.map((a) => a.value)],
135135
)
136136

0 commit comments

Comments
 (0)