Merge pull request #2186 from 0xProject/feat/3.0/delete-vaults

Delete `StakingPoolRewardVault` and `EthVault`
This commit is contained in:
Amir Bandeali 2019-09-23 18:05:53 -07:00 committed by GitHub
commit 2587cd380f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 466 additions and 1370 deletions

View File

@ -32,7 +32,6 @@ contract Staking is
IStakingEvents,
MixinAbstract,
MixinConstants,
MixinDeploymentConstants,
Ownable,
MixinStorage,
MixinStakingPoolModifiers,
@ -60,13 +59,9 @@ contract Staking is
/// This function should not be called directly.
/// The StakingProxy contract will call it in `attachStakingContract()`.
/// @param _wethProxyAddress The address that can transfer WETH for fees.
/// @param _ethVaultAddress Address of the EthVault contract.
/// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract.
/// @param _zrxVaultAddress Address of the ZrxVault contract.
function init(
address _wethProxyAddress,
address _ethVaultAddress,
address payable _rewardVaultAddress,
address _zrxVaultAddress
)
public
@ -77,8 +72,6 @@ contract Staking is
_initMixinScheduler();
_initMixinParams(
_wethProxyAddress,
_ethVaultAddress,
_rewardVaultAddress,
_zrxVaultAddress
);
}

View File

