Consolidate MixinStakingPool, MixinStakingPoolMakers, and MixinStakingPoolModifiers
This commit is contained in:
parent
0bc4b50818
commit
7f1afb57b0
@ -34,12 +34,10 @@ contract Staking is
|
|||||||
MixinConstants,
|
MixinConstants,
|
||||||
Ownable,
|
Ownable,
|
||||||
MixinStorage,
|
MixinStorage,
|
||||||
MixinStakingPoolModifiers,
|
|
||||||
MixinExchangeManager,
|
MixinExchangeManager,
|
||||||
MixinScheduler,
|
MixinScheduler,
|
||||||
MixinParams,
|
MixinParams,
|
||||||
MixinStakeStorage,
|
MixinStakeStorage,
|
||||||
MixinStakingPoolMakers,
|
|
||||||
MixinStakeBalances,
|
MixinStakeBalances,
|
||||||
MixinCumulativeRewards,
|
MixinCumulativeRewards,
|
||||||
MixinStakingPoolRewards,
|
MixinStakingPoolRewards,
|
||||||
|
@ -38,11 +38,9 @@ contract MixinExchangeFees is
|
|||||||
MixinConstants,
|
MixinConstants,
|
||||||
Ownable,
|
Ownable,
|
||||||
MixinStorage,
|
MixinStorage,
|
||||||
MixinStakingPoolModifiers,
|
|
||||||
MixinExchangeManager,
|
MixinExchangeManager,
|
||||||
MixinScheduler,
|
MixinScheduler,
|
||||||
MixinStakeStorage,
|
MixinStakeStorage,
|
||||||
MixinStakingPoolMakers,
|
|
||||||
MixinStakeBalances,
|
MixinStakeBalances,
|
||||||
MixinCumulativeRewards,
|
MixinCumulativeRewards,
|
||||||
MixinStakingPoolRewards,
|
MixinStakingPoolRewards,
|
||||||
@ -167,7 +165,7 @@ contract MixinExchangeFees is
|
|||||||
returns (uint256 membersStake, uint256 weightedStake)
|
returns (uint256 membersStake, uint256 weightedStake)
|
||||||
{
|
{
|
||||||
uint256 operatorStake = getStakeDelegatedToPoolByOwner(
|
uint256 operatorStake = getStakeDelegatedToPoolByOwner(
|
||||||
_poolById[poolId].operator,
|
_getStakingPoolOperator(poolId),
|
||||||
poolId
|
poolId
|
||||||
).currentEpochBalance;
|
).currentEpochBalance;
|
||||||
membersStake = totalStake.safeSub(operatorStake);
|
membersStake = totalStake.safeSub(operatorStake);
|
||||||
|
@ -75,13 +75,9 @@ library LibStakingRichErrors {
|
|||||||
bytes4 internal constant INSUFFICIENT_BALANCE_ERROR_SELECTOR =
|
bytes4 internal constant INSUFFICIENT_BALANCE_ERROR_SELECTOR =
|
||||||
0x84c8b7c9;
|
0x84c8b7c9;
|
||||||
|
|
||||||
// bytes4(keccak256("OnlyCallableByPoolOperatorError(address,address)"))
|
// bytes4(keccak256("OnlyCallableByPoolOperatorOrMakerError(address,address)"))
|
||||||
bytes4 internal constant ONLY_CALLABLE_BY_POOL_OPERATOR_ERROR_SELECTOR =
|
|
||||||
0x6cfa0c22;
|
|
||||||
|
|
||||||
// bytes4(keccak256("OnlyCallableByPoolOperatorOrMakerError(address,address,address)"))
|
|
||||||
bytes4 internal constant ONLY_CALLABLE_BY_POOL_OPERATOR_OR_MAKER_ERROR_SELECTOR =
|
bytes4 internal constant ONLY_CALLABLE_BY_POOL_OPERATOR_OR_MAKER_ERROR_SELECTOR =
|
||||||
0x7d9e1c10;
|
0x471c3580;
|
||||||
|
|
||||||
// bytes4(keccak256("MakerPoolAssignmentError(uint8,address,bytes32)"))
|
// bytes4(keccak256("MakerPoolAssignmentError(uint8,address,bytes32)"))
|
||||||
bytes4 internal constant MAKER_POOL_ASSIGNMENT_ERROR_SELECTOR =
|
bytes4 internal constant MAKER_POOL_ASSIGNMENT_ERROR_SELECTOR =
|
||||||
@ -217,35 +213,18 @@ library LibStakingRichErrors {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function OnlyCallableByPoolOperatorError(
|
function OnlyCallableByPoolOperatorOrMakerError(
|
||||||
address senderAddress,
|
address senderAddress,
|
||||||
address operator
|
address operator
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
returns (bytes memory)
|
returns (bytes memory)
|
||||||
{
|
|
||||||
return abi.encodeWithSelector(
|
|
||||||
ONLY_CALLABLE_BY_POOL_OPERATOR_ERROR_SELECTOR,
|
|
||||||
senderAddress,
|
|
||||||
operator
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function OnlyCallableByPoolOperatorOrMakerError(
|
|
||||||
address senderAddress,
|
|
||||||
address operator,
|
|
||||||
address makerAddress
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (bytes memory)
|
|
||||||
{
|
{
|
||||||
return abi.encodeWithSelector(
|
return abi.encodeWithSelector(
|
||||||
ONLY_CALLABLE_BY_POOL_OPERATOR_OR_MAKER_ERROR_SELECTOR,
|
ONLY_CALLABLE_BY_POOL_OPERATOR_OR_MAKER_ERROR_SELECTOR,
|
||||||
senderAddress,
|
senderAddress,
|
||||||
operator,
|
operator
|
||||||
makerAddress
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,10 +32,8 @@ contract MixinStake is
|
|||||||
MixinConstants,
|
MixinConstants,
|
||||||
Ownable,
|
Ownable,
|
||||||
MixinStorage,
|
MixinStorage,
|
||||||
MixinStakingPoolModifiers,
|
|
||||||
MixinScheduler,
|
MixinScheduler,
|
||||||
MixinStakeStorage,
|
MixinStakeStorage,
|
||||||
MixinStakingPoolMakers,
|
|
||||||
MixinStakeBalances,
|
MixinStakeBalances,
|
||||||
MixinCumulativeRewards,
|
MixinCumulativeRewards,
|
||||||
MixinStakingPoolRewards,
|
MixinStakingPoolRewards,
|
||||||
|
@ -24,7 +24,6 @@ import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
|||||||
import "../libs/LibStakingRichErrors.sol";
|
import "../libs/LibStakingRichErrors.sol";
|
||||||
import "../interfaces/IStructs.sol";
|
import "../interfaces/IStructs.sol";
|
||||||
import "./MixinStakingPoolRewards.sol";
|
import "./MixinStakingPoolRewards.sol";
|
||||||
import "./MixinStakingPoolMakers.sol";
|
|
||||||
|
|
||||||
|
|
||||||
contract MixinStakingPool is
|
contract MixinStakingPool is
|
||||||
@ -33,15 +32,21 @@ contract MixinStakingPool is
|
|||||||
MixinConstants,
|
MixinConstants,
|
||||||
Ownable,
|
Ownable,
|
||||||
MixinStorage,
|
MixinStorage,
|
||||||
MixinStakingPoolModifiers,
|
|
||||||
MixinScheduler,
|
MixinScheduler,
|
||||||
MixinStakeStorage,
|
MixinStakeStorage,
|
||||||
MixinStakingPoolMakers,
|
|
||||||
MixinStakeBalances,
|
MixinStakeBalances,
|
||||||
MixinCumulativeRewards,
|
MixinCumulativeRewards,
|
||||||
MixinStakingPoolRewards
|
MixinStakingPoolRewards
|
||||||
{
|
{
|
||||||
using LibSafeMath for uint256;
|
using LibSafeMath for uint256;
|
||||||
|
using LibSafeDowncast for uint256;
|
||||||
|
|
||||||
|
/// @dev Asserts that the sender is the operator of the input pool or the input maker.
|
||||||
|
/// @param poolId Pool sender must be operator of.
|
||||||
|
modifier onlyStakingPoolOperatorOrMaker(bytes32 poolId) {
|
||||||
|
_assertSenderIsPoolOperatorOrMaker(poolId);
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Create a new staking pool. The sender will be the operator of this pool.
|
/// @dev Create a new staking pool. The sender will be the operator of this pool.
|
||||||
/// Note that an operator must be payable.
|
/// Note that an operator must be payable.
|
||||||
@ -94,6 +99,7 @@ contract MixinStakingPool is
|
|||||||
/// @param newOperatorShare The newly decreased percentage of any rewards owned by the operator.
|
/// @param newOperatorShare The newly decreased percentage of any rewards owned by the operator.
|
||||||
function decreaseStakingPoolOperatorShare(bytes32 poolId, uint32 newOperatorShare)
|
function decreaseStakingPoolOperatorShare(bytes32 poolId, uint32 newOperatorShare)
|
||||||
external
|
external
|
||||||
|
onlyStakingPoolOperatorOrMaker(poolId)
|
||||||
{
|
{
|
||||||
// load pool and assert that we can decrease
|
// load pool and assert that we can decrease
|
||||||
uint32 currentOperatorShare = _poolById[poolId].operatorShare;
|
uint32 currentOperatorShare = _poolById[poolId].operatorShare;
|
||||||
@ -112,6 +118,110 @@ contract MixinStakingPool is
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Allows caller to join a staking pool if already assigned.
|
||||||
|
/// @param poolId Unique id of pool.
|
||||||
|
function joinStakingPoolAsMaker(bytes32 poolId)
|
||||||
|
external
|
||||||
|
{
|
||||||
|
// Is the maker already in a pool?
|
||||||
|
address makerAddress = msg.sender;
|
||||||
|
if (isMakerAssignedToStakingPool(makerAddress)) {
|
||||||
|
LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError(
|
||||||
|
LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered,
|
||||||
|
makerAddress,
|
||||||
|
getStakingPoolIdOfMaker(makerAddress)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
IStructs.MakerPoolJoinStatus memory poolJoinStatus = IStructs.MakerPoolJoinStatus({
|
||||||
|
poolId: poolId,
|
||||||
|
confirmed: false
|
||||||
|
});
|
||||||
|
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
|
||||||
|
IStructs.MakerPoolJoinStatus memory poolJoinStatus = IStructs.MakerPoolJoinStatus({
|
||||||
|
poolId: NIL_POOL_ID,
|
||||||
|
confirmed: false
|
||||||
|
});
|
||||||
|
poolJoinedByMakerAddress[makerAddress] = poolJoinStatus;
|
||||||
|
_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)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (bytes32)
|
||||||
|
{
|
||||||
|
if (isMakerAssignedToStakingPool(makerAddress)) {
|
||||||
|
return poolJoinedByMakerAddress[makerAddress].poolId;
|
||||||
|
} else {
|
||||||
|
return NIL_POOL_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Returns true iff the maker is assigned to a staking pool.
|
||||||
|
/// @param makerAddress Address of maker
|
||||||
|
/// @return True iff assigned.
|
||||||
|
function isMakerAssignedToStakingPool(address makerAddress)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return poolJoinedByMakerAddress[makerAddress].confirmed;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Returns a staking pool
|
/// @dev Returns a staking pool
|
||||||
/// @param poolId Unique id of pool.
|
/// @param poolId Unique id of pool.
|
||||||
function getStakingPool(bytes32 poolId)
|
function getStakingPool(bytes32 poolId)
|
||||||
@ -122,6 +232,75 @@ contract MixinStakingPool is
|
|||||||
return _poolById[poolId];
|
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 for use throughout this function
|
||||||
|
IStructs.Pool memory pool = _poolById[poolId];
|
||||||
|
|
||||||
|
// Is the maker already in a pool?
|
||||||
|
if (isMakerAssignedToStakingPool(makerAddress)) {
|
||||||
|
LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError(
|
||||||
|
LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered,
|
||||||
|
makerAddress,
|
||||||
|
getStakingPoolIdOfMaker(makerAddress)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the maker trying to join this pool; or are they the operator?
|
||||||
|
bytes32 makerPendingPoolId = poolJoinedByMakerAddress[makerAddress].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
|
||||||
|
IStructs.MakerPoolJoinStatus memory 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 return the staking pool operator
|
||||||
|
/// @param poolId Unique id of pool.
|
||||||
|
function _getStakingPoolOperator(bytes32 poolId)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (address operator)
|
||||||
|
{
|
||||||
|
operator = _poolById[poolId].operator;
|
||||||
|
return operator;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Computes the unique id that comes after the input pool id.
|
/// @dev Computes the unique id that comes after the input pool id.
|
||||||
/// @param poolId Unique id of pool.
|
/// @param poolId Unique id of pool.
|
||||||
/// @return Next pool id after input pool.
|
/// @return Next pool id after input pool.
|
||||||
@ -140,7 +319,7 @@ contract MixinStakingPool is
|
|||||||
view
|
view
|
||||||
returns (bool)
|
returns (bool)
|
||||||
{
|
{
|
||||||
if (_poolById[poolId].operator == NIL_ADDRESS) {
|
if (_getStakingPoolOperator(poolId) == NIL_ADDRESS) {
|
||||||
// we use the pool's operator as a proxy for its existence
|
// we use the pool's operator as a proxy for its existence
|
||||||
LibRichErrors.rrevert(
|
LibRichErrors.rrevert(
|
||||||
LibStakingRichErrors.PoolExistenceError(
|
LibStakingRichErrors.PoolExistenceError(
|
||||||
@ -180,4 +359,24 @@ contract MixinStakingPool is
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Asserts that the sender is the operator of the input pool or the input maker.
|
||||||
|
/// @param poolId Pool sender must be operator of.
|
||||||
|
function _assertSenderIsPoolOperatorOrMaker(bytes32 poolId)
|
||||||
|
private
|
||||||
|
view
|
||||||
|
{
|
||||||
|
address operator = _getStakingPoolOperator(poolId);
|
||||||
|
if (
|
||||||
|
msg.sender != operator &&
|
||||||
|
getStakingPoolIdOfMaker(msg.sender) != poolId
|
||||||
|
) {
|
||||||
|
LibRichErrors.rrevert(
|
||||||
|
LibStakingRichErrors.OnlyCallableByPoolOperatorOrMakerError(
|
||||||
|
msg.sender,
|
||||||
|
operator
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,206 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright 2019 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.5.9;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
|
||||||
import "../libs/LibStakingRichErrors.sol";
|
|
||||||
import "../libs/LibSafeDowncast.sol";
|
|
||||||
import "../interfaces/IStructs.sol";
|
|
||||||
import "../interfaces/IStakingEvents.sol";
|
|
||||||
import "../immutable/MixinStorage.sol";
|
|
||||||
import "./MixinStakingPoolModifiers.sol";
|
|
||||||
|
|
||||||
|
|
||||||
/// @dev This mixin contains logic for staking pools.
|
|
||||||
contract MixinStakingPoolMakers is
|
|
||||||
IStakingEvents,
|
|
||||||
MixinConstants,
|
|
||||||
Ownable,
|
|
||||||
MixinStorage,
|
|
||||||
MixinStakingPoolModifiers
|
|
||||||
{
|
|
||||||
|
|
||||||
using LibSafeMath for uint256;
|
|
||||||
using LibSafeDowncast for uint256;
|
|
||||||
|
|
||||||
/// @dev Allows caller to join a staking pool if already assigned.
|
|
||||||
/// @param poolId Unique id of pool.
|
|
||||||
function joinStakingPoolAsMaker(
|
|
||||||
bytes32 poolId
|
|
||||||
)
|
|
||||||
external
|
|
||||||
{
|
|
||||||
// Is the maker already in a pool?
|
|
||||||
address makerAddress = msg.sender;
|
|
||||||
if (isMakerAssignedToStakingPool(makerAddress)) {
|
|
||||||
LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError(
|
|
||||||
LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered,
|
|
||||||
makerAddress,
|
|
||||||
getStakingPoolIdOfMaker(makerAddress)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
IStructs.MakerPoolJoinStatus memory poolJoinStatus = IStructs.MakerPoolJoinStatus({
|
|
||||||
poolId: poolId,
|
|
||||||
confirmed: false
|
|
||||||
});
|
|
||||||
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
|
|
||||||
onlyStakingPoolOperator(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, makerAddress)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
IStructs.MakerPoolJoinStatus memory poolJoinStatus = IStructs.MakerPoolJoinStatus({
|
|
||||||
poolId: NIL_POOL_ID,
|
|
||||||
confirmed: false
|
|
||||||
});
|
|
||||||
poolJoinedByMakerAddress[makerAddress] = poolJoinStatus;
|
|
||||||
_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)
|
|
||||||
public
|
|
||||||
view
|
|
||||||
returns (bytes32)
|
|
||||||
{
|
|
||||||
if (isMakerAssignedToStakingPool(makerAddress)) {
|
|
||||||
return poolJoinedByMakerAddress[makerAddress].poolId;
|
|
||||||
} else {
|
|
||||||
return NIL_POOL_ID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Returns true iff the maker is assigned to a staking pool.
|
|
||||||
/// @param makerAddress Address of maker
|
|
||||||
/// @return True iff assigned.
|
|
||||||
function isMakerAssignedToStakingPool(address makerAddress)
|
|
||||||
public
|
|
||||||
view
|
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
return poolJoinedByMakerAddress[makerAddress].confirmed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @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 for use throughout this function
|
|
||||||
IStructs.Pool memory pool = _poolById[poolId];
|
|
||||||
|
|
||||||
// Is the maker already in a pool?
|
|
||||||
if (isMakerAssignedToStakingPool(makerAddress)) {
|
|
||||||
LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError(
|
|
||||||
LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered,
|
|
||||||
makerAddress,
|
|
||||||
getStakingPoolIdOfMaker(makerAddress)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the maker trying to join this pool; or are they the operator?
|
|
||||||
bytes32 makerPendingPoolId = poolJoinedByMakerAddress[makerAddress].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
|
|
||||||
IStructs.MakerPoolJoinStatus memory 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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright 2019 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.5.9;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
import "../immutable/MixinStorage.sol";
|
|
||||||
|
|
||||||
|
|
||||||
contract MixinStakingPoolModifiers is
|
|
||||||
MixinConstants,
|
|
||||||
Ownable,
|
|
||||||
MixinStorage
|
|
||||||
{
|
|
||||||
|
|
||||||
/// @dev Asserts that the sender is the operator of the input pool.
|
|
||||||
/// @param poolId Pool sender must be operator of.
|
|
||||||
modifier onlyStakingPoolOperator(bytes32 poolId) {
|
|
||||||
address operator = _poolById[poolId].operator;
|
|
||||||
if (msg.sender != operator) {
|
|
||||||
LibRichErrors.rrevert(LibStakingRichErrors.OnlyCallableByPoolOperatorError(
|
|
||||||
msg.sender,
|
|
||||||
operator
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Asserts that the sender is the operator of the input pool or the input maker.
|
|
||||||
/// @param poolId Pool sender must be operator of.
|
|
||||||
/// @param makerAddress Address of a maker in the pool.
|
|
||||||
modifier onlyStakingPoolOperatorOrMaker(bytes32 poolId, address makerAddress) {
|
|
||||||
address operator = _poolById[poolId].operator;
|
|
||||||
if (
|
|
||||||
msg.sender != operator &&
|
|
||||||
msg.sender != makerAddress
|
|
||||||
) {
|
|
||||||
LibRichErrors.rrevert(
|
|
||||||
LibStakingRichErrors.OnlyCallableByPoolOperatorOrMakerError(
|
|
||||||
msg.sender,
|
|
||||||
operator,
|
|
||||||
makerAddress
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
}
|
|
@ -37,7 +37,7 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||||
"abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingProxy|IStorage|IStorageInit|IStructs|IVaultCore|IZrxVault|LibCobbDouglas|LibFixedMath|LibFixedMathRichErrors|LibProxy|LibSafeDowncast|LibStakingRichErrors|MixinAbstract|MixinConstants|MixinCumulativeRewards|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinFinalizer|MixinParams|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakeStorage|MixinStakingPool|MixinStakingPoolMakers|MixinStakingPoolModifiers|MixinStakingPoolRewards|MixinStorage|MixinVaultCore|ReadOnlyProxy|Staking|StakingProxy|TestAssertStorageParams|TestCobbDouglas|TestCumulativeRewardTracking|TestDelegatorRewards|TestFinalizer|TestInitTarget|TestLibFixedMath|TestLibProxy|TestLibProxyReceiver|TestLibSafeDowncast|TestMixinVaultCore|TestProtocolFees|TestStaking|TestStakingNoWETH|TestStakingProxy|ZrxVault).json"
|
"abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingProxy|IStorage|IStorageInit|IStructs|IVaultCore|IZrxVault|LibCobbDouglas|LibFixedMath|LibFixedMathRichErrors|LibProxy|LibSafeDowncast|LibStakingRichErrors|MixinAbstract|MixinConstants|MixinCumulativeRewards|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinFinalizer|MixinParams|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakeStorage|MixinStakingPool|MixinStakingPoolRewards|MixinStorage|MixinVaultCore|ReadOnlyProxy|Staking|StakingProxy|TestAssertStorageParams|TestCobbDouglas|TestCumulativeRewardTracking|TestDelegatorRewards|TestFinalizer|TestInitTarget|TestLibFixedMath|TestLibProxy|TestLibProxyReceiver|TestLibSafeDowncast|TestMixinVaultCore|TestProtocolFees|TestStaking|TestStakingNoWETH|TestStakingProxy|ZrxVault).json"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -32,8 +32,6 @@ import * as MixinStake from '../generated-artifacts/MixinStake.json';
|
|||||||
import * as MixinStakeBalances from '../generated-artifacts/MixinStakeBalances.json';
|
import * as MixinStakeBalances from '../generated-artifacts/MixinStakeBalances.json';
|
||||||
import * as MixinStakeStorage from '../generated-artifacts/MixinStakeStorage.json';
|
import * as MixinStakeStorage from '../generated-artifacts/MixinStakeStorage.json';
|
||||||
import * as MixinStakingPool from '../generated-artifacts/MixinStakingPool.json';
|
import * as MixinStakingPool from '../generated-artifacts/MixinStakingPool.json';
|
||||||
import * as MixinStakingPoolMakers from '../generated-artifacts/MixinStakingPoolMakers.json';
|
|
||||||
import * as MixinStakingPoolModifiers from '../generated-artifacts/MixinStakingPoolModifiers.json';
|
|
||||||
import * as MixinStakingPoolRewards from '../generated-artifacts/MixinStakingPoolRewards.json';
|
import * as MixinStakingPoolRewards from '../generated-artifacts/MixinStakingPoolRewards.json';
|
||||||
import * as MixinStorage from '../generated-artifacts/MixinStorage.json';
|
import * as MixinStorage from '../generated-artifacts/MixinStorage.json';
|
||||||
import * as MixinVaultCore from '../generated-artifacts/MixinVaultCore.json';
|
import * as MixinVaultCore from '../generated-artifacts/MixinVaultCore.json';
|
||||||
@ -84,8 +82,6 @@ export const artifacts = {
|
|||||||
MixinStakeStorage: MixinStakeStorage as ContractArtifact,
|
MixinStakeStorage: MixinStakeStorage as ContractArtifact,
|
||||||
MixinCumulativeRewards: MixinCumulativeRewards as ContractArtifact,
|
MixinCumulativeRewards: MixinCumulativeRewards as ContractArtifact,
|
||||||
MixinStakingPool: MixinStakingPool as ContractArtifact,
|
MixinStakingPool: MixinStakingPool as ContractArtifact,
|
||||||
MixinStakingPoolMakers: MixinStakingPoolMakers as ContractArtifact,
|
|
||||||
MixinStakingPoolModifiers: MixinStakingPoolModifiers as ContractArtifact,
|
|
||||||
MixinStakingPoolRewards: MixinStakingPoolRewards as ContractArtifact,
|
MixinStakingPoolRewards: MixinStakingPoolRewards as ContractArtifact,
|
||||||
MixinAbstract: MixinAbstract as ContractArtifact,
|
MixinAbstract: MixinAbstract as ContractArtifact,
|
||||||
MixinFinalizer: MixinFinalizer as ContractArtifact,
|
MixinFinalizer: MixinFinalizer as ContractArtifact,
|
||||||
|
@ -30,8 +30,6 @@ export * from '../generated-wrappers/mixin_stake';
|
|||||||
export * from '../generated-wrappers/mixin_stake_balances';
|
export * from '../generated-wrappers/mixin_stake_balances';
|
||||||
export * from '../generated-wrappers/mixin_stake_storage';
|
export * from '../generated-wrappers/mixin_stake_storage';
|
||||||
export * from '../generated-wrappers/mixin_staking_pool';
|
export * from '../generated-wrappers/mixin_staking_pool';
|
||||||
export * from '../generated-wrappers/mixin_staking_pool_makers';
|
|
||||||
export * from '../generated-wrappers/mixin_staking_pool_modifiers';
|
|
||||||
export * from '../generated-wrappers/mixin_staking_pool_rewards';
|
export * from '../generated-wrappers/mixin_staking_pool_rewards';
|
||||||
export * from '../generated-wrappers/mixin_storage';
|
export * from '../generated-wrappers/mixin_storage';
|
||||||
export * from '../generated-wrappers/mixin_vault_core';
|
export * from '../generated-wrappers/mixin_vault_core';
|
||||||
|
@ -277,7 +277,7 @@ blockchainTests('Staking Pool Management', env => {
|
|||||||
expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID);
|
expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID);
|
||||||
// add maker to pool
|
// add maker to pool
|
||||||
await maker.joinStakingPoolAsMakerAsync(poolId);
|
await maker.joinStakingPoolAsMakerAsync(poolId);
|
||||||
const revertError = new StakingRevertErrors.OnlyCallableByPoolOperatorError(
|
const revertError = new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(
|
||||||
notOperatorAddress,
|
notOperatorAddress,
|
||||||
operatorAddress,
|
operatorAddress,
|
||||||
);
|
);
|
||||||
@ -306,7 +306,6 @@ blockchainTests('Staking Pool Management', env => {
|
|||||||
const revertError = new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(
|
const revertError = new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(
|
||||||
neitherOperatorNorMakerAddress,
|
neitherOperatorNorMakerAddress,
|
||||||
operatorAddress,
|
operatorAddress,
|
||||||
makerAddress,
|
|
||||||
);
|
);
|
||||||
const tx = stakingApiWrapper.stakingContract.removeMakerFromStakingPool.awaitTransactionSuccessAsync(
|
const tx = stakingApiWrapper.stakingContract.removeMakerFromStakingPool.awaitTransactionSuccessAsync(
|
||||||
poolId,
|
poolId,
|
||||||
|
@ -30,8 +30,6 @@
|
|||||||
"generated-artifacts/MixinStakeBalances.json",
|
"generated-artifacts/MixinStakeBalances.json",
|
||||||
"generated-artifacts/MixinStakeStorage.json",
|
"generated-artifacts/MixinStakeStorage.json",
|
||||||
"generated-artifacts/MixinStakingPool.json",
|
"generated-artifacts/MixinStakingPool.json",
|
||||||
"generated-artifacts/MixinStakingPoolMakers.json",
|
|
||||||
"generated-artifacts/MixinStakingPoolModifiers.json",
|
|
||||||
"generated-artifacts/MixinStakingPoolRewards.json",
|
"generated-artifacts/MixinStakingPoolRewards.json",
|
||||||
"generated-artifacts/MixinStorage.json",
|
"generated-artifacts/MixinStorage.json",
|
||||||
"generated-artifacts/MixinVaultCore.json",
|
"generated-artifacts/MixinVaultCore.json",
|
||||||
|
@ -77,22 +77,12 @@ export class InsufficientBalanceError extends RevertError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OnlyCallableByPoolOperatorError extends RevertError {
|
export class OnlyCallableByPoolOperatorOrMakerError extends RevertError {
|
||||||
constructor(senderAddress?: string, poolOperatorAddress?: string) {
|
constructor(senderAddress?: string, poolOperatorAddress?: string) {
|
||||||
super(
|
|
||||||
'OnlyCallableByPoolOperatorError',
|
|
||||||
'OnlyCallableByPoolOperatorError(address senderAddress, address poolOperatorAddress)',
|
|
||||||
{ senderAddress, poolOperatorAddress },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class OnlyCallableByPoolOperatorOrMakerError extends RevertError {
|
|
||||||
constructor(senderAddress?: string, poolOperatorAddress?: string, makerAddress?: string) {
|
|
||||||
super(
|
super(
|
||||||
'OnlyCallableByPoolOperatorOrMakerError',
|
'OnlyCallableByPoolOperatorOrMakerError',
|
||||||
'OnlyCallableByPoolOperatorOrMakerError(address senderAddress, address poolOperatorAddress, address makerAddress)',
|
'OnlyCallableByPoolOperatorOrMakerError(address senderAddress, address poolOperatorAddress)',
|
||||||
{ senderAddress, poolOperatorAddress, makerAddress },
|
{ senderAddress, poolOperatorAddress },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,7 +233,6 @@ const types = [
|
|||||||
MakerPoolAssignmentError,
|
MakerPoolAssignmentError,
|
||||||
MiscalculatedRewardsError,
|
MiscalculatedRewardsError,
|
||||||
OnlyCallableByExchangeError,
|
OnlyCallableByExchangeError,
|
||||||
OnlyCallableByPoolOperatorError,
|
|
||||||
OnlyCallableByPoolOperatorOrMakerError,
|
OnlyCallableByPoolOperatorOrMakerError,
|
||||||
OnlyCallableByStakingContractError,
|
OnlyCallableByStakingContractError,
|
||||||
OnlyCallableIfInCatastrophicFailureError,
|
OnlyCallableIfInCatastrophicFailureError,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user