Skip to content

Commit df1e51a

Browse files
abarmatHeikoFisch
andauthored
staking: channel allocation and settlement (#235)
* build: prettier 2.0 apply style * staking: refactor allocate * staking: - rename functions related to settlement and allocations - use interfaces for staking * misc: use interfaces for imports * staking: allow delegator to force settle channel * staking,curation: fixes and refactor tests * tests: improve tests * misc: - reorg tests - purge allocation - add tests and validations - add channelID in collect to avoid overwritting channel proxy on allocation - refactor how channel proxies are stored * curation: - add test for withdrawal fees - add test for conservation of token to signal exchange - improve state storage to take less space * staking: - make state transitions clearer - add build to test pipeline - remove grace period * connext: reallocate additions (#240) * connext: minor changes and cleanup * connext: adapt contracts and tests to new `Staking#collect` Co-authored-by: Heiko Fisch <[email protected]> * staking: review fixes Co-authored-by: Heiko Fisch <[email protected]>
1 parent 19da230 commit df1e51a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3011
-2191
lines changed

.eslintrc

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
"ecmaVersion": 2020,
55
"sourceType": "module"
66
},
7-
"extends": ["plugin:@typescript-eslint/recommended"],
7+
"extends": ["plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"],
88
"rules": {
99
"prefer-const": "warn",
10+
"no-extra-semi": "off",
11+
"@typescript-eslint/no-extra-semi": "warn",
1012
"@typescript-eslint/no-inferrable-types": "warn",
1113
"@typescript-eslint/no-empty-function": "warn"
1214
}

.prettierignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
contracts/DisputeManager.sol
1+

.soliumignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ contracts/bancor
44
contracts/ens
55
contracts/erc1056
66
contracts/openzeppelin
7+
contracts/IGraphToken.sol
78
contracts/MultiSigWallet.sol
89
contracts/Staking.sol
910
contracts/connext/IndexerMultiAssetInterpreter.sol

buidler.config.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ dotenv.config()
1010

1111
// Plugins
1212

13+
usePlugin('@nomiclabs/buidler-ethers')
1314
usePlugin('@nomiclabs/buidler-etherscan')
1415
usePlugin('@nomiclabs/buidler-waffle')
1516
usePlugin('solidity-coverage')
@@ -69,7 +70,7 @@ const config: BuidlerConfig = {
6970
buidlerevm: {
7071
chainId: 31337,
7172
loggingEnabled: false,
72-
gas: 'auto',
73+
gas: 8000000,
7374
gasPrice: 'auto',
7475
blockGasLimit: 9500000,
7576
accounts: [

contracts/Curation.sol

+38-38
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
pragma solidity ^0.6.4;
2-
pragma experimental ABIEncoderV2;
2+
3+
import "@openzeppelin/contracts/math/SafeMath.sol";
34

45
import "./Governed.sol";
5-
import "./GraphToken.sol";
6+
import "./ICuration.sol";
7+
import "./IGraphToken.sol";
68
import "./bancor/BancorFormula.sol";
7-
import "@openzeppelin/contracts/math/SafeMath.sol";
89

910
/**
1011
* @title Curation contract
@@ -14,38 +15,38 @@ import "@openzeppelin/contracts/math/SafeMath.sol";
1415
* A curators stake goes to a curation pool along with the stakes of other curators,
1516
* only one pool exists for each subgraph deployment.
1617
*/
17-
contract Curation is Governed, BancorFormula {
18+
contract Curation is ICuration, BancorFormula, Governed {
1819
using SafeMath for uint256;
1920

2021
// -- Curation --
2122

2223
struct CurationPool {
23-
uint256 reserveRatio; // Ratio for the bonding curve
2424
uint256 tokens; // Tokens stored as reserves for the SubgraphDeployment
2525
uint256 shares; // Shares issued for the SubgraphDeployment
26+
uint32 reserveRatio; // Ratio for the bonding curve
2627
mapping(address => uint256) curatorShares; // Mapping of curator => shares
2728
}
2829

2930
// 100% in parts per million
30-
uint256 private constant MAX_PPM = 1000000;
31+
uint32 private constant MAX_PPM = 1000000;
3132

3233
// Amount of shares you get with your minimum token stake
3334
uint256 private constant SHARES_PER_MINIMUM_STAKE = 1 ether;
3435

3536
// -- State --
3637

38+
// Fee charged when curator withdraw stake
39+
// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%)
40+
uint32 public withdrawalFeePercentage;
41+
3742
// Default reserve ratio to configure curator shares bonding curve
3843
// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%)
39-
uint256 public defaultReserveRatio;
44+
uint32 public defaultReserveRatio;
4045

4146
// Minimum amount allowed to be staked by curators
4247
// This is the `startPoolBalance` for the bonding curve
4348
uint256 public minimumCurationStake;
4449

45-
// Fee charged when curator withdraw stake
46-
// Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%)
47-
uint256 public withdrawalFeePercentage;
48-
4950
// Mapping of subgraphDeploymentID => CurationPool
5051
// There is only one CurationPool per SubgraphDeployment
5152
mapping(bytes32 => CurationPool) public pools;
@@ -54,7 +55,7 @@ contract Curation is Governed, BancorFormula {
5455
address public staking;
5556

5657
// Token used for staking
57-
GraphToken public token;
58+
IGraphToken public token;
5859

5960
// -- Events --
6061

@@ -98,10 +99,10 @@ contract Curation is Governed, BancorFormula {
9899
constructor(
99100
address _governor,
100101
address _token,
101-
uint256 _defaultReserveRatio,
102+
uint32 _defaultReserveRatio,
102103
uint256 _minimumCurationStake
103104
) public Governed(_governor) {
104-
token = GraphToken(_token);
105+
token = IGraphToken(_token);
105106
_setDefaultReserveRatio(_defaultReserveRatio);
106107
_setMinimumCurationStake(_minimumCurationStake);
107108
}
@@ -111,15 +112,15 @@ contract Curation is Governed, BancorFormula {
111112
* @notice Update the default reserver ratio to `_defaultReserveRatio`
112113
* @param _defaultReserveRatio Reserve ratio (in PPM)
113114
*/
114-
function setDefaultReserveRatio(uint256 _defaultReserveRatio) external onlyGovernor {
115+
function setDefaultReserveRatio(uint32 _defaultReserveRatio) external override onlyGovernor {
115116
_setDefaultReserveRatio(_defaultReserveRatio);
116117
}
117118

118119
/**
119120
* @dev Set the default reserve ratio percentage for a curation pool.
120121
* @param _defaultReserveRatio Reserve ratio (in PPM)
121122
*/
122-
function _setDefaultReserveRatio(uint256 _defaultReserveRatio) private {
123+
function _setDefaultReserveRatio(uint32 _defaultReserveRatio) private {
123124
// Reserve Ratio must be within 0% to 100% (exclusive, in PPM)
124125
require(_defaultReserveRatio > 0, "Default reserve ratio must be > 0");
125126
require(
@@ -136,7 +137,7 @@ contract Curation is Governed, BancorFormula {
136137
* @notice Update the staking contract to `_staking`
137138
* @param _staking Address of the staking contract
138139
*/
139-
function setStaking(address _staking) external onlyGovernor {
140+
function setStaking(address _staking) external override onlyGovernor {
140141
staking = _staking;
141142
emit ParameterUpdated("staking");
142143
}
@@ -146,7 +147,7 @@ contract Curation is Governed, BancorFormula {
146147
* @notice Update the minimum stake amount to `_minimumCurationStake`
147148
* @param _minimumCurationStake Minimum amount of tokens required stake
148149
*/
149-
function setMinimumCurationStake(uint256 _minimumCurationStake) external onlyGovernor {
150+
function setMinimumCurationStake(uint256 _minimumCurationStake) external override onlyGovernor {
150151
_setMinimumCurationStake(_minimumCurationStake);
151152
}
152153

@@ -164,7 +165,7 @@ contract Curation is Governed, BancorFormula {
164165
* @dev Set the fee percentage to charge when a curator withdraws stake.
165166
* @param _percentage Percentage fee charged when withdrawing stake
166167
*/
167-
function setWithdrawalFeePercentage(uint256 _percentage) external onlyGovernor {
168+
function setWithdrawalFeePercentage(uint32 _percentage) external override onlyGovernor {
168169
// Must be within 0% to 100% (inclusive)
169170
require(
170171
_percentage <= MAX_PPM,
@@ -179,7 +180,7 @@ contract Curation is Governed, BancorFormula {
179180
* @param _subgraphDeploymentID SubgraphDeployment where funds should be allocated as reserves
180181
* @param _tokens Amount of Graph Tokens to add to reserves
181182
*/
182-
function collect(bytes32 _subgraphDeploymentID, uint256 _tokens) external {
183+
function collect(bytes32 _subgraphDeploymentID, uint256 _tokens) external override {
183184
require(msg.sender == staking, "Caller must be the staking contract");
184185

185186
// Transfer tokens collected from the staking contract to this contract
@@ -197,7 +198,7 @@ contract Curation is Governed, BancorFormula {
197198
* @param _subgraphDeploymentID SubgraphDeployment where the curator is staking Graph Tokens
198199
* @param _tokens Amount of Graph Tokens to stake
199200
*/
200-
function stake(bytes32 _subgraphDeploymentID, uint256 _tokens) external {
201+
function stake(bytes32 _subgraphDeploymentID, uint256 _tokens) external override {
201202
address curator = msg.sender;
202203

203204
// Need to stake some funds
@@ -219,7 +220,7 @@ contract Curation is Governed, BancorFormula {
219220
* @param _subgraphDeploymentID SubgraphDeployment the curator is returning shares
220221
* @param _shares Amount of shares to return
221222
*/
222-
function redeem(bytes32 _subgraphDeploymentID, uint256 _shares) external {
223+
function redeem(bytes32 _subgraphDeploymentID, uint256 _shares) external override {
223224
address curator = msg.sender;
224225
CurationPool storage curationPool = pools[_subgraphDeploymentID];
225226

@@ -238,7 +239,7 @@ contract Curation is Governed, BancorFormula {
238239
}
239240

240241
// Calculate withdrawal fees and burn the tokens
241-
uint256 withdrawalFees = percentageOf(withdrawalFeePercentage, tokens);
242+
uint256 withdrawalFees = uint256(withdrawalFeePercentage).mul(tokens).div(MAX_PPM);
242243
if (withdrawalFees > 0) {
243244
tokens = tokens.sub(withdrawalFees);
244245
token.burn(withdrawalFees);
@@ -255,7 +256,16 @@ contract Curation is Governed, BancorFormula {
255256
* @param _subgraphDeploymentID SubgraphDeployment to check if curated
256257
* @return True if curated
257258
*/
258-
function isCurated(bytes32 _subgraphDeploymentID) public view returns (bool) {
259+
function isCurated(bytes32 _subgraphDeploymentID) external override view returns (bool) {
260+
return _isCurated(_subgraphDeploymentID);
261+
}
262+
263+
/**
264+
* @dev Check if any Graph tokens are staked for a SubgraphDeployment.
265+
* @param _subgraphDeploymentID SubgraphDeployment to check if curated
266+
* @return True if curated
267+
*/
268+
function _isCurated(bytes32 _subgraphDeploymentID) private view returns (bool) {
259269
return pools[_subgraphDeploymentID].tokens > 0;
260270
}
261271

@@ -290,9 +300,9 @@ contract Curation is Governed, BancorFormula {
290300
CurationPool memory curationPool = pools[_subgraphDeploymentID];
291301
if (curationPool.tokens == 0) {
292302
curationPool = CurationPool(
293-
defaultReserveRatio,
294303
minimumCurationStake,
295-
SHARES_PER_MINIMUM_STAKE
304+
SHARES_PER_MINIMUM_STAKE,
305+
defaultReserveRatio
296306
);
297307
tokens = tokens.sub(curationPool.tokens);
298308
shares = curationPool.shares;
@@ -393,7 +403,7 @@ contract Curation is Governed, BancorFormula {
393403
*/
394404
function _collect(bytes32 _subgraphDeploymentID, uint256 _tokens) private {
395405
require(
396-
isCurated(_subgraphDeploymentID),
406+
_isCurated(_subgraphDeploymentID),
397407
"SubgraphDeployment must be curated to collect fees"
398408
);
399409

@@ -418,7 +428,7 @@ contract Curation is Governed, BancorFormula {
418428
CurationPool storage curationPool = pools[_subgraphDeploymentID];
419429

420430
// If it hasn't been curated before then initialize the curve
421-
if (!isCurated(_subgraphDeploymentID)) {
431+
if (!_isCurated(_subgraphDeploymentID)) {
422432
require(_tokens >= minimumCurationStake, "Curation stake is below minimum required");
423433

424434
// Initialize
@@ -430,14 +440,4 @@ contract Curation is Governed, BancorFormula {
430440

431441
emit Staked(_curator, _subgraphDeploymentID, _tokens, shares);
432442
}
433-
434-
/**
435-
* @dev Calculate the percentage for value in parts per million (PPM)
436-
* @param _ppm Parts per million
437-
* @param _value Value to calculate percentage of
438-
* @return Percentage of value
439-
*/
440-
function percentageOf(uint256 _ppm, uint256 _value) private pure returns (uint256) {
441-
return _ppm.mul(_value).div(MAX_PPM);
442-
}
443443
}

0 commit comments

Comments
 (0)