@ -37,15 +37,11 @@ contract StakingProxy is
/// @param _stakingContract Staking contract to delegate calls to.
/// @param _readOnlyProxy The address of the read only proxy.
/// @param _wethProxyAddress The address that can transfer WETH for fees.
/// @param _ethVaultAddress Address of the EthVault contract.
/// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract.
/// @param _zrxVaultAddress Address of the ZrxVault contract.
constructor(
address _stakingContract,
address _readOnlyProxy,
address _wethProxyAddress,
address _ethVaultAddress,
address _rewardVaultAddress,
address _zrxVaultAddress
)
public
@ -55,8 +51,6 @@ contract StakingProxy is
_attachStakingContract(
_stakingContract,
_wethProxyAddress,
_ethVaultAddress,
_rewardVaultAddress,
_zrxVaultAddress
);
}
@ -78,17 +72,11 @@ contract StakingProxy is
/// @param _stakingContract Address of staking contract.
/// @param _wethProxyAddress The address that can transfer WETH for fees.
/// Use address in storage if NIL_ADDRESS is passed in.
/// @param _ethVaultAddress Address of the EthVault contract.
/// Use address in storage if NIL_ADDRESS is passed in.
/// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract.
/// Use address in storage if NIL_ADDRESS is passed in.
/// @param _zrxVaultAddress Address of the ZrxVault contract.
/// Use address in storage if NIL_ADDRESS is passed in.
function attachStakingContract(
address _stakingContract,
address _wethProxyAddress,
address _ethVaultAddress,
address _rewardVaultAddress,
address _zrxVaultAddress
)
external
@ -97,8 +85,6 @@ contract StakingProxy is
_attachStakingContract(
_stakingContract,
_wethProxyAddress == NIL_ADDRESS ? address(wethAssetProxy) : _wethProxyAddress,
_ethVaultAddress == NIL_ADDRESS ? address(ethVault) : _ethVaultAddress,
_rewardVaultAddress == NIL_ADDRESS ? address(rewardVault) : _rewardVaultAddress,
_zrxVaultAddress == NIL_ADDRESS ? address(zrxVault) : _zrxVaultAddress
);
}
@ -225,20 +211,6 @@ contract StakingProxy is
));
}
if (address(ethVault) == NIL_ADDRESS) {
LibRichErrors.rrevert(
LibStakingRichErrors.InvalidParamValueError(
LibStakingRichErrors.InvalidParamValueErrorCode.InvalidEthVaultAddress
));
}
if (address(rewardVault) == NIL_ADDRESS) {
LibRichErrors.rrevert(
LibStakingRichErrors.InvalidParamValueError(
LibStakingRichErrors.InvalidParamValueErrorCode.InvalidRewardVaultAddress
));
}
if (address(zrxVault) == NIL_ADDRESS) {
LibRichErrors.rrevert(
LibStakingRichErrors.InvalidParamValueError(
@ -250,14 +222,10 @@ contract StakingProxy is
/// @dev Attach a staking contract; future calls will be delegated to the staking contract.
/// @param _stakingContract Address of staking contract.
/// @param _wethProxyAddress The address that can transfer WETH for fees.
/// @param _ethVaultAddress Address of the EthVault contract.
/// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract.
/// @param _zrxVaultAddress Address of the ZrxVault contract.
function _attachStakingContract(
address _stakingContract,
address _wethProxyAddress,
address _ethVaultAddress,
address _rewardVaultAddress,
address _zrxVaultAddress
)
internal
@ -271,8 +239,6 @@ contract StakingProxy is
abi.encodeWithSelector(
IStorageInit(0).init.selector,
_wethProxyAddress,
_ethVaultAddress,
_rewardVaultAddress,
_zrxVaultAddress
)
);

View File

@ -25,7 +25,6 @@ import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "../libs/LibStakingRichErrors.sol";
import "../libs/LibCobbDouglas.sol";
import "../immutable/MixinDeploymentConstants.sol";
import "../interfaces/IStructs.sol";
import "../stake/MixinStakeBalances.sol";
import "../sys/MixinFinalizer.sol";
@ -37,7 +36,6 @@ contract MixinExchangeFees is
IStakingEvents,
MixinAbstract,
MixinConstants,
MixinDeploymentConstants,
Ownable,
MixinStorage,
MixinStakingPoolModifiers,
@ -74,7 +72,7 @@ contract MixinExchangeFees is
// WETH.
if (msg.value == 0) {
wethAssetProxy.transferFrom(
WETH_ASSET_DATA,
_getWethAssetData(),
payerAddress,
address(this),
protocolFeePaid
@ -99,6 +97,7 @@ contract MixinExchangeFees is
uint256 currentEpoch_ = currentEpoch;
mapping (bytes32 => IStructs.ActivePool) storage activePoolsThisEpoch =
_getActivePoolsFromEpoch(currentEpoch_);
IStructs.ActivePool memory pool = activePoolsThisEpoch[poolId];
// If the pool was previously inactive in this epoch, initialize it.
@ -127,6 +126,20 @@ 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.

View File

@ -18,8 +18,11 @@
pragma solidity ^0.5.9;
import "./MixinDeploymentConstants.sol";
contract MixinConstants
contract MixinConstants is
MixinDeploymentConstants
{
// 100% in parts-per-million.
uint32 constant internal PPM_DENOMINATOR = 10**6;

View File

@ -18,6 +18,7 @@
pragma solidity ^0.5.9;
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
@ -50,23 +51,41 @@ contract MixinDeploymentConstants {
// bytes constant internal WETH_ASSET_DATA = hex"f47261b0000000000000000000000000c778417e063141139fce010982780140aa0cd5ab";
/// @dev Ensures that the WETH_ASSET_DATA is correct.
constructor() public {
constructor()
public
{
// Ensure that the WETH_ASSET_DATA is correct.
if (!WETH_ASSET_DATA.equals(
abi.encodeWithSelector(IAssetData(address(0)).ERC20Token.selector, WETH_ADDRESS)
abi.encodeWithSelector(
IAssetData(address(0)).ERC20Token.selector,
WETH_ADDRESS
)
)) {
LibRichErrors.rrevert(LibStakingRichErrors.InvalidWethAssetDataError());
}
}
/// @dev An overridable way to access the deployed WETH address.
/// @dev An overridable way to access the deployed WETH contract.
/// Must be view to allow overrides to access state.
/// @return wethAddress The address of the configured WETH contract.
function _getWETHAddress()
/// @return wethContract The WETH contract instance.
function _getWethContract()
internal
view
returns (address wethAddress)
returns (IEtherToken wethContract)
{
return WETH_ADDRESS;
wethContract = IEtherToken(WETH_ADDRESS);
return wethContract;
}
/// @dev An overridable way to access the deployed WETH assetData.
/// Must be view to allow overrides to access state.
/// @return wethAssetData The assetData of the configured WETH contract.
function _getWethAssetData()
internal
view
returns (bytes memory wethAssetData)
{
wethAssetData = WETH_ASSET_DATA;
return wethAssetData;
}
}

View File

@ -24,8 +24,6 @@ import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
import "@0x/contracts-utils/contracts/src/Authorizable.sol";
import "./MixinConstants.sol";
import "../interfaces/IZrxVault.sol";
import "../interfaces/IEthVault.sol";
import "../interfaces/IStakingPoolRewardVault.sol";
import "../interfaces/IStructs.sol";
import "../libs/LibStakingRichErrors.sol";
@ -52,23 +50,23 @@ contract MixinStorage is
mapping (uint8 => IStructs.StoredBalance) public globalStakeByStatus;
// mapping from Owner to Amount of Active Stake
// (access using _loadAndSyncBalance or _loadUnsyncedBalance)
// (access using _loadSyncedBalance or _loadUnsyncedBalance)
mapping (address => IStructs.StoredBalance) internal _activeStakeByOwner;
// Mapping from Owner to Amount of Inactive Stake
// (access using _loadAndSyncBalance or _loadUnsyncedBalance)
// (access using _loadSyncedBalance or _loadUnsyncedBalance)
mapping (address => IStructs.StoredBalance) internal _inactiveStakeByOwner;
// Mapping from Owner to Amount Delegated
// (access using _loadAndSyncBalance or _loadUnsyncedBalance)
// (access using _loadSyncedBalance or _loadUnsyncedBalance)
mapping (address => IStructs.StoredBalance) internal _delegatedStakeByOwner;
// Mapping from Owner to Pool Id to Amount Delegated
// (access using _loadAndSyncBalance or _loadUnsyncedBalance)
// (access using _loadSyncedBalance or _loadUnsyncedBalance)
mapping (address => mapping (bytes32 => IStructs.StoredBalance)) internal _delegatedStakeToPoolByOwner;
// Mapping from Pool Id to Amount Delegated
// (access using _loadAndSyncBalance or _loadUnsyncedBalance)
// (access using _loadSyncedBalance or _loadUnsyncedBalance)
mapping (bytes32 => IStructs.StoredBalance) internal _delegatedStakeByPoolId;
// mapping from Owner to Amount of Withdrawable Stake
@ -84,6 +82,9 @@ contract MixinStorage is
// mapping from Pool Id to Pool
mapping (bytes32 => IStructs.Pool) internal _poolById;
// mapping from PoolId to balance of members
mapping (bytes32 => uint256) public rewardsByPoolId;
// current epoch
uint256 public currentEpoch = INITIAL_EPOCH;
@ -105,12 +106,6 @@ contract MixinStorage is
// ZRX vault (stores staked ZRX)
IZrxVault public zrxVault;
// ETH Vault (stores eth balances of stakers and pool operators)
IEthVault public ethVault;
// Rebate Vault (stores rewards for pools before they are moved to the eth vault on a per-user basis)
IStakingPoolRewardVault public rewardVault;
/* Tweakable parameters */
// Minimum seconds between epochs.
@ -151,6 +146,9 @@ contract MixinStorage is
/// @dev State for unfinalized rewards.
IStructs.UnfinalizedState public unfinalizedState;
/// @dev The WETH balance of this contract that is reserved for pool reward payouts.
uint256 _wethReservedForPoolRewards;
/// @dev Adds owner as an authorized address.
constructor()
public

View File

@ -1,70 +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;
/// @dev This vault manages Ether.
interface IEthVault {
/// @dev Emitted when Ether are deposited into the vault.
/// @param sender Address of sender (`msg.sender`).
/// @param owner of Ether.
/// @param amount of Ether deposited.
event EthDepositedIntoVault(
address indexed sender,
address indexed owner,
uint256 amount
);
/// @dev Emitted when Ether are withdrawn from the vault.
/// @param sender Address of sender (`msg.sender`).
/// @param owner of Ether.
/// @param amount of Ether withdrawn.
event EthWithdrawnFromVault(
address indexed sender,
address indexed owner,
uint256 amount
);
/// @dev Deposit an `amount` of WETH for `owner` into the vault.
/// The staking contract should have granted the vault an allowance
/// because it will pull the WETH via `transferFrom()`.
/// Note that this is only callable by the staking contract.
/// @param owner Owner of the WETH.
/// @param amount Amount of deposit.
function depositFor(address owner, uint256 amount)
external;
/// @dev Withdraw an `amount` of WETH to `msg.sender` from the vault.
/// @param amount of WETH to withdraw.
function withdraw(uint256 amount)
external;
/// @dev Withdraw ALL WETH to `msg.sender` from the vault.
function withdrawAll()
external
returns (uint256);
/// @dev Returns the balance in WETH of the `owner`
/// @return Balance in WETH.
function balanceOf(address owner)
external
view
returns (uint256);
}

View File

@ -96,8 +96,6 @@ interface IStakingEvents {
/// @param cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
/// @param cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
/// @param wethProxyAddress The address that can transfer WETH for fees.
/// @param ethVaultAddress Address of the EthVault contract.
/// @param rewardVaultAddress Address of the StakingPoolRewardVault contract.
/// @param zrxVaultAddress Address of the ZrxVault contract.
event ParamsSet(
uint256 epochDurationInSeconds,
@ -107,8 +105,6 @@ interface IStakingEvents {
uint256 cobbDouglasAlphaNumerator,
uint256 cobbDouglasAlphaDenominator,
address wethProxyAddress,
address ethVaultAddress,
address rewardVaultAddress,
address zrxVaultAddress
);

View File

@ -1,73 +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;
/// @dev This vault manages staking pool rewards.
interface IStakingPoolRewardVault {
/// @dev Emitted when WETH is deposited into the vault.
/// @param sender Address of sender (`msg.sender`).
/// @param poolId that owns of WETH.
/// @param amount of WETH deposited.
event EthDepositedIntoVault(
address indexed sender,
bytes32 indexed poolId,
uint256 amount
);
/// @dev Emitted when rewards are transferred out of the vault.
/// @param poolId Unique Id of pool.
/// @param to Address to send funds to.
/// @param amount Amount of WETH to transfer.
event PoolRewardTransferred(
bytes32 indexed poolId,
address indexed to,
uint256 amount
);
/// @dev Deposit an amount of WETH for `poolId` into the vault.
/// The staking contract should have granted the vault an allowance
/// because it will pull the WETH via `transferFrom()`.
/// Note that this is only callable by the staking contract.
/// @param poolId Pool that holds the WETH.
/// @param amount Amount of deposit.
function depositFor(bytes32 poolId, uint256 amount)
external;
/// @dev Withdraw some amount in WETH from a pool.
/// Note that this is only callable by the staking contract.
/// @param poolId Unique Id of pool.
/// @param to Address to send funds to.
/// @param amount Amount of WETH to transfer.
function transfer(
bytes32 poolId,
address payable to,
uint256 amount
)
external;
/// @dev Returns the balance in WETH of `poolId`
/// @return Balance in WETH.
function balanceOf(bytes32 poolId)
external
view
returns (uint256);
}

View File

@ -47,17 +47,11 @@ interface IStakingProxy /* is IStaking */
/// @param _stakingContract Address of staking contract.
/// @param _wethProxyAddress The address that can transfer WETH for fees.
/// Use address in storage if NIL_ADDRESS is passed in.
/// @param _ethVaultAddress Address of the EthVault contract.
/// Use address in storage if NIL_ADDRESS is passed in.
/// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract.
/// Use address in storage if NIL_ADDRESS is passed in.
/// @param _zrxVaultAddress Address of the ZrxVault contract.
/// Use address in storage if NIL_ADDRESS is passed in.
function attachStakingContract(
address _stakingContract,
address _wethProxyAddress,
address _ethVaultAddress,
address _rewardVaultAddress,
address _zrxVaultAddress
)
external;

View File

@ -21,8 +21,6 @@ pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
import "../interfaces/IZrxVault.sol";
import "../interfaces/IEthVault.sol";
import "../interfaces/IStakingPoolRewardVault.sol";
import "../interfaces/IStructs.sol";
@ -93,16 +91,6 @@ interface IStorage {
view
returns (IZrxVault);
function ethVault()
external
view
returns (IEthVault);
function rewardVault()
external
view
returns (IStakingPoolRewardVault);
function epochDurationInSeconds()
external
view

View File

@ -23,13 +23,9 @@ interface IStorageInit {
/// @dev Initialize storage owned by this contract.
/// @param _wethProxyAddress The address that can transfer WETH for fees.
/// @param _ethVaultAddress Address of the EthVault contract.
/// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract.
/// @param _zrxVaultAddress Address of the ZrxVault contract.
function init(
address _wethProxyAddress,
address _ethVaultAddress,
address _rewardVaultAddress,
address _zrxVaultAddress
)
external;

View File

@ -52,7 +52,7 @@ interface IStructs {
/// @dev Encapsulates a balance for the current and next epochs.
/// Note that these balances may be stale if the current epoch
/// is greater than `currentEpoch`.
/// Always load this struct using _loadAndSyncBalance or _loadUnsyncedBalance.
/// Always load this struct using _loadSyncedBalance or _loadUnsyncedBalance.
/// @param isInitialized
/// @param currentEpoch the current epoch
/// @param currentEpochBalance balance in the current epoch.

View File

@ -44,8 +44,6 @@ library LibStakingRichErrors {
InvalidMaximumMakersInPool,
InvalidMinimumPoolStake,
InvalidWethProxyAddress,
InvalidEthVaultAddress,
InvalidRewardVaultAddress,
InvalidZrxVaultAddress,
InvalidEpochDuration
}
@ -121,14 +119,6 @@ library LibStakingRichErrors {
bytes4 internal constant POOL_EXISTENCE_ERROR_SELECTOR =
0x9ae94f01;
// bytes4(keccak256("EthVaultNotSetError()"))
bytes4 internal constant ETH_VAULT_NOT_SET_ERROR_SELECTOR =
0xa067f596;
// bytes4(keccak256("RewardVaultNotSetError()"))
bytes4 internal constant REWARD_VAULT_NOT_SET_ERROR_SELECTOR =
0xe6976d70;
// bytes4(keccak256("InvalidStakeStatusError(uint256)"))
bytes4 internal constant INVALID_STAKE_STATUS_ERROR_SELECTOR =
0xb7161acd;
@ -382,26 +372,6 @@ library LibStakingRichErrors {
);
}
function EthVaultNotSetError()
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
ETH_VAULT_NOT_SET_ERROR_SELECTOR
);
}
function RewardVaultNotSetError()
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
REWARD_VAULT_NOT_SET_ERROR_SELECTOR
);
}
function InvalidProtocolFeePaymentError(
ProtocolFeePaymentErrorCodes errorCode,
uint256 expectedProtocolFeePaid,

View File

@ -216,8 +216,9 @@ contract MixinStake is
// Synchronizes reward state in the pool that the staker is delegating
// to.
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
_loadAndSyncBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
_syncRewardsForDelegator(
_loadSyncedBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
_withdrawAndSyncDelegatorRewards(
poolId,
owner,
initDelegatedStakeToPoolByOwner,
@ -255,8 +256,9 @@ contract MixinStake is
// synchronizes reward state in the pool that the staker is undelegating
// from
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
_loadAndSyncBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
_syncRewardsForDelegator(
_loadSyncedBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
_withdrawAndSyncDelegatorRewards(
poolId,
owner,
initDelegatedStakeToPoolByOwner,

View File

@ -43,7 +43,7 @@ contract MixinStakeBalances is
view
returns (IStructs.StakeBalance memory balance)
{
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(
globalStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)]
);
return IStructs.StakeBalance({
@ -59,7 +59,7 @@ contract MixinStakeBalances is
view
returns (IStructs.StakeBalance memory balance)
{
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(
globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)]
);
return IStructs.StakeBalance({
@ -75,7 +75,7 @@ contract MixinStakeBalances is
view
returns (IStructs.StakeBalance memory balance)
{
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(
globalStakeByStatus[uint8(IStructs.StakeStatus.DELEGATED)]
);
return IStructs.StakeBalance({
@ -103,7 +103,7 @@ contract MixinStakeBalances is
view
returns (IStructs.StakeBalance memory balance)
{
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(_activeStakeByOwner[owner]);
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_activeStakeByOwner[owner]);
return IStructs.StakeBalance({
currentEpochBalance: storedBalance.currentEpochBalance,
nextEpochBalance: storedBalance.nextEpochBalance
@ -118,7 +118,7 @@ contract MixinStakeBalances is
view
returns (IStructs.StakeBalance memory balance)
{
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(_inactiveStakeByOwner[owner]);
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_inactiveStakeByOwner[owner]);
return IStructs.StakeBalance({
currentEpochBalance: storedBalance.currentEpochBalance,
nextEpochBalance: storedBalance.nextEpochBalance
@ -133,7 +133,7 @@ contract MixinStakeBalances is
view
returns (IStructs.StakeBalance memory balance)
{
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(_delegatedStakeByOwner[owner]);
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_delegatedStakeByOwner[owner]);
return IStructs.StakeBalance({
currentEpochBalance: storedBalance.currentEpochBalance,
nextEpochBalance: storedBalance.nextEpochBalance
@ -160,7 +160,7 @@ contract MixinStakeBalances is
view
returns (IStructs.StakeBalance memory balance)
{
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
return IStructs.StakeBalance({
currentEpochBalance: storedBalance.currentEpochBalance,
nextEpochBalance: storedBalance.nextEpochBalance
@ -176,7 +176,7 @@ contract MixinStakeBalances is
view
returns (IStructs.StakeBalance memory balance)
{
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(_delegatedStakeByPoolId[poolId]);
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_delegatedStakeByPoolId[poolId]);
return IStructs.StakeBalance({
currentEpochBalance: storedBalance.currentEpochBalance,
nextEpochBalance: storedBalance.nextEpochBalance

View File

@ -53,8 +53,8 @@ contract MixinStakeStorage is
}
// load balance from storage and synchronize it
IStructs.StoredBalance memory from = _loadAndSyncBalance(fromPtr);
IStructs.StoredBalance memory to = _loadAndSyncBalance(toPtr);
IStructs.StoredBalance memory from = _loadSyncedBalance(fromPtr);
IStructs.StoredBalance memory to = _loadSyncedBalance(toPtr);
// sanity check on balance
if (amount > from.nextEpochBalance) {
@ -81,7 +81,7 @@ contract MixinStakeStorage is
/// was stored.
/// @param balancePtr to load and sync.
/// @return synchronized balance.
function _loadAndSyncBalance(IStructs.StoredBalance storage balancePtr)
function _loadSyncedBalance(IStructs.StoredBalance storage balancePtr)
internal
view
returns (IStructs.StoredBalance memory balance)
@ -119,7 +119,7 @@ contract MixinStakeStorage is
internal
{
// Remove stake from balance
IStructs.StoredBalance memory balance = _loadAndSyncBalance(balancePtr);
IStructs.StoredBalance memory balance = _loadSyncedBalance(balancePtr);
balance.nextEpochBalance = uint256(balance.nextEpochBalance).safeAdd(amount).downcastToUint96();
balance.currentEpochBalance = uint256(balance.currentEpochBalance).safeAdd(amount).downcastToUint96();
@ -134,7 +134,7 @@ contract MixinStakeStorage is
internal
{
// Remove stake from balance
IStructs.StoredBalance memory balance = _loadAndSyncBalance(balancePtr);
IStructs.StoredBalance memory balance = _loadSyncedBalance(balancePtr);
balance.nextEpochBalance = uint256(balance.nextEpochBalance).safeSub(amount).downcastToUint96();
balance.currentEpochBalance = uint256(balance.currentEpochBalance).safeSub(amount).downcastToUint96();
@ -149,7 +149,7 @@ contract MixinStakeStorage is
internal
{
// Add stake to balance
IStructs.StoredBalance memory balance = _loadAndSyncBalance(balancePtr);
IStructs.StoredBalance memory balance = _loadSyncedBalance(balancePtr);
balance.nextEpochBalance = uint256(balance.nextEpochBalance).safeAdd(amount).downcastToUint96();
// update state
@ -163,7 +163,7 @@ contract MixinStakeStorage is
internal
{
// Remove stake from balance
IStructs.StoredBalance memory balance = _loadAndSyncBalance(balancePtr);
IStructs.StoredBalance memory balance = _loadSyncedBalance(balancePtr);
balance.nextEpochBalance = uint256(balance.nextEpochBalance).safeSub(amount).downcastToUint96();
// update state

View File

@ -39,21 +39,22 @@ contract MixinStakingPoolRewards is
{
using LibSafeMath for uint256;
/// @dev Syncs rewards for a delegator. This includes transferring rewards
/// from the Reward Vault to the Eth Vault, and adding/removing
/// @dev Syncs rewards for a delegator. This includes transferring WETH
/// rewards to the delegator, and adding/removing
/// dependencies on cumulative rewards.
/// This is used by a delegator when they want to sync their rewards
/// without delegating/undelegating. It's effectively the same as
/// delegating zero stake.
/// @param poolId Unique id of pool.
function syncDelegatorRewards(bytes32 poolId)
function withdrawDelegatorRewards(bytes32 poolId)
external
{
address member = msg.sender;
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
_loadAndSyncBalance(_delegatedStakeToPoolByOwner[member][poolId]);
_syncRewardsForDelegator(
_loadSyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]);
_withdrawAndSyncDelegatorRewards(
poolId,
member,
// Initial balance
@ -68,7 +69,6 @@ contract MixinStakingPoolRewards is
}
/// @dev Computes the reward balance in ETH of the operator of a pool.
/// This does not include the balance in the ETH vault.
/// @param poolId Unique id of pool.
/// @return totalReward Balance in ETH.
function computeRewardBalanceOfOperator(bytes32 poolId)
@ -76,14 +76,16 @@ contract MixinStakingPoolRewards is
view
returns (uint256 reward)
{
// Because operator rewards are immediately sent to the ETH vault
// Because operator rewards are immediately withdrawn as WETH
// on finalization, the only factor in this function are unfinalized
// rewards.
IStructs.Pool memory pool = _poolById[poolId];
// Get any unfinalized rewards.
(uint256 unfinalizedTotalRewards, uint256 unfinalizedMembersStake) = _getUnfinalizedPoolRewards(poolId);
(uint256 unfinalizedTotalRewards, uint256 unfinalizedMembersStake) =
_getUnfinalizedPoolRewards(poolId);
// Get the operators' portion.
(reward,) = _computeSplitStakingPoolRewards(
(reward,) = _computePoolRewardsSplit(
pool.operatorShare,
unfinalizedTotalRewards,
unfinalizedMembersStake
@ -92,7 +94,6 @@ contract MixinStakingPoolRewards is
}
/// @dev Computes the reward balance in ETH of a specific member of a pool.
/// This does not include the balance in the ETH vault.
/// @param poolId Unique id of pool.
/// @param member The member of the pool.
/// @return totalReward Balance in ETH.
@ -105,13 +106,14 @@ contract MixinStakingPoolRewards is
// Get any unfinalized rewards.
(uint256 unfinalizedTotalRewards, uint256 unfinalizedMembersStake) =
_getUnfinalizedPoolRewards(poolId);
// Get the members' portion.
(, uint256 unfinalizedMembersReward) = _computeSplitStakingPoolRewards(
(, uint256 unfinalizedMembersReward) = _computePoolRewardsSplit(
pool.operatorShare,
unfinalizedTotalRewards,
unfinalizedMembersStake
);
return _computeRewardBalanceOfDelegator(
return _computeDelegatorReward(
poolId,
_loadUnsyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]),
currentEpoch,
@ -121,15 +123,14 @@ contract MixinStakingPoolRewards is
}
/// @dev Syncs rewards for a delegator. This includes transferring rewards
/// from the Reward Vault to the Eth Vault, and adding/removing
/// dependencies on cumulative rewards.
/// withdrawing rewards and adding/removing dependencies on cumulative rewards.
/// @param poolId Unique id of pool.
/// @param member of the pool.
/// @param initialDelegatedStakeToPoolByOwner The member's delegated
/// balance at the beginning of this transaction.
/// @param finalDelegatedStakeToPoolByOwner The member's delegated balance
/// at the end of this transaction.
function _syncRewardsForDelegator(
function _withdrawAndSyncDelegatorRewards(
bytes32 poolId,
address member,
IStructs.StoredBalance memory initialDelegatedStakeToPoolByOwner,
@ -137,10 +138,10 @@ contract MixinStakingPoolRewards is
)
internal
{
// Transfer any rewards from the transient pool vault to the eth vault;
// Withdraw any rewards from.
// this must be done before we can modify the owner's portion of the
// delegator pool.
_transferDelegatorRewardsToEthVault(
_finalizePoolAndWithdrawDelegatorRewards(
poolId,
member,
initialDelegatedStakeToPoolByOwner,
@ -175,7 +176,7 @@ contract MixinStakingPoolRewards is
/// will split the reward.
/// @return operatorReward Portion of `reward` given to the pool operator.
/// @return membersReward Portion of `reward` given to the pool members.
function _depositStakingPoolRewards(
function _syncPoolRewards(
bytes32 poolId,
uint256 reward,
uint256 membersStake
@ -186,44 +187,46 @@ contract MixinStakingPoolRewards is
IStructs.Pool memory pool = _poolById[poolId];
// Split the reward between operator and members
(operatorReward, membersReward) = _computeSplitStakingPoolRewards(
(operatorReward, membersReward) = _computePoolRewardsSplit(
pool.operatorShare,
reward,
membersStake
);
// Deposit the operator's reward in the eth vault.
ethVault.depositFor(pool.operator, operatorReward);
if (membersReward == 0) {
return (0, 0);
if (operatorReward > 0) {
// Transfer the operator's weth reward to the operator
_getWethContract().transfer(pool.operator, operatorReward);
}
// Deposit the members' reward in the reward vault.
rewardVault.depositFor(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.
IStructs.Fraction memory mostRecentCumulativeReward = _getMostRecentCumulativeReward(poolId);
if (membersReward > 0) {
// Increment the balance of the pool
_incrementPoolRewards(poolId, membersReward);
// Compute new cumulative reward
IStructs.Fraction memory cumulativeReward;
(cumulativeReward.numerator, cumulativeReward.denominator) = LibFractions.add(
// 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.
IStructs.Fraction memory mostRecentCumulativeReward = _getMostRecentCumulativeReward(poolId);
// Compute new cumulative reward
IStructs.Fraction memory cumulativeReward;
(cumulativeReward.numerator, cumulativeReward.denominator) = LibFractions.add(
mostRecentCumulativeReward.numerator,
mostRecentCumulativeReward.denominator,
membersReward,
membersStake
);
// Normalize to prevent overflows.
(cumulativeReward.numerator, cumulativeReward.denominator) = LibFractions.normalize(
// Normalize to prevent overflows.
(cumulativeReward.numerator, cumulativeReward.denominator) = LibFractions.normalize(
cumulativeReward.numerator,
cumulativeReward.denominator
);
// Store cumulative rewards for this epoch.
_forceSetCumulativeReward(
poolId,
currentEpoch,
cumulativeReward
);
// Store cumulative rewards for this epoch.
_forceSetCumulativeReward(
poolId,
currentEpoch,
cumulativeReward
);
}
return (operatorReward, membersReward);
}
@ -237,7 +240,7 @@ contract MixinStakingPoolRewards is
/// to the pool in the epoch the rewards were earned.
/// @return operatorReward Portion of `totalReward` given to the pool operator.
/// @return membersReward Portion of `totalReward` given to the pool members.
function _computeSplitStakingPoolRewards(
function _computePoolRewardsSplit(
uint32 operatorShare,
uint256 totalReward,
uint256 membersStake
@ -259,13 +262,12 @@ contract MixinStakingPoolRewards is
return (operatorReward, membersReward);
}
/// @dev Transfers a delegators accumulated rewards from the transient pool
/// Reward Pool vault to the Eth Vault. This is required before the
/// member's stake in the pool can be modified.
/// @dev Transfers a delegators accumulated rewards to the delegator.
/// This is required before the member's stake in the pool can be modified.
/// @param poolId Unique id of pool.
/// @param member The member of the pool.
/// @param unsyncedStake Unsynced stake of the delegator to the pool.
function _transferDelegatorRewardsToEthVault(
function _finalizePoolAndWithdrawDelegatorRewards(
bytes32 poolId,
address member,
IStructs.StoredBalance memory unsyncedStake,
@ -277,7 +279,7 @@ contract MixinStakingPoolRewards is
finalizePool(poolId);
// Compute balance owed to delegator
uint256 balance = _computeRewardBalanceOfDelegator(
uint256 balance = _computeDelegatorReward(
poolId,
unsyncedStake,
currentEpoch,
@ -290,10 +292,11 @@ contract MixinStakingPoolRewards is
return;
}
// Transfer from RewardVault to this contract.
rewardVault.transfer(poolId, address(uint160(address(this))), balance);
// Transfer to EthVault.
ethVault.depositFor(member, balance);
// Decrement the balance of the pool
_decrementPoolRewards(poolId, balance);
// Withdraw the member's WETH balance
_getWethContract().transfer(member, balance);
}
/// @dev Computes the reward balance in ETH of a specific member of a pool.
@ -304,7 +307,7 @@ contract MixinStakingPoolRewards is
/// (if any).
/// @param unfinalizedMembersStake Unfinalized total members stake (if any).
/// @return totalReward Balance in ETH.
function _computeRewardBalanceOfDelegator(
function _computeDelegatorReward(
bytes32 poolId,
IStructs.StoredBalance memory unsyncedStake,
uint256 currentEpoch,
@ -424,4 +427,24 @@ contract MixinStakingPoolRewards is
);
}
}
/// @dev Increments rewards for a pool.
/// @param poolId Unique id of pool.
/// @param amount Amount to increment rewards by.
function _incrementPoolRewards(bytes32 poolId, uint256 amount)
private
{
rewardsByPoolId[poolId] = rewardsByPoolId[poolId].safeAdd(amount);
_wethReservedForPoolRewards = _wethReservedForPoolRewards.safeAdd(amount);
}
/// @dev Decrements rewards for a pool.
/// @param poolId Unique id of pool.
/// @param amount Amount to decrement rewards by.
function _decrementPoolRewards(bytes32 poolId, uint256 amount)
private
{
rewardsByPoolId[poolId] = rewardsByPoolId[poolId].safeSub(amount);
_wethReservedForPoolRewards = _wethReservedForPoolRewards.safeSub(amount);
}
}

View File

@ -27,8 +27,8 @@ import "../interfaces/IStructs.sol";
contract MixinAbstract {
/// @dev Instantly finalizes a single pool that was active in the previous
/// epoch, crediting it rewards and sending those rewards to the reward
/// and eth vault. This can be called by internal functions that need
/// epoch, crediting it rewards for members and withdrawing operator's
/// rewards as WETH. This can be called by internal functions that need
/// to finalize a pool immediately. Does nothing if the pool is already
/// finalized or was not active in the previous epoch.
/// @param poolId The pool ID to finalize.

View File

@ -26,7 +26,6 @@ import "../libs/LibCobbDouglas.sol";
import "../libs/LibStakingRichErrors.sol";
import "../immutable/MixinStorage.sol";
import "../immutable/MixinConstants.sol";
import "../immutable/MixinDeploymentConstants.sol";
import "../interfaces/IStakingEvents.sol";
import "../interfaces/IStructs.sol";
import "../stake/MixinStakeBalances.sol";
@ -43,7 +42,6 @@ contract MixinFinalizer is
IStakingEvents,
MixinAbstract,
MixinConstants,
MixinDeploymentConstants,
Ownable,
MixinStorage,
MixinScheduler,
@ -78,8 +76,11 @@ contract MixinFinalizer is
);
}
// Convert all ETH to WETH
_wrapEth();
// Set up unfinalized state.
state.rewardsAvailable = _wrapBalanceToWETHAndGetBalance();
state.rewardsAvailable = _getAvailableWethBalance();
state.poolsRemaining = poolsRemaining = numActivePoolsThisEpoch;
state.totalFeesCollected = totalFeesCollectedThisEpoch;
state.totalWeightedStake = totalWeightedStakeThisEpoch;
@ -110,8 +111,8 @@ contract MixinFinalizer is
}
/// @dev Instantly finalizes a single pool that was active in the previous
/// epoch, crediting it rewards and sending those rewards to the reward
/// and eth vault. This can be called by internal functions that need
/// epoch, crediting it rewards for members and withdrawing operator's
/// rewards as WETH. This can be called by internal functions that need
/// to finalize a pool immediately. Does nothing if the pool is already
/// finalized or was not active in the previous epoch.
/// @param poolId The pool ID to finalize.
@ -202,7 +203,7 @@ contract MixinFinalizer is
return (0, 0);
}
IStructs.ActivePool memory pool = _getActivePoolFromEpoch(epoch - 1, poolId);
reward = _getUnfinalizedPoolRewards(pool, unfinalizedState);
reward = _getUnfinalizedPoolRewardsFromState(pool, unfinalizedState);
membersStake = pool.membersStake;
}
@ -238,27 +239,34 @@ contract MixinFinalizer is
return activePools;
}
/// @dev Converts the entire ETH balance of the contract into WETH and
/// returns the total WETH balance of this contract.
/// @return The WETH balance of this contract.
function _wrapBalanceToWETHAndGetBalance()
/// @dev Converts the entire ETH balance of this contract into WETH.
function _wrapEth()
internal
returns (uint256 balance)
{
IEtherToken weth = IEtherToken(_getWETHAddress());
uint256 ethBalance = address(this).balance;
if (ethBalance != 0) {
weth.deposit.value((address(this).balance))();
_getWethContract().deposit.value(ethBalance)();
}
balance = weth.balanceOf(address(this));
return balance;
}
/// @dev Returns the WETH balance of this contract, minus
/// any WETH that has already been reserved for rewards.
function _getAvailableWethBalance()
internal
view
returns (uint256 wethBalance)
{
wethBalance = _getWethContract().balanceOf(address(this))
.safeSub(_wethReservedForPoolRewards);
return wethBalance;
}
/// @dev Computes the reward owed to a pool during finalization.
/// @param pool The active pool.
/// @param state The current state of finalization.
/// @return rewards Unfinalized rewards for this pool.
function _getUnfinalizedPoolRewards(
function _getUnfinalizedPoolRewardsFromState(
IStructs.ActivePool memory pool,
IStructs.UnfinalizedState memory state
)
@ -314,12 +322,12 @@ contract MixinFinalizer is
delete _getActivePoolsFromEpoch(epoch.safeSub(1))[poolId];
// Compute the rewards.
uint256 rewards = _getUnfinalizedPoolRewards(pool, state);
uint256 rewards = _getUnfinalizedPoolRewardsFromState(pool, state);
// Pay the pool.
// Note that we credit at the CURRENT epoch even though these rewards
// were earned in the previous epoch.
(operatorReward, membersReward) = _depositStakingPoolRewards(
(operatorReward, membersReward) = _syncPoolRewards(
poolId,
rewards,
pool.membersStake

View File

@ -22,10 +22,7 @@ import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
import "../immutable/MixinStorage.sol";
import "../immutable/MixinDeploymentConstants.sol";
import "../interfaces/IStakingEvents.sol";
import "../interfaces/IEthVault.sol";
import "../interfaces/IStakingPoolRewardVault.sol";
import "../interfaces/IZrxVault.sol";
import "../libs/LibStakingRichErrors.sol";
@ -33,7 +30,6 @@ import "../libs/LibStakingRichErrors.sol";
contract MixinParams is
IStakingEvents,
MixinConstants,
MixinDeploymentConstants,
Ownable,
MixinStorage
{
@ -45,8 +41,6 @@ contract MixinParams is
/// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
/// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
/// @param _wethProxyAddress The address that can transfer WETH for fees.
/// @param _ethVaultAddress Address of the EthVault contract.
/// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract.
/// @param _zrxVaultAddress Address of the ZrxVault contract.
function setParams(
uint256 _epochDurationInSeconds,
@ -56,8 +50,6 @@ contract MixinParams is
uint32 _cobbDouglasAlphaNumerator,
uint32 _cobbDouglasAlphaDenominator,
address _wethProxyAddress,
address _ethVaultAddress,
address payable _rewardVaultAddress,
address _zrxVaultAddress
)
external
@ -71,8 +63,6 @@ contract MixinParams is
_cobbDouglasAlphaNumerator,
_cobbDouglasAlphaDenominator,
_wethProxyAddress,
_ethVaultAddress,
_rewardVaultAddress,
_zrxVaultAddress
);
}
@ -85,8 +75,6 @@ contract MixinParams is
/// @return _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
/// @return _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
/// @return _wethProxyAddress The address that can transfer WETH for fees.
/// @return _ethVaultAddress Address of the EthVault contract.
/// @return _rewardVaultAddress Address of the StakingPoolRewardVault contract.
/// @return _zrxVaultAddress Address of the ZrxVault contract.
function getParams()
external
@ -99,8 +87,6 @@ contract MixinParams is
uint32 _cobbDouglasAlphaNumerator,
uint32 _cobbDouglasAlphaDenominator,
address _wethProxyAddress,
address _ethVaultAddress,
address _rewardVaultAddress,
address _zrxVaultAddress
)
{
@ -111,20 +97,14 @@ contract MixinParams is
_cobbDouglasAlphaNumerator = cobbDouglasAlphaNumerator;
_cobbDouglasAlphaDenominator = cobbDouglasAlphaDenominator;
_wethProxyAddress = address(wethAssetProxy);
_ethVaultAddress = address(ethVault);
_rewardVaultAddress = address(rewardVault);
_zrxVaultAddress = address(zrxVault);
}
/// @dev Initialize storage belonging to this mixin.
/// @param _wethProxyAddress The address that can transfer WETH for fees.
/// @param _ethVaultAddress Address of the EthVault contract.
/// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract.
/// @param _zrxVaultAddress Address of the ZrxVault contract.
function _initMixinParams(
address _wethProxyAddress,
address _ethVaultAddress,
address payable _rewardVaultAddress,
address _zrxVaultAddress
)
internal
@ -142,8 +122,6 @@ contract MixinParams is
1, // cobbDouglasAlphaNumerator
2, // cobbDouglasAlphaDenominator
_wethProxyAddress,
_ethVaultAddress,
_rewardVaultAddress,
_zrxVaultAddress
);
}
@ -160,8 +138,6 @@ contract MixinParams is
cobbDouglasAlphaNumerator != 0 &&
cobbDouglasAlphaDenominator != 0 &&
address(wethAssetProxy) != NIL_ADDRESS &&
address(ethVault) != NIL_ADDRESS &&
address(rewardVault) != NIL_ADDRESS &&
address(zrxVault) != NIL_ADDRESS
) {
LibRichErrors.rrevert(
@ -172,26 +148,6 @@ contract MixinParams is
}
}
/// @dev Rescind the WETH allowance for `oldSpenders` and grant `newSpenders`
/// an unlimited allowance.
/// @param oldSpenders Addresses to remove allowance from.
/// @param newSpenders Addresses to grant allowance to.
function _transferWETHAllownces(
address[2] memory oldSpenders,
address[2] memory newSpenders
)
internal
{
IEtherToken weth = IEtherToken(_getWETHAddress());
// Grant new allowances.
for (uint256 i = 0; i < oldSpenders.length; i++) {
// Rescind old allowance.
weth.approve(oldSpenders[i], 0);
// Grant new allowance.
weth.approve(newSpenders[i], uint256(-1));
}
}
/// @dev Set all configurable parameters at once.
/// @param _epochDurationInSeconds Minimum seconds between epochs.
/// @param _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
@ -200,8 +156,6 @@ contract MixinParams is
/// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
/// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
/// @param _wethProxyAddress The address that can transfer WETH for fees.
/// @param _ethVaultAddress Address of the EthVault contract.
/// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract.
/// @param _zrxVaultAddress Address of the ZrxVault contract.
function _setParams(
uint256 _epochDurationInSeconds,
@ -211,17 +165,10 @@ contract MixinParams is
uint32 _cobbDouglasAlphaNumerator,
uint32 _cobbDouglasAlphaDenominator,
address _wethProxyAddress,
address _ethVaultAddress,
address payable _rewardVaultAddress,
address _zrxVaultAddress
)
private
{
_transferWETHAllownces(
[address(ethVault), address(rewardVault)],
[_ethVaultAddress, _rewardVaultAddress]
);
epochDurationInSeconds = _epochDurationInSeconds;
rewardDelegatedStakeWeight = _rewardDelegatedStakeWeight;
minimumPoolStake = _minimumPoolStake;
@ -229,8 +176,6 @@ contract MixinParams is
cobbDouglasAlphaNumerator = _cobbDouglasAlphaNumerator;
cobbDouglasAlphaDenominator = _cobbDouglasAlphaDenominator;
wethAssetProxy = IAssetProxy(_wethProxyAddress);
ethVault = IEthVault(_ethVaultAddress);
rewardVault = IStakingPoolRewardVault(_rewardVaultAddress);
zrxVault = IZrxVault(_zrxVaultAddress);
emit ParamsSet(
@ -241,8 +186,6 @@ contract MixinParams is
_cobbDouglasAlphaNumerator,
_cobbDouglasAlphaDenominator,
_wethProxyAddress,
_ethVaultAddress,
_rewardVaultAddress,
_zrxVaultAddress
);
}

View File

@ -1,109 +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;
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "../interfaces/IEthVault.sol";
import "./MixinVaultCore.sol";
/// @dev This vault manages WETH.
contract EthVault is
IEthVault,
IVaultCore,
MixinVaultCore
{
using LibSafeMath for uint256;
// Address of the WETH contract.
IEtherToken public weth;
// mapping from Owner to WETH balance
mapping (address => uint256) internal _balances;
/// @param wethAddress Address of the WETH contract.
constructor(address wethAddress) public {
weth = IEtherToken(wethAddress);
}
/// @dev Deposit an `amount` of WETH for `owner` into the vault.
/// The staking contract should have granted the vault an allowance
/// because it will pull the WETH via `transferFrom()`.
/// Note that this is only callable by the staking contract.
/// @param owner Owner of the WETH.
/// @param amount Amount of deposit.
function depositFor(address owner, uint256 amount)
external
onlyStakingProxy
{
// Transfer WETH from the staking contract into this contract.
weth.transferFrom(msg.sender, address(this), amount);
// Credit the owner.
_balances[owner] = _balances[owner].safeAdd(amount);
emit EthDepositedIntoVault(msg.sender, owner, amount);
}
/// @dev Withdraw an `amount` of WETH to `msg.sender` from the vault.
/// @param amount of WETH to withdraw.
function withdraw(uint256 amount)
external
{
_withdrawFrom(msg.sender, amount);
}
/// @dev Withdraw ALL WETH to `msg.sender` from the vault.
function withdrawAll()
external
returns (uint256 totalBalance)
{
// get total balance
address payable owner = msg.sender;
totalBalance = _balances[owner];
// withdraw WETH to owner
_withdrawFrom(owner, totalBalance);
return totalBalance;
}
/// @dev Returns the balance in WETH of the `owner`
/// @return Balance in WETH.
function balanceOf(address owner)
external
view
returns (uint256)
{
return _balances[owner];
}
/// @dev Withdraw an `amount` of WETH to `owner` from the vault.
/// @param owner of WETH.
/// @param amount of WETH to withdraw.
function _withdrawFrom(address payable owner, uint256 amount)
internal
{
//Uupdate balance.
_balances[owner] = _balances[owner].safeSub(amount);
// withdraw WETH to owner
weth.transfer(msg.sender, amount);
// notify
emit EthWithdrawnFromVault(msg.sender, owner, amount);
}
}

View File

@ -1,97 +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-erc20/contracts/src/interfaces/IEtherToken.sol";
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "../libs/LibStakingRichErrors.sol";
import "../libs/LibSafeDowncast.sol";
import "../interfaces/IStakingPoolRewardVault.sol";
import "./MixinVaultCore.sol";
/// @dev This vault manages staking pool rewards.
contract StakingPoolRewardVault is
IStakingPoolRewardVault,
IVaultCore,
MixinVaultCore
{
using LibSafeMath for uint256;
// Address of the WETH contract.
IEtherToken public weth;
// mapping from poolId to Pool metadata
mapping (bytes32 => uint256) internal _balanceByPoolId;
/// @param wethAddress Address of the WETH contract.
constructor(address wethAddress) public {
weth = IEtherToken(wethAddress);
}
/// @dev Deposit an amount of WETH for `poolId` into the vault.
/// The staking contract should have granted the vault an allowance
/// because it will pull the WETH via `transferFrom()`.
/// Note that this is only callable by the staking contract.
/// @param poolId Pool that holds the WETH.
/// @param amount Amount of deposit.
function depositFor(bytes32 poolId, uint256 amount)
external
onlyStakingProxy
{
// Transfer WETH from the staking contract into this contract.
weth.transferFrom(msg.sender, address(this), amount);
// Credit the pool.
_balanceByPoolId[poolId] = _balanceByPoolId[poolId].safeAdd(amount);
emit EthDepositedIntoVault(msg.sender, poolId, amount);
}
/// @dev Withdraw some amount in WETH from a pool.
/// Note that this is only callable by the staking contract.
/// @param poolId Unique Id of pool.
/// @param to Address to send funds to.
/// @param amount Amount of WETH to transfer.
function transfer(
bytes32 poolId,
address payable to,
uint256 amount
)
external
onlyStakingProxy
{
_balanceByPoolId[poolId] = _balanceByPoolId[poolId].safeSub(amount);
weth.transfer(to, amount);
emit PoolRewardTransferred(
poolId,
to,
amount
);
}
/// @dev Returns the balance in WETH of `poolId`
/// @return Balance in WETH.
function balanceOf(bytes32 poolId)
external
view
returns (uint256 balance)
{
return _balanceByPoolId[poolId];
}
}

View File

@ -33,16 +33,12 @@ contract TestAssertStorageParams is
uint32 cobbDouglasAlphaNumerator;
uint32 cobbDouglasAlphaDenominator;
address wethProxyAddress;
address ethVaultAddress;
address rewardVaultAddress;
address zrxVaultAddress;
}
constructor()
public
StakingProxy(
NIL_ADDRESS,
NIL_ADDRESS,
NIL_ADDRESS,
NIL_ADDRESS,
NIL_ADDRESS,
@ -60,13 +56,11 @@ contract TestAssertStorageParams is
cobbDouglasAlphaNumerator = params.cobbDouglasAlphaNumerator;
cobbDouglasAlphaDenominator = params.cobbDouglasAlphaDenominator;
wethAssetProxy = IAssetProxy(params.wethProxyAddress);
ethVault = IEthVault(params.ethVaultAddress);
rewardVault = IStakingPoolRewardVault(params.rewardVaultAddress);
zrxVault = IZrxVault(params.zrxVaultAddress);
_assertValidStorageParams();
}
function _attachStakingContract(address, address, address, address, address)
function _attachStakingContract(address, address, address)
internal
{}
}

View File

@ -42,7 +42,7 @@ contract TestCumulativeRewardTracking is
constructor(address wethAddress) public TestStaking(wethAddress) {}
function init(address, address, address payable, address) public {}
function init(address, address) public {}
function _forceSetCumulativeReward(
bytes32 poolId,

View File

@ -20,24 +20,12 @@ pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "../src/interfaces/IStructs.sol";
import "../src/interfaces/IStakingPoolRewardVault.sol";
import "../src/interfaces/IEthVault.sol";
import "./TestStakingNoWETH.sol";
contract TestDelegatorRewards is
TestStakingNoWETH
{
event RecordDepositToEthVault(
address owner,
uint256 amount
);
event RecordDepositToRewardVault(
bytes32 poolId,
uint256 membersReward
);
event FinalizePool(
bytes32 poolId,
uint256 operatorReward,
@ -51,17 +39,13 @@ contract TestDelegatorRewards is
uint256 membersStake;
}
constructor() public {
constructor()
public
{
init(
address(1),
address(1),
address(1),
address(1)
);
// Set this contract up as the eth and reward vault to intercept
// deposits.
ethVault = IEthVault(address(this));
rewardVault = IStakingPoolRewardVault(address(this));
}
mapping (uint256 => mapping (bytes32 => UnfinalizedPoolReward)) private
@ -93,8 +77,8 @@ contract TestDelegatorRewards is
_initGenesisCumulativeRewards(poolId);
}
/// @dev Expose/wrap `_depositStakingPoolRewards`.
function depositStakingPoolRewards(
/// @dev Expose/wrap `_syncPoolRewards`.
function syncPoolRewards(
bytes32 poolId,
address payable operatorAddress,
uint256 operatorReward,
@ -107,8 +91,8 @@ contract TestDelegatorRewards is
_poolById[poolId].operator = operatorAddress;
_setOperatorShare(poolId, operatorReward, membersReward);
_initGenesisCumulativeRewards(poolId);
_depositStakingPoolRewards(
_syncPoolRewards(
poolId,
operatorReward + membersReward,
membersStake
@ -122,7 +106,7 @@ contract TestDelegatorRewards is
/// @dev Create and delegate stake that is active in the current epoch.
/// Only used to test purportedly unreachable states.
/// Also withdraws pending rewards to the eth vault.
/// Also withdraws pending rewards.
function delegateStakeNow(
address delegator,
bytes32 poolId,
@ -137,7 +121,7 @@ contract TestDelegatorRewards is
_stake.currentEpochBalance += uint96(stake);
_stake.nextEpochBalance += uint96(stake);
_stake.currentEpoch = uint32(currentEpoch);
_syncRewardsForDelegator(
_withdrawAndSyncDelegatorRewards(
poolId,
delegator,
initialStake,
@ -147,7 +131,7 @@ contract TestDelegatorRewards is
/// @dev Create and delegate stake that will occur in the next epoch
/// (normal behavior).
/// Also withdraws pending rewards to the eth vault.
/// Also withdraws pending rewards.
function delegateStake(
address delegator,
bytes32 poolId,
@ -164,7 +148,7 @@ contract TestDelegatorRewards is
_stake.isInitialized = true;
_stake.nextEpochBalance += uint96(stake);
_stake.currentEpoch = uint32(currentEpoch);
_syncRewardsForDelegator(
_withdrawAndSyncDelegatorRewards(
poolId,
delegator,
initialStake,
@ -174,7 +158,7 @@ contract TestDelegatorRewards is
/// @dev Clear stake that will occur in the next epoch
/// (normal behavior).
/// Also withdraws pending rewards to the eth vault.
/// Also withdraws pending rewards.
function undelegateStake(
address delegator,
bytes32 poolId,
@ -191,7 +175,7 @@ contract TestDelegatorRewards is
_stake.isInitialized = true;
_stake.nextEpochBalance -= uint96(stake);
_stake.currentEpoch = uint32(currentEpoch);
_syncRewardsForDelegator(
_withdrawAndSyncDelegatorRewards(
poolId,
delegator,
initialStake,
@ -199,33 +183,6 @@ contract TestDelegatorRewards is
);
}
/// @dev `IEthVault.depositFor()`,` overridden to just emit events.
function depositFor(
address owner,
uint256 amount
)
external
{
emit RecordDepositToEthVault(
owner,
amount
);
}
/// @dev `IStakingPoolRewardVault.depositFor()`,`
/// overridden to just emit events.
function depositFor(
bytes32 poolId,
uint256 membersReward
)
external
{
emit RecordDepositToRewardVault(
poolId,
membersReward
);
}
// solhint-disable no-simple-event-func-name
/// @dev Overridden to realize `unfinalizedPoolRewardsByEpoch` in
/// the current epoch and emit a event,
@ -245,7 +202,7 @@ contract TestDelegatorRewards is
uint256 totalRewards = reward.operatorReward + reward.membersReward;
membersStake = reward.membersStake;
(operatorReward, membersReward) =
_depositStakingPoolRewards(poolId, totalRewards, membersStake);
_syncPoolRewards(poolId, totalRewards, membersStake);
emit FinalizePool(poolId, operatorReward, membersReward, membersStake);
}

View File

@ -57,8 +57,6 @@ contract TestFinalizer is
public
{
init(
address(1),
address(1),
address(1),
address(1)
);
@ -144,7 +142,7 @@ contract TestFinalizer is
}
/// @dev Overridden to log and transfer to receivers.
function _depositStakingPoolRewards(
function _syncPoolRewards(
bytes32 poolId,
uint256 reward,
uint256 membersStake
@ -153,7 +151,7 @@ contract TestFinalizer is
returns (uint256 operatorReward, uint256 membersReward)
{
uint32 operatorShare = _operatorSharesByPool[poolId];
(operatorReward, membersReward) = _computeSplitStakingPoolRewards(
(operatorReward, membersReward) = _computePoolRewardsSplit(
operatorShare,
reward,
membersStake

View File

@ -37,15 +37,11 @@ contract TestInitTarget is
event InitAddresses(
address wethProxyAddress,
address ethVaultAddress,
address rewardVaultAddress,
address zrxVaultAddress
);
function init(
address wethProxyAddress,
address ethVaultAddress,
address rewardVaultAddress,
address zrxVaultAddress
)
external
@ -58,8 +54,6 @@ contract TestInitTarget is
_initThisAddress = address(this);
emit InitAddresses(
wethProxyAddress,
ethVaultAddress,
rewardVaultAddress,
zrxVaultAddress
);
}

View File

@ -1,54 +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 "../src/interfaces/IEthVault.sol";
import "../src/interfaces/IStakingPoolRewardVault.sol";
import "../src/sys/MixinParams.sol";
// solhint-disable no-empty-blocks
contract TestMixinParams is
MixinParams
{
event WETHApprove(address spender, uint256 amount);
/// @dev Sets the eth and reward vault addresses.
function setVaultAddresses(
address ethVaultAddress,
address rewardVaultAddress
)
external
{
ethVault = IEthVault(ethVaultAddress);
rewardVault = IStakingPoolRewardVault(rewardVaultAddress);
}
/// @dev WETH `approve()` function that just logs events.
function approve(address spender, uint256 amount) external returns (bool) {
emit WETHApprove(spender, amount);
}
/// @dev Overridden return this contract's address.
function _getWETHAddress() internal view returns (address) {
return address(this);
}
}

View File

@ -48,8 +48,6 @@ contract TestProtocolFees is
// Use this contract as the ERC20Proxy.
address(this),
// vault addresses must be non-zero
address(1),
address(1),
address(1)
);
validExchanges[exchangeAddress] = true;
@ -98,8 +96,8 @@ contract TestProtocolFees is
emit ERC20ProxyTransferFrom(assetData, from, to, amount);
}
function getWethAssetData() external pure returns (bytes memory) {
return WETH_ASSET_DATA;
function getWethAssetData() external view returns (bytes memory) {
return _getWethAssetData();
}
/// @dev Overridden to use test pools.

View File

@ -20,6 +20,7 @@ pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "../src/Staking.sol";
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
contract TestStaking is
@ -32,10 +33,27 @@ contract TestStaking is
}
/// @dev Overridden to use testWethAddress;
function _getWETHAddress() internal view returns (address) {
function _getWethContract()
internal
view
returns (IEtherToken)
{
// `testWethAddress` will not be set on the proxy this contract is
// attached to, so we need to access the storage of the deployed
// instance of this contract.
return TestStaking(address(uint160(stakingContract))).testWethAddress();
address wethAddress = TestStaking(address(uint160(stakingContract))).testWethAddress();
return IEtherToken(wethAddress);
}
function _getWethAssetData()
internal
view
returns (bytes memory)
{
address wethAddress = TestStaking(address(uint160(stakingContract))).testWethAddress();
return abi.encodeWithSelector(
IAssetData(address(0)).ERC20Token.selector,
wethAddress
);
}
}

View File

@ -28,17 +28,37 @@ import "../src/Staking.sol";
contract TestStakingNoWETH is
Staking
{
function _transferWETHAllownces(
address[2] memory oldSpenders,
address[2] memory newSpenders
)
event Transfer(
address indexed _from,
address indexed _to,
uint256 _value
);
function transfer(address to, uint256 amount)
external
returns (bool)
{
emit Transfer(address(this), to, amount);
return true;
}
function _wrapEth()
internal
{}
function _wrapBalanceToWETHAndGetBalance()
function _getAvailableWethBalance()
internal
returns (uint256 balance)
view
returns (uint256)
{
return address(this).balance;
}
function _getWethContract()
internal
view
returns (IEtherToken)
{
return IEtherToken(address(this));
}
}

View File

@ -33,23 +33,17 @@ contract TestStakingProxy is
_stakingContract,
NIL_ADDRESS,
NIL_ADDRESS,
NIL_ADDRESS,
NIL_ADDRESS,
NIL_ADDRESS
)
{}
function setAddressParams(
address _wethProxyAddress,
address _ethVaultAddress,
address payable _rewardVaultAddress,
address _zrxVaultAddress
)
external
{
wethAssetProxy = IAssetProxy(_wethProxyAddress);
ethVault = IEthVault(_ethVaultAddress);
rewardVault = IStakingPoolRewardVault(_rewardVaultAddress);
zrxVault = IZrxVault(_zrxVaultAddress);
}

View File

@ -1,141 +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.5;
import "../src/immutable/MixinStorage.sol";
import "../src/interfaces/IStructs.sol";
contract TestStorageLayout is
Ownable,
MixinStorage
{
function assertExpectedStorageLayout()
public
pure
{
assembly {
function revertIncorrectStorageSlot() {
// Revert with `Error("INCORRECT_STORAGE_SLOT")`
mstore(0, 0x504fe8ef00000000000000000000000000000000000000000000000000000000)
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
mstore(64, 0x00000016494e434f52524543545f53544f524147455f534c4f54000000000000)
mstore(96, 0)
}
// The staking contract writes to state that's stored in the staking proxy contract; hence,
// we require that slots do not change across upgrades to the staking contract. We expect
// storage slots to match the ordering in MixinStorage.sol.
let slot := 0
if sub(owner_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(stakingContract_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(_activeStakeByOwner_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(_inactiveStakeByOwner_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(_delegatedStakeByOwner_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(_delegatedStakeToPoolByOwner_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(_delegatedStakeByPoolId_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(_withdrawableStakeByOwner_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(nextPoolId_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(poolJoinedByMakerAddress_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(_poolById_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(currentEpoch_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(currentEpochStartTimeInSeconds_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(_cumulativeRewardsByPool_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(_cumulativeRewardsByPoolReferenceCounter_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(_cumulativeRewardsByPoolLastStored_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(validExchanges_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(zrxVault_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(rewardVault_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(epochDurationInSeconds_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(rewardDelegatedStakeWeight_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(minimumPoolStake_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(maximumMakersInPool_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(cobbDouglasAlphaNumerator_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(cobbDouglasAlphaDenominator_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(totalFeesCollectedThisEpoch_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(totalWeightedStakeThisEpoch_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(_activePoolsByEpoch_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(numActivePoolsThisEpoch_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
if sub(unfinalizedState_slot, slot) { revertIncorrectStorageSlot() }
slot := add(slot, 1)
}
}
}

View File

@ -37,7 +37,7 @@
},
"config": {
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./generated-artifacts/@(EthVault|IEthVault|IStaking|IStakingEvents|IStakingPoolRewardVault|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|StakingPoolRewardVault|StakingProxy|TestAssertStorageParams|TestCobbDouglas|TestCumulativeRewardTracking|TestDelegatorRewards|TestFinalizer|TestInitTarget|TestLibFixedMath|TestLibProxy|TestLibProxyReceiver|TestLibSafeDowncast|TestMixinParams|TestMixinVaultCore|TestProtocolFees|TestStaking|TestStakingNoWETH|TestStakingProxy|TestStorageLayout|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|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"
},
"repository": {
"type": "git",

View File

@ -5,11 +5,8 @@
*/
import { ContractArtifact } from 'ethereum-types';
import * as EthVault from '../generated-artifacts/EthVault.json';
import * as IEthVault from '../generated-artifacts/IEthVault.json';
import * as IStaking from '../generated-artifacts/IStaking.json';
import * as IStakingEvents from '../generated-artifacts/IStakingEvents.json';
import * as IStakingPoolRewardVault from '../generated-artifacts/IStakingPoolRewardVault.json';
import * as IStakingProxy from '../generated-artifacts/IStakingProxy.json';
import * as IStorage from '../generated-artifacts/IStorage.json';
import * as IStorageInit from '../generated-artifacts/IStorageInit.json';
@ -42,7 +39,6 @@ import * as MixinStorage from '../generated-artifacts/MixinStorage.json';
import * as MixinVaultCore from '../generated-artifacts/MixinVaultCore.json';
import * as ReadOnlyProxy from '../generated-artifacts/ReadOnlyProxy.json';
import * as Staking from '../generated-artifacts/Staking.json';
import * as StakingPoolRewardVault from '../generated-artifacts/StakingPoolRewardVault.json';
import * as StakingProxy from '../generated-artifacts/StakingProxy.json';
import * as TestAssertStorageParams from '../generated-artifacts/TestAssertStorageParams.json';
import * as TestCobbDouglas from '../generated-artifacts/TestCobbDouglas.json';
@ -54,13 +50,11 @@ import * as TestLibFixedMath from '../generated-artifacts/TestLibFixedMath.json'
import * as TestLibProxy from '../generated-artifacts/TestLibProxy.json';
import * as TestLibProxyReceiver from '../generated-artifacts/TestLibProxyReceiver.json';
import * as TestLibSafeDowncast from '../generated-artifacts/TestLibSafeDowncast.json';
import * as TestMixinParams from '../generated-artifacts/TestMixinParams.json';
import * as TestMixinVaultCore from '../generated-artifacts/TestMixinVaultCore.json';
import * as TestProtocolFees from '../generated-artifacts/TestProtocolFees.json';
import * as TestStaking from '../generated-artifacts/TestStaking.json';
import * as TestStakingNoWETH from '../generated-artifacts/TestStakingNoWETH.json';
import * as TestStakingProxy from '../generated-artifacts/TestStakingProxy.json';
import * as TestStorageLayout from '../generated-artifacts/TestStorageLayout.json';
import * as ZrxVault from '../generated-artifacts/ZrxVault.json';
export const artifacts = {
ReadOnlyProxy: ReadOnlyProxy as ContractArtifact,
@ -71,10 +65,8 @@ export const artifacts = {
MixinConstants: MixinConstants as ContractArtifact,
MixinDeploymentConstants: MixinDeploymentConstants as ContractArtifact,
MixinStorage: MixinStorage as ContractArtifact,
IEthVault: IEthVault as ContractArtifact,
IStaking: IStaking as ContractArtifact,
IStakingEvents: IStakingEvents as ContractArtifact,
IStakingPoolRewardVault: IStakingPoolRewardVault as ContractArtifact,
IStakingProxy: IStakingProxy as ContractArtifact,
IStorage: IStorage as ContractArtifact,
IStorageInit: IStorageInit as ContractArtifact,
@ -99,9 +91,7 @@ export const artifacts = {
MixinFinalizer: MixinFinalizer as ContractArtifact,
MixinParams: MixinParams as ContractArtifact,
MixinScheduler: MixinScheduler as ContractArtifact,
EthVault: EthVault as ContractArtifact,
MixinVaultCore: MixinVaultCore as ContractArtifact,
StakingPoolRewardVault: StakingPoolRewardVault as ContractArtifact,
ZrxVault: ZrxVault as ContractArtifact,
TestAssertStorageParams: TestAssertStorageParams as ContractArtifact,
TestCobbDouglas: TestCobbDouglas as ContractArtifact,
@ -113,11 +103,9 @@ export const artifacts = {
TestLibProxy: TestLibProxy as ContractArtifact,
TestLibProxyReceiver: TestLibProxyReceiver as ContractArtifact,
TestLibSafeDowncast: TestLibSafeDowncast as ContractArtifact,
TestMixinParams: TestMixinParams as ContractArtifact,
TestMixinVaultCore: TestMixinVaultCore as ContractArtifact,
TestProtocolFees: TestProtocolFees as ContractArtifact,
TestStaking: TestStaking as ContractArtifact,
TestStakingNoWETH: TestStakingNoWETH as ContractArtifact,
TestStakingProxy: TestStakingProxy as ContractArtifact,
TestStorageLayout: TestStorageLayout as ContractArtifact,
};

View File

@ -3,11 +3,8 @@
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/eth_vault';
export * from '../generated-wrappers/i_eth_vault';
export * from '../generated-wrappers/i_staking';
export * from '../generated-wrappers/i_staking_events';
export * from '../generated-wrappers/i_staking_pool_reward_vault';
export * from '../generated-wrappers/i_staking_proxy';
export * from '../generated-wrappers/i_storage';
export * from '../generated-wrappers/i_storage_init';
@ -40,7 +37,6 @@ export * from '../generated-wrappers/mixin_storage';
export * from '../generated-wrappers/mixin_vault_core';
export * from '../generated-wrappers/read_only_proxy';
export * from '../generated-wrappers/staking';
export * from '../generated-wrappers/staking_pool_reward_vault';
export * from '../generated-wrappers/staking_proxy';
export * from '../generated-wrappers/test_assert_storage_params';
export * from '../generated-wrappers/test_cobb_douglas';
@ -52,11 +48,9 @@ export * from '../generated-wrappers/test_lib_fixed_math';
export * from '../generated-wrappers/test_lib_proxy';
export * from '../generated-wrappers/test_lib_proxy_receiver';
export * from '../generated-wrappers/test_lib_safe_downcast';
export * from '../generated-wrappers/test_mixin_params';
export * from '../generated-wrappers/test_mixin_vault_core';
export * from '../generated-wrappers/test_protocol_fees';
export * from '../generated-wrappers/test_staking';
export * from '../generated-wrappers/test_staking_no_w_e_t_h';
export * from '../generated-wrappers/test_staking_proxy';
export * from '../generated-wrappers/test_storage_layout';
export * from '../generated-wrappers/zrx_vault';

View File

@ -10,8 +10,8 @@ import {
OperatorBalanceByPoolId,
OperatorByPoolId,
OperatorShareByPoolId,
RewardBalanceByPoolId,
RewardByPoolId,
RewardVaultBalanceByPoolId,
} from '../utils/types';
import { BaseActor } from './base_actor';
@ -40,7 +40,7 @@ export class FinalizerActor extends BaseActor {
public async finalizeAsync(): Promise<void> {
// cache initial info and balances
const operatorShareByPoolId = await this._getOperatorShareByPoolIdAsync(this._poolIds);
const rewardVaultBalanceByPoolId = await this._getRewardVaultBalanceByPoolIdAsync(this._poolIds);
const rewardBalanceByPoolId = await this._getRewardBalanceByPoolIdAsync(this._poolIds);
const delegatorBalancesByPoolId = await this._getDelegatorBalancesByPoolIdAsync(this._delegatorsByPoolId);
const delegatorStakesByPoolId = await this._getDelegatorStakesByPoolIdAsync(this._delegatorsByPoolId);
const operatorBalanceByPoolId = await this._getOperatorBalanceByPoolIdAsync(this._operatorByPoolId);
@ -48,11 +48,11 @@ export class FinalizerActor extends BaseActor {
// compute expected changes
const [
expectedOperatorBalanceByPoolId,
expectedRewardVaultBalanceByPoolId,
] = await this._computeExpectedRewardVaultBalanceAsyncByPoolIdAsync(
expectedRewardBalanceByPoolId,
] = this._computeExpectedRewardBalanceByPoolId(
rewardByPoolId,
operatorBalanceByPoolId,
rewardVaultBalanceByPoolId,
rewardBalanceByPoolId,
delegatorStakesByPoolId,
operatorShareByPoolId,
);
@ -65,19 +65,19 @@ export class FinalizerActor extends BaseActor {
);
// finalize
await this._stakingApiWrapper.utils.skipToNextEpochAndFinalizeAsync();
// assert reward vault changes
const finalRewardVaultBalanceByPoolId = await this._getRewardVaultBalanceByPoolIdAsync(this._poolIds);
expect(finalRewardVaultBalanceByPoolId, 'final pool balances in reward vault').to.be.deep.equal(
expectedRewardVaultBalanceByPoolId,
// assert reward changes
const finalRewardBalanceByPoolId = await this._getRewardBalanceByPoolIdAsync(this._poolIds);
expect(finalRewardBalanceByPoolId, 'final pool reward balances').to.be.deep.equal(
expectedRewardBalanceByPoolId,
);
// assert delegator balances
const finalDelegatorBalancesByPoolId = await this._getDelegatorBalancesByPoolIdAsync(this._delegatorsByPoolId);
expect(finalDelegatorBalancesByPoolId, 'final delegator balances in reward vault').to.be.deep.equal(
expect(finalDelegatorBalancesByPoolId, 'final delegator reward balances').to.be.deep.equal(
expectedDelegatorBalancesByPoolId,
);
// assert operator balances
const finalOperatorBalanceByPoolId = await this._getOperatorBalanceByPoolIdAsync(this._operatorByPoolId);
expect(finalOperatorBalanceByPoolId, 'final operator balances in eth vault').to.be.deep.equal(
expect(finalOperatorBalanceByPoolId, 'final operator weth balance').to.be.deep.equal(
expectedOperatorBalanceByPoolId,
);
}
@ -159,40 +159,40 @@ export class FinalizerActor extends BaseActor {
return delegatorBalancesByPoolId;
}
private async _computeExpectedRewardVaultBalanceAsyncByPoolIdAsync(
private _computeExpectedRewardBalanceByPoolId(
rewardByPoolId: RewardByPoolId,
operatorBalanceByPoolId: OperatorBalanceByPoolId,
rewardVaultBalanceByPoolId: RewardVaultBalanceByPoolId,
rewardBalanceByPoolId: RewardBalanceByPoolId,
delegatorStakesByPoolId: DelegatorBalancesByPoolId,
operatorShareByPoolId: OperatorShareByPoolId,
): Promise<[RewardVaultBalanceByPoolId, OperatorBalanceByPoolId]> {
): [RewardBalanceByPoolId, OperatorBalanceByPoolId] {
const expectedOperatorBalanceByPoolId = _.cloneDeep(operatorBalanceByPoolId);
const expectedRewardVaultBalanceByPoolId = _.cloneDeep(rewardVaultBalanceByPoolId);
const expectedRewardBalanceByPoolId = _.cloneDeep(rewardBalanceByPoolId);
for (const poolId of Object.keys(rewardByPoolId)) {
const operatorShare = operatorShareByPoolId[poolId];
[
expectedOperatorBalanceByPoolId[poolId],
expectedRewardVaultBalanceByPoolId[poolId],
] = await this._computeExpectedRewardVaultBalanceAsync(
expectedRewardBalanceByPoolId[poolId],
] = this._computeExpectedRewardBalance(
poolId,
rewardByPoolId[poolId],
expectedOperatorBalanceByPoolId[poolId],
expectedRewardVaultBalanceByPoolId[poolId],
expectedRewardBalanceByPoolId[poolId],
delegatorStakesByPoolId[poolId],
operatorShare,
);
}
return [expectedOperatorBalanceByPoolId, expectedRewardVaultBalanceByPoolId];
return [expectedOperatorBalanceByPoolId, expectedRewardBalanceByPoolId];
}
private async _computeExpectedRewardVaultBalanceAsync(
private _computeExpectedRewardBalance(
poolId: string,
reward: BigNumber,
operatorBalance: BigNumber,
rewardVaultBalance: BigNumber,
rewardBalance: BigNumber,
stakeBalances: BalanceByOwner,
operatorShare: BigNumber,
): Promise<[BigNumber, BigNumber]> {
): [BigNumber, BigNumber] {
const totalStakeDelegatedToPool = BigNumber.sum(...Object.values(stakeBalances));
const stakeDelegatedToPoolByOperator = stakeBalances[this._operatorByPoolId[poolId]];
const membersStakeDelegatedToPool = totalStakeDelegatedToPool.minus(stakeDelegatedToPoolByOperator);
@ -200,7 +200,7 @@ export class FinalizerActor extends BaseActor {
? reward
: reward.times(operatorShare).dividedToIntegerBy(PPM_100_PERCENT);
const membersPortion = reward.minus(operatorPortion);
return [operatorBalance.plus(operatorPortion), rewardVaultBalance.plus(membersPortion)];
return [operatorBalance.plus(operatorPortion), rewardBalance.plus(membersPortion)];
}
private async _getOperatorBalanceByPoolIdAsync(
@ -208,7 +208,7 @@ export class FinalizerActor extends BaseActor {
): Promise<OperatorBalanceByPoolId> {
const operatorBalanceByPoolId: OperatorBalanceByPoolId = {};
for (const poolId of Object.keys(operatorByPoolId)) {
operatorBalanceByPoolId[poolId] = await this._stakingApiWrapper.ethVaultContract.balanceOf.callAsync(
operatorBalanceByPoolId[poolId] = await this._stakingApiWrapper.wethContract.balanceOf.callAsync(
operatorByPoolId[poolId],
);
}
@ -225,14 +225,14 @@ export class FinalizerActor extends BaseActor {
return operatorShareByPoolId;
}
private async _getRewardVaultBalanceByPoolIdAsync(poolIds: string[]): Promise<RewardVaultBalanceByPoolId> {
const rewardVaultBalanceByPoolId: RewardVaultBalanceByPoolId = {};
private async _getRewardBalanceByPoolIdAsync(poolIds: string[]): Promise<RewardBalanceByPoolId> {
const rewardBalanceByPoolId: RewardBalanceByPoolId = {};
for (const poolId of poolIds) {
rewardVaultBalanceByPoolId[poolId] = await this._stakingApiWrapper.rewardVaultContract.balanceOf.callAsync(
rewardBalanceByPoolId[poolId] = await this._stakingApiWrapper.stakingContract.rewardsByPoolId.callAsync(
poolId,
);
}
return rewardVaultBalanceByPoolId;
return rewardBalanceByPoolId;
}
private async _getRewardByPoolIdAsync(poolIds: string[]): Promise<RewardByPoolId> {
@ -241,9 +241,7 @@ export class FinalizerActor extends BaseActor {
this._stakingApiWrapper.stakingContract.getActiveStakingPoolThisEpoch.callAsync(poolId),
),
);
const totalRewards = await this._stakingApiWrapper.utils.getEthAndWethBalanceOfAsync(
this._stakingApiWrapper.stakingContract.address,
);
const totalRewards = await this._stakingApiWrapper.stakingContract.getAvailableRewardsBalance.callAsync();
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)) {

View File

@ -155,8 +155,8 @@ export class StakerActor extends BaseActor {
);
}
public async syncDelegatorRewardsAsync(poolId: string, revertError?: RevertError): Promise<void> {
const txReceiptPromise = this._stakingApiWrapper.stakingContract.syncDelegatorRewards.awaitTransactionSuccessAsync(
public async withdrawDelegatorRewardsAsync(poolId: string, revertError?: RevertError): Promise<void> {
const txReceiptPromise = this._stakingApiWrapper.stakingContract.withdrawDelegatorRewards.awaitTransactionSuccessAsync(
poolId,
{ from: this._owner },
);

View File

@ -101,8 +101,6 @@ blockchainTests('Migration tests', env => {
it('should set the correct initial params', async () => {
const wethProxyAddress = randomAddress();
const ethVaultAddress = randomAddress();
const rewardVaultAddress = randomAddress();
const zrxVaultAddress = randomAddress();
const stakingProxyContractAddress = (await StakingProxyContract.deployFrom0xArtifactAsync(
@ -113,8 +111,6 @@ blockchainTests('Migration tests', env => {
stakingContract.address,
stakingContract.address,
wethProxyAddress,
ethVaultAddress,
rewardVaultAddress,
zrxVaultAddress,
)).address;
@ -131,9 +127,7 @@ blockchainTests('Migration tests', env => {
expect(params[4]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaNumerator);
expect(params[5]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaDenominator);
expect(params[6]).to.eq(wethProxyAddress);
expect(params[7]).to.eq(ethVaultAddress);
expect(params[8]).to.eq(rewardVaultAddress);
expect(params[9]).to.eq(zrxVaultAddress);
expect(params[7]).to.eq(zrxVaultAddress);
});
});
@ -149,8 +143,6 @@ blockchainTests('Migration tests', env => {
initTargetContract.address,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
{
from: notAuthorizedAddress,
},
@ -164,8 +156,6 @@ blockchainTests('Migration tests', env => {
initTargetContract.address,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
);
await assertInitStateAsync(proxyContract);
});
@ -175,8 +165,6 @@ blockchainTests('Migration tests', env => {
initTargetContract.address,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
);
const logsArgs = filterLogsToArguments<TestStakingProxyStakingContractAttachedToProxyEventArgs>(
receipt.logs,
@ -195,29 +183,18 @@ blockchainTests('Migration tests', env => {
initTargetContract.address,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
);
return expect(tx).to.revertWith(INIT_REVERT_ERROR);
});
it('calls init with initialized addresses if passed in args are null', async () => {
const wethProxyAddress = randomAddress();
const ethVaultAddress = randomAddress();
const rewardVaultAddress = randomAddress();
const zrxVaultAddress = randomAddress();
await proxyContract.setAddressParams.awaitTransactionSuccessAsync(
wethProxyAddress,
ethVaultAddress,
rewardVaultAddress,
zrxVaultAddress,
);
await proxyContract.setAddressParams.awaitTransactionSuccessAsync(wethProxyAddress, zrxVaultAddress);
const receipt = await proxyContract.attachStakingContract.awaitTransactionSuccessAsync(
initTargetContract.address,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
);
const logsArgs = filterLogsToArguments<TestInitTargetInitAddressesEventArgs>(
receipt.logs,
@ -225,21 +202,15 @@ blockchainTests('Migration tests', env => {
);
for (const args of logsArgs) {
expect(args.wethProxyAddress).to.eq(wethProxyAddress);
expect(args.ethVaultAddress).to.eq(ethVaultAddress);
expect(args.rewardVaultAddress).to.eq(rewardVaultAddress);
expect(args.zrxVaultAddress).to.eq(zrxVaultAddress);
}
});
it('calls init with passed in addresses if they are not null', async () => {
const wethProxyAddress = randomAddress();
const ethVaultAddress = randomAddress();
const rewardVaultAddress = randomAddress();
const zrxVaultAddress = randomAddress();
const receipt = await proxyContract.attachStakingContract.awaitTransactionSuccessAsync(
initTargetContract.address,
wethProxyAddress,
ethVaultAddress,
rewardVaultAddress,
zrxVaultAddress,
);
const logsArgs = filterLogsToArguments<TestInitTargetInitAddressesEventArgs>(
@ -248,8 +219,6 @@ blockchainTests('Migration tests', env => {
);
for (const args of logsArgs) {
expect(args.wethProxyAddress).to.eq(wethProxyAddress);
expect(args.ethVaultAddress).to.eq(ethVaultAddress);
expect(args.rewardVaultAddress).to.eq(rewardVaultAddress);
expect(args.zrxVaultAddress).to.eq(zrxVaultAddress);
}
});
@ -259,8 +228,6 @@ blockchainTests('Migration tests', env => {
revertAddress,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
);
return expect(tx).to.revertWith(STORAGE_PARAMS_REVERT_ERROR);
});
@ -273,8 +240,6 @@ blockchainTests('Migration tests', env => {
initTargetContract.address,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
);
const initCounter = await initTargetContract.getInitCounter.callAsync({ to: proxyContract.address });
expect(initCounter).to.bignumber.eq(2);
@ -284,32 +249,16 @@ blockchainTests('Migration tests', env => {
blockchainTests.resets('Staking.init()', async () => {
it('throws if not called by an authorized address', async () => {
const tx = stakingContract.init.awaitTransactionSuccessAsync(
randomAddress(),
randomAddress(),
randomAddress(),
randomAddress(),
{
from: notAuthorizedAddress,
},
);
const tx = stakingContract.init.awaitTransactionSuccessAsync(randomAddress(), randomAddress(), {
from: notAuthorizedAddress,
});
const expectedError = new AuthorizableRevertErrors.SenderNotAuthorizedError(notAuthorizedAddress);
return expect(tx).to.revertWith(expectedError);
});
it('throws if already intitialized', async () => {
await stakingContract.init.awaitTransactionSuccessAsync(
randomAddress(),
randomAddress(),
randomAddress(),
randomAddress(),
);
const tx = stakingContract.init.awaitTransactionSuccessAsync(
randomAddress(),
randomAddress(),
randomAddress(),
randomAddress(),
);
await stakingContract.init.awaitTransactionSuccessAsync(randomAddress(), randomAddress());
const tx = stakingContract.init.awaitTransactionSuccessAsync(randomAddress(), randomAddress());
const expectedError = new StakingRevertErrors.InitializationError();
return expect(tx).to.revertWith(expectedError);
});
@ -441,26 +390,6 @@ blockchainTests('Migration tests', env => {
);
expect(tx).to.revertWith(expectedError);
});
it('reverts if ethVault is 0', async () => {
const tx = proxyContract.setAndAssertParams.awaitTransactionSuccessAsync({
...stakingConstants.DEFAULT_PARAMS,
ethVaultAddress: constants.NULL_ADDRESS,
});
const expectedError = new StakingRevertErrors.InvalidParamValueError(
StakingRevertErrors.InvalidParamValueErrorCode.InvalidEthVaultAddress,
);
expect(tx).to.revertWith(expectedError);
});
it('reverts if rewardVault is 0', async () => {
const tx = proxyContract.setAndAssertParams.awaitTransactionSuccessAsync({
...stakingConstants.DEFAULT_PARAMS,
rewardVaultAddress: constants.NULL_ADDRESS,
});
const expectedError = new StakingRevertErrors.InvalidParamValueError(
StakingRevertErrors.InvalidParamValueErrorCode.InvalidRewardVaultAddress,
);
expect(tx).to.revertWith(expectedError);
});
it('reverts if zrxVault is 0', async () => {
const tx = proxyContract.setAndAssertParams.awaitTransactionSuccessAsync({
...stakingConstants.DEFAULT_PARAMS,

View File

@ -1,28 +1,22 @@
import { blockchainTests, constants, expect, filterLogsToArguments, randomAddress } from '@0x/contracts-test-utils';
import { blockchainTests, expect, filterLogsToArguments } from '@0x/contracts-test-utils';
import { AuthorizableRevertErrors, BigNumber } from '@0x/utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import {
artifacts,
IStakingEventsParamsSetEventArgs,
TestMixinParamsContract,
TestMixinParamsEvents,
TestMixinParamsWETHApproveEventArgs,
} from '../src/';
import { artifacts, IStakingEventsParamsSetEventArgs, MixinParamsContract } from '../src/';
import { constants as stakingConstants } from './utils/constants';
import { StakingParams } from './utils/types';
blockchainTests('Configurable Parameters unit tests', env => {
let testContract: TestMixinParamsContract;
let testContract: MixinParamsContract;
let authorizedAddress: string;
let notAuthorizedAddress: string;
before(async () => {
[authorizedAddress, notAuthorizedAddress] = await env.getAccountAddressesAsync();
testContract = await TestMixinParamsContract.deployFrom0xArtifactAsync(
artifacts.TestMixinParams,
testContract = await MixinParamsContract.deployFrom0xArtifactAsync(
artifacts.MixinParams,
env.provider,
env.txDefaults,
artifacts,
@ -46,8 +40,6 @@ blockchainTests('Configurable Parameters unit tests', env => {
new BigNumber(_params.cobbDouglasAlphaNumerator),
new BigNumber(_params.cobbDouglasAlphaDenominator),
_params.wethProxyAddress,
_params.ethVaultAddress,
_params.rewardVaultAddress,
_params.zrxVaultAddress,
{ from },
);
@ -62,8 +54,6 @@ blockchainTests('Configurable Parameters unit tests', env => {
expect(event.cobbDouglasAlphaNumerator).to.bignumber.eq(_params.cobbDouglasAlphaNumerator);
expect(event.cobbDouglasAlphaDenominator).to.bignumber.eq(_params.cobbDouglasAlphaDenominator);
expect(event.wethProxyAddress).to.eq(_params.wethProxyAddress);
expect(event.ethVaultAddress).to.eq(_params.ethVaultAddress);
expect(event.rewardVaultAddress).to.eq(_params.rewardVaultAddress);
expect(event.zrxVaultAddress).to.eq(_params.zrxVaultAddress);
// Assert `getParams()`.
const actual = await testContract.getParams.callAsync();
@ -74,9 +64,7 @@ blockchainTests('Configurable Parameters unit tests', env => {
expect(actual[4]).to.bignumber.eq(_params.cobbDouglasAlphaNumerator);
expect(actual[5]).to.bignumber.eq(_params.cobbDouglasAlphaDenominator);
expect(actual[6]).to.eq(_params.wethProxyAddress);
expect(actual[7]).to.eq(_params.ethVaultAddress);
expect(actual[8]).to.eq(_params.rewardVaultAddress);
expect(actual[9]).to.eq(_params.zrxVaultAddress);
expect(actual[7]).to.eq(_params.zrxVaultAddress);
return receipt;
}
@ -89,43 +77,6 @@ blockchainTests('Configurable Parameters unit tests', env => {
it('works if called by owner', async () => {
return setParamsAndAssertAsync({});
});
describe('WETH allowance', () => {
it('rescinds allowance for old vaults and grants unlimited allowance to new ones', async () => {
const [oldEthVaultAddress, oldRewardVaultAddress, newEthVaultAddress, newRewardVaultAddress] = _.times(
4,
() => randomAddress(),
);
await testContract.setVaultAddresses.awaitTransactionSuccessAsync(
oldEthVaultAddress,
oldRewardVaultAddress,
);
const { logs } = await setParamsAndAssertAsync({
ethVaultAddress: newEthVaultAddress,
rewardVaultAddress: newRewardVaultAddress,
});
const approveEvents = filterLogsToArguments<TestMixinParamsWETHApproveEventArgs>(
logs,
TestMixinParamsEvents.WETHApprove,
);
expect(approveEvents[0]).to.deep.eq({
spender: oldEthVaultAddress,
amount: constants.ZERO_AMOUNT,
});
expect(approveEvents[1]).to.deep.eq({
spender: newEthVaultAddress,
amount: constants.MAX_UINT256,
});
expect(approveEvents[2]).to.deep.eq({
spender: oldRewardVaultAddress,
amount: constants.ZERO_AMOUNT,
});
expect(approveEvents[3]).to.deep.eq({
spender: newRewardVaultAddress,
amount: constants.MAX_UINT256,
});
});
});
});
});
// tslint:enable:no-unnecessary-type-assertion

View File

@ -1,5 +1,5 @@
import { ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { blockchainTests, describe, expect, shortZip } from '@0x/contracts-test-utils';
import { blockchainTests, constants, describe, expect, shortZip } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
@ -46,8 +46,6 @@ blockchainTests.resets('Testing Rewards', env => {
minimumPoolStake: new BigNumber(2),
cobbDouglasAlphaNumerator: new BigNumber(1),
cobbDouglasAlphaDenominator: new BigNumber(6),
rewardVaultAddress: stakingApiWrapper.rewardVaultContract.address,
ethVaultAddress: stakingApiWrapper.ethVaultContract.address,
zrxVaultAddress: stakingApiWrapper.zrxVaultContract.address,
});
// setup stakers
@ -75,47 +73,47 @@ blockchainTests.resets('Testing Rewards', env => {
describe('Reward Simulation', () => {
interface EndBalances {
// staker 1
stakerRewardVaultBalance_1?: BigNumber;
stakerEthVaultBalance_1?: BigNumber;
stakerRewardBalance_1?: BigNumber;
stakerWethBalance_1?: BigNumber;
// staker 2
stakerRewardVaultBalance_2?: BigNumber;
stakerEthVaultBalance_2?: BigNumber;
stakerRewardBalance_2?: BigNumber;
stakerWethBalance_2?: BigNumber;
// operator
operatorEthVaultBalance?: BigNumber;
operatorWethBalance?: BigNumber;
// undivided balance in reward pool
poolRewardVaultBalance?: BigNumber;
membersRewardVaultBalance?: BigNumber;
poolRewardBalance?: BigNumber;
membersRewardBalance?: BigNumber;
}
const validateEndBalances = async (_expectedEndBalances: EndBalances): Promise<void> => {
const expectedEndBalances = {
// staker 1
stakerRewardVaultBalance_1:
_expectedEndBalances.stakerRewardVaultBalance_1 !== undefined
? _expectedEndBalances.stakerRewardVaultBalance_1
: ZERO,
stakerEthVaultBalance_1:
_expectedEndBalances.stakerEthVaultBalance_1 !== undefined
? _expectedEndBalances.stakerEthVaultBalance_1
: ZERO,
stakerRewardBalance_1:
_expectedEndBalances.stakerRewardBalance_1 !== undefined
? _expectedEndBalances.stakerRewardBalance_1
: constants.ZERO_AMOUNT,
stakerWethBalance_1:
_expectedEndBalances.stakerWethBalance_1 !== undefined
? _expectedEndBalances.stakerWethBalance_1
: constants.ZERO_AMOUNT,
// staker 2
stakerRewardVaultBalance_2:
_expectedEndBalances.stakerRewardVaultBalance_2 !== undefined
? _expectedEndBalances.stakerRewardVaultBalance_2
: ZERO,
stakerEthVaultBalance_2:
_expectedEndBalances.stakerEthVaultBalance_2 !== undefined
? _expectedEndBalances.stakerEthVaultBalance_2
: ZERO,
stakerRewardBalance_2:
_expectedEndBalances.stakerRewardBalance_2 !== undefined
? _expectedEndBalances.stakerRewardBalance_2
: constants.ZERO_AMOUNT,
stakerWethBalance_2:
_expectedEndBalances.stakerWethBalance_2 !== undefined
? _expectedEndBalances.stakerWethBalance_2
: constants.ZERO_AMOUNT,
// operator
operatorEthVaultBalance:
_expectedEndBalances.operatorEthVaultBalance !== undefined
? _expectedEndBalances.operatorEthVaultBalance
: ZERO,
operatorWethBalance:
_expectedEndBalances.operatorWethBalance !== undefined
? _expectedEndBalances.operatorWethBalance
: constants.ZERO_AMOUNT,
// undivided balance in reward pool
poolRewardVaultBalance:
_expectedEndBalances.poolRewardVaultBalance !== undefined
? _expectedEndBalances.poolRewardVaultBalance
: ZERO,
poolRewardBalance:
_expectedEndBalances.poolRewardBalance !== undefined
? _expectedEndBalances.poolRewardBalance
: constants.ZERO_AMOUNT,
};
const finalEndBalancesAsArray = await Promise.all([
// staker 1
@ -123,40 +121,40 @@ blockchainTests.resets('Testing Rewards', env => {
poolId,
stakers[0].getOwner(),
),
stakingApiWrapper.ethVaultContract.balanceOf.callAsync(stakers[0].getOwner()),
stakingApiWrapper.wethContract.balanceOf.callAsync(stakers[0].getOwner()),
// staker 2
stakingApiWrapper.stakingContract.computeRewardBalanceOfDelegator.callAsync(
poolId,
stakers[1].getOwner(),
),
stakingApiWrapper.ethVaultContract.balanceOf.callAsync(stakers[1].getOwner()),
stakingApiWrapper.wethContract.balanceOf.callAsync(stakers[1].getOwner()),
// operator
stakingApiWrapper.ethVaultContract.balanceOf.callAsync(poolOperator.getOwner()),
stakingApiWrapper.wethContract.balanceOf.callAsync(poolOperator.getOwner()),
// undivided balance in reward pool
stakingApiWrapper.rewardVaultContract.balanceOf.callAsync(poolId),
stakingApiWrapper.stakingContract.rewardsByPoolId.callAsync(poolId),
]);
expect(finalEndBalancesAsArray[0], 'stakerRewardVaultBalance_1').to.be.bignumber.equal(
expectedEndBalances.stakerRewardVaultBalance_1,
expect(finalEndBalancesAsArray[0], 'stakerRewardBalance_1').to.be.bignumber.equal(
expectedEndBalances.stakerRewardBalance_1,
);
expect(finalEndBalancesAsArray[1], 'stakerEthVaultBalance_1').to.be.bignumber.equal(
expectedEndBalances.stakerEthVaultBalance_1,
expect(finalEndBalancesAsArray[1], 'stakerWethBalance_1').to.be.bignumber.equal(
expectedEndBalances.stakerWethBalance_1,
);
expect(finalEndBalancesAsArray[2], 'stakerRewardVaultBalance_2').to.be.bignumber.equal(
expectedEndBalances.stakerRewardVaultBalance_2,
expect(finalEndBalancesAsArray[2], 'stakerRewardBalance_2').to.be.bignumber.equal(
expectedEndBalances.stakerRewardBalance_2,
);
expect(finalEndBalancesAsArray[3], 'stakerEthVaultBalance_2').to.be.bignumber.equal(
expectedEndBalances.stakerEthVaultBalance_2,
expect(finalEndBalancesAsArray[3], 'stakerWethBalance_2').to.be.bignumber.equal(
expectedEndBalances.stakerWethBalance_2,
);
expect(finalEndBalancesAsArray[4], 'operatorEthVaultBalance').to.be.bignumber.equal(
expectedEndBalances.operatorEthVaultBalance,
expect(finalEndBalancesAsArray[4], 'operatorWethBalance').to.be.bignumber.equal(
expectedEndBalances.operatorWethBalance,
);
expect(finalEndBalancesAsArray[5], 'poolRewardVaultBalance').to.be.bignumber.equal(
expectedEndBalances.poolRewardVaultBalance,
expect(finalEndBalancesAsArray[5], 'poolRewardBalance').to.be.bignumber.equal(
expectedEndBalances.poolRewardBalance,
);
};
const payProtocolFeeAndFinalize = async (_fee?: BigNumber) => {
const fee = _fee !== undefined ? _fee : ZERO;
if (!fee.eq(ZERO)) {
const fee = _fee !== undefined ? _fee : constants.ZERO_AMOUNT;
if (!fee.eq(constants.ZERO_AMOUNT)) {
await stakingApiWrapper.stakingContract.payProtocolFee.awaitTransactionSuccessAsync(
poolOperator.getOwner(),
takerAddress,
@ -166,7 +164,6 @@ blockchainTests.resets('Testing Rewards', env => {
}
await finalizer.finalizeAsync();
};
const ZERO = new BigNumber(0);
it('Reward balance should be zero if not delegated', async () => {
// sanity balances - all zero
await validateEndBalances({});
@ -193,7 +190,7 @@ blockchainTests.resets('Testing Rewards', env => {
await payProtocolFeeAndFinalize(reward);
// sanity check final balances - all zero
await validateEndBalances({
operatorEthVaultBalance: reward,
operatorWethBalance: reward,
});
});
it(`Operator should receive entire reward if no delegators in their pool
@ -206,7 +203,7 @@ blockchainTests.resets('Testing Rewards', env => {
await payProtocolFeeAndFinalize(reward);
// sanity check final balances
await validateEndBalances({
operatorEthVaultBalance: reward,
operatorWethBalance: reward,
});
});
it('Should give pool reward to delegator', async () => {
@ -220,9 +217,9 @@ blockchainTests.resets('Testing Rewards', env => {
await payProtocolFeeAndFinalize(reward);
// sanity check final balances
await validateEndBalances({
stakerRewardVaultBalance_1: reward,
poolRewardVaultBalance: reward,
membersRewardVaultBalance: reward,
stakerRewardBalance_1: reward,
poolRewardBalance: reward,
membersRewardBalance: reward,
});
});
it('Should split pool reward between delegators', async () => {
@ -239,10 +236,10 @@ blockchainTests.resets('Testing Rewards', env => {
await payProtocolFeeAndFinalize(reward);
// sanity check final balances
await validateEndBalances({
stakerRewardVaultBalance_1: reward.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
stakerRewardVaultBalance_2: reward.times(stakeAmounts[1]).dividedToIntegerBy(totalStakeAmount),
poolRewardVaultBalance: reward,
membersRewardVaultBalance: reward,
stakerRewardBalance_1: reward.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
stakerRewardBalance_2: reward.times(stakeAmounts[1]).dividedToIntegerBy(totalStakeAmount),
poolRewardBalance: reward,
membersRewardBalance: reward,
});
});
it('Should split pool reward between delegators, when they join in different epochs', async () => {
@ -276,10 +273,10 @@ blockchainTests.resets('Testing Rewards', env => {
await payProtocolFeeAndFinalize(reward);
// sanity check final balances
await validateEndBalances({
stakerRewardVaultBalance_1: reward.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
stakerRewardVaultBalance_2: reward.times(stakeAmounts[1]).dividedToIntegerBy(totalStakeAmount),
poolRewardVaultBalance: reward,
membersRewardVaultBalance: reward,
stakerRewardBalance_1: reward.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
stakerRewardBalance_2: reward.times(stakeAmounts[1]).dividedToIntegerBy(totalStakeAmount),
poolRewardBalance: reward,
membersRewardBalance: reward,
});
});
it('Should give pool reward to delegators only for the epoch during which they delegated', async () => {
@ -299,14 +296,14 @@ blockchainTests.resets('Testing Rewards', env => {
await payProtocolFeeAndFinalize(rewardForBothDelegators);
// sanity check final balances
await validateEndBalances({
stakerRewardVaultBalance_1: rewardForOnlyFirstDelegator.plus(
stakerRewardBalance_1: rewardForOnlyFirstDelegator.plus(
rewardForBothDelegators.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
),
stakerRewardVaultBalance_2: rewardForBothDelegators
stakerRewardBalance_2: rewardForBothDelegators
.times(stakeAmounts[1])
.dividedToIntegerBy(totalStakeAmount),
poolRewardVaultBalance: rewardForOnlyFirstDelegator.plus(rewardForBothDelegators),
membersRewardVaultBalance: rewardForOnlyFirstDelegator.plus(rewardForBothDelegators),
poolRewardBalance: rewardForOnlyFirstDelegator.plus(rewardForBothDelegators),
membersRewardBalance: rewardForOnlyFirstDelegator.plus(rewardForBothDelegators),
});
});
it('Should split pool reward between delegators, over several consecutive epochs', async () => {
@ -339,17 +336,15 @@ blockchainTests.resets('Testing Rewards', env => {
}
// sanity check final balances
await validateEndBalances({
stakerRewardVaultBalance_1: rewardForOnlyFirstDelegator.plus(
stakerRewardBalance_1: rewardForOnlyFirstDelegator.plus(
totalSharedRewards.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
),
stakerRewardVaultBalance_2: totalSharedRewards
.times(stakeAmounts[1])
.dividedToIntegerBy(totalStakeAmount),
poolRewardVaultBalance: rewardForOnlyFirstDelegator.plus(totalSharedRewards),
membersRewardVaultBalance: rewardForOnlyFirstDelegator.plus(totalSharedRewards),
stakerRewardBalance_2: totalSharedRewards.times(stakeAmounts[1]).dividedToIntegerBy(totalStakeAmount),
poolRewardBalance: rewardForOnlyFirstDelegator.plus(totalSharedRewards),
membersRewardBalance: rewardForOnlyFirstDelegator.plus(totalSharedRewards),
});
});
it('Should send existing rewards from reward vault to eth vault correctly when undelegating stake', async () => {
it('Should withdraw existing rewards when undelegating stake', async () => {
const stakeAmount = toBaseUnitAmount(4);
// first staker delegates (epoch 0)
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
@ -358,7 +353,7 @@ blockchainTests.resets('Testing Rewards', env => {
// earn reward
const reward = toBaseUnitAmount(10);
await payProtocolFeeAndFinalize(reward);
// undelegate (moves delegator's from the transient reward vault into the eth vault)
// undelegate (withdraws delegator's rewards)
await stakers[0].moveStakeAsync(
new StakeInfo(StakeStatus.Delegated, poolId),
new StakeInfo(StakeStatus.Active),
@ -366,11 +361,11 @@ blockchainTests.resets('Testing Rewards', env => {
);
// sanity check final balances
await validateEndBalances({
stakerRewardVaultBalance_1: ZERO,
stakerEthVaultBalance_1: reward,
stakerRewardBalance_1: constants.ZERO_AMOUNT,
stakerWethBalance_1: reward,
});
});
it('Should send existing rewards from reward vault to eth vault correctly when delegating more stake', async () => {
it('Should withdraw existing rewards correctly when delegating more stake', async () => {
const stakeAmount = toBaseUnitAmount(4);
// first staker delegates (epoch 0)
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
@ -383,8 +378,8 @@ blockchainTests.resets('Testing Rewards', env => {
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
// sanity check final balances
await validateEndBalances({
stakerRewardVaultBalance_1: ZERO,
stakerEthVaultBalance_1: reward,
stakerRewardBalance_1: constants.ZERO_AMOUNT,
stakerWethBalance_1: reward,
});
});
it('Should continue earning rewards after adding more stake and progressing several epochs', async () => {
@ -414,18 +409,18 @@ blockchainTests.resets('Testing Rewards', env => {
}
// sanity check final balances
await validateEndBalances({
stakerRewardVaultBalance_1: rewardBeforeAddingMoreStake.plus(
stakerRewardBalance_1: rewardBeforeAddingMoreStake.plus(
totalRewardsAfterAddingMoreStake
.times(stakeAmounts[0])
.dividedBy(totalStake)
.integerValue(BigNumber.ROUND_DOWN),
),
stakerRewardVaultBalance_2: totalRewardsAfterAddingMoreStake
stakerRewardBalance_2: totalRewardsAfterAddingMoreStake
.times(stakeAmounts[1])
.dividedBy(totalStake)
.integerValue(BigNumber.ROUND_DOWN),
poolRewardVaultBalance: rewardBeforeAddingMoreStake.plus(totalRewardsAfterAddingMoreStake),
membersRewardVaultBalance: rewardBeforeAddingMoreStake.plus(totalRewardsAfterAddingMoreStake),
poolRewardBalance: rewardBeforeAddingMoreStake.plus(totalRewardsAfterAddingMoreStake),
membersRewardBalance: rewardBeforeAddingMoreStake.plus(totalRewardsAfterAddingMoreStake),
});
});
it('Should stop collecting rewards after undelegating', async () => {
@ -453,8 +448,8 @@ blockchainTests.resets('Testing Rewards', env => {
// sanity check final balances
await validateEndBalances({
stakerEthVaultBalance_1: rewardForDelegator,
operatorEthVaultBalance: rewardNotForDelegator,
stakerWethBalance_1: rewardForDelegator,
operatorWethBalance: rewardNotForDelegator,
});
});
it('Should stop collecting rewards after undelegating, after several epochs', async () => {
@ -488,8 +483,8 @@ blockchainTests.resets('Testing Rewards', env => {
}
// sanity check final balances
await validateEndBalances({
stakerEthVaultBalance_1: rewardForDelegator,
operatorEthVaultBalance: totalRewardsNotForDelegator,
stakerWethBalance_1: rewardForDelegator,
operatorWethBalance: totalRewardsNotForDelegator,
});
});
it('Should collect fees correctly when leaving and returning to a pool', async () => {
@ -522,10 +517,10 @@ blockchainTests.resets('Testing Rewards', env => {
await payProtocolFeeAndFinalize(rewardsForDelegator[1]);
// sanity check final balances
await validateEndBalances({
stakerRewardVaultBalance_1: rewardsForDelegator[1],
stakerEthVaultBalance_1: rewardsForDelegator[0],
operatorEthVaultBalance: rewardNotForDelegator,
poolRewardVaultBalance: rewardsForDelegator[1],
stakerRewardBalance_1: rewardsForDelegator[1],
stakerWethBalance_1: rewardsForDelegator[0],
operatorWethBalance: rewardNotForDelegator,
poolRewardBalance: rewardsForDelegator[1],
});
});
it('Should collect fees correctly when re-delegating after un-delegating', async () => {
@ -559,13 +554,13 @@ blockchainTests.resets('Testing Rewards', env => {
);
// sanity check final balances
await validateEndBalances({
stakerRewardVaultBalance_1: ZERO,
stakerEthVaultBalance_1: rewardForDelegator,
operatorEthVaultBalance: ZERO,
poolRewardVaultBalance: ZERO,
stakerRewardBalance_1: constants.ZERO_AMOUNT,
stakerWethBalance_1: rewardForDelegator,
operatorWethBalance: constants.ZERO_AMOUNT,
poolRewardBalance: constants.ZERO_AMOUNT,
});
});
it('Should withdraw delegator rewards to eth vault when calling `syncDelegatorRewards`', async () => {
it('Should withdraw delegator rewards when calling `withdrawDelegatorRewards`', async () => {
// first staker delegates (epoch 0)
const rewardForDelegator = toBaseUnitAmount(10);
const stakeAmount = toBaseUnitAmount(4);
@ -579,15 +574,15 @@ blockchainTests.resets('Testing Rewards', env => {
await payProtocolFeeAndFinalize();
// this should go to the delegator
await payProtocolFeeAndFinalize(rewardForDelegator);
await stakingApiWrapper.stakingContract.syncDelegatorRewards.awaitTransactionSuccessAsync(poolId, {
await stakingApiWrapper.stakingContract.withdrawDelegatorRewards.awaitTransactionSuccessAsync(poolId, {
from: stakers[0].getOwner(),
});
// sanity check final balances
await validateEndBalances({
stakerRewardVaultBalance_1: ZERO,
stakerEthVaultBalance_1: rewardForDelegator,
operatorEthVaultBalance: ZERO,
poolRewardVaultBalance: ZERO,
stakerRewardBalance_1: constants.ZERO_AMOUNT,
stakerWethBalance_1: rewardForDelegator,
operatorWethBalance: constants.ZERO_AMOUNT,
poolRewardBalance: constants.ZERO_AMOUNT,
});
});
it(`payout should be based on stake at the time of rewards`, async () => {
@ -607,11 +602,11 @@ blockchainTests.resets('Testing Rewards', env => {
// finalize
const reward = toBaseUnitAmount(10);
await payProtocolFeeAndFinalize(reward);
// Sync rewards to move the rewards into the EthVault.
await staker.syncDelegatorRewardsAsync(poolId);
// withdraw rewards
await staker.withdrawDelegatorRewardsAsync(poolId);
await validateEndBalances({
stakerRewardVaultBalance_1: toBaseUnitAmount(0),
stakerEthVaultBalance_1: reward,
stakerRewardBalance_1: toBaseUnitAmount(0),
stakerWethBalance_1: reward,
});
});
it(`should split payout between two delegators when syncing rewards`, async () => {
@ -627,18 +622,18 @@ blockchainTests.resets('Testing Rewards', env => {
// finalize
const reward = toBaseUnitAmount(10);
await payProtocolFeeAndFinalize(reward);
// Sync rewards to move rewards from RewardVault into the EthVault.
// withdraw rewards
for (const [staker] of _.reverse(stakersAndStake)) {
await staker.syncDelegatorRewardsAsync(poolId);
await staker.withdrawDelegatorRewardsAsync(poolId);
}
const expectedStakerRewards = stakeAmounts.map(n => reward.times(n).dividedToIntegerBy(totalStakeAmount));
await validateEndBalances({
stakerRewardVaultBalance_1: toBaseUnitAmount(0),
stakerRewardVaultBalance_2: toBaseUnitAmount(0),
stakerEthVaultBalance_1: expectedStakerRewards[0],
stakerEthVaultBalance_2: expectedStakerRewards[1],
poolRewardVaultBalance: new BigNumber(1), // Rounding error
membersRewardVaultBalance: new BigNumber(1), // Rounding error
stakerRewardBalance_1: toBaseUnitAmount(0),
stakerRewardBalance_2: toBaseUnitAmount(0),
stakerWethBalance_1: expectedStakerRewards[0],
stakerWethBalance_2: expectedStakerRewards[1],
poolRewardBalance: new BigNumber(1), // Rounding error
membersRewardBalance: new BigNumber(1), // Rounding error
});
});
it(`delegator should not be credited payout twice by syncing rewards twice`, async () => {
@ -656,32 +651,30 @@ blockchainTests.resets('Testing Rewards', env => {
await payProtocolFeeAndFinalize(reward);
const expectedStakerRewards = stakeAmounts.map(n => reward.times(n).dividedToIntegerBy(totalStakeAmount));
await validateEndBalances({
stakerRewardVaultBalance_1: expectedStakerRewards[0],
stakerRewardVaultBalance_2: expectedStakerRewards[1],
stakerEthVaultBalance_1: toBaseUnitAmount(0),
stakerEthVaultBalance_2: toBaseUnitAmount(0),
poolRewardVaultBalance: reward,
membersRewardVaultBalance: reward,
stakerRewardBalance_1: expectedStakerRewards[0],
stakerRewardBalance_2: expectedStakerRewards[1],
stakerWethBalance_1: toBaseUnitAmount(0),
stakerWethBalance_2: toBaseUnitAmount(0),
poolRewardBalance: reward,
membersRewardBalance: reward,
});
// First staker will sync rewards to get rewards transferred to EthVault.
// First staker will withdraw rewards.
const sneakyStaker = stakers[0];
const sneakyStakerExpectedEthVaultBalance = expectedStakerRewards[0];
await sneakyStaker.syncDelegatorRewardsAsync(poolId);
const sneakyStakerExpectedWethBalance = expectedStakerRewards[0];
await sneakyStaker.withdrawDelegatorRewardsAsync(poolId);
// Should have been credited the correct amount of rewards.
let sneakyStakerEthVaultBalance = await stakingApiWrapper.ethVaultContract.balanceOf.callAsync(
let sneakyStakerWethBalance = await stakingApiWrapper.wethContract.balanceOf.callAsync(
sneakyStaker.getOwner(),
);
expect(sneakyStakerEthVaultBalance, 'EthVault balance after first undelegate').to.bignumber.eq(
sneakyStakerExpectedEthVaultBalance,
expect(sneakyStakerWethBalance, 'WETH balance after first undelegate').to.bignumber.eq(
sneakyStakerExpectedWethBalance,
);
// Now he'll try to do it again to see if he gets credited twice.
await sneakyStaker.syncDelegatorRewardsAsync(poolId);
await sneakyStaker.withdrawDelegatorRewardsAsync(poolId);
/// The total amount credited should remain the same.
sneakyStakerEthVaultBalance = await stakingApiWrapper.ethVaultContract.balanceOf.callAsync(
sneakyStaker.getOwner(),
);
expect(sneakyStakerEthVaultBalance, 'EthVault balance after second undelegate').to.bignumber.eq(
sneakyStakerExpectedEthVaultBalance,
sneakyStakerWethBalance = await stakingApiWrapper.wethContract.balanceOf.callAsync(sneakyStaker.getOwner());
expect(sneakyStakerWethBalance, 'WETH balance after second undelegate').to.bignumber.eq(
sneakyStakerExpectedWethBalance,
);
});
});

View File

@ -1,19 +0,0 @@
import { blockchainTests, expect } from '@0x/contracts-test-utils';
import { artifacts, TestStorageLayoutContract } from '../src';
blockchainTests.resets('Storage layout tests', env => {
let testStorageLayoutContract: TestStorageLayoutContract;
before(async () => {
testStorageLayoutContract = await TestStorageLayoutContract.deployFrom0xArtifactAsync(
artifacts.TestStorageLayout,
env.provider,
env.txDefaults,
{},
);
});
it('should have the correct storage slots', async () => {
return expect(testStorageLayoutContract.assertExpectedStorageLayout.callAsync()).to.be.fulfilled('');
});
});

View File

@ -16,8 +16,7 @@ import {
artifacts,
TestDelegatorRewardsContract,
TestDelegatorRewardsEvents,
TestDelegatorRewardsRecordDepositToEthVaultEventArgs as EthVaultDepositEventArgs,
TestDelegatorRewardsRecordDepositToRewardVaultEventArgs as RewardVaultDepositEventArgs,
TestDelegatorRewardsTransferEventArgs,
} from '../../src';
import {
@ -57,7 +56,7 @@ blockchainTests.resets('delegator unit rewards', env => {
};
// Generate a deterministic operator address based on the poolId.
_opts.operator = poolIdToOperator(_opts.poolId);
await testContract.depositStakingPoolRewards.awaitTransactionSuccessAsync(
await testContract.syncPoolRewards.awaitTransactionSuccessAsync(
_opts.poolId,
_opts.operator,
new BigNumber(_opts.operatorReward),
@ -123,9 +122,8 @@ blockchainTests.resets('delegator unit rewards', env => {
return [_operatorReward, _membersReward];
}
type ResultWithDeposits<T extends {}> = T & {
ethVaultDeposit: BigNumber;
rewardVaultDeposit: BigNumber;
type ResultWithTransfers<T extends {}> = T & {
delegatorTransfers: BigNumber;
};
interface DelegateStakeOpts {
@ -136,7 +134,7 @@ blockchainTests.resets('delegator unit rewards', env => {
async function delegateStakeNowAsync(
poolId: string,
opts?: Partial<DelegateStakeOpts>,
): Promise<ResultWithDeposits<DelegateStakeOpts>> {
): Promise<ResultWithTransfers<DelegateStakeOpts>> {
return delegateStakeAsync(poolId, opts, true);
}
@ -144,7 +142,7 @@ blockchainTests.resets('delegator unit rewards', env => {
poolId: string,
opts?: Partial<DelegateStakeOpts>,
now?: boolean,
): Promise<ResultWithDeposits<DelegateStakeOpts>> {
): Promise<ResultWithTransfers<DelegateStakeOpts>> {
const _opts = {
delegator: randomAddress(),
stake: getRandomInteger(1, toBaseUnitAmount(10)),
@ -152,11 +150,10 @@ blockchainTests.resets('delegator unit rewards', env => {
};
const fn = now ? testContract.delegateStakeNow : testContract.delegateStake;
const receipt = await fn.awaitTransactionSuccessAsync(_opts.delegator, poolId, new BigNumber(_opts.stake));
const [ethVaultDeposit, rewardVaultDeposit] = getDepositsFromLogs(receipt.logs, poolId, _opts.delegator);
const delegatorTransfers = getTransfersFromLogs(receipt.logs, _opts.delegator);
return {
..._opts,
ethVaultDeposit,
rewardVaultDeposit,
delegatorTransfers,
};
}
@ -164,42 +161,31 @@ blockchainTests.resets('delegator unit rewards', env => {
poolId: string,
delegator: string,
stake?: Numberish,
): Promise<ResultWithDeposits<{ stake: BigNumber }>> {
): Promise<ResultWithTransfers<{ stake: BigNumber }>> {
const _stake = new BigNumber(
stake ||
(await testContract.getStakeDelegatedToPoolByOwner.callAsync(delegator, poolId)).currentEpochBalance,
);
const receipt = await testContract.undelegateStake.awaitTransactionSuccessAsync(delegator, poolId, _stake);
const [ethVaultDeposit, rewardVaultDeposit] = getDepositsFromLogs(receipt.logs, poolId, delegator);
const delegatorTransfers = getTransfersFromLogs(receipt.logs, delegator);
return {
stake: _stake,
ethVaultDeposit,
rewardVaultDeposit,
delegatorTransfers,
};
}
function getDepositsFromLogs(logs: LogEntry[], poolId: string, delegator?: string): [BigNumber, BigNumber] {
let ethVaultDeposit = constants.ZERO_AMOUNT;
let rewardVaultDeposit = constants.ZERO_AMOUNT;
const ethVaultDepositArgs = filterLogsToArguments<EthVaultDepositEventArgs>(
function getTransfersFromLogs(logs: LogEntry[], delegator?: string): BigNumber {
let delegatorTransfers = constants.ZERO_AMOUNT;
const transferArgs = filterLogsToArguments<TestDelegatorRewardsTransferEventArgs>(
logs,
TestDelegatorRewardsEvents.RecordDepositToEthVault,
TestDelegatorRewardsEvents.Transfer,
);
for (const event of ethVaultDepositArgs) {
if (event.owner === delegator) {
ethVaultDeposit = ethVaultDeposit.plus(event.amount);
for (const event of transferArgs) {
if (event._to === delegator) {
delegatorTransfers = delegatorTransfers.plus(event._value);
}
}
const rewardVaultDepositArgs = filterLogsToArguments<RewardVaultDepositEventArgs>(
logs,
TestDelegatorRewardsEvents.RecordDepositToRewardVault,
);
if (rewardVaultDepositArgs.length > 0) {
expect(rewardVaultDepositArgs.length).to.eq(1);
expect(rewardVaultDepositArgs[0].poolId).to.eq(poolId);
rewardVaultDeposit = rewardVaultDepositArgs[0].amount;
}
return [ethVaultDeposit, rewardVaultDeposit];
return delegatorTransfers;
}
async function advanceEpochAsync(): Promise<number> {
@ -216,16 +202,15 @@ blockchainTests.resets('delegator unit rewards', env => {
return testContract.computeRewardBalanceOfOperator.callAsync(poolId);
}
async function touchStakeAsync(poolId: string, delegator: string): Promise<ResultWithDeposits<{}>> {
async function touchStakeAsync(poolId: string, delegator: string): Promise<ResultWithTransfers<{}>> {
return undelegateStakeAsync(poolId, delegator, 0);
}
async function finalizePoolAsync(poolId: string): Promise<ResultWithDeposits<{}>> {
async function finalizePoolAsync(poolId: string): Promise<ResultWithTransfers<{}>> {
const receipt = await testContract.originalFinalizePool.awaitTransactionSuccessAsync(poolId);
const [ethVaultDeposit, rewardVaultDeposit] = getDepositsFromLogs(receipt.logs, poolId);
const delegatorTransfers = getTransfersFromLogs(receipt.logs, poolId);
return {
ethVaultDeposit,
rewardVaultDeposit,
delegatorTransfers,
};
}
@ -384,8 +369,8 @@ blockchainTests.resets('delegator unit rewards', env => {
await advanceEpochAsync(); // epoch 2
// rewards paid for stake in epoch 1.
const { membersReward: reward } = await rewardPoolAsync({ poolId, membersStake: stake });
const { ethVaultDeposit: deposit } = await undelegateStakeAsync(poolId, delegator);
assertRoughlyEquals(deposit, reward);
const { delegatorTransfers: withdrawal } = await undelegateStakeAsync(poolId, delegator);
assertRoughlyEquals(withdrawal, reward);
const delegatorReward = await getDelegatorRewardBalanceAsync(poolId, delegator);
expect(delegatorReward).to.bignumber.eq(0);
});
@ -397,8 +382,8 @@ blockchainTests.resets('delegator unit rewards', env => {
await advanceEpochAsync(); // epoch 2
// rewards paid for stake in epoch 1.
const { membersReward: reward } = await rewardPoolAsync({ poolId, membersStake: stake });
const { ethVaultDeposit: deposit } = await undelegateStakeAsync(poolId, delegator);
assertRoughlyEquals(deposit, reward);
const { delegatorTransfers: withdrawal } = await undelegateStakeAsync(poolId, delegator);
assertRoughlyEquals(withdrawal, reward);
await delegateStakeAsync(poolId, { delegator, stake });
const delegatorReward = await getDelegatorRewardBalanceAsync(poolId, delegator);
expect(delegatorReward).to.bignumber.eq(0);
@ -448,7 +433,7 @@ blockchainTests.resets('delegator unit rewards', env => {
// Pay rewards for epoch 1.
const { membersReward: reward1 } = await rewardPoolAsync({ poolId, membersStake: rewardStake });
// add extra stake
const { ethVaultDeposit: deposit } = await delegateStakeAsync(poolId, { delegator, stake: stake2 });
const { delegatorTransfers: withdrawal } = await delegateStakeAsync(poolId, { delegator, stake: stake2 });
await advanceEpochAsync(); // epoch 3 (stake2 now active)
// Pay rewards for epoch 2.
await advanceEpochAsync(); // epoch 4
@ -459,7 +444,7 @@ blockchainTests.resets('delegator unit rewards', env => {
computeDelegatorRewards(reward1, stake1, rewardStake),
computeDelegatorRewards(reward2, totalStake, rewardStake),
);
assertRoughlyEquals(BigNumber.sum(deposit, delegatorReward), expectedDelegatorReward);
assertRoughlyEquals(BigNumber.sum(withdrawal, delegatorReward), expectedDelegatorReward);
});
it('uses old stake for rewards paid in the epoch right after extra stake is added', async () => {
@ -666,16 +651,16 @@ blockchainTests.resets('delegator unit rewards', env => {
});
describe('reward transfers', async () => {
it('transfers all rewards to eth vault when touching stake', async () => {
it('transfers all rewards to delegator when touching stake', async () => {
const poolId = hexRandom();
const { delegator, stake } = await delegateStakeAsync(poolId);
await advanceEpochAsync(); // epoch 1 (stake now active)
await advanceEpochAsync(); // epoch 2
// rewards paid for stake in epoch 1
const { membersReward: reward } = await rewardPoolAsync({ poolId, membersStake: stake });
const { ethVaultDeposit: deposit } = await touchStakeAsync(poolId, delegator);
const { delegatorTransfers: withdrawal } = await touchStakeAsync(poolId, delegator);
const finalRewardBalance = await getDelegatorRewardBalanceAsync(poolId, delegator);
expect(deposit).to.bignumber.eq(reward);
expect(withdrawal).to.bignumber.eq(reward);
expect(finalRewardBalance).to.bignumber.eq(0);
});
@ -697,7 +682,7 @@ blockchainTests.resets('delegator unit rewards', env => {
// touch the stake one last time
stakeResults.push(await touchStakeAsync(poolId, delegator));
// Should only see deposits for epoch 2.
const allDeposits = stakeResults.map(r => r.ethVaultDeposit);
const allDeposits = stakeResults.map(r => r.delegatorTransfers);
const expectedReward = computeDelegatorRewards(reward, stake, rewardStake);
assertRoughlyEquals(BigNumber.sum(...allDeposits), expectedReward);
});
@ -725,7 +710,7 @@ blockchainTests.resets('delegator unit rewards', env => {
const { membersReward: reward2 } = await rewardPoolAsync({ poolId, membersStake: rewardStake });
// touch the stake to claim rewards
stakeResults.push(await touchStakeAsync(poolId, delegator));
const allDeposits = stakeResults.map(r => r.ethVaultDeposit);
const allDeposits = stakeResults.map(r => r.delegatorTransfers);
const expectedReward = BigNumber.sum(
computeDelegatorRewards(reward1, stake, rewardStake),
computeDelegatorRewards(reward2, new BigNumber(stake).minus(unstake), rewardStake),
@ -743,11 +728,11 @@ blockchainTests.resets('delegator unit rewards', env => {
// rewards paid for stake in epoch 1
const { membersReward: reward } = await rewardPoolAsync({ poolId, membersStake: totalStake });
// delegator A will finalize and collect rewards by touching stake.
const { ethVaultDeposit: depositA } = await touchStakeAsync(poolId, delegatorA);
assertRoughlyEquals(depositA, computeDelegatorRewards(reward, stakeA, totalStake));
const { delegatorTransfers: withdrawalA } = await touchStakeAsync(poolId, delegatorA);
assertRoughlyEquals(withdrawalA, computeDelegatorRewards(reward, stakeA, totalStake));
// delegator B will collect rewards by touching stake
const { ethVaultDeposit: depositB } = await touchStakeAsync(poolId, delegatorB);
assertRoughlyEquals(depositB, computeDelegatorRewards(reward, stakeB, totalStake));
const { delegatorTransfers: withdrawalB } = await touchStakeAsync(poolId, delegatorB);
assertRoughlyEquals(withdrawalB, computeDelegatorRewards(reward, stakeB, totalStake));
});
it('delegator B collects correct rewards after delegator A finalizes', async () => {
@ -767,11 +752,11 @@ blockchainTests.resets('delegator unit rewards', env => {
});
const totalRewards = BigNumber.sum(prevReward, unfinalizedReward);
// delegator A will finalize and collect rewards by touching stake.
const { ethVaultDeposit: depositA } = await touchStakeAsync(poolId, delegatorA);
assertRoughlyEquals(depositA, computeDelegatorRewards(totalRewards, stakeA, totalStake));
const { delegatorTransfers: withdrawalA } = await touchStakeAsync(poolId, delegatorA);
assertRoughlyEquals(withdrawalA, computeDelegatorRewards(totalRewards, stakeA, totalStake));
// delegator B will collect rewards by touching stake
const { ethVaultDeposit: depositB } = await touchStakeAsync(poolId, delegatorB);
assertRoughlyEquals(depositB, computeDelegatorRewards(totalRewards, stakeB, totalStake));
const { delegatorTransfers: withdrawalB } = await touchStakeAsync(poolId, delegatorB);
assertRoughlyEquals(withdrawalB, computeDelegatorRewards(totalRewards, stakeB, totalStake));
});
it('delegator A and B collect correct rewards after external finalization', async () => {
@ -793,11 +778,11 @@ blockchainTests.resets('delegator unit rewards', env => {
// finalize
await finalizePoolAsync(poolId);
// delegator A will collect rewards by touching stake.
const { ethVaultDeposit: depositA } = await touchStakeAsync(poolId, delegatorA);
assertRoughlyEquals(depositA, computeDelegatorRewards(totalRewards, stakeA, totalStake));
const { delegatorTransfers: withdrawalA } = await touchStakeAsync(poolId, delegatorA);
assertRoughlyEquals(withdrawalA, computeDelegatorRewards(totalRewards, stakeA, totalStake));
// delegator B will collect rewards by touching stake
const { ethVaultDeposit: depositB } = await touchStakeAsync(poolId, delegatorB);
assertRoughlyEquals(depositB, computeDelegatorRewards(totalRewards, stakeB, totalStake));
const { delegatorTransfers: withdrawalB } = await touchStakeAsync(poolId, delegatorB);
assertRoughlyEquals(withdrawalB, computeDelegatorRewards(totalRewards, stakeB, totalStake));
});
});
});

View File

@ -8,11 +8,9 @@ import * as _ from 'lodash';
import {
artifacts,
EthVaultContract,
IStakingEventsEpochEndedEventArgs,
IStakingEventsStakingPoolActivatedEventArgs,
ReadOnlyProxyContract,
StakingPoolRewardVaultContract,
StakingProxyContract,
TestCobbDouglasContract,
TestStakingContract,
@ -31,8 +29,6 @@ export class StakingApiWrapper {
// The StakingProxy.sol contract as a StakingProxyContract
public stakingProxyContract: StakingProxyContract;
public zrxVaultContract: ZrxVaultContract;
public ethVaultContract: EthVaultContract;
public rewardVaultContract: StakingPoolRewardVaultContract;
public zrxTokenContract: DummyERC20TokenContract;
public wethContract: WETH9Contract;
public cobbDouglasContract: TestCobbDouglasContract;
@ -122,8 +118,6 @@ export class StakingApiWrapper {
new BigNumber(_params.cobbDouglasAlphaNumerator),
new BigNumber(_params.cobbDouglasAlphaDenominator),
_params.wethProxyAddress,
_params.ethVaultAddress,
_params.rewardVaultAddress,
_params.zrxVaultAddress,
);
},
@ -144,8 +138,6 @@ export class StakingApiWrapper {
'cobbDouglasAlphaNumerator',
'cobbDouglasAlphaDenominator',
'wethProxyAddress',
'ethVaultAddress',
'rewardVaultAddress',
'zrxVaultAddress',
],
await this.stakingContract.getParams.callAsync(),
@ -180,16 +172,12 @@ export class StakingApiWrapper {
stakingProxyContract: StakingProxyContract,
stakingContract: TestStakingContract,
zrxVaultContract: ZrxVaultContract,
ethVaultContract: EthVaultContract,
rewardVaultContract: StakingPoolRewardVaultContract,
zrxTokenContract: DummyERC20TokenContract,
wethContract: WETH9Contract,
cobbDouglasContract: TestCobbDouglasContract,
) {
this._web3Wrapper = env.web3Wrapper;
this.zrxVaultContract = zrxVaultContract;
this.ethVaultContract = ethVaultContract;
this.rewardVaultContract = rewardVaultContract;
this.zrxTokenContract = zrxTokenContract;
this.wethContract = wethContract;
this.cobbDouglasContract = cobbDouglasContract;
@ -253,22 +241,6 @@ export async function deployAndConfigureContractsAsync(
env.txDefaults,
artifacts,
);
// deploy eth vault
const ethVaultContract = await EthVaultContract.deployFrom0xArtifactAsync(
artifacts.EthVault,
env.provider,
env.txDefaults,
artifacts,
wethContract.address,
);
// deploy reward vault
const rewardVaultContract = await StakingPoolRewardVaultContract.deployFrom0xArtifactAsync(
artifacts.StakingPoolRewardVault,
env.provider,
env.txDefaults,
artifacts,
wethContract.address,
);
// deploy zrx vault
const zrxVaultContract = await ZrxVaultContract.deployFrom0xArtifactAsync(
artifacts.ZrxVault,
@ -287,8 +259,6 @@ export async function deployAndConfigureContractsAsync(
stakingContract.address,
readOnlyProxyContract.address,
erc20ProxyContract.address,
ethVaultContract.address,
rewardVaultContract.address,
zrxVaultContract.address,
);
// deploy cobb douglas contract
@ -303,18 +273,12 @@ export async function deployAndConfigureContractsAsync(
await erc20ProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync(zrxVaultContract.address);
// set staking proxy contract in zrx vault
await zrxVaultContract.setStakingProxy.awaitTransactionSuccessAsync(stakingProxyContract.address);
// set staking proxy contract in reward vault
await rewardVaultContract.setStakingProxy.awaitTransactionSuccessAsync(stakingProxyContract.address);
// set staking proxy contract in eth vault
await ethVaultContract.setStakingProxy.awaitTransactionSuccessAsync(stakingProxyContract.address);
return new StakingApiWrapper(
env,
ownerAddress,
stakingProxyContract,
stakingContract,
zrxVaultContract,
ethVaultContract,
rewardVaultContract,
zrxTokenContract,
wethContract,
cobbDouglasContract,

View File

@ -18,8 +18,6 @@ export const constants = {
cobbDouglasAlphaNumerator: new BigNumber(1),
cobbDouglasAlphaDenominator: new BigNumber(2),
wethProxyAddress: randomAddress(),
ethVaultAddress: randomAddress(),
rewardVaultAddress: randomAddress(),
zrxVaultAddress: randomAddress(),
},
PPM,

View File

@ -111,8 +111,6 @@ export class CumulativeRewardTrackingSimulation {
this.getTestCumulativeRewardTrackingContract().address,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
constants.NULL_ADDRESS,
);
const testLogs = await this._executeActionsAsync(testActions);
CumulativeRewardTrackingSimulation._assertTestLogs(expectedTestLogs, testLogs);

View File

@ -12,8 +12,6 @@ export interface StakingParams {
cobbDouglasAlphaNumerator: Numberish;
cobbDouglasAlphaDenominator: Numberish;
wethProxyAddress: string;
ethVaultAddress: string;
rewardVaultAddress: string;
zrxVaultAddress: string;
}
@ -103,7 +101,7 @@ export interface StakeBalances {
totalDelegatedStakeByPool: StakeBalanceByPool;
}
export interface RewardVaultBalanceByPoolId {
export interface RewardBalanceByPoolId {
[key: string]: BigNumber;
}

View File

@ -3,11 +3,8 @@
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
"files": [
"generated-artifacts/EthVault.json",
"generated-artifacts/IEthVault.json",
"generated-artifacts/IStaking.json",
"generated-artifacts/IStakingEvents.json",
"generated-artifacts/IStakingPoolRewardVault.json",
"generated-artifacts/IStakingProxy.json",
"generated-artifacts/IStorage.json",
"generated-artifacts/IStorageInit.json",
@ -40,7 +37,6 @@
"generated-artifacts/MixinVaultCore.json",
"generated-artifacts/ReadOnlyProxy.json",
"generated-artifacts/Staking.json",
"generated-artifacts/StakingPoolRewardVault.json",
"generated-artifacts/StakingProxy.json",
"generated-artifacts/TestAssertStorageParams.json",
"generated-artifacts/TestCobbDouglas.json",
@ -52,13 +48,11 @@
"generated-artifacts/TestLibProxy.json",
"generated-artifacts/TestLibProxyReceiver.json",
"generated-artifacts/TestLibSafeDowncast.json",
"generated-artifacts/TestMixinParams.json",
"generated-artifacts/TestMixinVaultCore.json",
"generated-artifacts/TestProtocolFees.json",
"generated-artifacts/TestStaking.json",
"generated-artifacts/TestStakingNoWETH.json",
"generated-artifacts/TestStakingProxy.json",
"generated-artifacts/TestStorageLayout.json",
"generated-artifacts/ZrxVault.json"
],
"exclude": ["./deploy/solc/solc_bin"]

View File

@ -25,8 +25,6 @@ export enum InvalidParamValueErrorCode {
InvalidMaximumMakersInPool,
InvalidMinimumPoolStake,
InvalidWethProxyAddress,
InvalidEthVaultAddress,
InvalidRewardVaultAddress,
InvalidZrxVaultAddress,
InvalidEpochDuration,
}
@ -190,18 +188,6 @@ export class InvalidParamValueError extends RevertError {
}
}
export class EthVaultNotSetError extends RevertError {
constructor() {
super('EthVaultNotSetError', 'EthVaultNotSetError()');
}
}
export class RewardVaultNotSetError extends RevertError {
constructor() {
super('RewardVaultNotSetError', 'RewardVaultNotSetError()');
}
}
export class InvalidStakeStatusError extends RevertError {
constructor(status?: BigNumber) {
super('InvalidStakeStatusError', 'InvalidStakeStatusError(uint256 status)', { status });
@ -247,7 +233,6 @@ export class PreviousEpochNotFinalizedError extends RevertError {
const types = [
AmountExceedsBalanceOfPoolError,
BlockTimestampTooLowError,
EthVaultNotSetError,
ExchangeAddressAlreadyRegisteredError,
ExchangeAddressNotRegisteredError,
InitializationError,
@ -267,7 +252,6 @@ const types = [
PoolExistenceError,
PreviousEpochNotFinalizedError,
ProxyDestinationCannotBeNilError,
RewardVaultNotSetError,
WithdrawAmountExceedsMemberBalanceError,
];