Simplify Makers Interactions with Staking Pools.

- No longer an upper limit on how many makers can be in a pool.
- No longer a handshake for a maker to join a pool.
- No longer any special powers given to makers.
- Pool Id starts at 1 and increments by 1.
This commit is contained in:
Greg Hysen
2019-10-07 13:50:23 +09:00
parent ee508f70bc
commit a0f5a8b64b
26 changed files with 90 additions and 755 deletions

View File

@@ -173,14 +173,6 @@ contract StakingProxy is
));
}
// Pools must allow at least one maker
if (maximumMakersInPool == 0) {
LibRichErrors.rrevert(
LibStakingRichErrors.InvalidParamValueError(
LibStakingRichErrors.InvalidParamValueErrorCodes.InvalidMaximumMakersInPool
));
}
// Minimum stake must be > 1
if (minimumPoolStake < 2) {
LibRichErrors.rrevert(

View File

@@ -67,7 +67,8 @@ contract MixinExchangeFees is
}
// Get the pool id of the maker address.
bytes32 poolId = getStakingPoolIdOfMaker(makerAddress);
bytes32 poolId = poolIdByMaker[makerAddress];
// Only attribute the protocol fee payment to a pool if the maker is
// registered to a pool.
if (poolId == NIL_POOL_ID) {

View File

@@ -69,12 +69,10 @@ contract MixinStorage is
mapping (address => uint256) internal _withdrawableStakeByOwner;
// tracking Pool Id
bytes32 public nextPoolId = INITIAL_POOL_ID;
bytes32 public nextPoolId = bytes32(uint256(1));
// mapping from Maker Address to a struct representing the pool the maker has joined and
// whether the operator of that pool has subsequently added the maker.
// (access externally using `getStakingPoolIdOfMaker`)
mapping (address => IStructs.MakerPoolJoinStatus) internal _poolJoinedByMakerAddress;
// mapping from Maker Address to Pool Id of maker
mapping (address => bytes32) public poolIdByMaker;
// mapping from Pool Id to Pool
mapping (bytes32 => IStructs.Pool) internal _poolById;
@@ -83,7 +81,7 @@ contract MixinStorage is
mapping (bytes32 => uint256) public rewardsByPoolId;
// current epoch
uint256 public currentEpoch = INITIAL_EPOCH;
uint256 public currentEpoch;
// current epoch start time
uint256 public currentEpochStartTimeInSeconds;
@@ -108,9 +106,6 @@ contract MixinStorage is
// Minimum amount of stake required in a pool to collect rewards.
uint256 public minimumPoolStake;
// Maximum number of maker addresses allowed to be registered to a pool.
uint256 public maximumMakersInPool;
// Numerator for cobb douglas alpha factor.
uint32 public cobbDouglasAlphaNumerator;

View File

@@ -92,14 +92,12 @@ interface IStakingEvents {
/// @param epochDurationInSeconds Minimum seconds between epochs.
/// @param rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
/// @param minimumPoolStake Minimum amount of stake required in a pool to collect rewards.
/// @param maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool.
/// @param cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
/// @param cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
event ParamsSet(
uint256 epochDurationInSeconds,
uint32 rewardDelegatedStakeWeight,
uint256 minimumPoolStake,
uint256 maximumMakersInPool,
uint256 cobbDouglasAlphaNumerator,
uint256 cobbDouglasAlphaDenominator
);
@@ -114,28 +112,12 @@ interface IStakingEvents {
uint32 operatorShare
);
/// @dev Emitted by MixinStakingPool when a new maker requests to join a pool.
/// @param poolId Unique id of pool.
/// @param makerAddress Adress of maker joining the pool.
event PendingAddMakerToPool(
bytes32 indexed poolId,
address makerAddress
);
/// @dev Emitted by MixinStakingPool when a new maker is added to a pool.
/// @param poolId Unique id of pool.
/// @dev Emitted by MixinStakingPool when a maker sets their pool.
/// @param makerAddress Adress of maker added to pool.
event MakerAddedToStakingPool(
bytes32 indexed poolId,
address makerAddress
);
/// @dev Emitted by MixinStakingPool when a maker is removed from a pool.
/// @param poolId Unique id of pool.
/// @param makerAddress Adress of maker added to pool.
event MakerRemovedFromStakingPool(
bytes32 indexed poolId,
address makerAddress
event MakerStakingPoolSet(
address indexed makerAddress,
bytes32 indexed poolId
);
/// @dev Emitted when a staking pool's operator share is decreased.

View File

@@ -90,11 +90,6 @@ interface IStorage {
view
returns (uint256);
function maximumMakersInPool()
external
view
returns(uint256);
function cobbDouglasAlphaNumerator()
external
view

View File

@@ -95,24 +95,13 @@ interface IStructs {
uint256 denominator;
}
/// @dev State for keeping track of which pool a maker has joined, and if the operator has
/// added them (see MixinStakingPool).
/// @param poolId Unique Id of staking pool.
/// @param confirmed Whether the operator has added the maker to the pool.
struct MakerPoolJoinStatus {
bytes32 poolId;
bool confirmed;
}
/// @dev Holds the metadata for a staking pool.
/// @param initialized True iff the balance struct is initialized.
/// @param operator of the pool.
/// @param operatorShare Fraction of the total balance owned by the operator, in ppm.
/// @param numberOfMakers Number of makers in the pool.
struct Pool {
bool initialized;
address payable operator;
uint32 operatorShare;
uint32 numberOfMakers;
}
}

View File

@@ -47,13 +47,6 @@ library LibStakingRichErrors {
InvalidEpochDuration
}
enum MakerPoolAssignmentErrorCodes {
MakerAddressAlreadyRegistered,
MakerAddressNotRegistered,
MakerAddressNotPendingAdd,
PoolIsFull
}
enum ExchangeManagerErrorCodes {
ExchangeAlreadyRegistered,
ExchangeNotRegistered
@@ -71,13 +64,9 @@ library LibStakingRichErrors {
bytes4 internal constant INSUFFICIENT_BALANCE_ERROR_SELECTOR =
0x84c8b7c9;
// bytes4(keccak256("OnlyCallableByPoolOperatorOrMakerError(address,bytes32)"))
bytes4 internal constant ONLY_CALLABLE_BY_POOL_OPERATOR_OR_MAKER_ERROR_SELECTOR =
0x7677eb13;
// bytes4(keccak256("MakerPoolAssignmentError(uint8,address,bytes32)"))
bytes4 internal constant MAKER_POOL_ASSIGNMENT_ERROR_SELECTOR =
0x69945e3f;
// bytes4(keccak256("OnlyCallableByPoolOperatorError(address,bytes32)"))
bytes4 internal constant ONLY_CALLABLE_BY_POOL_OPERATOR_ERROR_SELECTOR =
0x82ded785;
// bytes4(keccak256("BlockTimestampTooLowError(uint256,uint256)"))
bytes4 internal constant BLOCK_TIMESTAMP_TOO_LOW_ERROR_SELECTOR =
@@ -171,7 +160,7 @@ library LibStakingRichErrors {
);
}
function OnlyCallableByPoolOperatorOrMakerError(
function OnlyCallableByPoolOperatorError(
address senderAddress,
bytes32 poolId
)
@@ -180,29 +169,12 @@ library LibStakingRichErrors {
returns (bytes memory)
{
return abi.encodeWithSelector(
ONLY_CALLABLE_BY_POOL_OPERATOR_OR_MAKER_ERROR_SELECTOR,
ONLY_CALLABLE_BY_POOL_OPERATOR_ERROR_SELECTOR,
senderAddress,
poolId
);
}
function MakerPoolAssignmentError(
MakerPoolAssignmentErrorCodes errorCodes,
address makerAddress,
bytes32 poolId
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
MAKER_POOL_ASSIGNMENT_ERROR_SELECTOR,
errorCodes,
makerAddress,
poolId
);
}
function BlockTimestampTooLowError(
uint256 epochEndTime,
uint256 currentBlockTimestamp

View File

@@ -34,10 +34,10 @@ contract MixinStakingPool is
using LibSafeMath for uint256;
using LibSafeDowncast for uint256;
/// @dev Asserts that the sender is the operator of the input pool or the input maker.
/// @dev Asserts that the sender is the operator of the input pool.
/// @param poolId Pool sender must be operator of.
modifier onlyStakingPoolOperatorOrMaker(bytes32 poolId) {
_assertSenderIsPoolOperatorOrMaker(poolId);
modifier onlyStakingPoolOperator(bytes32 poolId) {
_assertSenderIsPoolOperator(poolId);
_;
}
@@ -68,8 +68,7 @@ contract MixinStakingPool is
IStructs.Pool memory pool = IStructs.Pool({
initialized: true,
operator: operator,
operatorShare: operatorShare,
numberOfMakers: 0
operatorShare: operatorShare
});
_poolById[poolId] = pool;
@@ -81,7 +80,7 @@ contract MixinStakingPool is
emit StakingPoolCreated(poolId, operator, operatorShare);
if (addOperatorAsMaker) {
_addMakerToStakingPool(poolId, operator);
setMakerStakingPool(poolId);
}
return poolId;
@@ -92,7 +91,7 @@ contract MixinStakingPool is
/// @param newOperatorShare The newly decreased percentage of any rewards owned by the operator.
function decreaseStakingPoolOperatorShare(bytes32 poolId, uint32 newOperatorShare)
external
onlyStakingPoolOperatorOrMaker(poolId)
onlyStakingPoolOperator(poolId)
{
// load pool and assert that we can decrease
uint32 currentOperatorShare = _poolById[poolId].operatorShare;
@@ -111,92 +110,17 @@ contract MixinStakingPool is
);
}
/// @dev Allows caller to join a staking pool if already assigned.
/// @dev Allows caller to join a staking pool as a maker.
/// @param poolId Unique id of pool.
function joinStakingPoolAsMaker(bytes32 poolId)
external
{
// Is the maker already in a pool?
address makerAddress = msg.sender;
IStructs.MakerPoolJoinStatus memory poolJoinStatus = _poolJoinedByMakerAddress[makerAddress];
if (poolJoinStatus.confirmed) {
LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError(
LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered,
makerAddress,
poolJoinStatus.poolId
));
}
poolJoinStatus.poolId = poolId;
_poolJoinedByMakerAddress[makerAddress] = poolJoinStatus;
// Maker has joined to the pool, awaiting operator confirmation
emit PendingAddMakerToPool(
poolId,
makerAddress
);
}
/// @dev Adds a maker to a staking pool. Note that this is only callable by the pool operator.
/// Note also that the maker must have previously called joinStakingPoolAsMaker.
/// @param poolId Unique id of pool.
/// @param makerAddress Address of maker.
function addMakerToStakingPool(
bytes32 poolId,
address makerAddress
)
external
onlyStakingPoolOperatorOrMaker(poolId)
{
_addMakerToStakingPool(poolId, makerAddress);
}
/// @dev Removes a maker from a staking pool. Note that this is only callable by the pool operator or maker.
/// Note also that the maker does not have to *agree* to leave the pool; this action is
/// at the sole discretion of the pool operator.
/// @param poolId Unique id of pool.
/// @param makerAddress Address of maker.
function removeMakerFromStakingPool(
bytes32 poolId,
address makerAddress
)
external
onlyStakingPoolOperatorOrMaker(poolId)
{
bytes32 makerPoolId = getStakingPoolIdOfMaker(makerAddress);
if (makerPoolId != poolId) {
LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError(
LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressNotRegistered,
makerAddress,
makerPoolId
));
}
// remove the pool and confirmation from the maker status
delete _poolJoinedByMakerAddress[makerAddress];
_poolById[poolId].numberOfMakers = uint256(_poolById[poolId].numberOfMakers).safeSub(1).downcastToUint32();
// Maker has been removed from the pool`
emit MakerRemovedFromStakingPool(
poolId,
makerAddress
);
}
/// @dev Returns the pool id of the input maker.
/// @param makerAddress Address of maker
/// @return Pool id, nil if maker is not yet assigned to a pool.
function getStakingPoolIdOfMaker(address makerAddress)
function setMakerStakingPool(bytes32 poolId)
public
view
returns (bytes32)
{
IStructs.MakerPoolJoinStatus memory poolJoinStatus = _poolJoinedByMakerAddress[makerAddress];
if (poolJoinStatus.confirmed) {
return poolJoinStatus.poolId;
} else {
return NIL_POOL_ID;
}
address maker = msg.sender;
poolIdByMaker[maker] = poolId;
emit MakerStakingPoolSet(
maker,
poolId
);
}
/// @dev Returns a staking pool
@@ -209,65 +133,6 @@ contract MixinStakingPool is
return _poolById[poolId];
}
/// @dev Adds a maker to a staking pool. Note that this is only callable by the pool operator.
/// Note also that the maker must have previously called joinStakingPoolAsMaker.
/// @param poolId Unique id of pool.
/// @param makerAddress Address of maker.
function _addMakerToStakingPool(
bytes32 poolId,
address makerAddress
)
internal
{
// cache pool and join status for use throughout this function
IStructs.Pool memory pool = _poolById[poolId];
IStructs.MakerPoolJoinStatus memory poolJoinStatus = _poolJoinedByMakerAddress[makerAddress];
// Is the maker already in a pool?
if (poolJoinStatus.confirmed) {
LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError(
LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered,
makerAddress,
poolJoinStatus.poolId
));
}
// Is the maker trying to join this pool; or are they the operator?
bytes32 makerPendingPoolId = poolJoinStatus.poolId;
if (makerPendingPoolId != poolId && makerAddress != pool.operator) {
LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError(
LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressNotPendingAdd,
makerAddress,
makerPendingPoolId
));
}
// Is the pool already full?
// NOTE: If maximumMakersInPool is decreased below the number of makers currently in a pool,
// the pool will no longer be able to add more makers.
if (pool.numberOfMakers >= maximumMakersInPool) {
LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError(
LibStakingRichErrors.MakerPoolAssignmentErrorCodes.PoolIsFull,
makerAddress,
poolId
));
}
// Add maker to pool
poolJoinStatus = IStructs.MakerPoolJoinStatus({
poolId: poolId,
confirmed: true
});
_poolJoinedByMakerAddress[makerAddress] = poolJoinStatus;
_poolById[poolId].numberOfMakers = uint256(pool.numberOfMakers).safeAdd(1).downcastToUint32();
// Maker has been added to the pool
emit MakerAddedToStakingPool(
poolId,
makerAddress
);
}
/// @dev Computes the unique id that comes after the input pool id.
/// @param poolId Unique id of pool.
/// @return Next pool id after input pool.
@@ -276,7 +141,7 @@ contract MixinStakingPool is
pure
returns (bytes32)
{
return bytes32(uint256(poolId).safeAdd(POOL_ID_INCREMENT_AMOUNT));
return bytes32(uint256(poolId).safeAdd(1));
}
/// @dev Reverts iff a staking pool does not exist.
@@ -327,19 +192,16 @@ contract MixinStakingPool is
}
}
/// @dev Asserts that the sender is the operator of the input pool or the input maker.
/// @dev Asserts that the sender is the operator of the input pool.
/// @param poolId Pool sender must be operator of.
function _assertSenderIsPoolOperatorOrMaker(bytes32 poolId)
function _assertSenderIsPoolOperator(bytes32 poolId)
private
view
{
address operator = _poolById[poolId].operator;
if (
msg.sender != operator &&
getStakingPoolIdOfMaker(msg.sender) != poolId
) {
if (msg.sender != operator) {
LibRichErrors.rrevert(
LibStakingRichErrors.OnlyCallableByPoolOperatorOrMakerError(
LibStakingRichErrors.OnlyCallableByPoolOperatorError(
msg.sender,
poolId
)

View File

@@ -32,14 +32,12 @@ contract MixinParams is
/// @param _epochDurationInSeconds Minimum seconds between epochs.
/// @param _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
/// @param _minimumPoolStake Minimum amount of stake required in a pool to collect rewards.
/// @param _maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool.
/// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
/// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
function setParams(
uint256 _epochDurationInSeconds,
uint32 _rewardDelegatedStakeWeight,
uint256 _minimumPoolStake,
uint256 _maximumMakersInPool,
uint32 _cobbDouglasAlphaNumerator,
uint32 _cobbDouglasAlphaDenominator
)
@@ -50,7 +48,6 @@ contract MixinParams is
_epochDurationInSeconds,
_rewardDelegatedStakeWeight,
_minimumPoolStake,
_maximumMakersInPool,
_cobbDouglasAlphaNumerator,
_cobbDouglasAlphaDenominator
);
@@ -60,7 +57,6 @@ contract MixinParams is
/// @return _epochDurationInSeconds Minimum seconds between epochs.
/// @return _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
/// @return _minimumPoolStake Minimum amount of stake required in a pool to collect rewards.
/// @return _maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool.
/// @return _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
/// @return _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
function getParams()
@@ -70,7 +66,6 @@ contract MixinParams is
uint256 _epochDurationInSeconds,
uint32 _rewardDelegatedStakeWeight,
uint256 _minimumPoolStake,
uint256 _maximumMakersInPool,
uint32 _cobbDouglasAlphaNumerator,
uint32 _cobbDouglasAlphaDenominator
)
@@ -78,7 +73,6 @@ contract MixinParams is
_epochDurationInSeconds = epochDurationInSeconds;
_rewardDelegatedStakeWeight = rewardDelegatedStakeWeight;
_minimumPoolStake = minimumPoolStake;
_maximumMakersInPool = maximumMakersInPool;
_cobbDouglasAlphaNumerator = cobbDouglasAlphaNumerator;
_cobbDouglasAlphaDenominator = cobbDouglasAlphaDenominator;
}
@@ -96,7 +90,6 @@ contract MixinParams is
10 days, // epochDurationInSeconds
(90 * PPM_DENOMINATOR) / 100, // rewardDelegatedStakeWeight
100 * MIN_TOKEN_VALUE, // minimumPoolStake
10, // maximumMakersInPool
1, // cobbDouglasAlphaNumerator
2 // cobbDouglasAlphaDenominator
);
@@ -110,7 +103,6 @@ contract MixinParams is
if (epochDurationInSeconds != 0 &&
rewardDelegatedStakeWeight != 0 &&
minimumPoolStake != 0 &&
maximumMakersInPool != 0 &&
cobbDouglasAlphaNumerator != 0 &&
cobbDouglasAlphaDenominator != 0
) {
@@ -126,14 +118,12 @@ contract MixinParams is
/// @param _epochDurationInSeconds Minimum seconds between epochs.
/// @param _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
/// @param _minimumPoolStake Minimum amount of stake required in a pool to collect rewards.
/// @param _maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool.
/// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
/// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
function _setParams(
uint256 _epochDurationInSeconds,
uint32 _rewardDelegatedStakeWeight,
uint256 _minimumPoolStake,
uint256 _maximumMakersInPool,
uint32 _cobbDouglasAlphaNumerator,
uint32 _cobbDouglasAlphaDenominator
)
@@ -142,7 +132,6 @@ contract MixinParams is
epochDurationInSeconds = _epochDurationInSeconds;
rewardDelegatedStakeWeight = _rewardDelegatedStakeWeight;
minimumPoolStake = _minimumPoolStake;
maximumMakersInPool = _maximumMakersInPool;
cobbDouglasAlphaNumerator = _cobbDouglasAlphaNumerator;
cobbDouglasAlphaDenominator = _cobbDouglasAlphaDenominator;
@@ -150,7 +139,6 @@ contract MixinParams is
_epochDurationInSeconds,
_rewardDelegatedStakeWeight,
_minimumPoolStake,
_maximumMakersInPool,
_cobbDouglasAlphaNumerator,
_cobbDouglasAlphaDenominator
);

View File

@@ -29,7 +29,6 @@ contract TestAssertStorageParams is
uint256 epochDurationInSeconds;
uint32 rewardDelegatedStakeWeight;
uint256 minimumPoolStake;
uint256 maximumMakersInPool;
uint32 cobbDouglasAlphaNumerator;
uint32 cobbDouglasAlphaDenominator;
}
@@ -48,7 +47,6 @@ contract TestAssertStorageParams is
epochDurationInSeconds = params.epochDurationInSeconds;
rewardDelegatedStakeWeight = params.rewardDelegatedStakeWeight;
minimumPoolStake = params.minimumPoolStake;
maximumMakersInPool = params.maximumMakersInPool;
cobbDouglasAlphaNumerator = params.cobbDouglasAlphaNumerator;
cobbDouglasAlphaDenominator = params.cobbDouglasAlphaDenominator;
_assertValidStorageParams();

