diff --git a/contracts/exchange/test/codesize.ts b/contracts/exchange/test/codesize.ts index e84f3b47a1..e7b2d7a498 100644 --- a/contracts/exchange/test/codesize.ts +++ b/contracts/exchange/test/codesize.ts @@ -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'; chaiSetup.configure(); @@ -7,12 +7,10 @@ const expect = chai.expect; import { artifacts } from '../src'; describe('Contract Size Checks', () => { - const MAX_CODE_SIZE = 24576; - describe('Exchange', () => { it('should have a codesize less than the maximum', async () => { const actualSize = getCodesizeFromArtifact(artifacts.Exchange); - expect(actualSize).to.be.lt(MAX_CODE_SIZE); + expect(actualSize).to.be.lt(constants.MAX_CODE_SIZE); }); }); }); diff --git a/contracts/staking/contracts/src/Staking.sol b/contracts/staking/contracts/src/Staking.sol index e832188e76..65f16a07fd 100644 --- a/contracts/staking/contracts/src/Staking.sol +++ b/contracts/staking/contracts/src/Staking.sol @@ -34,12 +34,10 @@ contract Staking is MixinConstants, Ownable, MixinStorage, - MixinStakingPoolModifiers, MixinExchangeManager, MixinScheduler, MixinParams, MixinStakeStorage, - MixinStakingPoolMakers, MixinStakeBalances, MixinCumulativeRewards, MixinStakingPoolRewards, @@ -214,8 +212,8 @@ contract Staking is slot := add(slot, 0x1) assertSlotAndOffset( - poolJoinedByMakerAddress_slot, - poolJoinedByMakerAddress_offset, + _poolJoinedByMakerAddress_slot, + _poolJoinedByMakerAddress_offset, slot, offset ) @@ -378,8 +376,8 @@ contract Staking is slot := add(slot, 0x1) assertSlotAndOffset( - _wethReservedForPoolRewards_slot, - _wethReservedForPoolRewards_offset, + wethReservedForPoolRewards_slot, + wethReservedForPoolRewards_offset, slot, offset ) diff --git a/contracts/staking/contracts/src/fees/MixinExchangeFees.sol b/contracts/staking/contracts/src/fees/MixinExchangeFees.sol index 67f3306e37..fddf0235b1 100644 --- a/contracts/staking/contracts/src/fees/MixinExchangeFees.sol +++ b/contracts/staking/contracts/src/fees/MixinExchangeFees.sol @@ -38,11 +38,9 @@ contract MixinExchangeFees is MixinConstants, Ownable, MixinStorage, - MixinStakingPoolModifiers, MixinExchangeManager, MixinScheduler, MixinStakeStorage, - MixinStakingPoolMakers, MixinStakeBalances, MixinCumulativeRewards, MixinStakingPoolRewards, @@ -126,20 +124,6 @@ contract MixinExchangeFees is 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. /// @param poolId Pool Id to query. /// @return pool ActivePool struct. @@ -170,6 +154,7 @@ contract MixinExchangeFees is _poolById[poolId].operator, poolId ).currentEpochBalance; + membersStake = totalStake.safeSub(operatorStake); weightedStake = operatorStake.safeAdd( LibMath.getPartialAmountFloor( diff --git a/contracts/staking/contracts/src/immutable/MixinStorage.sol b/contracts/staking/contracts/src/immutable/MixinStorage.sol index ee9ed4c4aa..db22b767e9 100644 --- a/contracts/staking/contracts/src/immutable/MixinStorage.sol +++ b/contracts/staking/contracts/src/immutable/MixinStorage.sol @@ -77,7 +77,8 @@ contract MixinStorage is // 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. - mapping (address => IStructs.MakerPoolJoinStatus) public poolJoinedByMakerAddress; + // (access externally using `getStakingPoolIdOfMaker`) + mapping (address => IStructs.MakerPoolJoinStatus) internal _poolJoinedByMakerAddress; // mapping from Pool Id to Pool mapping (bytes32 => IStructs.Pool) internal _poolById; @@ -144,7 +145,7 @@ contract MixinStorage is IStructs.UnfinalizedState public unfinalizedState; /// @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. constructor() diff --git a/contracts/staking/contracts/src/interfaces/IStorage.sol b/contracts/staking/contracts/src/interfaces/IStorage.sol index 2c3a513c47..a82c9ccbd8 100644 --- a/contracts/staking/contracts/src/interfaces/IStorage.sol +++ b/contracts/staking/contracts/src/interfaces/IStorage.sol @@ -51,11 +51,6 @@ interface IStorage { view returns (bytes32); - function poolJoinedByMakerAddress(address makerAddress) - external - view - returns (IStructs.MakerPoolJoinStatus memory); - function numMakersByPoolId(bytes32 poolId) external view diff --git a/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol b/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol index 5b6954b92e..191b026176 100644 --- a/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol +++ b/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol @@ -75,13 +75,9 @@ library LibStakingRichErrors { bytes4 internal constant INSUFFICIENT_BALANCE_ERROR_SELECTOR = 0x84c8b7c9; - // bytes4(keccak256("OnlyCallableByPoolOperatorError(address,address)")) - bytes4 internal constant ONLY_CALLABLE_BY_POOL_OPERATOR_ERROR_SELECTOR = - 0x6cfa0c22; - - // bytes4(keccak256("OnlyCallableByPoolOperatorOrMakerError(address,address,address)")) + // bytes4(keccak256("OnlyCallableByPoolOperatorOrMakerError(address,bytes32)")) bytes4 internal constant ONLY_CALLABLE_BY_POOL_OPERATOR_OR_MAKER_ERROR_SELECTOR = - 0x7d9e1c10; + 0x7677eb13; // bytes4(keccak256("MakerPoolAssignmentError(uint8,address,bytes32)")) 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( address senderAddress, - address operator, - address makerAddress + bytes32 poolId ) internal pure @@ -244,8 +224,7 @@ library LibStakingRichErrors { return abi.encodeWithSelector( ONLY_CALLABLE_BY_POOL_OPERATOR_OR_MAKER_ERROR_SELECTOR, senderAddress, - operator, - makerAddress + poolId ); } diff --git a/contracts/staking/contracts/src/stake/MixinStake.sol b/contracts/staking/contracts/src/stake/MixinStake.sol index 7e9d727510..0c50007155 100644 --- a/contracts/staking/contracts/src/stake/MixinStake.sol +++ b/contracts/staking/contracts/src/stake/MixinStake.sol @@ -32,10 +32,8 @@ contract MixinStake is MixinConstants, Ownable, MixinStorage, - MixinStakingPoolModifiers, MixinScheduler, MixinStakeStorage, - MixinStakingPoolMakers, MixinStakeBalances, MixinCumulativeRewards, MixinStakingPoolRewards, diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol index df00a9f000..0466f8de63 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol @@ -24,7 +24,6 @@ import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "../libs/LibStakingRichErrors.sol"; import "../interfaces/IStructs.sol"; import "./MixinStakingPoolRewards.sol"; -import "./MixinStakingPoolMakers.sol"; contract MixinStakingPool is @@ -33,15 +32,21 @@ contract MixinStakingPool is MixinConstants, Ownable, MixinStorage, - MixinStakingPoolModifiers, MixinScheduler, MixinStakeStorage, - MixinStakingPoolMakers, MixinStakeBalances, MixinCumulativeRewards, MixinStakingPoolRewards { 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. /// 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. function decreaseStakingPoolOperatorShare(bytes32 poolId, uint32 newOperatorShare) external + onlyStakingPoolOperatorOrMaker(poolId) { // load pool and assert that we can decrease 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 /// @param poolId Unique id of pool. function getStakingPool(bytes32 poolId) @@ -122,6 +216,65 @@ contract MixinStakingPool is return _poolById[poolId]; } + /// @dev Adds a maker to a staking pool. Note that this is only callable by the pool operator. + /// Note also that the maker must have previously called joinStakingPoolAsMaker. + /// @param poolId Unique id of pool. + /// @param makerAddress Address of maker. + function _addMakerToStakingPool( + bytes32 poolId, + address makerAddress + ) + internal + { + // cache pool and join status for use throughout this function + IStructs.Pool memory pool = _poolById[poolId]; + IStructs.MakerPoolJoinStatus memory poolJoinStatus = _poolJoinedByMakerAddress[makerAddress]; + + // Is the maker already in a pool? + if (poolJoinStatus.confirmed) { + LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError( + LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered, + makerAddress, + poolJoinStatus.poolId + )); + } + + // Is the maker trying to join this pool; or are they the operator? + bytes32 makerPendingPoolId = poolJoinStatus.poolId; + if (makerPendingPoolId != poolId && makerAddress != pool.operator) { + LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError( + LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressNotPendingAdd, + makerAddress, + makerPendingPoolId + )); + } + + // Is the pool already full? + // NOTE: If maximumMakersInPool is decreased below the number of makers currently in a pool, + // the pool will no longer be able to add more makers. + if (pool.numberOfMakers >= maximumMakersInPool) { + LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError( + LibStakingRichErrors.MakerPoolAssignmentErrorCodes.PoolIsFull, + makerAddress, + poolId + )); + } + + // Add maker to pool + poolJoinStatus = IStructs.MakerPoolJoinStatus({ + poolId: poolId, + confirmed: true + }); + _poolJoinedByMakerAddress[makerAddress] = poolJoinStatus; + _poolById[poolId].numberOfMakers = uint256(pool.numberOfMakers).safeAdd(1).downcastToUint32(); + + // Maker has been added to the pool + emit MakerAddedToStakingPool( + poolId, + makerAddress + ); + } + /// @dev Computes the unique id that comes after the input pool id. /// @param poolId Unique id of pool. /// @return Next pool id after input pool. @@ -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 + ) + ); + } + } } diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolMakers.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolMakers.sol deleted file mode 100644 index 287331c2c9..0000000000 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolMakers.sol +++ /dev/null @@ -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 - ); - } -} diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolModifiers.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolModifiers.sol deleted file mode 100644 index 52ac7b1829..0000000000 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolModifiers.sol +++ /dev/null @@ -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 - ) - ); - } - - _; - } -} diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol index f620565333..64956ae01c 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol @@ -188,8 +188,8 @@ contract MixinStakingPoolRewards is } if (membersReward > 0) { - // Increment the balance of the pool - _incrementPoolRewards(poolId, membersReward); + // Increase the balance of the pool + _increasePoolRewards(poolId, membersReward); // 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. @@ -279,8 +279,8 @@ contract MixinStakingPoolRewards is return; } - // Decrement the balance of the pool - _decrementPoolRewards(poolId, balance); + // Decrease the balance of the pool + _decreasePoolRewards(poolId, balance); // Withdraw the member's WETH 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 amount Amount to increment rewards by. - function _incrementPoolRewards(bytes32 poolId, uint256 amount) + function _increasePoolRewards(bytes32 poolId, uint256 amount) private { 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 amount Amount to decrement rewards by. - function _decrementPoolRewards(bytes32 poolId, uint256 amount) + function _decreasePoolRewards(bytes32 poolId, uint256 amount) private { rewardsByPoolId[poolId] = rewardsByPoolId[poolId].safeSub(amount); - _wethReservedForPoolRewards = _wethReservedForPoolRewards.safeSub(amount); + wethReservedForPoolRewards = wethReservedForPoolRewards.safeSub(amount); } } diff --git a/contracts/staking/contracts/src/sys/MixinFinalizer.sol b/contracts/staking/contracts/src/sys/MixinFinalizer.sol index 8d511f14e3..bc3a6dd9df 100644 --- a/contracts/staking/contracts/src/sys/MixinFinalizer.sol +++ b/contracts/staking/contracts/src/sys/MixinFinalizer.sol @@ -257,7 +257,7 @@ contract MixinFinalizer is returns (uint256 wethBalance) { wethBalance = _getWethContract().balanceOf(address(this)) - .safeSub(_wethReservedForPoolRewards); + .safeSub(wethReservedForPoolRewards); return wethBalance; } diff --git a/contracts/staking/contracts/test/TestProtocolFees.sol b/contracts/staking/contracts/test/TestProtocolFees.sol index c89b9724fd..ae9657e001 100644 --- a/contracts/staking/contracts/test/TestProtocolFees.sol +++ b/contracts/staking/contracts/test/TestProtocolFees.sol @@ -56,8 +56,8 @@ contract TestProtocolFees is function addMakerToPool(bytes32 poolId, address makerAddress) external { - poolJoinedByMakerAddress[makerAddress].poolId = poolId; - poolJoinedByMakerAddress[makerAddress].confirmed = true; + _poolJoinedByMakerAddress[makerAddress].poolId = poolId; + _poolJoinedByMakerAddress[makerAddress].confirmed = true; } function advanceEpoch() diff --git a/contracts/staking/package.json b/contracts/staking/package.json index f68c4ac585..65dc340614 100644 --- a/contracts/staking/package.json +++ b/contracts/staking/package.json @@ -37,7 +37,7 @@ }, "config": { "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": { "type": "git", diff --git a/contracts/staking/src/artifacts.ts b/contracts/staking/src/artifacts.ts index 011e0f0468..268359a620 100644 --- a/contracts/staking/src/artifacts.ts +++ b/contracts/staking/src/artifacts.ts @@ -32,8 +32,6 @@ import * as MixinStake from '../generated-artifacts/MixinStake.json'; import * as MixinStakeBalances from '../generated-artifacts/MixinStakeBalances.json'; import * as MixinStakeStorage from '../generated-artifacts/MixinStakeStorage.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 MixinStorage from '../generated-artifacts/MixinStorage.json'; import * as MixinVaultCore from '../generated-artifacts/MixinVaultCore.json'; @@ -84,8 +82,6 @@ export const artifacts = { MixinStakeStorage: MixinStakeStorage as ContractArtifact, MixinCumulativeRewards: MixinCumulativeRewards as ContractArtifact, MixinStakingPool: MixinStakingPool as ContractArtifact, - MixinStakingPoolMakers: MixinStakingPoolMakers as ContractArtifact, - MixinStakingPoolModifiers: MixinStakingPoolModifiers as ContractArtifact, MixinStakingPoolRewards: MixinStakingPoolRewards as ContractArtifact, MixinAbstract: MixinAbstract as ContractArtifact, MixinFinalizer: MixinFinalizer as ContractArtifact, diff --git a/contracts/staking/src/wrappers.ts b/contracts/staking/src/wrappers.ts index 641e983bee..067ec7f9fc 100644 --- a/contracts/staking/src/wrappers.ts +++ b/contracts/staking/src/wrappers.ts @@ -30,8 +30,6 @@ export * from '../generated-wrappers/mixin_stake'; export * from '../generated-wrappers/mixin_stake_balances'; export * from '../generated-wrappers/mixin_stake_storage'; 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_storage'; export * from '../generated-wrappers/mixin_vault_core'; diff --git a/contracts/staking/test/actors/finalizer_actor.ts b/contracts/staking/test/actors/finalizer_actor.ts index 744b4802b2..36dcd237f5 100644 --- a/contracts/staking/test/actors/finalizer_actor.ts +++ b/contracts/staking/test/actors/finalizer_actor.ts @@ -241,7 +241,7 @@ export class FinalizerActor extends BaseActor { 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 totalWeightedStake = BigNumber.sum(...activePools.map(p => p.weightedStake)); if (totalRewards.eq(0) || totalFeesCollected.eq(0) || totalWeightedStake.eq(0)) { diff --git a/contracts/staking/test/actors/maker_actor.ts b/contracts/staking/test/actors/maker_actor.ts index 235eeb8a8d..ecca34c9d1 100644 --- a/contracts/staking/test/actors/maker_actor.ts +++ b/contracts/staking/test/actors/maker_actor.ts @@ -4,9 +4,9 @@ import * as _ from 'lodash'; 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 { // Join pool 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); } - - public async removeMakerFromStakingPoolAsync( - poolId: string, - makerAddress: string, - revertError?: RevertError, - ): Promise { - // 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); - } } diff --git a/contracts/staking/test/codesize.ts b/contracts/staking/test/codesize.ts new file mode 100644 index 0000000000..912ac09fa4 --- /dev/null +++ b/contracts/staking/test/codesize.ts @@ -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); + }); + }); +}); diff --git a/contracts/staking/test/pools_test.ts b/contracts/staking/test/pools_test.ts index 71f6e98163..85ff51fb2d 100644 --- a/contracts/staking/test/pools_test.ts +++ b/contracts/staking/test/pools_test.ts @@ -9,6 +9,7 @@ import { deployAndConfigureContractsAsync, StakingApiWrapper } from './utils/api import { constants as stakingConstants } from './utils/constants'; // tslint:disable:no-unnecessary-type-assertion +// tslint:disable:max-file-line-count blockchainTests('Staking Pool Management', env => { // constants const { PPM_100_PERCENT, PPM_DENOMINATOR } = constants; @@ -23,8 +24,7 @@ blockchainTests('Staking Pool Management', env => { before(async () => { // create accounts accounts = await env.getAccountAddressesAsync(); - owner = accounts[0]; - users = accounts.slice(1); + [owner, ...users] = accounts; // set up ERC20Wrapper erc20Wrapper = new ERC20Wrapper(env.provider, accounts, owner); // deploy staking contracts @@ -102,6 +102,65 @@ blockchainTests('Staking Pool Management', env => { // operator removes maker from pool 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 () => { // test parameters const operatorAddress = users[0]; @@ -119,6 +178,23 @@ blockchainTests('Staking Pool Management', env => { // maker removes themselves from pool 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 () => { // test parameters const operatorAddress = users[0]; @@ -152,6 +228,28 @@ blockchainTests('Staking Pool Management', env => { pool = await stakingApiWrapper.stakingContract.getStakingPool.callAsync(poolId); 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 () => { // test parameters const operatorShare = (39 / 100) * PPM_DENOMINATOR; @@ -264,30 +362,6 @@ blockchainTests('Staking Pool Management', env => { // remove non-existent maker from pool 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 () => { // test parameters 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 const revertError = new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError( neitherOperatorNorMakerAddress, - operatorAddress, - makerAddress, + poolId, ); const tx = stakingApiWrapper.stakingContract.removeMakerFromStakingPool.awaitTransactionSuccessAsync( poolId, @@ -364,6 +437,24 @@ blockchainTests('Staking Pool Management', env => { // decrease operator share 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 () => { // test parameters const operatorAddress = users[0]; @@ -401,6 +492,22 @@ blockchainTests('Staking Pool Management', env => { // decrease operator share 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 diff --git a/contracts/staking/test/utils/api_wrapper.ts b/contracts/staking/test/utils/api_wrapper.ts index 94ac58c1e1..c1f6b5a829 100644 --- a/contracts/staking/test/utils/api_wrapper.ts +++ b/contracts/staking/test/utils/api_wrapper.ts @@ -122,10 +122,13 @@ export class StakingApiWrapper { ); }, - getEthAndWethBalanceOfAsync: async (address: string): Promise => { - const ethBalance = await this._web3Wrapper.getBalanceInWeiAsync(address); - const wethBalance = await this.wethContract.balanceOf.callAsync(address); - return BigNumber.sum(ethBalance, wethBalance); + getAvailableRewardsBalanceAsync: async (): Promise => { + const [ethBalance, wethBalance, reservedRewards] = await Promise.all([ + this._web3Wrapper.getBalanceInWeiAsync(this.stakingProxyContract.address), + this.wethContract.balanceOf.callAsync(this.stakingProxyContract.address), + this.stakingContract.wethReservedForPoolRewards.callAsync(), + ]); + return BigNumber.sum(ethBalance, wethBalance).minus(reservedRewards); }, getParamsAsync: async (): Promise => { diff --git a/contracts/staking/tsconfig.json b/contracts/staking/tsconfig.json index fab0abce47..e0349ba978 100644 --- a/contracts/staking/tsconfig.json +++ b/contracts/staking/tsconfig.json @@ -30,8 +30,6 @@ "generated-artifacts/MixinStakeBalances.json", "generated-artifacts/MixinStakeStorage.json", "generated-artifacts/MixinStakingPool.json", - "generated-artifacts/MixinStakingPoolMakers.json", - "generated-artifacts/MixinStakingPoolModifiers.json", "generated-artifacts/MixinStakingPoolRewards.json", "generated-artifacts/MixinStorage.json", "generated-artifacts/MixinVaultCore.json", diff --git a/contracts/test-utils/src/constants.ts b/contracts/test-utils/src/constants.ts index 83f6bd4197..45bcc6ff72 100644 --- a/contracts/test-utils/src/constants.ts +++ b/contracts/test-utils/src/constants.ts @@ -83,4 +83,5 @@ export const constants = { NUM_TEST_ACCOUNTS: 20, PPM_DENOMINATOR: 1e6, PPM_100_PERCENT: 1e6, + MAX_CODE_SIZE: 24576, }; diff --git a/packages/order-utils/src/staking_revert_errors.ts b/packages/order-utils/src/staking_revert_errors.ts index 698037a989..4035dab69f 100644 --- a/packages/order-utils/src/staking_revert_errors.ts +++ b/packages/order-utils/src/staking_revert_errors.ts @@ -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 { - constructor(senderAddress?: string, poolOperatorAddress?: string, makerAddress?: string) { + constructor(senderAddress?: string, poolId?: string) { super( 'OnlyCallableByPoolOperatorOrMakerError', - 'OnlyCallableByPoolOperatorOrMakerError(address senderAddress, address poolOperatorAddress, address makerAddress)', - { senderAddress, poolOperatorAddress, makerAddress }, + 'OnlyCallableByPoolOperatorOrMakerError(address senderAddress, bytes32 poolId)', + { senderAddress, poolId }, ); } } @@ -243,7 +233,6 @@ const types = [ MakerPoolAssignmentError, MiscalculatedRewardsError, OnlyCallableByExchangeError, - OnlyCallableByPoolOperatorError, OnlyCallableByPoolOperatorOrMakerError, OnlyCallableByStakingContractError, OnlyCallableIfInCatastrophicFailureError,