Merge pull request #2190 from 0xProject/feat/3.0/consolidate-pool-mixins
Consolidate staking pool mixins
This commit is contained in:
commit
0c5f0271c7
@ -1,4 +1,4 @@
|
|||||||
import { chaiSetup, getCodesizeFromArtifact } from '@0x/contracts-test-utils';
|
import { chaiSetup, constants, getCodesizeFromArtifact } from '@0x/contracts-test-utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
@ -7,12 +7,10 @@ const expect = chai.expect;
|
|||||||
import { artifacts } from '../src';
|
import { artifacts } from '../src';
|
||||||
|
|
||||||
describe('Contract Size Checks', () => {
|
describe('Contract Size Checks', () => {
|
||||||
const MAX_CODE_SIZE = 24576;
|
|
||||||
|
|
||||||
describe('Exchange', () => {
|
describe('Exchange', () => {
|
||||||
it('should have a codesize less than the maximum', async () => {
|
it('should have a codesize less than the maximum', async () => {
|
||||||
const actualSize = getCodesizeFromArtifact(artifacts.Exchange);
|
const actualSize = getCodesizeFromArtifact(artifacts.Exchange);
|
||||||
expect(actualSize).to.be.lt(MAX_CODE_SIZE);
|
expect(actualSize).to.be.lt(constants.MAX_CODE_SIZE);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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,
|
||||||
@ -214,8 +212,8 @@ contract Staking is
|
|||||||
slot := add(slot, 0x1)
|
slot := add(slot, 0x1)
|
||||||
|
|
||||||
assertSlotAndOffset(
|
assertSlotAndOffset(
|
||||||
poolJoinedByMakerAddress_slot,
|
_poolJoinedByMakerAddress_slot,
|
||||||
poolJoinedByMakerAddress_offset,
|
_poolJoinedByMakerAddress_offset,
|
||||||
slot,
|
slot,
|
||||||
offset
|
offset
|
||||||
)
|
)
|
||||||
@ -378,8 +376,8 @@ contract Staking is
|
|||||||
slot := add(slot, 0x1)
|
slot := add(slot, 0x1)
|
||||||
|
|
||||||
assertSlotAndOffset(
|
assertSlotAndOffset(
|
||||||
_wethReservedForPoolRewards_slot,
|
wethReservedForPoolRewards_slot,
|
||||||
_wethReservedForPoolRewards_offset,
|
wethReservedForPoolRewards_offset,
|
||||||
slot,
|
slot,
|
||||||
offset
|
offset
|
||||||
)
|
)
|
||||||
|
@ -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,
|
||||||
@ -126,20 +124,6 @@ contract MixinExchangeFees is
|
|||||||
activePoolsThisEpoch[poolId] = pool;
|
activePoolsThisEpoch[poolId] = pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Returns the total balance of this contract, including WETH,
|
|
||||||
/// minus any WETH that has been reserved for rewards.
|
|
||||||
/// @return totalBalance Total balance.
|
|
||||||
function getAvailableRewardsBalance()
|
|
||||||
external
|
|
||||||
view
|
|
||||||
returns (uint256 totalBalance)
|
|
||||||
{
|
|
||||||
totalBalance = address(this).balance.safeAdd(
|
|
||||||
_getAvailableWethBalance()
|
|
||||||
);
|
|
||||||
return totalBalance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Get information on an active staking pool in this epoch.
|
/// @dev Get information on an active staking pool in this epoch.
|
||||||
/// @param poolId Pool Id to query.
|
/// @param poolId Pool Id to query.
|
||||||
/// @return pool ActivePool struct.
|
/// @return pool ActivePool struct.
|
||||||
@ -170,6 +154,7 @@ contract MixinExchangeFees is
|
|||||||
_poolById[poolId].operator,
|
_poolById[poolId].operator,
|
||||||
poolId
|
poolId
|
||||||
).currentEpochBalance;
|
).currentEpochBalance;
|
||||||
|
|
||||||
membersStake = totalStake.safeSub(operatorStake);
|
membersStake = totalStake.safeSub(operatorStake);
|
||||||
weightedStake = operatorStake.safeAdd(
|
weightedStake = operatorStake.safeAdd(
|
||||||
LibMath.getPartialAmountFloor(
|
LibMath.getPartialAmountFloor(
|
||||||
|
@ -77,7 +77,8 @@ contract MixinStorage is
|
|||||||
|
|
||||||
// mapping from Maker Address to a struct representing the pool the maker has joined and
|
// 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.
|
// whether the operator of that pool has subsequently added the maker.
|
||||||
mapping (address => IStructs.MakerPoolJoinStatus) public poolJoinedByMakerAddress;
|
// (access externally using `getStakingPoolIdOfMaker`)
|
||||||
|
mapping (address => IStructs.MakerPoolJoinStatus) internal _poolJoinedByMakerAddress;
|
||||||
|
|
||||||
// mapping from Pool Id to Pool
|
// mapping from Pool Id to Pool
|
||||||
mapping (bytes32 => IStructs.Pool) internal _poolById;
|
mapping (bytes32 => IStructs.Pool) internal _poolById;
|
||||||
@ -144,7 +145,7 @@ contract MixinStorage is
|
|||||||
IStructs.UnfinalizedState public unfinalizedState;
|
IStructs.UnfinalizedState public unfinalizedState;
|
||||||
|
|
||||||
/// @dev The WETH balance of this contract that is reserved for pool reward payouts.
|
/// @dev The WETH balance of this contract that is reserved for pool reward payouts.
|
||||||
uint256 _wethReservedForPoolRewards;
|
uint256 public wethReservedForPoolRewards;
|
||||||
|
|
||||||
/// @dev Adds owner as an authorized address.
|
/// @dev Adds owner as an authorized address.
|
||||||
constructor()
|
constructor()
|
||||||
|
@ -51,11 +51,6 @@ interface IStorage {
|
|||||||
view
|
view
|
||||||
returns (bytes32);
|
returns (bytes32);
|
||||||
|
|
||||||
function poolJoinedByMakerAddress(address makerAddress)
|
|
||||||
external
|
|
||||||
view
|
|
||||||
returns (IStructs.MakerPoolJoinStatus memory);
|
|
||||||
|
|
||||||
function numMakersByPoolId(bytes32 poolId)
|
function numMakersByPoolId(bytes32 poolId)
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
|
@ -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,bytes32)"))
|
||||||
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;
|
0x7677eb13;
|
||||||
|
|
||||||
// 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,25 +213,9 @@ library LibStakingRichErrors {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function OnlyCallableByPoolOperatorError(
|
|
||||||
address senderAddress,
|
|
||||||
address operator
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (bytes memory)
|
|
||||||
{
|
|
||||||
return abi.encodeWithSelector(
|
|
||||||
ONLY_CALLABLE_BY_POOL_OPERATOR_ERROR_SELECTOR,
|
|
||||||
senderAddress,
|
|
||||||
operator
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function OnlyCallableByPoolOperatorOrMakerError(
|
function OnlyCallableByPoolOperatorOrMakerError(
|
||||||
address senderAddress,
|
address senderAddress,
|
||||||
address operator,
|
bytes32 poolId
|
||||||
address makerAddress
|
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
@ -244,8 +224,7 @@ library LibStakingRichErrors {
|
|||||||
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,
|
poolId
|
||||||
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,94 @@ 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;
|
||||||
|
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)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (bytes32)
|
||||||
|
{
|
||||||
|
IStructs.MakerPoolJoinStatus memory poolJoinStatus = _poolJoinedByMakerAddress[makerAddress];
|
||||||
|
if (poolJoinStatus.confirmed) {
|
||||||
|
return poolJoinStatus.poolId;
|
||||||
|
} else {
|
||||||
|
return NIL_POOL_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @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 +216,65 @@ 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 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.
|
/// @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.
|
||||||
@ -180,4 +333,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 = _poolById[poolId].operator;
|
||||||
|
if (
|
||||||
|
msg.sender != operator &&
|
||||||
|
getStakingPoolIdOfMaker(msg.sender) != poolId
|
||||||
|
) {
|
||||||
|
LibRichErrors.rrevert(
|
||||||
|
LibStakingRichErrors.OnlyCallableByPoolOperatorOrMakerError(
|
||||||
|
msg.sender,
|
||||||
|
poolId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
}
|
|
@ -188,8 +188,8 @@ contract MixinStakingPoolRewards is
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (membersReward > 0) {
|
if (membersReward > 0) {
|
||||||
// Increment the balance of the pool
|
// Increase the balance of the pool
|
||||||
_incrementPoolRewards(poolId, membersReward);
|
_increasePoolRewards(poolId, membersReward);
|
||||||
|
|
||||||
// Fetch the last epoch at which we stored an entry for this pool;
|
// Fetch the last epoch at which we stored an entry for this pool;
|
||||||
// this is the most up-to-date cumulative rewards for this pool.
|
// this is the most up-to-date cumulative rewards for this pool.
|
||||||
@ -279,8 +279,8 @@ contract MixinStakingPoolRewards is
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrement the balance of the pool
|
// Decrease the balance of the pool
|
||||||
_decrementPoolRewards(poolId, balance);
|
_decreasePoolRewards(poolId, balance);
|
||||||
|
|
||||||
// Withdraw the member's WETH balance
|
// Withdraw the member's WETH balance
|
||||||
_getWethContract().transfer(member, balance);
|
_getWethContract().transfer(member, balance);
|
||||||
@ -421,23 +421,23 @@ contract MixinStakingPoolRewards is
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Increments rewards for a pool.
|
/// @dev Increases rewards for a pool.
|
||||||
/// @param poolId Unique id of pool.
|
/// @param poolId Unique id of pool.
|
||||||
/// @param amount Amount to increment rewards by.
|
/// @param amount Amount to increment rewards by.
|
||||||
function _incrementPoolRewards(bytes32 poolId, uint256 amount)
|
function _increasePoolRewards(bytes32 poolId, uint256 amount)
|
||||||
private
|
private
|
||||||
{
|
{
|
||||||
rewardsByPoolId[poolId] = rewardsByPoolId[poolId].safeAdd(amount);
|
rewardsByPoolId[poolId] = rewardsByPoolId[poolId].safeAdd(amount);
|
||||||
_wethReservedForPoolRewards = _wethReservedForPoolRewards.safeAdd(amount);
|
wethReservedForPoolRewards = wethReservedForPoolRewards.safeAdd(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Decrements rewards for a pool.
|
/// @dev Decreases rewards for a pool.
|
||||||
/// @param poolId Unique id of pool.
|
/// @param poolId Unique id of pool.
|
||||||
/// @param amount Amount to decrement rewards by.
|
/// @param amount Amount to decrement rewards by.
|
||||||
function _decrementPoolRewards(bytes32 poolId, uint256 amount)
|
function _decreasePoolRewards(bytes32 poolId, uint256 amount)
|
||||||
private
|
private
|
||||||
{
|
{
|
||||||
rewardsByPoolId[poolId] = rewardsByPoolId[poolId].safeSub(amount);
|
rewardsByPoolId[poolId] = rewardsByPoolId[poolId].safeSub(amount);
|
||||||
_wethReservedForPoolRewards = _wethReservedForPoolRewards.safeSub(amount);
|
wethReservedForPoolRewards = wethReservedForPoolRewards.safeSub(amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ contract MixinFinalizer is
|
|||||||
returns (uint256 wethBalance)
|
returns (uint256 wethBalance)
|
||||||
{
|
{
|
||||||
wethBalance = _getWethContract().balanceOf(address(this))
|
wethBalance = _getWethContract().balanceOf(address(this))
|
||||||
.safeSub(_wethReservedForPoolRewards);
|
.safeSub(wethReservedForPoolRewards);
|
||||||
|
|
||||||
return wethBalance;
|
return wethBalance;
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,8 @@ contract TestProtocolFees is
|
|||||||
function addMakerToPool(bytes32 poolId, address makerAddress)
|
function addMakerToPool(bytes32 poolId, address makerAddress)
|
||||||
external
|
external
|
||||||
{
|
{
|
||||||
poolJoinedByMakerAddress[makerAddress].poolId = poolId;
|
_poolJoinedByMakerAddress[makerAddress].poolId = poolId;
|
||||||
poolJoinedByMakerAddress[makerAddress].confirmed = true;
|
_poolJoinedByMakerAddress[makerAddress].confirmed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function advanceEpoch()
|
function advanceEpoch()
|
||||||
|
@ -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';
|
||||||
|
@ -241,7 +241,7 @@ export class FinalizerActor extends BaseActor {
|
|||||||
this._stakingApiWrapper.stakingContract.getActiveStakingPoolThisEpoch.callAsync(poolId),
|
this._stakingApiWrapper.stakingContract.getActiveStakingPoolThisEpoch.callAsync(poolId),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const totalRewards = await this._stakingApiWrapper.stakingContract.getAvailableRewardsBalance.callAsync();
|
const totalRewards = await this._stakingApiWrapper.utils.getAvailableRewardsBalanceAsync();
|
||||||
const totalFeesCollected = BigNumber.sum(...activePools.map(p => p.feesCollected));
|
const totalFeesCollected = BigNumber.sum(...activePools.map(p => p.feesCollected));
|
||||||
const totalWeightedStake = BigNumber.sum(...activePools.map(p => p.weightedStake));
|
const totalWeightedStake = BigNumber.sum(...activePools.map(p => p.weightedStake));
|
||||||
if (totalRewards.eq(0) || totalFeesCollected.eq(0) || totalWeightedStake.eq(0)) {
|
if (totalRewards.eq(0) || totalFeesCollected.eq(0) || totalWeightedStake.eq(0)) {
|
||||||
|
@ -4,9 +4,9 @@ import * as _ from 'lodash';
|
|||||||
|
|
||||||
import { constants as stakingConstants } from '../utils/constants';
|
import { constants as stakingConstants } from '../utils/constants';
|
||||||
|
|
||||||
import { BaseActor } from './base_actor';
|
import { PoolOperatorActor } from './pool_operator_actor';
|
||||||
|
|
||||||
export class MakerActor extends BaseActor {
|
export class MakerActor extends PoolOperatorActor {
|
||||||
public async joinStakingPoolAsMakerAsync(poolId: string, revertError?: RevertError): Promise<void> {
|
public async joinStakingPoolAsMakerAsync(poolId: string, revertError?: RevertError): Promise<void> {
|
||||||
// Join pool
|
// Join pool
|
||||||
const txReceiptPromise = this._stakingApiWrapper.stakingContract.joinStakingPoolAsMaker.awaitTransactionSuccessAsync(
|
const txReceiptPromise = this._stakingApiWrapper.stakingContract.joinStakingPoolAsMaker.awaitTransactionSuccessAsync(
|
||||||
@ -26,29 +26,4 @@ export class MakerActor extends BaseActor {
|
|||||||
);
|
);
|
||||||
expect(poolIdOfMaker, 'pool id of maker').to.be.equal(stakingConstants.NIL_POOL_ID);
|
expect(poolIdOfMaker, 'pool id of maker').to.be.equal(stakingConstants.NIL_POOL_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async removeMakerFromStakingPoolAsync(
|
|
||||||
poolId: string,
|
|
||||||
makerAddress: string,
|
|
||||||
revertError?: RevertError,
|
|
||||||
): Promise<void> {
|
|
||||||
// remove maker (should fail if makerAddress !== this._owner)
|
|
||||||
const txReceiptPromise = this._stakingApiWrapper.stakingContract.removeMakerFromStakingPool.awaitTransactionSuccessAsync(
|
|
||||||
poolId,
|
|
||||||
makerAddress,
|
|
||||||
{ from: this._owner },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (revertError !== undefined) {
|
|
||||||
await expect(txReceiptPromise).to.revertWith(revertError);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await txReceiptPromise;
|
|
||||||
|
|
||||||
// check the pool id of the maker
|
|
||||||
const poolIdOfMakerAfterRemoving = await this._stakingApiWrapper.stakingContract.getStakingPoolIdOfMaker.callAsync(
|
|
||||||
this._owner,
|
|
||||||
);
|
|
||||||
expect(poolIdOfMakerAfterRemoving, 'pool id of maker').to.be.equal(stakingConstants.NIL_POOL_ID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
18
contracts/staking/test/codesize.ts
Normal file
18
contracts/staking/test/codesize.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { constants, expect, getCodesizeFromArtifact } from '@0x/contracts-test-utils';
|
||||||
|
|
||||||
|
import { artifacts } from '../src';
|
||||||
|
|
||||||
|
describe.skip('Contract Size Checks', () => {
|
||||||
|
describe('Staking', () => {
|
||||||
|
it('should have a codesize less than the maximum', async () => {
|
||||||
|
const actualSize = getCodesizeFromArtifact(artifacts.Staking);
|
||||||
|
expect(actualSize).to.be.lt(constants.MAX_CODE_SIZE);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('StakingProxy', () => {
|
||||||
|
it('should have a codesize less than the maximum', async () => {
|
||||||
|
const actualSize = getCodesizeFromArtifact(artifacts.StakingProxy);
|
||||||
|
expect(actualSize).to.be.lt(constants.MAX_CODE_SIZE);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -9,6 +9,7 @@ import { deployAndConfigureContractsAsync, StakingApiWrapper } from './utils/api
|
|||||||
import { constants as stakingConstants } from './utils/constants';
|
import { constants as stakingConstants } from './utils/constants';
|
||||||
|
|
||||||
// tslint:disable:no-unnecessary-type-assertion
|
// tslint:disable:no-unnecessary-type-assertion
|
||||||
|
// tslint:disable:max-file-line-count
|
||||||
blockchainTests('Staking Pool Management', env => {
|
blockchainTests('Staking Pool Management', env => {
|
||||||
// constants
|
// constants
|
||||||
const { PPM_100_PERCENT, PPM_DENOMINATOR } = constants;
|
const { PPM_100_PERCENT, PPM_DENOMINATOR } = constants;
|
||||||
@ -23,8 +24,7 @@ blockchainTests('Staking Pool Management', env => {
|
|||||||
before(async () => {
|
before(async () => {
|
||||||
// create accounts
|
// create accounts
|
||||||
accounts = await env.getAccountAddressesAsync();
|
accounts = await env.getAccountAddressesAsync();
|
||||||
owner = accounts[0];
|
[owner, ...users] = accounts;
|
||||||
users = accounts.slice(1);
|
|
||||||
// set up ERC20Wrapper
|
// set up ERC20Wrapper
|
||||||
erc20Wrapper = new ERC20Wrapper(env.provider, accounts, owner);
|
erc20Wrapper = new ERC20Wrapper(env.provider, accounts, owner);
|
||||||
// deploy staking contracts
|
// deploy staking contracts
|
||||||
@ -102,6 +102,65 @@ blockchainTests('Staking Pool Management', env => {
|
|||||||
// operator removes maker from pool
|
// operator removes maker from pool
|
||||||
await poolOperator.removeMakerFromStakingPoolAsync(poolId, makerAddress);
|
await poolOperator.removeMakerFromStakingPoolAsync(poolId, makerAddress);
|
||||||
});
|
});
|
||||||
|
it('Should successfully add/remove a maker to a pool if approved by maker', async () => {
|
||||||
|
// test parameters
|
||||||
|
const operatorAddress = users[0];
|
||||||
|
const operatorShare = (39 / 100) * PPM_DENOMINATOR;
|
||||||
|
const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper);
|
||||||
|
const maker1Address = users[1];
|
||||||
|
const maker1 = new MakerActor(maker1Address, stakingApiWrapper);
|
||||||
|
const maker2Address = users[2];
|
||||||
|
const maker2 = new MakerActor(maker2Address, stakingApiWrapper);
|
||||||
|
// create pool
|
||||||
|
const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true);
|
||||||
|
expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID);
|
||||||
|
// maker joins pool
|
||||||
|
await maker1.joinStakingPoolAsMakerAsync(poolId);
|
||||||
|
// operator adds maker to pool
|
||||||
|
await poolOperator.addMakerToStakingPoolAsync(poolId, maker1Address);
|
||||||
|
// maker joins pool
|
||||||
|
await maker2.joinStakingPoolAsMakerAsync(poolId);
|
||||||
|
// approved maker adds new maker to pool
|
||||||
|
await maker1.addMakerToStakingPoolAsync(poolId, maker2Address);
|
||||||
|
});
|
||||||
|
it('should fail to add a maker to a pool if called by pending maker', async () => {
|
||||||
|
// test parameters
|
||||||
|
const operatorAddress = users[0];
|
||||||
|
const operatorShare = (39 / 100) * PPM_DENOMINATOR;
|
||||||
|
const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper);
|
||||||
|
const makerAddress = users[1];
|
||||||
|
const maker = new MakerActor(makerAddress, stakingApiWrapper);
|
||||||
|
// create pool
|
||||||
|
const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true);
|
||||||
|
expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID);
|
||||||
|
// maker joins pool
|
||||||
|
await maker.joinStakingPoolAsMakerAsync(poolId);
|
||||||
|
await maker.addMakerToStakingPoolAsync(
|
||||||
|
poolId,
|
||||||
|
makerAddress,
|
||||||
|
new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(makerAddress, poolId),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('should fail to add a maker to a pool if not called by operator/registered maker', async () => {
|
||||||
|
// test parameters
|
||||||
|
const operatorAddress = users[0];
|
||||||
|
const operatorShare = (39 / 100) * PPM_DENOMINATOR;
|
||||||
|
const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper);
|
||||||
|
const maker1Address = users[1];
|
||||||
|
const maker1 = new MakerActor(maker1Address, stakingApiWrapper);
|
||||||
|
const maker2Address = users[2];
|
||||||
|
const maker2 = new MakerActor(maker2Address, stakingApiWrapper);
|
||||||
|
// create pool
|
||||||
|
const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true);
|
||||||
|
expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID);
|
||||||
|
// maker joins pool
|
||||||
|
await maker1.joinStakingPoolAsMakerAsync(poolId);
|
||||||
|
await maker2.addMakerToStakingPoolAsync(
|
||||||
|
poolId,
|
||||||
|
maker1Address,
|
||||||
|
new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(maker2Address, poolId),
|
||||||
|
);
|
||||||
|
});
|
||||||
it('Maker should successfully remove themselves from a pool', async () => {
|
it('Maker should successfully remove themselves from a pool', async () => {
|
||||||
// test parameters
|
// test parameters
|
||||||
const operatorAddress = users[0];
|
const operatorAddress = users[0];
|
||||||
@ -119,6 +178,23 @@ blockchainTests('Staking Pool Management', env => {
|
|||||||
// maker removes themselves from pool
|
// maker removes themselves from pool
|
||||||
await maker.removeMakerFromStakingPoolAsync(poolId, makerAddress);
|
await maker.removeMakerFromStakingPoolAsync(poolId, makerAddress);
|
||||||
});
|
});
|
||||||
|
it('operator can remove a maker from their pool', async () => {
|
||||||
|
// test parameters
|
||||||
|
const operatorAddress = users[0];
|
||||||
|
const operatorShare = (39 / 100) * PPM_DENOMINATOR;
|
||||||
|
const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper);
|
||||||
|
const makerAddress = users[1];
|
||||||
|
const maker = new MakerActor(makerAddress, stakingApiWrapper);
|
||||||
|
// create pool
|
||||||
|
const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true);
|
||||||
|
expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID);
|
||||||
|
// maker joins pool
|
||||||
|
await maker.joinStakingPoolAsMakerAsync(poolId);
|
||||||
|
// operator adds maker to pool
|
||||||
|
await poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress);
|
||||||
|
// operator removes maker from pool
|
||||||
|
await poolOperator.removeMakerFromStakingPoolAsync(poolId, makerAddress);
|
||||||
|
});
|
||||||
it('Should successfully add/remove multiple makers to the same pool', async () => {
|
it('Should successfully add/remove multiple makers to the same pool', async () => {
|
||||||
// test parameters
|
// test parameters
|
||||||
const operatorAddress = users[0];
|
const operatorAddress = users[0];
|
||||||
@ -152,6 +228,28 @@ blockchainTests('Staking Pool Management', env => {
|
|||||||
pool = await stakingApiWrapper.stakingContract.getStakingPool.callAsync(poolId);
|
pool = await stakingApiWrapper.stakingContract.getStakingPool.callAsync(poolId);
|
||||||
expect(pool.numberOfMakers, 'number of makers in pool after removing').to.be.bignumber.equal(0);
|
expect(pool.numberOfMakers, 'number of makers in pool after removing').to.be.bignumber.equal(0);
|
||||||
});
|
});
|
||||||
|
it('should fail to remove a maker from a pool if not called by operator/registered maker', async () => {
|
||||||
|
// test parameters
|
||||||
|
const operatorAddress = users[0];
|
||||||
|
const operatorShare = (39 / 100) * PPM_DENOMINATOR;
|
||||||
|
const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper);
|
||||||
|
const maker1Address = users[1];
|
||||||
|
const maker1 = new MakerActor(maker1Address, stakingApiWrapper);
|
||||||
|
const maker2Address = users[2];
|
||||||
|
const maker2 = new MakerActor(maker2Address, stakingApiWrapper);
|
||||||
|
// create pool
|
||||||
|
const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true);
|
||||||
|
expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID);
|
||||||
|
// maker joins pool
|
||||||
|
await maker1.joinStakingPoolAsMakerAsync(poolId);
|
||||||
|
// operator adds maker to pool
|
||||||
|
await poolOperator.addMakerToStakingPoolAsync(poolId, maker1Address);
|
||||||
|
await maker2.removeMakerFromStakingPoolAsync(
|
||||||
|
poolId,
|
||||||
|
maker1Address,
|
||||||
|
new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(maker2Address, poolId),
|
||||||
|
);
|
||||||
|
});
|
||||||
it('Should fail if maker already assigned to another pool tries to join', async () => {
|
it('Should fail if maker already assigned to another pool tries to join', async () => {
|
||||||
// test parameters
|
// test parameters
|
||||||
const operatorShare = (39 / 100) * PPM_DENOMINATOR;
|
const operatorShare = (39 / 100) * PPM_DENOMINATOR;
|
||||||
@ -264,30 +362,6 @@ blockchainTests('Staking Pool Management', env => {
|
|||||||
// remove non-existent maker from pool
|
// remove non-existent maker from pool
|
||||||
await poolOperator.removeMakerFromStakingPoolAsync(poolId, makerAddress, revertError);
|
await poolOperator.removeMakerFromStakingPoolAsync(poolId, makerAddress, revertError);
|
||||||
});
|
});
|
||||||
it('Should fail to add a maker when called by someone other than the pool operator', async () => {
|
|
||||||
// test parameters
|
|
||||||
const operatorAddress = users[0];
|
|
||||||
const operatorShare = (39 / 100) * PPM_DENOMINATOR;
|
|
||||||
const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper);
|
|
||||||
const makerAddress = users[1];
|
|
||||||
const maker = new MakerActor(makerAddress, stakingApiWrapper);
|
|
||||||
const notOperatorAddress = users[2];
|
|
||||||
// create pool
|
|
||||||
const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true);
|
|
||||||
expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID);
|
|
||||||
// add maker to pool
|
|
||||||
await maker.joinStakingPoolAsMakerAsync(poolId);
|
|
||||||
const revertError = new StakingRevertErrors.OnlyCallableByPoolOperatorError(
|
|
||||||
notOperatorAddress,
|
|
||||||
operatorAddress,
|
|
||||||
);
|
|
||||||
const tx = stakingApiWrapper.stakingContract.addMakerToStakingPool.awaitTransactionSuccessAsync(
|
|
||||||
poolId,
|
|
||||||
makerAddress,
|
|
||||||
{ from: notOperatorAddress },
|
|
||||||
);
|
|
||||||
await expect(tx).to.revertWith(revertError);
|
|
||||||
});
|
|
||||||
it('Should fail to remove a maker when called by someone other than the pool operator or maker', async () => {
|
it('Should fail to remove a maker when called by someone other than the pool operator or maker', async () => {
|
||||||
// test parameters
|
// test parameters
|
||||||
const operatorAddress = users[0];
|
const operatorAddress = users[0];
|
||||||
@ -305,8 +379,7 @@ blockchainTests('Staking Pool Management', env => {
|
|||||||
// try to remove the maker address from an address other than the operator
|
// try to remove the maker address from an address other than the operator
|
||||||
const revertError = new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(
|
const revertError = new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(
|
||||||
neitherOperatorNorMakerAddress,
|
neitherOperatorNorMakerAddress,
|
||||||
operatorAddress,
|
poolId,
|
||||||
makerAddress,
|
|
||||||
);
|
);
|
||||||
const tx = stakingApiWrapper.stakingContract.removeMakerFromStakingPool.awaitTransactionSuccessAsync(
|
const tx = stakingApiWrapper.stakingContract.removeMakerFromStakingPool.awaitTransactionSuccessAsync(
|
||||||
poolId,
|
poolId,
|
||||||
@ -364,6 +437,24 @@ blockchainTests('Staking Pool Management', env => {
|
|||||||
// decrease operator share
|
// decrease operator share
|
||||||
await poolOperator.decreaseStakingPoolOperatorShareAsync(poolId, operatorShare - 1);
|
await poolOperator.decreaseStakingPoolOperatorShareAsync(poolId, operatorShare - 1);
|
||||||
});
|
});
|
||||||
|
it('Maker should successfuly decrease their share of rewards', async () => {
|
||||||
|
// test parameters
|
||||||
|
const operatorAddress = users[0];
|
||||||
|
const operatorShare = (39 / 100) * PPM_DENOMINATOR;
|
||||||
|
const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper);
|
||||||
|
const makerAddress = users[1];
|
||||||
|
const maker = new MakerActor(makerAddress, stakingApiWrapper);
|
||||||
|
// create pool
|
||||||
|
const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true);
|
||||||
|
expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID);
|
||||||
|
// maker joins pool
|
||||||
|
await maker.joinStakingPoolAsMakerAsync(poolId);
|
||||||
|
// operator adds maker to pool
|
||||||
|
await poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress);
|
||||||
|
|
||||||
|
// decrease operator share
|
||||||
|
await maker.decreaseStakingPoolOperatorShareAsync(poolId, operatorShare - 1);
|
||||||
|
});
|
||||||
it('Should fail if operator tries to increase their share of rewards', async () => {
|
it('Should fail if operator tries to increase their share of rewards', async () => {
|
||||||
// test parameters
|
// test parameters
|
||||||
const operatorAddress = users[0];
|
const operatorAddress = users[0];
|
||||||
@ -401,6 +492,22 @@ blockchainTests('Staking Pool Management', env => {
|
|||||||
// decrease operator share
|
// decrease operator share
|
||||||
await poolOperator.decreaseStakingPoolOperatorShareAsync(poolId, operatorShare, revertError);
|
await poolOperator.decreaseStakingPoolOperatorShareAsync(poolId, operatorShare, revertError);
|
||||||
});
|
});
|
||||||
|
it('should fail to decrease operator share if not called by operator/registered maker', async () => {
|
||||||
|
// test parameters
|
||||||
|
const operatorAddress = users[0];
|
||||||
|
const operatorShare = (39 / 100) * PPM_DENOMINATOR;
|
||||||
|
const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper);
|
||||||
|
const makerAddress = users[1];
|
||||||
|
const maker = new MakerActor(makerAddress, stakingApiWrapper);
|
||||||
|
// create pool
|
||||||
|
const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true);
|
||||||
|
expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID);
|
||||||
|
await maker.decreaseStakingPoolOperatorShareAsync(
|
||||||
|
poolId,
|
||||||
|
operatorShare - 1,
|
||||||
|
new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(makerAddress, poolId),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// tslint:enable:no-unnecessary-type-assertion
|
// tslint:enable:no-unnecessary-type-assertion
|
||||||
|
@ -122,10 +122,13 @@ export class StakingApiWrapper {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
getEthAndWethBalanceOfAsync: async (address: string): Promise<BigNumber> => {
|
getAvailableRewardsBalanceAsync: async (): Promise<BigNumber> => {
|
||||||
const ethBalance = await this._web3Wrapper.getBalanceInWeiAsync(address);
|
const [ethBalance, wethBalance, reservedRewards] = await Promise.all([
|
||||||
const wethBalance = await this.wethContract.balanceOf.callAsync(address);
|
this._web3Wrapper.getBalanceInWeiAsync(this.stakingProxyContract.address),
|
||||||
return BigNumber.sum(ethBalance, wethBalance);
|
this.wethContract.balanceOf.callAsync(this.stakingProxyContract.address),
|
||||||
|
this.stakingContract.wethReservedForPoolRewards.callAsync(),
|
||||||
|
]);
|
||||||
|
return BigNumber.sum(ethBalance, wethBalance).minus(reservedRewards);
|
||||||
},
|
},
|
||||||
|
|
||||||
getParamsAsync: async (): Promise<StakingParams> => {
|
getParamsAsync: async (): Promise<StakingParams> => {
|
||||||
|
@ -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",
|
||||||
|
@ -83,4 +83,5 @@ export const constants = {
|
|||||||
NUM_TEST_ACCOUNTS: 20,
|
NUM_TEST_ACCOUNTS: 20,
|
||||||
PPM_DENOMINATOR: 1e6,
|
PPM_DENOMINATOR: 1e6,
|
||||||
PPM_100_PERCENT: 1e6,
|
PPM_100_PERCENT: 1e6,
|
||||||
|
MAX_CODE_SIZE: 24576,
|
||||||
};
|
};
|
||||||
|
@ -77,22 +77,12 @@ export class InsufficientBalanceError extends RevertError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OnlyCallableByPoolOperatorError extends RevertError {
|
|
||||||
constructor(senderAddress?: string, poolOperatorAddress?: string) {
|
|
||||||
super(
|
|
||||||
'OnlyCallableByPoolOperatorError',
|
|
||||||
'OnlyCallableByPoolOperatorError(address senderAddress, address poolOperatorAddress)',
|
|
||||||
{ senderAddress, poolOperatorAddress },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class OnlyCallableByPoolOperatorOrMakerError extends RevertError {
|
export class OnlyCallableByPoolOperatorOrMakerError extends RevertError {
|
||||||
constructor(senderAddress?: string, poolOperatorAddress?: string, makerAddress?: string) {
|
constructor(senderAddress?: string, poolId?: string) {
|
||||||
super(
|
super(
|
||||||
'OnlyCallableByPoolOperatorOrMakerError',
|
'OnlyCallableByPoolOperatorOrMakerError',
|
||||||
'OnlyCallableByPoolOperatorOrMakerError(address senderAddress, address poolOperatorAddress, address makerAddress)',
|
'OnlyCallableByPoolOperatorOrMakerError(address senderAddress, bytes32 poolId)',
|
||||||
{ senderAddress, poolOperatorAddress, makerAddress },
|
{ senderAddress, poolId },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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