View File

@@ -48,13 +48,6 @@ contract TestProtocolFees is
_removeAuthorizedAddressAtIndex(msg.sender, 0);
}
function addMakerToPool(bytes32 poolId, address makerAddress)
external
{
_poolJoinedByMakerAddress[makerAddress].poolId = poolId;
_poolJoinedByMakerAddress[makerAddress].confirmed = true;
}
function advanceEpoch()
external
{
@@ -76,6 +69,7 @@ contract TestProtocolFees is
for (uint256 i = 0; i < makerAddresses.length; ++i) {
pool.isMaker[makerAddresses[i]] = true;
_makersToTestPoolIds[makerAddresses[i]] = poolId;
poolIdByMaker[makerAddresses[i]] = poolId;
}
}

View File

@@ -183,8 +183,8 @@ contract TestStorageLayoutAndConstants is
slot := add(slot, 0x1)
assertSlotAndOffset(
_poolJoinedByMakerAddress_slot,
_poolJoinedByMakerAddress_offset,
poolIdByMaker_slot,
poolIdByMaker_offset,
slot,
offset
)
@@ -270,14 +270,6 @@ contract TestStorageLayoutAndConstants is
)
slot := add(slot, 0x1)
assertSlotAndOffset(
maximumMakersInPool_slot,
maximumMakersInPool_offset,
slot,
offset
)
slot := add(slot, 0x1)
assertSlotAndOffset(
cobbDouglasAlphaNumerator_slot,
cobbDouglasAlphaNumerator_offset,