Merge pull request #2186 from 0xProject/feat/3.0/delete-vaults
Delete `StakingPoolRewardVault` and `EthVault`
This commit is contained in:
commit
2587cd380f
@ -32,7 +32,6 @@ contract Staking is
|
|||||||
IStakingEvents,
|
IStakingEvents,
|
||||||
MixinAbstract,
|
MixinAbstract,
|
||||||
MixinConstants,
|
MixinConstants,
|
||||||
MixinDeploymentConstants,
|
|
||||||
Ownable,
|
Ownable,
|
||||||
MixinStorage,
|
MixinStorage,
|
||||||
MixinStakingPoolModifiers,
|
MixinStakingPoolModifiers,
|
||||||
@ -60,13 +59,9 @@ contract Staking is
|
|||||||
/// This function should not be called directly.
|
/// This function should not be called directly.
|
||||||
/// The StakingProxy contract will call it in `attachStakingContract()`.
|
/// The StakingProxy contract will call it in `attachStakingContract()`.
|
||||||
/// @param _wethProxyAddress The address that can transfer WETH for fees.
|
/// @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.
|
/// @param _zrxVaultAddress Address of the ZrxVault contract.
|
||||||
function init(
|
function init(
|
||||||
address _wethProxyAddress,
|
address _wethProxyAddress,
|
||||||
address _ethVaultAddress,
|
|
||||||
address payable _rewardVaultAddress,
|
|
||||||
address _zrxVaultAddress
|
address _zrxVaultAddress
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
@ -77,8 +72,6 @@ contract Staking is
|
|||||||
_initMixinScheduler();
|
_initMixinScheduler();
|
||||||
_initMixinParams(
|
_initMixinParams(
|
||||||
_wethProxyAddress,
|
_wethProxyAddress,
|
||||||
_ethVaultAddress,
|
|
||||||
_rewardVaultAddress,
|
|
||||||
_zrxVaultAddress
|
_zrxVaultAddress
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -37,15 +37,11 @@ contract StakingProxy is
|
|||||||
/// @param _stakingContract Staking contract to delegate calls to.
|
/// @param _stakingContract Staking contract to delegate calls to.
|
||||||
/// @param _readOnlyProxy The address of the read only proxy.
|
/// @param _readOnlyProxy The address of the read only proxy.
|
||||||
/// @param _wethProxyAddress The address that can transfer WETH for fees.
|
/// @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.
|
/// @param _zrxVaultAddress Address of the ZrxVault contract.
|
||||||
constructor(
|
constructor(
|
||||||
address _stakingContract,
|
address _stakingContract,
|
||||||
address _readOnlyProxy,
|
address _readOnlyProxy,
|
||||||
address _wethProxyAddress,
|
address _wethProxyAddress,
|
||||||
address _ethVaultAddress,
|
|
||||||
address _rewardVaultAddress,
|
|
||||||
address _zrxVaultAddress
|
address _zrxVaultAddress
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
@ -55,8 +51,6 @@ contract StakingProxy is
|
|||||||
_attachStakingContract(
|
_attachStakingContract(
|
||||||
_stakingContract,
|
_stakingContract,
|
||||||
_wethProxyAddress,
|
_wethProxyAddress,
|
||||||
_ethVaultAddress,
|
|
||||||
_rewardVaultAddress,
|
|
||||||
_zrxVaultAddress
|
_zrxVaultAddress
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -78,17 +72,11 @@ contract StakingProxy is
|
|||||||
/// @param _stakingContract Address of staking contract.
|
/// @param _stakingContract Address of staking contract.
|
||||||
/// @param _wethProxyAddress The address that can transfer WETH for fees.
|
/// @param _wethProxyAddress The address that can transfer WETH for fees.
|
||||||
/// Use address in storage if NIL_ADDRESS is passed in.
|
/// 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.
|
/// @param _zrxVaultAddress Address of the ZrxVault contract.
|
||||||
/// Use address in storage if NIL_ADDRESS is passed in.
|
/// Use address in storage if NIL_ADDRESS is passed in.
|
||||||
function attachStakingContract(
|
function attachStakingContract(
|
||||||
address _stakingContract,
|
address _stakingContract,
|
||||||
address _wethProxyAddress,
|
address _wethProxyAddress,
|
||||||
address _ethVaultAddress,
|
|
||||||
address _rewardVaultAddress,
|
|
||||||
address _zrxVaultAddress
|
address _zrxVaultAddress
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
@ -97,8 +85,6 @@ contract StakingProxy is
|
|||||||
_attachStakingContract(
|
_attachStakingContract(
|
||||||
_stakingContract,
|
_stakingContract,
|
||||||
_wethProxyAddress == NIL_ADDRESS ? address(wethAssetProxy) : _wethProxyAddress,
|
_wethProxyAddress == NIL_ADDRESS ? address(wethAssetProxy) : _wethProxyAddress,
|
||||||
_ethVaultAddress == NIL_ADDRESS ? address(ethVault) : _ethVaultAddress,
|
|
||||||
_rewardVaultAddress == NIL_ADDRESS ? address(rewardVault) : _rewardVaultAddress,
|
|
||||||
_zrxVaultAddress == NIL_ADDRESS ? address(zrxVault) : _zrxVaultAddress
|
_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) {
|
if (address(zrxVault) == NIL_ADDRESS) {
|
||||||
LibRichErrors.rrevert(
|
LibRichErrors.rrevert(
|
||||||
LibStakingRichErrors.InvalidParamValueError(
|
LibStakingRichErrors.InvalidParamValueError(
|
||||||
@ -250,14 +222,10 @@ contract StakingProxy is
|
|||||||
/// @dev Attach a staking contract; future calls will be delegated to the staking contract.
|
/// @dev Attach a staking contract; future calls will be delegated to the staking contract.
|
||||||
/// @param _stakingContract Address of staking contract.
|
/// @param _stakingContract Address of staking contract.
|
||||||
/// @param _wethProxyAddress The address that can transfer WETH for fees.
|
/// @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.
|
/// @param _zrxVaultAddress Address of the ZrxVault contract.
|
||||||
function _attachStakingContract(
|
function _attachStakingContract(
|
||||||
address _stakingContract,
|
address _stakingContract,
|
||||||
address _wethProxyAddress,
|
address _wethProxyAddress,
|
||||||
address _ethVaultAddress,
|
|
||||||
address _rewardVaultAddress,
|
|
||||||
address _zrxVaultAddress
|
address _zrxVaultAddress
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
@ -271,8 +239,6 @@ contract StakingProxy is
|
|||||||
abi.encodeWithSelector(
|
abi.encodeWithSelector(
|
||||||
IStorageInit(0).init.selector,
|
IStorageInit(0).init.selector,
|
||||||
_wethProxyAddress,
|
_wethProxyAddress,
|
||||||
_ethVaultAddress,
|
|
||||||
_rewardVaultAddress,
|
|
||||||
_zrxVaultAddress
|
_zrxVaultAddress
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -25,7 +25,6 @@ import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
|||||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||||
import "../libs/LibStakingRichErrors.sol";
|
import "../libs/LibStakingRichErrors.sol";
|
||||||
import "../libs/LibCobbDouglas.sol";
|
import "../libs/LibCobbDouglas.sol";
|
||||||
import "../immutable/MixinDeploymentConstants.sol";
|
|
||||||
import "../interfaces/IStructs.sol";
|
import "../interfaces/IStructs.sol";
|
||||||
import "../stake/MixinStakeBalances.sol";
|
import "../stake/MixinStakeBalances.sol";
|
||||||
import "../sys/MixinFinalizer.sol";
|
import "../sys/MixinFinalizer.sol";
|
||||||
@ -37,7 +36,6 @@ contract MixinExchangeFees is
|
|||||||
IStakingEvents,
|
IStakingEvents,
|
||||||
MixinAbstract,
|
MixinAbstract,
|
||||||
MixinConstants,
|
MixinConstants,
|
||||||
MixinDeploymentConstants,
|
|
||||||
Ownable,
|
Ownable,
|
||||||
MixinStorage,
|
MixinStorage,
|
||||||
MixinStakingPoolModifiers,
|
MixinStakingPoolModifiers,
|
||||||
@ -74,7 +72,7 @@ contract MixinExchangeFees is
|
|||||||
// WETH.
|
// WETH.
|
||||||
if (msg.value == 0) {
|
if (msg.value == 0) {
|
||||||
wethAssetProxy.transferFrom(
|
wethAssetProxy.transferFrom(
|
||||||
WETH_ASSET_DATA,
|
_getWethAssetData(),
|
||||||
payerAddress,
|
payerAddress,
|
||||||
address(this),
|
address(this),
|
||||||
protocolFeePaid
|
protocolFeePaid
|
||||||
@ -99,6 +97,7 @@ contract MixinExchangeFees is
|
|||||||
uint256 currentEpoch_ = currentEpoch;
|
uint256 currentEpoch_ = currentEpoch;
|
||||||
mapping (bytes32 => IStructs.ActivePool) storage activePoolsThisEpoch =
|
mapping (bytes32 => IStructs.ActivePool) storage activePoolsThisEpoch =
|
||||||
_getActivePoolsFromEpoch(currentEpoch_);
|
_getActivePoolsFromEpoch(currentEpoch_);
|
||||||
|
|
||||||
IStructs.ActivePool memory pool = activePoolsThisEpoch[poolId];
|
IStructs.ActivePool memory pool = activePoolsThisEpoch[poolId];
|
||||||
|
|
||||||
// If the pool was previously inactive in this epoch, initialize it.
|
// If the pool was previously inactive in this epoch, initialize it.
|
||||||
@ -127,6 +126,20 @@ contract MixinExchangeFees is
|
|||||||
activePoolsThisEpoch[poolId] = pool;
|
activePoolsThisEpoch[poolId] = pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Returns the total balance of this contract, including WETH,
|
||||||
|
/// minus any WETH that has been reserved for rewards.
|
||||||
|
/// @return totalBalance Total balance.
|
||||||
|
function getAvailableRewardsBalance()
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (uint256 totalBalance)
|
||||||
|
{
|
||||||
|
totalBalance = address(this).balance.safeAdd(
|
||||||
|
_getAvailableWethBalance()
|
||||||
|
);
|
||||||
|
return totalBalance;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Get information on an active staking pool in this epoch.
|
/// @dev Get information on an active staking pool in this epoch.
|
||||||
/// @param poolId Pool Id to query.
|
/// @param poolId Pool Id to query.
|
||||||
/// @return pool ActivePool struct.
|
/// @return pool ActivePool struct.
|
||||||
|
@ -18,8 +18,11 @@
|
|||||||
|
|
||||||
pragma solidity ^0.5.9;
|
pragma solidity ^0.5.9;
|
||||||
|
|
||||||
|
import "./MixinDeploymentConstants.sol";
|
||||||
|
|
||||||
contract MixinConstants
|
|
||||||
|
contract MixinConstants is
|
||||||
|
MixinDeploymentConstants
|
||||||
{
|
{
|
||||||
// 100% in parts-per-million.
|
// 100% in parts-per-million.
|
||||||
uint32 constant internal PPM_DENOMINATOR = 10**6;
|
uint32 constant internal PPM_DENOMINATOR = 10**6;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
pragma solidity ^0.5.9;
|
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-asset-proxy/contracts/src/interfaces/IAssetData.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||||
@ -50,23 +51,41 @@ contract MixinDeploymentConstants {
|
|||||||
// bytes constant internal WETH_ASSET_DATA = hex"f47261b0000000000000000000000000c778417e063141139fce010982780140aa0cd5ab";
|
// bytes constant internal WETH_ASSET_DATA = hex"f47261b0000000000000000000000000c778417e063141139fce010982780140aa0cd5ab";
|
||||||
|
|
||||||
/// @dev Ensures that the WETH_ASSET_DATA is correct.
|
/// @dev Ensures that the WETH_ASSET_DATA is correct.
|
||||||
constructor() public {
|
constructor()
|
||||||
|
public
|
||||||
|
{
|
||||||
// Ensure that the WETH_ASSET_DATA is correct.
|
// Ensure that the WETH_ASSET_DATA is correct.
|
||||||
if (!WETH_ASSET_DATA.equals(
|
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());
|
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.
|
/// Must be view to allow overrides to access state.
|
||||||
/// @return wethAddress The address of the configured WETH contract.
|
/// @return wethContract The WETH contract instance.
|
||||||
function _getWETHAddress()
|
function _getWethContract()
|
||||||
internal
|
internal
|
||||||
view
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,6 @@ import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
|||||||
import "@0x/contracts-utils/contracts/src/Authorizable.sol";
|
import "@0x/contracts-utils/contracts/src/Authorizable.sol";
|
||||||
import "./MixinConstants.sol";
|
import "./MixinConstants.sol";
|
||||||
import "../interfaces/IZrxVault.sol";
|
import "../interfaces/IZrxVault.sol";
|
||||||
import "../interfaces/IEthVault.sol";
|
|
||||||
import "../interfaces/IStakingPoolRewardVault.sol";
|
|
||||||
import "../interfaces/IStructs.sol";
|
import "../interfaces/IStructs.sol";
|
||||||
import "../libs/LibStakingRichErrors.sol";
|
import "../libs/LibStakingRichErrors.sol";
|
||||||
|
|
||||||
@ -52,23 +50,23 @@ contract MixinStorage is
|
|||||||
mapping (uint8 => IStructs.StoredBalance) public globalStakeByStatus;
|
mapping (uint8 => IStructs.StoredBalance) public globalStakeByStatus;
|
||||||
|
|
||||||
// mapping from Owner to Amount of Active Stake
|
// 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 (address => IStructs.StoredBalance) internal _activeStakeByOwner;
|
||||||
|
|
||||||
// Mapping from Owner to Amount of Inactive Stake
|
// 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 (address => IStructs.StoredBalance) internal _inactiveStakeByOwner;
|
||||||
|
|
||||||
// Mapping from Owner to Amount Delegated
|
// Mapping from Owner to Amount Delegated
|
||||||
// (access using _loadAndSyncBalance or _loadUnsyncedBalance)
|
// (access using _loadSyncedBalance or _loadUnsyncedBalance)
|
||||||
mapping (address => IStructs.StoredBalance) internal _delegatedStakeByOwner;
|
mapping (address => IStructs.StoredBalance) internal _delegatedStakeByOwner;
|
||||||
|
|
||||||
// Mapping from Owner to Pool Id to Amount Delegated
|
// 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 (address => mapping (bytes32 => IStructs.StoredBalance)) internal _delegatedStakeToPoolByOwner;
|
||||||
|
|
||||||
// Mapping from Pool Id to Amount Delegated
|
// Mapping from Pool Id to Amount Delegated
|
||||||
// (access using _loadAndSyncBalance or _loadUnsyncedBalance)
|
// (access using _loadSyncedBalance or _loadUnsyncedBalance)
|
||||||
mapping (bytes32 => IStructs.StoredBalance) internal _delegatedStakeByPoolId;
|
mapping (bytes32 => IStructs.StoredBalance) internal _delegatedStakeByPoolId;
|
||||||
|
|
||||||
// mapping from Owner to Amount of Withdrawable Stake
|
// mapping from Owner to Amount of Withdrawable Stake
|
||||||
@ -84,6 +82,9 @@ contract MixinStorage is
|
|||||||
// mapping from Pool Id to Pool
|
// mapping from Pool Id to Pool
|
||||||
mapping (bytes32 => IStructs.Pool) internal _poolById;
|
mapping (bytes32 => IStructs.Pool) internal _poolById;
|
||||||
|
|
||||||
|
// mapping from PoolId to balance of members
|
||||||
|
mapping (bytes32 => uint256) public rewardsByPoolId;
|
||||||
|
|
||||||
// current epoch
|
// current epoch
|
||||||
uint256 public currentEpoch = INITIAL_EPOCH;
|
uint256 public currentEpoch = INITIAL_EPOCH;
|
||||||
|
|
||||||
@ -105,12 +106,6 @@ contract MixinStorage is
|
|||||||
// ZRX vault (stores staked ZRX)
|
// ZRX vault (stores staked ZRX)
|
||||||
IZrxVault public zrxVault;
|
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 */
|
/* Tweakable parameters */
|
||||||
|
|
||||||
// Minimum seconds between epochs.
|
// Minimum seconds between epochs.
|
||||||
@ -151,6 +146,9 @@ contract MixinStorage is
|
|||||||
/// @dev State for unfinalized rewards.
|
/// @dev State for unfinalized rewards.
|
||||||
IStructs.UnfinalizedState public unfinalizedState;
|
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.
|
/// @dev Adds owner as an authorized address.
|
||||||
constructor()
|
constructor()
|
||||||
public
|
public
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -96,8 +96,6 @@ interface IStakingEvents {
|
|||||||
/// @param cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
|
/// @param cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
|
||||||
/// @param cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
|
/// @param cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
|
||||||
/// @param wethProxyAddress The address that can transfer WETH for fees.
|
/// @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.
|
/// @param zrxVaultAddress Address of the ZrxVault contract.
|
||||||
event ParamsSet(
|
event ParamsSet(
|
||||||
uint256 epochDurationInSeconds,
|
uint256 epochDurationInSeconds,
|
||||||
@ -107,8 +105,6 @@ interface IStakingEvents {
|
|||||||
uint256 cobbDouglasAlphaNumerator,
|
uint256 cobbDouglasAlphaNumerator,
|
||||||
uint256 cobbDouglasAlphaDenominator,
|
uint256 cobbDouglasAlphaDenominator,
|
||||||
address wethProxyAddress,
|
address wethProxyAddress,
|
||||||
address ethVaultAddress,
|
|
||||||
address rewardVaultAddress,
|
|
||||||
address zrxVaultAddress
|
address zrxVaultAddress
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -47,17 +47,11 @@ interface IStakingProxy /* is IStaking */
|
|||||||
/// @param _stakingContract Address of staking contract.
|
/// @param _stakingContract Address of staking contract.
|
||||||
/// @param _wethProxyAddress The address that can transfer WETH for fees.
|
/// @param _wethProxyAddress The address that can transfer WETH for fees.
|
||||||
/// Use address in storage if NIL_ADDRESS is passed in.
|
/// 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.
|
/// @param _zrxVaultAddress Address of the ZrxVault contract.
|
||||||
/// Use address in storage if NIL_ADDRESS is passed in.
|
/// Use address in storage if NIL_ADDRESS is passed in.
|
||||||
function attachStakingContract(
|
function attachStakingContract(
|
||||||
address _stakingContract,
|
address _stakingContract,
|
||||||
address _wethProxyAddress,
|
address _wethProxyAddress,
|
||||||
address _ethVaultAddress,
|
|
||||||
address _rewardVaultAddress,
|
|
||||||
address _zrxVaultAddress
|
address _zrxVaultAddress
|
||||||
)
|
)
|
||||||
external;
|
external;
|
||||||
|
@ -21,8 +21,6 @@ pragma experimental ABIEncoderV2;
|
|||||||
|
|
||||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
|
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
|
||||||
import "../interfaces/IZrxVault.sol";
|
import "../interfaces/IZrxVault.sol";
|
||||||
import "../interfaces/IEthVault.sol";
|
|
||||||
import "../interfaces/IStakingPoolRewardVault.sol";
|
|
||||||
import "../interfaces/IStructs.sol";
|
import "../interfaces/IStructs.sol";
|
||||||
|
|
||||||
|
|
||||||
@ -93,16 +91,6 @@ interface IStorage {
|
|||||||
view
|
view
|
||||||
returns (IZrxVault);
|
returns (IZrxVault);
|
||||||
|
|
||||||
function ethVault()
|
|
||||||
external
|
|
||||||
view
|
|
||||||
returns (IEthVault);
|
|
||||||
|
|
||||||
function rewardVault()
|
|
||||||
external
|
|
||||||
view
|
|
||||||
returns (IStakingPoolRewardVault);
|
|
||||||
|
|
||||||
function epochDurationInSeconds()
|
function epochDurationInSeconds()
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
|
@ -23,13 +23,9 @@ interface IStorageInit {
|
|||||||
|
|
||||||
/// @dev Initialize storage owned by this contract.
|
/// @dev Initialize storage owned by this contract.
|
||||||
/// @param _wethProxyAddress The address that can transfer WETH for fees.
|
/// @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.
|
/// @param _zrxVaultAddress Address of the ZrxVault contract.
|
||||||
function init(
|
function init(
|
||||||
address _wethProxyAddress,
|
address _wethProxyAddress,
|
||||||
address _ethVaultAddress,
|
|
||||||
address _rewardVaultAddress,
|
|
||||||
address _zrxVaultAddress
|
address _zrxVaultAddress
|
||||||
)
|
)
|
||||||
external;
|
external;
|
||||||
|
@ -52,7 +52,7 @@ interface IStructs {
|
|||||||
/// @dev Encapsulates a balance for the current and next epochs.
|
/// @dev Encapsulates a balance for the current and next epochs.
|
||||||
/// Note that these balances may be stale if the current epoch
|
/// Note that these balances may be stale if the current epoch
|
||||||
/// is greater than `currentEpoch`.
|
/// is greater than `currentEpoch`.
|
||||||
/// Always load this struct using _loadAndSyncBalance or _loadUnsyncedBalance.
|
/// Always load this struct using _loadSyncedBalance or _loadUnsyncedBalance.
|
||||||
/// @param isInitialized
|
/// @param isInitialized
|
||||||
/// @param currentEpoch the current epoch
|
/// @param currentEpoch the current epoch
|
||||||
/// @param currentEpochBalance balance in the current epoch.
|
/// @param currentEpochBalance balance in the current epoch.
|
||||||
|
@ -44,8 +44,6 @@ library LibStakingRichErrors {
|
|||||||
InvalidMaximumMakersInPool,
|
InvalidMaximumMakersInPool,
|
||||||
InvalidMinimumPoolStake,
|
InvalidMinimumPoolStake,
|
||||||
InvalidWethProxyAddress,
|
InvalidWethProxyAddress,
|
||||||
InvalidEthVaultAddress,
|
|
||||||
InvalidRewardVaultAddress,
|
|
||||||
InvalidZrxVaultAddress,
|
InvalidZrxVaultAddress,
|
||||||
InvalidEpochDuration
|
InvalidEpochDuration
|
||||||
}
|
}
|
||||||
@ -121,14 +119,6 @@ library LibStakingRichErrors {
|
|||||||
bytes4 internal constant POOL_EXISTENCE_ERROR_SELECTOR =
|
bytes4 internal constant POOL_EXISTENCE_ERROR_SELECTOR =
|
||||||
0x9ae94f01;
|
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(keccak256("InvalidStakeStatusError(uint256)"))
|
||||||
bytes4 internal constant INVALID_STAKE_STATUS_ERROR_SELECTOR =
|
bytes4 internal constant INVALID_STAKE_STATUS_ERROR_SELECTOR =
|
||||||
0xb7161acd;
|
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(
|
function InvalidProtocolFeePaymentError(
|
||||||
ProtocolFeePaymentErrorCodes errorCode,
|
ProtocolFeePaymentErrorCodes errorCode,
|
||||||
uint256 expectedProtocolFeePaid,
|
uint256 expectedProtocolFeePaid,
|
||||||
|
@ -216,8 +216,9 @@ contract MixinStake is
|
|||||||
// Synchronizes reward state in the pool that the staker is delegating
|
// Synchronizes reward state in the pool that the staker is delegating
|
||||||
// to.
|
// to.
|
||||||
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
|
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
|
||||||
_loadAndSyncBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
|
_loadSyncedBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
|
||||||
_syncRewardsForDelegator(
|
|
||||||
|
_withdrawAndSyncDelegatorRewards(
|
||||||
poolId,
|
poolId,
|
||||||
owner,
|
owner,
|
||||||
initDelegatedStakeToPoolByOwner,
|
initDelegatedStakeToPoolByOwner,
|
||||||
@ -255,8 +256,9 @@ contract MixinStake is
|
|||||||
// synchronizes reward state in the pool that the staker is undelegating
|
// synchronizes reward state in the pool that the staker is undelegating
|
||||||
// from
|
// from
|
||||||
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
|
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
|
||||||
_loadAndSyncBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
|
_loadSyncedBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
|
||||||
_syncRewardsForDelegator(
|
|
||||||
|
_withdrawAndSyncDelegatorRewards(
|
||||||
poolId,
|
poolId,
|
||||||
owner,
|
owner,
|
||||||
initDelegatedStakeToPoolByOwner,
|
initDelegatedStakeToPoolByOwner,
|
||||||
|
@ -43,7 +43,7 @@ contract MixinStakeBalances is
|
|||||||
view
|
view
|
||||||
returns (IStructs.StakeBalance memory balance)
|
returns (IStructs.StakeBalance memory balance)
|
||||||
{
|
{
|
||||||
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(
|
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(
|
||||||
globalStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)]
|
globalStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)]
|
||||||
);
|
);
|
||||||
return IStructs.StakeBalance({
|
return IStructs.StakeBalance({
|
||||||
@ -59,7 +59,7 @@ contract MixinStakeBalances is
|
|||||||
view
|
view
|
||||||
returns (IStructs.StakeBalance memory balance)
|
returns (IStructs.StakeBalance memory balance)
|
||||||
{
|
{
|
||||||
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(
|
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(
|
||||||
globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)]
|
globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)]
|
||||||
);
|
);
|
||||||
return IStructs.StakeBalance({
|
return IStructs.StakeBalance({
|
||||||
@ -75,7 +75,7 @@ contract MixinStakeBalances is
|
|||||||
view
|
view
|
||||||
returns (IStructs.StakeBalance memory balance)
|
returns (IStructs.StakeBalance memory balance)
|
||||||
{
|
{
|
||||||
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(
|
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(
|
||||||
globalStakeByStatus[uint8(IStructs.StakeStatus.DELEGATED)]
|
globalStakeByStatus[uint8(IStructs.StakeStatus.DELEGATED)]
|
||||||
);
|
);
|
||||||
return IStructs.StakeBalance({
|
return IStructs.StakeBalance({
|
||||||
@ -103,7 +103,7 @@ contract MixinStakeBalances is
|
|||||||
view
|
view
|
||||||
returns (IStructs.StakeBalance memory balance)
|
returns (IStructs.StakeBalance memory balance)
|
||||||
{
|
{
|
||||||
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(_activeStakeByOwner[owner]);
|
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_activeStakeByOwner[owner]);
|
||||||
return IStructs.StakeBalance({
|
return IStructs.StakeBalance({
|
||||||
currentEpochBalance: storedBalance.currentEpochBalance,
|
currentEpochBalance: storedBalance.currentEpochBalance,
|
||||||
nextEpochBalance: storedBalance.nextEpochBalance
|
nextEpochBalance: storedBalance.nextEpochBalance
|
||||||
@ -118,7 +118,7 @@ contract MixinStakeBalances is
|
|||||||
view
|
view
|
||||||
returns (IStructs.StakeBalance memory balance)
|
returns (IStructs.StakeBalance memory balance)
|
||||||
{
|
{
|
||||||
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(_inactiveStakeByOwner[owner]);
|
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_inactiveStakeByOwner[owner]);
|
||||||
return IStructs.StakeBalance({
|
return IStructs.StakeBalance({
|
||||||
currentEpochBalance: storedBalance.currentEpochBalance,
|
currentEpochBalance: storedBalance.currentEpochBalance,
|
||||||
nextEpochBalance: storedBalance.nextEpochBalance
|
nextEpochBalance: storedBalance.nextEpochBalance
|
||||||
@ -133,7 +133,7 @@ contract MixinStakeBalances is
|
|||||||
view
|
view
|
||||||
returns (IStructs.StakeBalance memory balance)
|
returns (IStructs.StakeBalance memory balance)
|
||||||
{
|
{
|
||||||
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(_delegatedStakeByOwner[owner]);
|
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_delegatedStakeByOwner[owner]);
|
||||||
return IStructs.StakeBalance({
|
return IStructs.StakeBalance({
|
||||||
currentEpochBalance: storedBalance.currentEpochBalance,
|
currentEpochBalance: storedBalance.currentEpochBalance,
|
||||||
nextEpochBalance: storedBalance.nextEpochBalance
|
nextEpochBalance: storedBalance.nextEpochBalance
|
||||||
@ -160,7 +160,7 @@ contract MixinStakeBalances is
|
|||||||
view
|
view
|
||||||
returns (IStructs.StakeBalance memory balance)
|
returns (IStructs.StakeBalance memory balance)
|
||||||
{
|
{
|
||||||
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
|
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_delegatedStakeToPoolByOwner[owner][poolId]);
|
||||||
return IStructs.StakeBalance({
|
return IStructs.StakeBalance({
|
||||||
currentEpochBalance: storedBalance.currentEpochBalance,
|
currentEpochBalance: storedBalance.currentEpochBalance,
|
||||||
nextEpochBalance: storedBalance.nextEpochBalance
|
nextEpochBalance: storedBalance.nextEpochBalance
|
||||||
@ -176,7 +176,7 @@ contract MixinStakeBalances is
|
|||||||
view
|
view
|
||||||
returns (IStructs.StakeBalance memory balance)
|
returns (IStructs.StakeBalance memory balance)
|
||||||
{
|
{
|
||||||
IStructs.StoredBalance memory storedBalance = _loadAndSyncBalance(_delegatedStakeByPoolId[poolId]);
|
IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_delegatedStakeByPoolId[poolId]);
|
||||||
return IStructs.StakeBalance({
|
return IStructs.StakeBalance({
|
||||||
currentEpochBalance: storedBalance.currentEpochBalance,
|
currentEpochBalance: storedBalance.currentEpochBalance,
|
||||||
nextEpochBalance: storedBalance.nextEpochBalance
|
nextEpochBalance: storedBalance.nextEpochBalance
|
||||||
|
@ -53,8 +53,8 @@ contract MixinStakeStorage is
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load balance from storage and synchronize it
|
// load balance from storage and synchronize it
|
||||||
IStructs.StoredBalance memory from = _loadAndSyncBalance(fromPtr);
|
IStructs.StoredBalance memory from = _loadSyncedBalance(fromPtr);
|
||||||
IStructs.StoredBalance memory to = _loadAndSyncBalance(toPtr);
|
IStructs.StoredBalance memory to = _loadSyncedBalance(toPtr);
|
||||||
|
|
||||||
// sanity check on balance
|
// sanity check on balance
|
||||||
if (amount > from.nextEpochBalance) {
|
if (amount > from.nextEpochBalance) {
|
||||||
@ -81,7 +81,7 @@ contract MixinStakeStorage is
|
|||||||
/// was stored.
|
/// was stored.
|
||||||
/// @param balancePtr to load and sync.
|
/// @param balancePtr to load and sync.
|
||||||
/// @return synchronized balance.
|
/// @return synchronized balance.
|
||||||
function _loadAndSyncBalance(IStructs.StoredBalance storage balancePtr)
|
function _loadSyncedBalance(IStructs.StoredBalance storage balancePtr)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (IStructs.StoredBalance memory balance)
|
returns (IStructs.StoredBalance memory balance)
|
||||||
@ -119,7 +119,7 @@ contract MixinStakeStorage is
|
|||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
// Remove stake from balance
|
// 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.nextEpochBalance = uint256(balance.nextEpochBalance).safeAdd(amount).downcastToUint96();
|
||||||
balance.currentEpochBalance = uint256(balance.currentEpochBalance).safeAdd(amount).downcastToUint96();
|
balance.currentEpochBalance = uint256(balance.currentEpochBalance).safeAdd(amount).downcastToUint96();
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ contract MixinStakeStorage is
|
|||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
// Remove stake from balance
|
// 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.nextEpochBalance = uint256(balance.nextEpochBalance).safeSub(amount).downcastToUint96();
|
||||||
balance.currentEpochBalance = uint256(balance.currentEpochBalance).safeSub(amount).downcastToUint96();
|
balance.currentEpochBalance = uint256(balance.currentEpochBalance).safeSub(amount).downcastToUint96();
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ contract MixinStakeStorage is
|
|||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
// Add stake to balance
|
// Add stake to balance
|
||||||
IStructs.StoredBalance memory balance = _loadAndSyncBalance(balancePtr);
|
IStructs.StoredBalance memory balance = _loadSyncedBalance(balancePtr);
|
||||||
balance.nextEpochBalance = uint256(balance.nextEpochBalance).safeAdd(amount).downcastToUint96();
|
balance.nextEpochBalance = uint256(balance.nextEpochBalance).safeAdd(amount).downcastToUint96();
|
||||||
|
|
||||||
// update state
|
// update state
|
||||||
@ -163,7 +163,7 @@ contract MixinStakeStorage is
|
|||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
// Remove stake from balance
|
// 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.nextEpochBalance = uint256(balance.nextEpochBalance).safeSub(amount).downcastToUint96();
|
||||||
|
|
||||||
// update state
|
// update state
|
||||||
|
@ -39,21 +39,22 @@ contract MixinStakingPoolRewards is
|
|||||||
{
|
{
|
||||||
using LibSafeMath for uint256;
|
using LibSafeMath for uint256;
|
||||||
|
|
||||||
/// @dev Syncs rewards for a delegator. This includes transferring rewards
|
/// @dev Syncs rewards for a delegator. This includes transferring WETH
|
||||||
/// from the Reward Vault to the Eth Vault, and adding/removing
|
/// rewards to the delegator, and adding/removing
|
||||||
/// dependencies on cumulative rewards.
|
/// dependencies on cumulative rewards.
|
||||||
/// This is used by a delegator when they want to sync their rewards
|
/// This is used by a delegator when they want to sync their rewards
|
||||||
/// without delegating/undelegating. It's effectively the same as
|
/// without delegating/undelegating. It's effectively the same as
|
||||||
/// delegating zero stake.
|
/// delegating zero stake.
|
||||||
/// @param poolId Unique id of pool.
|
/// @param poolId Unique id of pool.
|
||||||
function syncDelegatorRewards(bytes32 poolId)
|
function withdrawDelegatorRewards(bytes32 poolId)
|
||||||
external
|
external
|
||||||
{
|
{
|
||||||
address member = msg.sender;
|
address member = msg.sender;
|
||||||
|
|
||||||
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
|
IStructs.StoredBalance memory finalDelegatedStakeToPoolByOwner =
|
||||||
_loadAndSyncBalance(_delegatedStakeToPoolByOwner[member][poolId]);
|
_loadSyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]);
|
||||||
_syncRewardsForDelegator(
|
|
||||||
|
_withdrawAndSyncDelegatorRewards(
|
||||||
poolId,
|
poolId,
|
||||||
member,
|
member,
|
||||||
// Initial balance
|
// Initial balance
|
||||||
@ -68,7 +69,6 @@ contract MixinStakingPoolRewards is
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Computes the reward balance in ETH of the operator of a pool.
|
/// @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.
|
/// @param poolId Unique id of pool.
|
||||||
/// @return totalReward Balance in ETH.
|
/// @return totalReward Balance in ETH.
|
||||||
function computeRewardBalanceOfOperator(bytes32 poolId)
|
function computeRewardBalanceOfOperator(bytes32 poolId)
|
||||||
@ -76,14 +76,16 @@ contract MixinStakingPoolRewards is
|
|||||||
view
|
view
|
||||||
returns (uint256 reward)
|
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
|
// on finalization, the only factor in this function are unfinalized
|
||||||
// rewards.
|
// rewards.
|
||||||
IStructs.Pool memory pool = _poolById[poolId];
|
IStructs.Pool memory pool = _poolById[poolId];
|
||||||
// Get any unfinalized rewards.
|
// Get any unfinalized rewards.
|
||||||
(uint256 unfinalizedTotalRewards, uint256 unfinalizedMembersStake) = _getUnfinalizedPoolRewards(poolId);
|
(uint256 unfinalizedTotalRewards, uint256 unfinalizedMembersStake) =
|
||||||
|
_getUnfinalizedPoolRewards(poolId);
|
||||||
|
|
||||||
// Get the operators' portion.
|
// Get the operators' portion.
|
||||||
(reward,) = _computeSplitStakingPoolRewards(
|
(reward,) = _computePoolRewardsSplit(
|
||||||
pool.operatorShare,
|
pool.operatorShare,
|
||||||
unfinalizedTotalRewards,
|
unfinalizedTotalRewards,
|
||||||
unfinalizedMembersStake
|
unfinalizedMembersStake
|
||||||
@ -92,7 +94,6 @@ contract MixinStakingPoolRewards is
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Computes the reward balance in ETH of a specific member of a pool.
|
/// @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 poolId Unique id of pool.
|
||||||
/// @param member The member of the pool.
|
/// @param member The member of the pool.
|
||||||
/// @return totalReward Balance in ETH.
|
/// @return totalReward Balance in ETH.
|
||||||
@ -105,13 +106,14 @@ contract MixinStakingPoolRewards is
|
|||||||
// Get any unfinalized rewards.
|
// Get any unfinalized rewards.
|
||||||
(uint256 unfinalizedTotalRewards, uint256 unfinalizedMembersStake) =
|
(uint256 unfinalizedTotalRewards, uint256 unfinalizedMembersStake) =
|
||||||
_getUnfinalizedPoolRewards(poolId);
|
_getUnfinalizedPoolRewards(poolId);
|
||||||
|
|
||||||
// Get the members' portion.
|
// Get the members' portion.
|
||||||
(, uint256 unfinalizedMembersReward) = _computeSplitStakingPoolRewards(
|
(, uint256 unfinalizedMembersReward) = _computePoolRewardsSplit(
|
||||||
pool.operatorShare,
|
pool.operatorShare,
|
||||||
unfinalizedTotalRewards,
|
unfinalizedTotalRewards,
|
||||||
unfinalizedMembersStake
|
unfinalizedMembersStake
|
||||||
);
|
);
|
||||||
return _computeRewardBalanceOfDelegator(
|
return _computeDelegatorReward(
|
||||||
poolId,
|
poolId,
|
||||||
_loadUnsyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]),
|
_loadUnsyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]),
|
||||||
currentEpoch,
|
currentEpoch,
|
||||||
@ -121,15 +123,14 @@ contract MixinStakingPoolRewards is
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Syncs rewards for a delegator. This includes transferring rewards
|
/// @dev Syncs rewards for a delegator. This includes transferring rewards
|
||||||
/// from the Reward Vault to the Eth Vault, and adding/removing
|
/// withdrawing rewards and adding/removing dependencies on cumulative rewards.
|
||||||
/// dependencies on cumulative rewards.
|
|
||||||
/// @param poolId Unique id of pool.
|
/// @param poolId Unique id of pool.
|
||||||
/// @param member of the pool.
|
/// @param member of the pool.
|
||||||
/// @param initialDelegatedStakeToPoolByOwner The member's delegated
|
/// @param initialDelegatedStakeToPoolByOwner The member's delegated
|
||||||
/// balance at the beginning of this transaction.
|
/// balance at the beginning of this transaction.
|
||||||
/// @param finalDelegatedStakeToPoolByOwner The member's delegated balance
|
/// @param finalDelegatedStakeToPoolByOwner The member's delegated balance
|
||||||
/// at the end of this transaction.
|
/// at the end of this transaction.
|
||||||
function _syncRewardsForDelegator(
|
function _withdrawAndSyncDelegatorRewards(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
address member,
|
address member,
|
||||||
IStructs.StoredBalance memory initialDelegatedStakeToPoolByOwner,
|
IStructs.StoredBalance memory initialDelegatedStakeToPoolByOwner,
|
||||||
@ -137,10 +138,10 @@ contract MixinStakingPoolRewards is
|
|||||||
)
|
)
|
||||||
internal
|
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
|
// this must be done before we can modify the owner's portion of the
|
||||||
// delegator pool.
|
// delegator pool.
|
||||||
_transferDelegatorRewardsToEthVault(
|
_finalizePoolAndWithdrawDelegatorRewards(
|
||||||
poolId,
|
poolId,
|
||||||
member,
|
member,
|
||||||
initialDelegatedStakeToPoolByOwner,
|
initialDelegatedStakeToPoolByOwner,
|
||||||
@ -175,7 +176,7 @@ contract MixinStakingPoolRewards is
|
|||||||
/// will split the reward.
|
/// will split the reward.
|
||||||
/// @return operatorReward Portion of `reward` given to the pool operator.
|
/// @return operatorReward Portion of `reward` given to the pool operator.
|
||||||
/// @return membersReward Portion of `reward` given to the pool members.
|
/// @return membersReward Portion of `reward` given to the pool members.
|
||||||
function _depositStakingPoolRewards(
|
function _syncPoolRewards(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
uint256 reward,
|
uint256 reward,
|
||||||
uint256 membersStake
|
uint256 membersStake
|
||||||
@ -186,19 +187,20 @@ contract MixinStakingPoolRewards is
|
|||||||
IStructs.Pool memory pool = _poolById[poolId];
|
IStructs.Pool memory pool = _poolById[poolId];
|
||||||
|
|
||||||
// Split the reward between operator and members
|
// Split the reward between operator and members
|
||||||
(operatorReward, membersReward) = _computeSplitStakingPoolRewards(
|
(operatorReward, membersReward) = _computePoolRewardsSplit(
|
||||||
pool.operatorShare,
|
pool.operatorShare,
|
||||||
reward,
|
reward,
|
||||||
membersStake
|
membersStake
|
||||||
);
|
);
|
||||||
// Deposit the operator's reward in the eth vault.
|
|
||||||
ethVault.depositFor(pool.operator, operatorReward);
|
|
||||||
|
|
||||||
if (membersReward == 0) {
|
if (operatorReward > 0) {
|
||||||
return (0, 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);
|
if (membersReward > 0) {
|
||||||
|
// Increment the balance of the pool
|
||||||
|
_incrementPoolRewards(poolId, membersReward);
|
||||||
|
|
||||||
// Fetch the last epoch at which we stored an entry for this pool;
|
// Fetch the last epoch at which we stored an entry for this pool;
|
||||||
// this is the most up-to-date cumulative rewards for this pool.
|
// this is the most up-to-date cumulative rewards for this pool.
|
||||||
@ -224,6 +226,7 @@ contract MixinStakingPoolRewards is
|
|||||||
currentEpoch,
|
currentEpoch,
|
||||||
cumulativeReward
|
cumulativeReward
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (operatorReward, membersReward);
|
return (operatorReward, membersReward);
|
||||||
}
|
}
|
||||||
@ -237,7 +240,7 @@ contract MixinStakingPoolRewards is
|
|||||||
/// to the pool in the epoch the rewards were earned.
|
/// to the pool in the epoch the rewards were earned.
|
||||||
/// @return operatorReward Portion of `totalReward` given to the pool operator.
|
/// @return operatorReward Portion of `totalReward` given to the pool operator.
|
||||||
/// @return membersReward Portion of `totalReward` given to the pool members.
|
/// @return membersReward Portion of `totalReward` given to the pool members.
|
||||||
function _computeSplitStakingPoolRewards(
|
function _computePoolRewardsSplit(
|
||||||
uint32 operatorShare,
|
uint32 operatorShare,
|
||||||
uint256 totalReward,
|
uint256 totalReward,
|
||||||
uint256 membersStake
|
uint256 membersStake
|
||||||
@ -259,13 +262,12 @@ contract MixinStakingPoolRewards is
|
|||||||
return (operatorReward, membersReward);
|
return (operatorReward, membersReward);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Transfers a delegators accumulated rewards from the transient pool
|
/// @dev Transfers a delegators accumulated rewards to the delegator.
|
||||||
/// Reward Pool vault to the Eth Vault. This is required before the
|
/// This is required before the member's stake in the pool can be modified.
|
||||||
/// member's stake in the pool can be modified.
|
|
||||||
/// @param poolId Unique id of pool.
|
/// @param poolId Unique id of pool.
|
||||||
/// @param member The member of the pool.
|
/// @param member The member of the pool.
|
||||||
/// @param unsyncedStake Unsynced stake of the delegator to the pool.
|
/// @param unsyncedStake Unsynced stake of the delegator to the pool.
|
||||||
function _transferDelegatorRewardsToEthVault(
|
function _finalizePoolAndWithdrawDelegatorRewards(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
address member,
|
address member,
|
||||||
IStructs.StoredBalance memory unsyncedStake,
|
IStructs.StoredBalance memory unsyncedStake,
|
||||||
@ -277,7 +279,7 @@ contract MixinStakingPoolRewards is
|
|||||||
finalizePool(poolId);
|
finalizePool(poolId);
|
||||||
|
|
||||||
// Compute balance owed to delegator
|
// Compute balance owed to delegator
|
||||||
uint256 balance = _computeRewardBalanceOfDelegator(
|
uint256 balance = _computeDelegatorReward(
|
||||||
poolId,
|
poolId,
|
||||||
unsyncedStake,
|
unsyncedStake,
|
||||||
currentEpoch,
|
currentEpoch,
|
||||||
@ -290,10 +292,11 @@ contract MixinStakingPoolRewards is
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer from RewardVault to this contract.
|
// Decrement the balance of the pool
|
||||||
rewardVault.transfer(poolId, address(uint160(address(this))), balance);
|
_decrementPoolRewards(poolId, balance);
|
||||||
// Transfer to EthVault.
|
|
||||||
ethVault.depositFor(member, 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.
|
/// @dev Computes the reward balance in ETH of a specific member of a pool.
|
||||||
@ -304,7 +307,7 @@ contract MixinStakingPoolRewards is
|
|||||||
/// (if any).
|
/// (if any).
|
||||||
/// @param unfinalizedMembersStake Unfinalized total members stake (if any).
|
/// @param unfinalizedMembersStake Unfinalized total members stake (if any).
|
||||||
/// @return totalReward Balance in ETH.
|
/// @return totalReward Balance in ETH.
|
||||||
function _computeRewardBalanceOfDelegator(
|
function _computeDelegatorReward(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
IStructs.StoredBalance memory unsyncedStake,
|
IStructs.StoredBalance memory unsyncedStake,
|
||||||
uint256 currentEpoch,
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,8 @@ import "../interfaces/IStructs.sol";
|
|||||||
contract MixinAbstract {
|
contract MixinAbstract {
|
||||||
|
|
||||||
/// @dev Instantly finalizes a single pool that was active in the previous
|
/// @dev Instantly finalizes a single pool that was active in the previous
|
||||||
/// epoch, crediting it rewards and sending those rewards to the reward
|
/// epoch, crediting it rewards for members and withdrawing operator's
|
||||||
/// and eth vault. This can be called by internal functions that need
|
/// rewards as WETH. This can be called by internal functions that need
|
||||||
/// to finalize a pool immediately. Does nothing if the pool is already
|
/// to finalize a pool immediately. Does nothing if the pool is already
|
||||||
/// finalized or was not active in the previous epoch.
|
/// finalized or was not active in the previous epoch.
|
||||||
/// @param poolId The pool ID to finalize.
|
/// @param poolId The pool ID to finalize.
|
||||||
|
@ -26,7 +26,6 @@ import "../libs/LibCobbDouglas.sol";
|
|||||||
import "../libs/LibStakingRichErrors.sol";
|
import "../libs/LibStakingRichErrors.sol";
|
||||||
import "../immutable/MixinStorage.sol";
|
import "../immutable/MixinStorage.sol";
|
||||||
import "../immutable/MixinConstants.sol";
|
import "../immutable/MixinConstants.sol";
|
||||||
import "../immutable/MixinDeploymentConstants.sol";
|
|
||||||
import "../interfaces/IStakingEvents.sol";
|
import "../interfaces/IStakingEvents.sol";
|
||||||
import "../interfaces/IStructs.sol";
|
import "../interfaces/IStructs.sol";
|
||||||
import "../stake/MixinStakeBalances.sol";
|
import "../stake/MixinStakeBalances.sol";
|
||||||
@ -43,7 +42,6 @@ contract MixinFinalizer is
|
|||||||
IStakingEvents,
|
IStakingEvents,
|
||||||
MixinAbstract,
|
MixinAbstract,
|
||||||
MixinConstants,
|
MixinConstants,
|
||||||
MixinDeploymentConstants,
|
|
||||||
Ownable,
|
Ownable,
|
||||||
MixinStorage,
|
MixinStorage,
|
||||||
MixinScheduler,
|
MixinScheduler,
|
||||||
@ -78,8 +76,11 @@ contract MixinFinalizer is
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert all ETH to WETH
|
||||||
|
_wrapEth();
|
||||||
|
|
||||||
// Set up unfinalized state.
|
// Set up unfinalized state.
|
||||||
state.rewardsAvailable = _wrapBalanceToWETHAndGetBalance();
|
state.rewardsAvailable = _getAvailableWethBalance();
|
||||||
state.poolsRemaining = poolsRemaining = numActivePoolsThisEpoch;
|
state.poolsRemaining = poolsRemaining = numActivePoolsThisEpoch;
|
||||||
state.totalFeesCollected = totalFeesCollectedThisEpoch;
|
state.totalFeesCollected = totalFeesCollectedThisEpoch;
|
||||||
state.totalWeightedStake = totalWeightedStakeThisEpoch;
|
state.totalWeightedStake = totalWeightedStakeThisEpoch;
|
||||||
@ -110,8 +111,8 @@ contract MixinFinalizer is
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Instantly finalizes a single pool that was active in the previous
|
/// @dev Instantly finalizes a single pool that was active in the previous
|
||||||
/// epoch, crediting it rewards and sending those rewards to the reward
|
/// epoch, crediting it rewards for members and withdrawing operator's
|
||||||
/// and eth vault. This can be called by internal functions that need
|
/// rewards as WETH. This can be called by internal functions that need
|
||||||
/// to finalize a pool immediately. Does nothing if the pool is already
|
/// to finalize a pool immediately. Does nothing if the pool is already
|
||||||
/// finalized or was not active in the previous epoch.
|
/// finalized or was not active in the previous epoch.
|
||||||
/// @param poolId The pool ID to finalize.
|
/// @param poolId The pool ID to finalize.
|
||||||
@ -202,7 +203,7 @@ contract MixinFinalizer is
|
|||||||
return (0, 0);
|
return (0, 0);
|
||||||
}
|
}
|
||||||
IStructs.ActivePool memory pool = _getActivePoolFromEpoch(epoch - 1, poolId);
|
IStructs.ActivePool memory pool = _getActivePoolFromEpoch(epoch - 1, poolId);
|
||||||
reward = _getUnfinalizedPoolRewards(pool, unfinalizedState);
|
reward = _getUnfinalizedPoolRewardsFromState(pool, unfinalizedState);
|
||||||
membersStake = pool.membersStake;
|
membersStake = pool.membersStake;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,27 +239,34 @@ contract MixinFinalizer is
|
|||||||
return activePools;
|
return activePools;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Converts the entire ETH balance of the contract into WETH and
|
/// @dev Converts the entire ETH balance of this contract into WETH.
|
||||||
/// returns the total WETH balance of this contract.
|
function _wrapEth()
|
||||||
/// @return The WETH balance of this contract.
|
|
||||||
function _wrapBalanceToWETHAndGetBalance()
|
|
||||||
internal
|
internal
|
||||||
returns (uint256 balance)
|
|
||||||
{
|
{
|
||||||
IEtherToken weth = IEtherToken(_getWETHAddress());
|
|
||||||
uint256 ethBalance = address(this).balance;
|
uint256 ethBalance = address(this).balance;
|
||||||
if (ethBalance != 0) {
|
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.
|
/// @dev Computes the reward owed to a pool during finalization.
|
||||||
/// @param pool The active pool.
|
/// @param pool The active pool.
|
||||||
/// @param state The current state of finalization.
|
/// @param state The current state of finalization.
|
||||||
/// @return rewards Unfinalized rewards for this pool.
|
/// @return rewards Unfinalized rewards for this pool.
|
||||||
function _getUnfinalizedPoolRewards(
|
function _getUnfinalizedPoolRewardsFromState(
|
||||||
IStructs.ActivePool memory pool,
|
IStructs.ActivePool memory pool,
|
||||||
IStructs.UnfinalizedState memory state
|
IStructs.UnfinalizedState memory state
|
||||||
)
|
)
|
||||||
@ -314,12 +322,12 @@ contract MixinFinalizer is
|
|||||||
delete _getActivePoolsFromEpoch(epoch.safeSub(1))[poolId];
|
delete _getActivePoolsFromEpoch(epoch.safeSub(1))[poolId];
|
||||||
|
|
||||||
// Compute the rewards.
|
// Compute the rewards.
|
||||||
uint256 rewards = _getUnfinalizedPoolRewards(pool, state);
|
uint256 rewards = _getUnfinalizedPoolRewardsFromState(pool, state);
|
||||||
|
|
||||||
// Pay the pool.
|
// Pay the pool.
|
||||||
// Note that we credit at the CURRENT epoch even though these rewards
|
// Note that we credit at the CURRENT epoch even though these rewards
|
||||||
// were earned in the previous epoch.
|
// were earned in the previous epoch.
|
||||||
(operatorReward, membersReward) = _depositStakingPoolRewards(
|
(operatorReward, membersReward) = _syncPoolRewards(
|
||||||
poolId,
|
poolId,
|
||||||
rewards,
|
rewards,
|
||||||
pool.membersStake
|
pool.membersStake
|
||||||
|
@ -22,10 +22,7 @@ import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
|||||||
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
||||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
|
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
|
||||||
import "../immutable/MixinStorage.sol";
|
import "../immutable/MixinStorage.sol";
|
||||||
import "../immutable/MixinDeploymentConstants.sol";
|
|
||||||
import "../interfaces/IStakingEvents.sol";
|
import "../interfaces/IStakingEvents.sol";
|
||||||
import "../interfaces/IEthVault.sol";
|
|
||||||
import "../interfaces/IStakingPoolRewardVault.sol";
|
|
||||||
import "../interfaces/IZrxVault.sol";
|
import "../interfaces/IZrxVault.sol";
|
||||||
import "../libs/LibStakingRichErrors.sol";
|
import "../libs/LibStakingRichErrors.sol";
|
||||||
|
|
||||||
@ -33,7 +30,6 @@ import "../libs/LibStakingRichErrors.sol";
|
|||||||
contract MixinParams is
|
contract MixinParams is
|
||||||
IStakingEvents,
|
IStakingEvents,
|
||||||
MixinConstants,
|
MixinConstants,
|
||||||
MixinDeploymentConstants,
|
|
||||||
Ownable,
|
Ownable,
|
||||||
MixinStorage
|
MixinStorage
|
||||||
{
|
{
|
||||||
@ -45,8 +41,6 @@ contract MixinParams is
|
|||||||
/// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
|
/// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
|
||||||
/// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
|
/// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
|
||||||
/// @param _wethProxyAddress The address that can transfer WETH for fees.
|
/// @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.
|
/// @param _zrxVaultAddress Address of the ZrxVault contract.
|
||||||
function setParams(
|
function setParams(
|
||||||
uint256 _epochDurationInSeconds,
|
uint256 _epochDurationInSeconds,
|
||||||
@ -56,8 +50,6 @@ contract MixinParams is
|
|||||||
uint32 _cobbDouglasAlphaNumerator,
|
uint32 _cobbDouglasAlphaNumerator,
|
||||||
uint32 _cobbDouglasAlphaDenominator,
|
uint32 _cobbDouglasAlphaDenominator,
|
||||||
address _wethProxyAddress,
|
address _wethProxyAddress,
|
||||||
address _ethVaultAddress,
|
|
||||||
address payable _rewardVaultAddress,
|
|
||||||
address _zrxVaultAddress
|
address _zrxVaultAddress
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
@ -71,8 +63,6 @@ contract MixinParams is
|
|||||||
_cobbDouglasAlphaNumerator,
|
_cobbDouglasAlphaNumerator,
|
||||||
_cobbDouglasAlphaDenominator,
|
_cobbDouglasAlphaDenominator,
|
||||||
_wethProxyAddress,
|
_wethProxyAddress,
|
||||||
_ethVaultAddress,
|
|
||||||
_rewardVaultAddress,
|
|
||||||
_zrxVaultAddress
|
_zrxVaultAddress
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -85,8 +75,6 @@ contract MixinParams is
|
|||||||
/// @return _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
|
/// @return _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
|
||||||
/// @return _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
|
/// @return _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
|
||||||
/// @return _wethProxyAddress The address that can transfer WETH for fees.
|
/// @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.
|
/// @return _zrxVaultAddress Address of the ZrxVault contract.
|
||||||
function getParams()
|
function getParams()
|
||||||
external
|
external
|
||||||
@ -99,8 +87,6 @@ contract MixinParams is
|
|||||||
uint32 _cobbDouglasAlphaNumerator,
|
uint32 _cobbDouglasAlphaNumerator,
|
||||||
uint32 _cobbDouglasAlphaDenominator,
|
uint32 _cobbDouglasAlphaDenominator,
|
||||||
address _wethProxyAddress,
|
address _wethProxyAddress,
|
||||||
address _ethVaultAddress,
|
|
||||||
address _rewardVaultAddress,
|
|
||||||
address _zrxVaultAddress
|
address _zrxVaultAddress
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -111,20 +97,14 @@ contract MixinParams is
|
|||||||
_cobbDouglasAlphaNumerator = cobbDouglasAlphaNumerator;
|
_cobbDouglasAlphaNumerator = cobbDouglasAlphaNumerator;
|
||||||
_cobbDouglasAlphaDenominator = cobbDouglasAlphaDenominator;
|
_cobbDouglasAlphaDenominator = cobbDouglasAlphaDenominator;
|
||||||
_wethProxyAddress = address(wethAssetProxy);
|
_wethProxyAddress = address(wethAssetProxy);
|
||||||
_ethVaultAddress = address(ethVault);
|
|
||||||
_rewardVaultAddress = address(rewardVault);
|
|
||||||
_zrxVaultAddress = address(zrxVault);
|
_zrxVaultAddress = address(zrxVault);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Initialize storage belonging to this mixin.
|
/// @dev Initialize storage belonging to this mixin.
|
||||||
/// @param _wethProxyAddress The address that can transfer WETH for fees.
|
/// @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.
|
/// @param _zrxVaultAddress Address of the ZrxVault contract.
|
||||||
function _initMixinParams(
|
function _initMixinParams(
|
||||||
address _wethProxyAddress,
|
address _wethProxyAddress,
|
||||||
address _ethVaultAddress,
|
|
||||||
address payable _rewardVaultAddress,
|
|
||||||
address _zrxVaultAddress
|
address _zrxVaultAddress
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
@ -142,8 +122,6 @@ contract MixinParams is
|
|||||||
1, // cobbDouglasAlphaNumerator
|
1, // cobbDouglasAlphaNumerator
|
||||||
2, // cobbDouglasAlphaDenominator
|
2, // cobbDouglasAlphaDenominator
|
||||||
_wethProxyAddress,
|
_wethProxyAddress,
|
||||||
_ethVaultAddress,
|
|
||||||
_rewardVaultAddress,
|
|
||||||
_zrxVaultAddress
|
_zrxVaultAddress
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -160,8 +138,6 @@ contract MixinParams is
|
|||||||
cobbDouglasAlphaNumerator != 0 &&
|
cobbDouglasAlphaNumerator != 0 &&
|
||||||
cobbDouglasAlphaDenominator != 0 &&
|
cobbDouglasAlphaDenominator != 0 &&
|
||||||
address(wethAssetProxy) != NIL_ADDRESS &&
|
address(wethAssetProxy) != NIL_ADDRESS &&
|
||||||
address(ethVault) != NIL_ADDRESS &&
|
|
||||||
address(rewardVault) != NIL_ADDRESS &&
|
|
||||||
address(zrxVault) != NIL_ADDRESS
|
address(zrxVault) != NIL_ADDRESS
|
||||||
) {
|
) {
|
||||||
LibRichErrors.rrevert(
|
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.
|
/// @dev Set all configurable parameters at once.
|
||||||
/// @param _epochDurationInSeconds Minimum seconds between epochs.
|
/// @param _epochDurationInSeconds Minimum seconds between epochs.
|
||||||
/// @param _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm.
|
/// @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 _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
|
||||||
/// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
|
/// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
|
||||||
/// @param _wethProxyAddress The address that can transfer WETH for fees.
|
/// @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.
|
/// @param _zrxVaultAddress Address of the ZrxVault contract.
|
||||||
function _setParams(
|
function _setParams(
|
||||||
uint256 _epochDurationInSeconds,
|
uint256 _epochDurationInSeconds,
|
||||||
@ -211,17 +165,10 @@ contract MixinParams is
|
|||||||
uint32 _cobbDouglasAlphaNumerator,
|
uint32 _cobbDouglasAlphaNumerator,
|
||||||
uint32 _cobbDouglasAlphaDenominator,
|
uint32 _cobbDouglasAlphaDenominator,
|
||||||
address _wethProxyAddress,
|
address _wethProxyAddress,
|
||||||
address _ethVaultAddress,
|
|
||||||
address payable _rewardVaultAddress,
|
|
||||||
address _zrxVaultAddress
|
address _zrxVaultAddress
|
||||||
)
|
)
|
||||||
private
|
private
|
||||||
{
|
{
|
||||||
_transferWETHAllownces(
|
|
||||||
[address(ethVault), address(rewardVault)],
|
|
||||||
[_ethVaultAddress, _rewardVaultAddress]
|
|
||||||
);
|
|
||||||
|
|
||||||
epochDurationInSeconds = _epochDurationInSeconds;
|
epochDurationInSeconds = _epochDurationInSeconds;
|
||||||
rewardDelegatedStakeWeight = _rewardDelegatedStakeWeight;
|
rewardDelegatedStakeWeight = _rewardDelegatedStakeWeight;
|
||||||
minimumPoolStake = _minimumPoolStake;
|
minimumPoolStake = _minimumPoolStake;
|
||||||
@ -229,8 +176,6 @@ contract MixinParams is
|
|||||||
cobbDouglasAlphaNumerator = _cobbDouglasAlphaNumerator;
|
cobbDouglasAlphaNumerator = _cobbDouglasAlphaNumerator;
|
||||||
cobbDouglasAlphaDenominator = _cobbDouglasAlphaDenominator;
|
cobbDouglasAlphaDenominator = _cobbDouglasAlphaDenominator;
|
||||||
wethAssetProxy = IAssetProxy(_wethProxyAddress);
|
wethAssetProxy = IAssetProxy(_wethProxyAddress);
|
||||||
ethVault = IEthVault(_ethVaultAddress);
|
|
||||||
rewardVault = IStakingPoolRewardVault(_rewardVaultAddress);
|
|
||||||
zrxVault = IZrxVault(_zrxVaultAddress);
|
zrxVault = IZrxVault(_zrxVaultAddress);
|
||||||
|
|
||||||
emit ParamsSet(
|
emit ParamsSet(
|
||||||
@ -241,8 +186,6 @@ contract MixinParams is
|
|||||||
_cobbDouglasAlphaNumerator,
|
_cobbDouglasAlphaNumerator,
|
||||||
_cobbDouglasAlphaDenominator,
|
_cobbDouglasAlphaDenominator,
|
||||||
_wethProxyAddress,
|
_wethProxyAddress,
|
||||||
_ethVaultAddress,
|
|
||||||
_rewardVaultAddress,
|
|
||||||
_zrxVaultAddress
|
_zrxVaultAddress
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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];
|
|
||||||
}
|
|
||||||
}
|
|
@ -33,16 +33,12 @@ contract TestAssertStorageParams is
|
|||||||
uint32 cobbDouglasAlphaNumerator;
|
uint32 cobbDouglasAlphaNumerator;
|
||||||
uint32 cobbDouglasAlphaDenominator;
|
uint32 cobbDouglasAlphaDenominator;
|
||||||
address wethProxyAddress;
|
address wethProxyAddress;
|
||||||
address ethVaultAddress;
|
|
||||||
address rewardVaultAddress;
|
|
||||||
address zrxVaultAddress;
|
address zrxVaultAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor()
|
constructor()
|
||||||
public
|
public
|
||||||
StakingProxy(
|
StakingProxy(
|
||||||
NIL_ADDRESS,
|
|
||||||
NIL_ADDRESS,
|
|
||||||
NIL_ADDRESS,
|
NIL_ADDRESS,
|
||||||
NIL_ADDRESS,
|
NIL_ADDRESS,
|
||||||
NIL_ADDRESS,
|
NIL_ADDRESS,
|
||||||
@ -60,13 +56,11 @@ contract TestAssertStorageParams is
|
|||||||
cobbDouglasAlphaNumerator = params.cobbDouglasAlphaNumerator;
|
cobbDouglasAlphaNumerator = params.cobbDouglasAlphaNumerator;
|
||||||
cobbDouglasAlphaDenominator = params.cobbDouglasAlphaDenominator;
|
cobbDouglasAlphaDenominator = params.cobbDouglasAlphaDenominator;
|
||||||
wethAssetProxy = IAssetProxy(params.wethProxyAddress);
|
wethAssetProxy = IAssetProxy(params.wethProxyAddress);
|
||||||
ethVault = IEthVault(params.ethVaultAddress);
|
|
||||||
rewardVault = IStakingPoolRewardVault(params.rewardVaultAddress);
|
|
||||||
zrxVault = IZrxVault(params.zrxVaultAddress);
|
zrxVault = IZrxVault(params.zrxVaultAddress);
|
||||||
_assertValidStorageParams();
|
_assertValidStorageParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _attachStakingContract(address, address, address, address, address)
|
function _attachStakingContract(address, address, address)
|
||||||
internal
|
internal
|
||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ contract TestCumulativeRewardTracking is
|
|||||||
|
|
||||||
constructor(address wethAddress) public TestStaking(wethAddress) {}
|
constructor(address wethAddress) public TestStaking(wethAddress) {}
|
||||||
|
|
||||||
function init(address, address, address payable, address) public {}
|
function init(address, address) public {}
|
||||||
|
|
||||||
function _forceSetCumulativeReward(
|
function _forceSetCumulativeReward(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
|
@ -20,24 +20,12 @@ pragma solidity ^0.5.9;
|
|||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "../src/interfaces/IStructs.sol";
|
import "../src/interfaces/IStructs.sol";
|
||||||
import "../src/interfaces/IStakingPoolRewardVault.sol";
|
|
||||||
import "../src/interfaces/IEthVault.sol";
|
|
||||||
import "./TestStakingNoWETH.sol";
|
import "./TestStakingNoWETH.sol";
|
||||||
|
|
||||||
|
|
||||||
contract TestDelegatorRewards is
|
contract TestDelegatorRewards is
|
||||||
TestStakingNoWETH
|
TestStakingNoWETH
|
||||||
{
|
{
|
||||||
event RecordDepositToEthVault(
|
|
||||||
address owner,
|
|
||||||
uint256 amount
|
|
||||||
);
|
|
||||||
|
|
||||||
event RecordDepositToRewardVault(
|
|
||||||
bytes32 poolId,
|
|
||||||
uint256 membersReward
|
|
||||||
);
|
|
||||||
|
|
||||||
event FinalizePool(
|
event FinalizePool(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
uint256 operatorReward,
|
uint256 operatorReward,
|
||||||
@ -51,17 +39,13 @@ contract TestDelegatorRewards is
|
|||||||
uint256 membersStake;
|
uint256 membersStake;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() public {
|
constructor()
|
||||||
|
public
|
||||||
|
{
|
||||||
init(
|
init(
|
||||||
address(1),
|
|
||||||
address(1),
|
|
||||||
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
|
mapping (uint256 => mapping (bytes32 => UnfinalizedPoolReward)) private
|
||||||
@ -93,8 +77,8 @@ contract TestDelegatorRewards is
|
|||||||
_initGenesisCumulativeRewards(poolId);
|
_initGenesisCumulativeRewards(poolId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Expose/wrap `_depositStakingPoolRewards`.
|
/// @dev Expose/wrap `_syncPoolRewards`.
|
||||||
function depositStakingPoolRewards(
|
function syncPoolRewards(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
address payable operatorAddress,
|
address payable operatorAddress,
|
||||||
uint256 operatorReward,
|
uint256 operatorReward,
|
||||||
@ -108,7 +92,7 @@ contract TestDelegatorRewards is
|
|||||||
_setOperatorShare(poolId, operatorReward, membersReward);
|
_setOperatorShare(poolId, operatorReward, membersReward);
|
||||||
_initGenesisCumulativeRewards(poolId);
|
_initGenesisCumulativeRewards(poolId);
|
||||||
|
|
||||||
_depositStakingPoolRewards(
|
_syncPoolRewards(
|
||||||
poolId,
|
poolId,
|
||||||
operatorReward + membersReward,
|
operatorReward + membersReward,
|
||||||
membersStake
|
membersStake
|
||||||
@ -122,7 +106,7 @@ contract TestDelegatorRewards is
|
|||||||
|
|
||||||
/// @dev Create and delegate stake that is active in the current epoch.
|
/// @dev Create and delegate stake that is active in the current epoch.
|
||||||
/// Only used to test purportedly unreachable states.
|
/// Only used to test purportedly unreachable states.
|
||||||
/// Also withdraws pending rewards to the eth vault.
|
/// Also withdraws pending rewards.
|
||||||
function delegateStakeNow(
|
function delegateStakeNow(
|
||||||
address delegator,
|
address delegator,
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
@ -137,7 +121,7 @@ contract TestDelegatorRewards is
|
|||||||
_stake.currentEpochBalance += uint96(stake);
|
_stake.currentEpochBalance += uint96(stake);
|
||||||
_stake.nextEpochBalance += uint96(stake);
|
_stake.nextEpochBalance += uint96(stake);
|
||||||
_stake.currentEpoch = uint32(currentEpoch);
|
_stake.currentEpoch = uint32(currentEpoch);
|
||||||
_syncRewardsForDelegator(
|
_withdrawAndSyncDelegatorRewards(
|
||||||
poolId,
|
poolId,
|
||||||
delegator,
|
delegator,
|
||||||
initialStake,
|
initialStake,
|
||||||
@ -147,7 +131,7 @@ contract TestDelegatorRewards is
|
|||||||
|
|
||||||
/// @dev Create and delegate stake that will occur in the next epoch
|
/// @dev Create and delegate stake that will occur in the next epoch
|
||||||
/// (normal behavior).
|
/// (normal behavior).
|
||||||
/// Also withdraws pending rewards to the eth vault.
|
/// Also withdraws pending rewards.
|
||||||
function delegateStake(
|
function delegateStake(
|
||||||
address delegator,
|
address delegator,
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
@ -164,7 +148,7 @@ contract TestDelegatorRewards is
|
|||||||
_stake.isInitialized = true;
|
_stake.isInitialized = true;
|
||||||
_stake.nextEpochBalance += uint96(stake);
|
_stake.nextEpochBalance += uint96(stake);
|
||||||
_stake.currentEpoch = uint32(currentEpoch);
|
_stake.currentEpoch = uint32(currentEpoch);
|
||||||
_syncRewardsForDelegator(
|
_withdrawAndSyncDelegatorRewards(
|
||||||
poolId,
|
poolId,
|
||||||
delegator,
|
delegator,
|
||||||
initialStake,
|
initialStake,
|
||||||
@ -174,7 +158,7 @@ contract TestDelegatorRewards is
|
|||||||
|
|
||||||
/// @dev Clear stake that will occur in the next epoch
|
/// @dev Clear stake that will occur in the next epoch
|
||||||
/// (normal behavior).
|
/// (normal behavior).
|
||||||
/// Also withdraws pending rewards to the eth vault.
|
/// Also withdraws pending rewards.
|
||||||
function undelegateStake(
|
function undelegateStake(
|
||||||
address delegator,
|
address delegator,
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
@ -191,7 +175,7 @@ contract TestDelegatorRewards is
|
|||||||
_stake.isInitialized = true;
|
_stake.isInitialized = true;
|
||||||
_stake.nextEpochBalance -= uint96(stake);
|
_stake.nextEpochBalance -= uint96(stake);
|
||||||
_stake.currentEpoch = uint32(currentEpoch);
|
_stake.currentEpoch = uint32(currentEpoch);
|
||||||
_syncRewardsForDelegator(
|
_withdrawAndSyncDelegatorRewards(
|
||||||
poolId,
|
poolId,
|
||||||
delegator,
|
delegator,
|
||||||
initialStake,
|
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
|
// solhint-disable no-simple-event-func-name
|
||||||
/// @dev Overridden to realize `unfinalizedPoolRewardsByEpoch` in
|
/// @dev Overridden to realize `unfinalizedPoolRewardsByEpoch` in
|
||||||
/// the current epoch and emit a event,
|
/// the current epoch and emit a event,
|
||||||
@ -245,7 +202,7 @@ contract TestDelegatorRewards is
|
|||||||
uint256 totalRewards = reward.operatorReward + reward.membersReward;
|
uint256 totalRewards = reward.operatorReward + reward.membersReward;
|
||||||
membersStake = reward.membersStake;
|
membersStake = reward.membersStake;
|
||||||
(operatorReward, membersReward) =
|
(operatorReward, membersReward) =
|
||||||
_depositStakingPoolRewards(poolId, totalRewards, membersStake);
|
_syncPoolRewards(poolId, totalRewards, membersStake);
|
||||||
emit FinalizePool(poolId, operatorReward, membersReward, membersStake);
|
emit FinalizePool(poolId, operatorReward, membersReward, membersStake);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,8 +57,6 @@ contract TestFinalizer is
|
|||||||
public
|
public
|
||||||
{
|
{
|
||||||
init(
|
init(
|
||||||
address(1),
|
|
||||||
address(1),
|
|
||||||
address(1),
|
address(1),
|
||||||
address(1)
|
address(1)
|
||||||
);
|
);
|
||||||
@ -144,7 +142,7 @@ contract TestFinalizer is
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Overridden to log and transfer to receivers.
|
/// @dev Overridden to log and transfer to receivers.
|
||||||
function _depositStakingPoolRewards(
|
function _syncPoolRewards(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
uint256 reward,
|
uint256 reward,
|
||||||
uint256 membersStake
|
uint256 membersStake
|
||||||
@ -153,7 +151,7 @@ contract TestFinalizer is
|
|||||||
returns (uint256 operatorReward, uint256 membersReward)
|
returns (uint256 operatorReward, uint256 membersReward)
|
||||||
{
|
{
|
||||||
uint32 operatorShare = _operatorSharesByPool[poolId];
|
uint32 operatorShare = _operatorSharesByPool[poolId];
|
||||||
(operatorReward, membersReward) = _computeSplitStakingPoolRewards(
|
(operatorReward, membersReward) = _computePoolRewardsSplit(
|
||||||
operatorShare,
|
operatorShare,
|
||||||
reward,
|
reward,
|
||||||
membersStake
|
membersStake
|
||||||
|
@ -37,15 +37,11 @@ contract TestInitTarget is
|
|||||||
|
|
||||||
event InitAddresses(
|
event InitAddresses(
|
||||||
address wethProxyAddress,
|
address wethProxyAddress,
|
||||||
address ethVaultAddress,
|
|
||||||
address rewardVaultAddress,
|
|
||||||
address zrxVaultAddress
|
address zrxVaultAddress
|
||||||
);
|
);
|
||||||
|
|
||||||
function init(
|
function init(
|
||||||
address wethProxyAddress,
|
address wethProxyAddress,
|
||||||
address ethVaultAddress,
|
|
||||||
address rewardVaultAddress,
|
|
||||||
address zrxVaultAddress
|
address zrxVaultAddress
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
@ -58,8 +54,6 @@ contract TestInitTarget is
|
|||||||
_initThisAddress = address(this);
|
_initThisAddress = address(this);
|
||||||
emit InitAddresses(
|
emit InitAddresses(
|
||||||
wethProxyAddress,
|
wethProxyAddress,
|
||||||
ethVaultAddress,
|
|
||||||
rewardVaultAddress,
|
|
||||||
zrxVaultAddress
|
zrxVaultAddress
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -48,8 +48,6 @@ contract TestProtocolFees is
|
|||||||
// Use this contract as the ERC20Proxy.
|
// Use this contract as the ERC20Proxy.
|
||||||
address(this),
|
address(this),
|
||||||
// vault addresses must be non-zero
|
// vault addresses must be non-zero
|
||||||
address(1),
|
|
||||||
address(1),
|
|
||||||
address(1)
|
address(1)
|
||||||
);
|
);
|
||||||
validExchanges[exchangeAddress] = true;
|
validExchanges[exchangeAddress] = true;
|
||||||
@ -98,8 +96,8 @@ contract TestProtocolFees is
|
|||||||
emit ERC20ProxyTransferFrom(assetData, from, to, amount);
|
emit ERC20ProxyTransferFrom(assetData, from, to, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWethAssetData() external pure returns (bytes memory) {
|
function getWethAssetData() external view returns (bytes memory) {
|
||||||
return WETH_ASSET_DATA;
|
return _getWethAssetData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Overridden to use test pools.
|
/// @dev Overridden to use test pools.
|
||||||
|
@ -20,6 +20,7 @@ pragma solidity ^0.5.9;
|
|||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "../src/Staking.sol";
|
import "../src/Staking.sol";
|
||||||
|
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
||||||
|
|
||||||
|
|
||||||
contract TestStaking is
|
contract TestStaking is
|
||||||
@ -32,10 +33,27 @@ contract TestStaking is
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Overridden to use testWethAddress;
|
/// @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
|
// `testWethAddress` will not be set on the proxy this contract is
|
||||||
// attached to, so we need to access the storage of the deployed
|
// attached to, so we need to access the storage of the deployed
|
||||||
// instance of this contract.
|
// 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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,17 +28,37 @@ import "../src/Staking.sol";
|
|||||||
contract TestStakingNoWETH is
|
contract TestStakingNoWETH is
|
||||||
Staking
|
Staking
|
||||||
{
|
{
|
||||||
function _transferWETHAllownces(
|
event Transfer(
|
||||||
address[2] memory oldSpenders,
|
address indexed _from,
|
||||||
address[2] memory newSpenders
|
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
|
internal
|
||||||
{}
|
{}
|
||||||
|
|
||||||
function _wrapBalanceToWETHAndGetBalance()
|
function _getAvailableWethBalance()
|
||||||
internal
|
internal
|
||||||
returns (uint256 balance)
|
view
|
||||||
|
returns (uint256)
|
||||||
{
|
{
|
||||||
return address(this).balance;
|
return address(this).balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _getWethContract()
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (IEtherToken)
|
||||||
|
{
|
||||||
|
return IEtherToken(address(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,23 +33,17 @@ contract TestStakingProxy is
|
|||||||
_stakingContract,
|
_stakingContract,
|
||||||
NIL_ADDRESS,
|
NIL_ADDRESS,
|
||||||
NIL_ADDRESS,
|
NIL_ADDRESS,
|
||||||
NIL_ADDRESS,
|
|
||||||
NIL_ADDRESS,
|
|
||||||
NIL_ADDRESS
|
NIL_ADDRESS
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
function setAddressParams(
|
function setAddressParams(
|
||||||
address _wethProxyAddress,
|
address _wethProxyAddress,
|
||||||
address _ethVaultAddress,
|
|
||||||
address payable _rewardVaultAddress,
|
|
||||||
address _zrxVaultAddress
|
address _zrxVaultAddress
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
{
|
{
|
||||||
wethAssetProxy = IAssetProxy(_wethProxyAddress);
|
wethAssetProxy = IAssetProxy(_wethProxyAddress);
|
||||||
ethVault = IEthVault(_ethVaultAddress);
|
|
||||||
rewardVault = IStakingPoolRewardVault(_rewardVaultAddress);
|
|
||||||
zrxVault = IZrxVault(_zrxVaultAddress);
|
zrxVault = IZrxVault(_zrxVaultAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -37,7 +37,7 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||||
"abis": "./generated-artifacts/@(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": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -5,11 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
import { ContractArtifact } from 'ethereum-types';
|
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 IStaking from '../generated-artifacts/IStaking.json';
|
||||||
import * as IStakingEvents from '../generated-artifacts/IStakingEvents.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 IStakingProxy from '../generated-artifacts/IStakingProxy.json';
|
||||||
import * as IStorage from '../generated-artifacts/IStorage.json';
|
import * as IStorage from '../generated-artifacts/IStorage.json';
|
||||||
import * as IStorageInit from '../generated-artifacts/IStorageInit.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 MixinVaultCore from '../generated-artifacts/MixinVaultCore.json';
|
||||||
import * as ReadOnlyProxy from '../generated-artifacts/ReadOnlyProxy.json';
|
import * as ReadOnlyProxy from '../generated-artifacts/ReadOnlyProxy.json';
|
||||||
import * as Staking from '../generated-artifacts/Staking.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 StakingProxy from '../generated-artifacts/StakingProxy.json';
|
||||||
import * as TestAssertStorageParams from '../generated-artifacts/TestAssertStorageParams.json';
|
import * as TestAssertStorageParams from '../generated-artifacts/TestAssertStorageParams.json';
|
||||||
import * as TestCobbDouglas from '../generated-artifacts/TestCobbDouglas.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 TestLibProxy from '../generated-artifacts/TestLibProxy.json';
|
||||||
import * as TestLibProxyReceiver from '../generated-artifacts/TestLibProxyReceiver.json';
|
import * as TestLibProxyReceiver from '../generated-artifacts/TestLibProxyReceiver.json';
|
||||||
import * as TestLibSafeDowncast from '../generated-artifacts/TestLibSafeDowncast.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 TestMixinVaultCore from '../generated-artifacts/TestMixinVaultCore.json';
|
||||||
import * as TestProtocolFees from '../generated-artifacts/TestProtocolFees.json';
|
import * as TestProtocolFees from '../generated-artifacts/TestProtocolFees.json';
|
||||||
import * as TestStaking from '../generated-artifacts/TestStaking.json';
|
import * as TestStaking from '../generated-artifacts/TestStaking.json';
|
||||||
import * as TestStakingNoWETH from '../generated-artifacts/TestStakingNoWETH.json';
|
import * as TestStakingNoWETH from '../generated-artifacts/TestStakingNoWETH.json';
|
||||||
import * as TestStakingProxy from '../generated-artifacts/TestStakingProxy.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';
|
import * as ZrxVault from '../generated-artifacts/ZrxVault.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
ReadOnlyProxy: ReadOnlyProxy as ContractArtifact,
|
ReadOnlyProxy: ReadOnlyProxy as ContractArtifact,
|
||||||
@ -71,10 +65,8 @@ export const artifacts = {
|
|||||||
MixinConstants: MixinConstants as ContractArtifact,
|
MixinConstants: MixinConstants as ContractArtifact,
|
||||||
MixinDeploymentConstants: MixinDeploymentConstants as ContractArtifact,
|
MixinDeploymentConstants: MixinDeploymentConstants as ContractArtifact,
|
||||||
MixinStorage: MixinStorage as ContractArtifact,
|
MixinStorage: MixinStorage as ContractArtifact,
|
||||||
IEthVault: IEthVault as ContractArtifact,
|
|
||||||
IStaking: IStaking as ContractArtifact,
|
IStaking: IStaking as ContractArtifact,
|
||||||
IStakingEvents: IStakingEvents as ContractArtifact,
|
IStakingEvents: IStakingEvents as ContractArtifact,
|
||||||
IStakingPoolRewardVault: IStakingPoolRewardVault as ContractArtifact,
|
|
||||||
IStakingProxy: IStakingProxy as ContractArtifact,
|
IStakingProxy: IStakingProxy as ContractArtifact,
|
||||||
IStorage: IStorage as ContractArtifact,
|
IStorage: IStorage as ContractArtifact,
|
||||||
IStorageInit: IStorageInit as ContractArtifact,
|
IStorageInit: IStorageInit as ContractArtifact,
|
||||||
@ -99,9 +91,7 @@ export const artifacts = {
|
|||||||
MixinFinalizer: MixinFinalizer as ContractArtifact,
|
MixinFinalizer: MixinFinalizer as ContractArtifact,
|
||||||
MixinParams: MixinParams as ContractArtifact,
|
MixinParams: MixinParams as ContractArtifact,
|
||||||
MixinScheduler: MixinScheduler as ContractArtifact,
|
MixinScheduler: MixinScheduler as ContractArtifact,
|
||||||
EthVault: EthVault as ContractArtifact,
|
|
||||||
MixinVaultCore: MixinVaultCore as ContractArtifact,
|
MixinVaultCore: MixinVaultCore as ContractArtifact,
|
||||||
StakingPoolRewardVault: StakingPoolRewardVault as ContractArtifact,
|
|
||||||
ZrxVault: ZrxVault as ContractArtifact,
|
ZrxVault: ZrxVault as ContractArtifact,
|
||||||
TestAssertStorageParams: TestAssertStorageParams as ContractArtifact,
|
TestAssertStorageParams: TestAssertStorageParams as ContractArtifact,
|
||||||
TestCobbDouglas: TestCobbDouglas as ContractArtifact,
|
TestCobbDouglas: TestCobbDouglas as ContractArtifact,
|
||||||
@ -113,11 +103,9 @@ export const artifacts = {
|
|||||||
TestLibProxy: TestLibProxy as ContractArtifact,
|
TestLibProxy: TestLibProxy as ContractArtifact,
|
||||||
TestLibProxyReceiver: TestLibProxyReceiver as ContractArtifact,
|
TestLibProxyReceiver: TestLibProxyReceiver as ContractArtifact,
|
||||||
TestLibSafeDowncast: TestLibSafeDowncast as ContractArtifact,
|
TestLibSafeDowncast: TestLibSafeDowncast as ContractArtifact,
|
||||||
TestMixinParams: TestMixinParams as ContractArtifact,
|
|
||||||
TestMixinVaultCore: TestMixinVaultCore as ContractArtifact,
|
TestMixinVaultCore: TestMixinVaultCore as ContractArtifact,
|
||||||
TestProtocolFees: TestProtocolFees as ContractArtifact,
|
TestProtocolFees: TestProtocolFees as ContractArtifact,
|
||||||
TestStaking: TestStaking as ContractArtifact,
|
TestStaking: TestStaking as ContractArtifact,
|
||||||
TestStakingNoWETH: TestStakingNoWETH as ContractArtifact,
|
TestStakingNoWETH: TestStakingNoWETH as ContractArtifact,
|
||||||
TestStakingProxy: TestStakingProxy as ContractArtifact,
|
TestStakingProxy: TestStakingProxy as ContractArtifact,
|
||||||
TestStorageLayout: TestStorageLayout as ContractArtifact,
|
|
||||||
};
|
};
|
||||||
|
@ -3,11 +3,8 @@
|
|||||||
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
* 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';
|
||||||
export * from '../generated-wrappers/i_staking_events';
|
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_staking_proxy';
|
||||||
export * from '../generated-wrappers/i_storage';
|
export * from '../generated-wrappers/i_storage';
|
||||||
export * from '../generated-wrappers/i_storage_init';
|
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/mixin_vault_core';
|
||||||
export * from '../generated-wrappers/read_only_proxy';
|
export * from '../generated-wrappers/read_only_proxy';
|
||||||
export * from '../generated-wrappers/staking';
|
export * from '../generated-wrappers/staking';
|
||||||
export * from '../generated-wrappers/staking_pool_reward_vault';
|
|
||||||
export * from '../generated-wrappers/staking_proxy';
|
export * from '../generated-wrappers/staking_proxy';
|
||||||
export * from '../generated-wrappers/test_assert_storage_params';
|
export * from '../generated-wrappers/test_assert_storage_params';
|
||||||
export * from '../generated-wrappers/test_cobb_douglas';
|
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';
|
||||||
export * from '../generated-wrappers/test_lib_proxy_receiver';
|
export * from '../generated-wrappers/test_lib_proxy_receiver';
|
||||||
export * from '../generated-wrappers/test_lib_safe_downcast';
|
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_mixin_vault_core';
|
||||||
export * from '../generated-wrappers/test_protocol_fees';
|
export * from '../generated-wrappers/test_protocol_fees';
|
||||||
export * from '../generated-wrappers/test_staking';
|
export * from '../generated-wrappers/test_staking';
|
||||||
export * from '../generated-wrappers/test_staking_no_w_e_t_h';
|
export * from '../generated-wrappers/test_staking_no_w_e_t_h';
|
||||||
export * from '../generated-wrappers/test_staking_proxy';
|
export * from '../generated-wrappers/test_staking_proxy';
|
||||||
export * from '../generated-wrappers/test_storage_layout';
|
|
||||||
export * from '../generated-wrappers/zrx_vault';
|
export * from '../generated-wrappers/zrx_vault';
|
||||||
|
@ -10,8 +10,8 @@ import {
|
|||||||
OperatorBalanceByPoolId,
|
OperatorBalanceByPoolId,
|
||||||
OperatorByPoolId,
|
OperatorByPoolId,
|
||||||
OperatorShareByPoolId,
|
OperatorShareByPoolId,
|
||||||
|
RewardBalanceByPoolId,
|
||||||
RewardByPoolId,
|
RewardByPoolId,
|
||||||
RewardVaultBalanceByPoolId,
|
|
||||||
} from '../utils/types';
|
} from '../utils/types';
|
||||||
|
|
||||||
import { BaseActor } from './base_actor';
|
import { BaseActor } from './base_actor';
|
||||||
@ -40,7 +40,7 @@ export class FinalizerActor extends BaseActor {
|
|||||||
public async finalizeAsync(): Promise<void> {
|
public async finalizeAsync(): Promise<void> {
|
||||||
// cache initial info and balances
|
// cache initial info and balances
|
||||||
const operatorShareByPoolId = await this._getOperatorShareByPoolIdAsync(this._poolIds);
|
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 delegatorBalancesByPoolId = await this._getDelegatorBalancesByPoolIdAsync(this._delegatorsByPoolId);
|
||||||
const delegatorStakesByPoolId = await this._getDelegatorStakesByPoolIdAsync(this._delegatorsByPoolId);
|
const delegatorStakesByPoolId = await this._getDelegatorStakesByPoolIdAsync(this._delegatorsByPoolId);
|
||||||
const operatorBalanceByPoolId = await this._getOperatorBalanceByPoolIdAsync(this._operatorByPoolId);
|
const operatorBalanceByPoolId = await this._getOperatorBalanceByPoolIdAsync(this._operatorByPoolId);
|
||||||
@ -48,11 +48,11 @@ export class FinalizerActor extends BaseActor {
|
|||||||
// compute expected changes
|
// compute expected changes
|
||||||
const [
|
const [
|
||||||
expectedOperatorBalanceByPoolId,
|
expectedOperatorBalanceByPoolId,
|
||||||
expectedRewardVaultBalanceByPoolId,
|
expectedRewardBalanceByPoolId,
|
||||||
] = await this._computeExpectedRewardVaultBalanceAsyncByPoolIdAsync(
|
] = this._computeExpectedRewardBalanceByPoolId(
|
||||||
rewardByPoolId,
|
rewardByPoolId,
|
||||||
operatorBalanceByPoolId,
|
operatorBalanceByPoolId,
|
||||||
rewardVaultBalanceByPoolId,
|
rewardBalanceByPoolId,
|
||||||
delegatorStakesByPoolId,
|
delegatorStakesByPoolId,
|
||||||
operatorShareByPoolId,
|
operatorShareByPoolId,
|
||||||
);
|
);
|
||||||
@ -65,19 +65,19 @@ export class FinalizerActor extends BaseActor {
|
|||||||
);
|
);
|
||||||
// finalize
|
// finalize
|
||||||
await this._stakingApiWrapper.utils.skipToNextEpochAndFinalizeAsync();
|
await this._stakingApiWrapper.utils.skipToNextEpochAndFinalizeAsync();
|
||||||
// assert reward vault changes
|
// assert reward changes
|
||||||
const finalRewardVaultBalanceByPoolId = await this._getRewardVaultBalanceByPoolIdAsync(this._poolIds);
|
const finalRewardBalanceByPoolId = await this._getRewardBalanceByPoolIdAsync(this._poolIds);
|
||||||
expect(finalRewardVaultBalanceByPoolId, 'final pool balances in reward vault').to.be.deep.equal(
|
expect(finalRewardBalanceByPoolId, 'final pool reward balances').to.be.deep.equal(
|
||||||
expectedRewardVaultBalanceByPoolId,
|
expectedRewardBalanceByPoolId,
|
||||||
);
|
);
|
||||||
// assert delegator balances
|
// assert delegator balances
|
||||||
const finalDelegatorBalancesByPoolId = await this._getDelegatorBalancesByPoolIdAsync(this._delegatorsByPoolId);
|
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,
|
expectedDelegatorBalancesByPoolId,
|
||||||
);
|
);
|
||||||
// assert operator balances
|
// assert operator balances
|
||||||
const finalOperatorBalanceByPoolId = await this._getOperatorBalanceByPoolIdAsync(this._operatorByPoolId);
|
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,
|
expectedOperatorBalanceByPoolId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -159,40 +159,40 @@ export class FinalizerActor extends BaseActor {
|
|||||||
return delegatorBalancesByPoolId;
|
return delegatorBalancesByPoolId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _computeExpectedRewardVaultBalanceAsyncByPoolIdAsync(
|
private _computeExpectedRewardBalanceByPoolId(
|
||||||
rewardByPoolId: RewardByPoolId,
|
rewardByPoolId: RewardByPoolId,
|
||||||
operatorBalanceByPoolId: OperatorBalanceByPoolId,
|
operatorBalanceByPoolId: OperatorBalanceByPoolId,
|
||||||
rewardVaultBalanceByPoolId: RewardVaultBalanceByPoolId,
|
rewardBalanceByPoolId: RewardBalanceByPoolId,
|
||||||
delegatorStakesByPoolId: DelegatorBalancesByPoolId,
|
delegatorStakesByPoolId: DelegatorBalancesByPoolId,
|
||||||
operatorShareByPoolId: OperatorShareByPoolId,
|
operatorShareByPoolId: OperatorShareByPoolId,
|
||||||
): Promise<[RewardVaultBalanceByPoolId, OperatorBalanceByPoolId]> {
|
): [RewardBalanceByPoolId, OperatorBalanceByPoolId] {
|
||||||
const expectedOperatorBalanceByPoolId = _.cloneDeep(operatorBalanceByPoolId);
|
const expectedOperatorBalanceByPoolId = _.cloneDeep(operatorBalanceByPoolId);
|
||||||
const expectedRewardVaultBalanceByPoolId = _.cloneDeep(rewardVaultBalanceByPoolId);
|
const expectedRewardBalanceByPoolId = _.cloneDeep(rewardBalanceByPoolId);
|
||||||
for (const poolId of Object.keys(rewardByPoolId)) {
|
for (const poolId of Object.keys(rewardByPoolId)) {
|
||||||
const operatorShare = operatorShareByPoolId[poolId];
|
const operatorShare = operatorShareByPoolId[poolId];
|
||||||
[
|
[
|
||||||
expectedOperatorBalanceByPoolId[poolId],
|
expectedOperatorBalanceByPoolId[poolId],
|
||||||
expectedRewardVaultBalanceByPoolId[poolId],
|
expectedRewardBalanceByPoolId[poolId],
|
||||||
] = await this._computeExpectedRewardVaultBalanceAsync(
|
] = this._computeExpectedRewardBalance(
|
||||||
poolId,
|
poolId,
|
||||||
rewardByPoolId[poolId],
|
rewardByPoolId[poolId],
|
||||||
expectedOperatorBalanceByPoolId[poolId],
|
expectedOperatorBalanceByPoolId[poolId],
|
||||||
expectedRewardVaultBalanceByPoolId[poolId],
|
expectedRewardBalanceByPoolId[poolId],
|
||||||
delegatorStakesByPoolId[poolId],
|
delegatorStakesByPoolId[poolId],
|
||||||
operatorShare,
|
operatorShare,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return [expectedOperatorBalanceByPoolId, expectedRewardVaultBalanceByPoolId];
|
return [expectedOperatorBalanceByPoolId, expectedRewardBalanceByPoolId];
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _computeExpectedRewardVaultBalanceAsync(
|
private _computeExpectedRewardBalance(
|
||||||
poolId: string,
|
poolId: string,
|
||||||
reward: BigNumber,
|
reward: BigNumber,
|
||||||
operatorBalance: BigNumber,
|
operatorBalance: BigNumber,
|
||||||
rewardVaultBalance: BigNumber,
|
rewardBalance: BigNumber,
|
||||||
stakeBalances: BalanceByOwner,
|
stakeBalances: BalanceByOwner,
|
||||||
operatorShare: BigNumber,
|
operatorShare: BigNumber,
|
||||||
): Promise<[BigNumber, BigNumber]> {
|
): [BigNumber, BigNumber] {
|
||||||
const totalStakeDelegatedToPool = BigNumber.sum(...Object.values(stakeBalances));
|
const totalStakeDelegatedToPool = BigNumber.sum(...Object.values(stakeBalances));
|
||||||
const stakeDelegatedToPoolByOperator = stakeBalances[this._operatorByPoolId[poolId]];
|
const stakeDelegatedToPoolByOperator = stakeBalances[this._operatorByPoolId[poolId]];
|
||||||
const membersStakeDelegatedToPool = totalStakeDelegatedToPool.minus(stakeDelegatedToPoolByOperator);
|
const membersStakeDelegatedToPool = totalStakeDelegatedToPool.minus(stakeDelegatedToPoolByOperator);
|
||||||
@ -200,7 +200,7 @@ export class FinalizerActor extends BaseActor {
|
|||||||
? reward
|
? reward
|
||||||
: reward.times(operatorShare).dividedToIntegerBy(PPM_100_PERCENT);
|
: reward.times(operatorShare).dividedToIntegerBy(PPM_100_PERCENT);
|
||||||
const membersPortion = reward.minus(operatorPortion);
|
const membersPortion = reward.minus(operatorPortion);
|
||||||
return [operatorBalance.plus(operatorPortion), rewardVaultBalance.plus(membersPortion)];
|
return [operatorBalance.plus(operatorPortion), rewardBalance.plus(membersPortion)];
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _getOperatorBalanceByPoolIdAsync(
|
private async _getOperatorBalanceByPoolIdAsync(
|
||||||
@ -208,7 +208,7 @@ export class FinalizerActor extends BaseActor {
|
|||||||
): Promise<OperatorBalanceByPoolId> {
|
): Promise<OperatorBalanceByPoolId> {
|
||||||
const operatorBalanceByPoolId: OperatorBalanceByPoolId = {};
|
const operatorBalanceByPoolId: OperatorBalanceByPoolId = {};
|
||||||
for (const poolId of Object.keys(operatorByPoolId)) {
|
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],
|
operatorByPoolId[poolId],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -225,14 +225,14 @@ export class FinalizerActor extends BaseActor {
|
|||||||
return operatorShareByPoolId;
|
return operatorShareByPoolId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _getRewardVaultBalanceByPoolIdAsync(poolIds: string[]): Promise<RewardVaultBalanceByPoolId> {
|
private async _getRewardBalanceByPoolIdAsync(poolIds: string[]): Promise<RewardBalanceByPoolId> {
|
||||||
const rewardVaultBalanceByPoolId: RewardVaultBalanceByPoolId = {};
|
const rewardBalanceByPoolId: RewardBalanceByPoolId = {};
|
||||||
for (const poolId of poolIds) {
|
for (const poolId of poolIds) {
|
||||||
rewardVaultBalanceByPoolId[poolId] = await this._stakingApiWrapper.rewardVaultContract.balanceOf.callAsync(
|
rewardBalanceByPoolId[poolId] = await this._stakingApiWrapper.stakingContract.rewardsByPoolId.callAsync(
|
||||||
poolId,
|
poolId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return rewardVaultBalanceByPoolId;
|
return rewardBalanceByPoolId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _getRewardByPoolIdAsync(poolIds: string[]): Promise<RewardByPoolId> {
|
private async _getRewardByPoolIdAsync(poolIds: string[]): Promise<RewardByPoolId> {
|
||||||
@ -241,9 +241,7 @@ export class FinalizerActor extends BaseActor {
|
|||||||
this._stakingApiWrapper.stakingContract.getActiveStakingPoolThisEpoch.callAsync(poolId),
|
this._stakingApiWrapper.stakingContract.getActiveStakingPoolThisEpoch.callAsync(poolId),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const totalRewards = await this._stakingApiWrapper.utils.getEthAndWethBalanceOfAsync(
|
const totalRewards = await this._stakingApiWrapper.stakingContract.getAvailableRewardsBalance.callAsync();
|
||||||
this._stakingApiWrapper.stakingContract.address,
|
|
||||||
);
|
|
||||||
const totalFeesCollected = BigNumber.sum(...activePools.map(p => p.feesCollected));
|
const totalFeesCollected = BigNumber.sum(...activePools.map(p => p.feesCollected));
|
||||||
const totalWeightedStake = BigNumber.sum(...activePools.map(p => p.weightedStake));
|
const totalWeightedStake = BigNumber.sum(...activePools.map(p => p.weightedStake));
|
||||||
if (totalRewards.eq(0) || totalFeesCollected.eq(0) || totalWeightedStake.eq(0)) {
|
if (totalRewards.eq(0) || totalFeesCollected.eq(0) || totalWeightedStake.eq(0)) {
|
||||||
|
@ -155,8 +155,8 @@ export class StakerActor extends BaseActor {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async syncDelegatorRewardsAsync(poolId: string, revertError?: RevertError): Promise<void> {
|
public async withdrawDelegatorRewardsAsync(poolId: string, revertError?: RevertError): Promise<void> {
|
||||||
const txReceiptPromise = this._stakingApiWrapper.stakingContract.syncDelegatorRewards.awaitTransactionSuccessAsync(
|
const txReceiptPromise = this._stakingApiWrapper.stakingContract.withdrawDelegatorRewards.awaitTransactionSuccessAsync(
|
||||||
poolId,
|
poolId,
|
||||||
{ from: this._owner },
|
{ from: this._owner },
|
||||||
);
|
);
|
||||||
|
@ -101,8 +101,6 @@ blockchainTests('Migration tests', env => {
|
|||||||
|
|
||||||
it('should set the correct initial params', async () => {
|
it('should set the correct initial params', async () => {
|
||||||
const wethProxyAddress = randomAddress();
|
const wethProxyAddress = randomAddress();
|
||||||
const ethVaultAddress = randomAddress();
|
|
||||||
const rewardVaultAddress = randomAddress();
|
|
||||||
const zrxVaultAddress = randomAddress();
|
const zrxVaultAddress = randomAddress();
|
||||||
|
|
||||||
const stakingProxyContractAddress = (await StakingProxyContract.deployFrom0xArtifactAsync(
|
const stakingProxyContractAddress = (await StakingProxyContract.deployFrom0xArtifactAsync(
|
||||||
@ -113,8 +111,6 @@ blockchainTests('Migration tests', env => {
|
|||||||
stakingContract.address,
|
stakingContract.address,
|
||||||
stakingContract.address,
|
stakingContract.address,
|
||||||
wethProxyAddress,
|
wethProxyAddress,
|
||||||
ethVaultAddress,
|
|
||||||
rewardVaultAddress,
|
|
||||||
zrxVaultAddress,
|
zrxVaultAddress,
|
||||||
)).address;
|
)).address;
|
||||||
|
|
||||||
@ -131,9 +127,7 @@ blockchainTests('Migration tests', env => {
|
|||||||
expect(params[4]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaNumerator);
|
expect(params[4]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaNumerator);
|
||||||
expect(params[5]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaDenominator);
|
expect(params[5]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaDenominator);
|
||||||
expect(params[6]).to.eq(wethProxyAddress);
|
expect(params[6]).to.eq(wethProxyAddress);
|
||||||
expect(params[7]).to.eq(ethVaultAddress);
|
expect(params[7]).to.eq(zrxVaultAddress);
|
||||||
expect(params[8]).to.eq(rewardVaultAddress);
|
|
||||||
expect(params[9]).to.eq(zrxVaultAddress);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -149,8 +143,6 @@ blockchainTests('Migration tests', env => {
|
|||||||
initTargetContract.address,
|
initTargetContract.address,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
{
|
{
|
||||||
from: notAuthorizedAddress,
|
from: notAuthorizedAddress,
|
||||||
},
|
},
|
||||||
@ -164,8 +156,6 @@ blockchainTests('Migration tests', env => {
|
|||||||
initTargetContract.address,
|
initTargetContract.address,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
);
|
);
|
||||||
await assertInitStateAsync(proxyContract);
|
await assertInitStateAsync(proxyContract);
|
||||||
});
|
});
|
||||||
@ -175,8 +165,6 @@ blockchainTests('Migration tests', env => {
|
|||||||
initTargetContract.address,
|
initTargetContract.address,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
);
|
);
|
||||||
const logsArgs = filterLogsToArguments<TestStakingProxyStakingContractAttachedToProxyEventArgs>(
|
const logsArgs = filterLogsToArguments<TestStakingProxyStakingContractAttachedToProxyEventArgs>(
|
||||||
receipt.logs,
|
receipt.logs,
|
||||||
@ -195,29 +183,18 @@ blockchainTests('Migration tests', env => {
|
|||||||
initTargetContract.address,
|
initTargetContract.address,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
);
|
);
|
||||||
return expect(tx).to.revertWith(INIT_REVERT_ERROR);
|
return expect(tx).to.revertWith(INIT_REVERT_ERROR);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls init with initialized addresses if passed in args are null', async () => {
|
it('calls init with initialized addresses if passed in args are null', async () => {
|
||||||
const wethProxyAddress = randomAddress();
|
const wethProxyAddress = randomAddress();
|
||||||
const ethVaultAddress = randomAddress();
|
|
||||||
const rewardVaultAddress = randomAddress();
|
|
||||||
const zrxVaultAddress = randomAddress();
|
const zrxVaultAddress = randomAddress();
|
||||||
await proxyContract.setAddressParams.awaitTransactionSuccessAsync(
|
await proxyContract.setAddressParams.awaitTransactionSuccessAsync(wethProxyAddress, zrxVaultAddress);
|
||||||
wethProxyAddress,
|
|
||||||
ethVaultAddress,
|
|
||||||
rewardVaultAddress,
|
|
||||||
zrxVaultAddress,
|
|
||||||
);
|
|
||||||
const receipt = await proxyContract.attachStakingContract.awaitTransactionSuccessAsync(
|
const receipt = await proxyContract.attachStakingContract.awaitTransactionSuccessAsync(
|
||||||
initTargetContract.address,
|
initTargetContract.address,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
);
|
);
|
||||||
const logsArgs = filterLogsToArguments<TestInitTargetInitAddressesEventArgs>(
|
const logsArgs = filterLogsToArguments<TestInitTargetInitAddressesEventArgs>(
|
||||||
receipt.logs,
|
receipt.logs,
|
||||||
@ -225,21 +202,15 @@ blockchainTests('Migration tests', env => {
|
|||||||
);
|
);
|
||||||
for (const args of logsArgs) {
|
for (const args of logsArgs) {
|
||||||
expect(args.wethProxyAddress).to.eq(wethProxyAddress);
|
expect(args.wethProxyAddress).to.eq(wethProxyAddress);
|
||||||
expect(args.ethVaultAddress).to.eq(ethVaultAddress);
|
|
||||||
expect(args.rewardVaultAddress).to.eq(rewardVaultAddress);
|
|
||||||
expect(args.zrxVaultAddress).to.eq(zrxVaultAddress);
|
expect(args.zrxVaultAddress).to.eq(zrxVaultAddress);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
it('calls init with passed in addresses if they are not null', async () => {
|
it('calls init with passed in addresses if they are not null', async () => {
|
||||||
const wethProxyAddress = randomAddress();
|
const wethProxyAddress = randomAddress();
|
||||||
const ethVaultAddress = randomAddress();
|
|
||||||
const rewardVaultAddress = randomAddress();
|
|
||||||
const zrxVaultAddress = randomAddress();
|
const zrxVaultAddress = randomAddress();
|
||||||
const receipt = await proxyContract.attachStakingContract.awaitTransactionSuccessAsync(
|
const receipt = await proxyContract.attachStakingContract.awaitTransactionSuccessAsync(
|
||||||
initTargetContract.address,
|
initTargetContract.address,
|
||||||
wethProxyAddress,
|
wethProxyAddress,
|
||||||
ethVaultAddress,
|
|
||||||
rewardVaultAddress,
|
|
||||||
zrxVaultAddress,
|
zrxVaultAddress,
|
||||||
);
|
);
|
||||||
const logsArgs = filterLogsToArguments<TestInitTargetInitAddressesEventArgs>(
|
const logsArgs = filterLogsToArguments<TestInitTargetInitAddressesEventArgs>(
|
||||||
@ -248,8 +219,6 @@ blockchainTests('Migration tests', env => {
|
|||||||
);
|
);
|
||||||
for (const args of logsArgs) {
|
for (const args of logsArgs) {
|
||||||
expect(args.wethProxyAddress).to.eq(wethProxyAddress);
|
expect(args.wethProxyAddress).to.eq(wethProxyAddress);
|
||||||
expect(args.ethVaultAddress).to.eq(ethVaultAddress);
|
|
||||||
expect(args.rewardVaultAddress).to.eq(rewardVaultAddress);
|
|
||||||
expect(args.zrxVaultAddress).to.eq(zrxVaultAddress);
|
expect(args.zrxVaultAddress).to.eq(zrxVaultAddress);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -259,8 +228,6 @@ blockchainTests('Migration tests', env => {
|
|||||||
revertAddress,
|
revertAddress,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
);
|
);
|
||||||
return expect(tx).to.revertWith(STORAGE_PARAMS_REVERT_ERROR);
|
return expect(tx).to.revertWith(STORAGE_PARAMS_REVERT_ERROR);
|
||||||
});
|
});
|
||||||
@ -273,8 +240,6 @@ blockchainTests('Migration tests', env => {
|
|||||||
initTargetContract.address,
|
initTargetContract.address,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
);
|
);
|
||||||
const initCounter = await initTargetContract.getInitCounter.callAsync({ to: proxyContract.address });
|
const initCounter = await initTargetContract.getInitCounter.callAsync({ to: proxyContract.address });
|
||||||
expect(initCounter).to.bignumber.eq(2);
|
expect(initCounter).to.bignumber.eq(2);
|
||||||
@ -284,32 +249,16 @@ blockchainTests('Migration tests', env => {
|
|||||||
|
|
||||||
blockchainTests.resets('Staking.init()', async () => {
|
blockchainTests.resets('Staking.init()', async () => {
|
||||||
it('throws if not called by an authorized address', async () => {
|
it('throws if not called by an authorized address', async () => {
|
||||||
const tx = stakingContract.init.awaitTransactionSuccessAsync(
|
const tx = stakingContract.init.awaitTransactionSuccessAsync(randomAddress(), randomAddress(), {
|
||||||
randomAddress(),
|
|
||||||
randomAddress(),
|
|
||||||
randomAddress(),
|
|
||||||
randomAddress(),
|
|
||||||
{
|
|
||||||
from: notAuthorizedAddress,
|
from: notAuthorizedAddress,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
const expectedError = new AuthorizableRevertErrors.SenderNotAuthorizedError(notAuthorizedAddress);
|
const expectedError = new AuthorizableRevertErrors.SenderNotAuthorizedError(notAuthorizedAddress);
|
||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws if already intitialized', async () => {
|
it('throws if already intitialized', async () => {
|
||||||
await stakingContract.init.awaitTransactionSuccessAsync(
|
await stakingContract.init.awaitTransactionSuccessAsync(randomAddress(), randomAddress());
|
||||||
randomAddress(),
|
const tx = stakingContract.init.awaitTransactionSuccessAsync(randomAddress(), randomAddress());
|
||||||
randomAddress(),
|
|
||||||
randomAddress(),
|
|
||||||
randomAddress(),
|
|
||||||
);
|
|
||||||
const tx = stakingContract.init.awaitTransactionSuccessAsync(
|
|
||||||
randomAddress(),
|
|
||||||
randomAddress(),
|
|
||||||
randomAddress(),
|
|
||||||
randomAddress(),
|
|
||||||
);
|
|
||||||
const expectedError = new StakingRevertErrors.InitializationError();
|
const expectedError = new StakingRevertErrors.InitializationError();
|
||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
@ -441,26 +390,6 @@ blockchainTests('Migration tests', env => {
|
|||||||
);
|
);
|
||||||
expect(tx).to.revertWith(expectedError);
|
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 () => {
|
it('reverts if zrxVault is 0', async () => {
|
||||||
const tx = proxyContract.setAndAssertParams.awaitTransactionSuccessAsync({
|
const tx = proxyContract.setAndAssertParams.awaitTransactionSuccessAsync({
|
||||||
...stakingConstants.DEFAULT_PARAMS,
|
...stakingConstants.DEFAULT_PARAMS,
|
||||||
|
@ -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 { AuthorizableRevertErrors, BigNumber } from '@0x/utils';
|
||||||
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {
|
import { artifacts, IStakingEventsParamsSetEventArgs, MixinParamsContract } from '../src/';
|
||||||
artifacts,
|
|
||||||
IStakingEventsParamsSetEventArgs,
|
|
||||||
TestMixinParamsContract,
|
|
||||||
TestMixinParamsEvents,
|
|
||||||
TestMixinParamsWETHApproveEventArgs,
|
|
||||||
} from '../src/';
|
|
||||||
|
|
||||||
import { constants as stakingConstants } from './utils/constants';
|
import { constants as stakingConstants } from './utils/constants';
|
||||||
import { StakingParams } from './utils/types';
|
import { StakingParams } from './utils/types';
|
||||||
|
|
||||||
blockchainTests('Configurable Parameters unit tests', env => {
|
blockchainTests('Configurable Parameters unit tests', env => {
|
||||||
let testContract: TestMixinParamsContract;
|
let testContract: MixinParamsContract;
|
||||||
let authorizedAddress: string;
|
let authorizedAddress: string;
|
||||||
let notAuthorizedAddress: string;
|
let notAuthorizedAddress: string;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
[authorizedAddress, notAuthorizedAddress] = await env.getAccountAddressesAsync();
|
[authorizedAddress, notAuthorizedAddress] = await env.getAccountAddressesAsync();
|
||||||
testContract = await TestMixinParamsContract.deployFrom0xArtifactAsync(
|
testContract = await MixinParamsContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.TestMixinParams,
|
artifacts.MixinParams,
|
||||||
env.provider,
|
env.provider,
|
||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
artifacts,
|
artifacts,
|
||||||
@ -46,8 +40,6 @@ blockchainTests('Configurable Parameters unit tests', env => {
|
|||||||
new BigNumber(_params.cobbDouglasAlphaNumerator),
|
new BigNumber(_params.cobbDouglasAlphaNumerator),
|
||||||
new BigNumber(_params.cobbDouglasAlphaDenominator),
|
new BigNumber(_params.cobbDouglasAlphaDenominator),
|
||||||
_params.wethProxyAddress,
|
_params.wethProxyAddress,
|
||||||
_params.ethVaultAddress,
|
|
||||||
_params.rewardVaultAddress,
|
|
||||||
_params.zrxVaultAddress,
|
_params.zrxVaultAddress,
|
||||||
{ from },
|
{ from },
|
||||||
);
|
);
|
||||||
@ -62,8 +54,6 @@ blockchainTests('Configurable Parameters unit tests', env => {
|
|||||||
expect(event.cobbDouglasAlphaNumerator).to.bignumber.eq(_params.cobbDouglasAlphaNumerator);
|
expect(event.cobbDouglasAlphaNumerator).to.bignumber.eq(_params.cobbDouglasAlphaNumerator);
|
||||||
expect(event.cobbDouglasAlphaDenominator).to.bignumber.eq(_params.cobbDouglasAlphaDenominator);
|
expect(event.cobbDouglasAlphaDenominator).to.bignumber.eq(_params.cobbDouglasAlphaDenominator);
|
||||||
expect(event.wethProxyAddress).to.eq(_params.wethProxyAddress);
|
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);
|
expect(event.zrxVaultAddress).to.eq(_params.zrxVaultAddress);
|
||||||
// Assert `getParams()`.
|
// Assert `getParams()`.
|
||||||
const actual = await testContract.getParams.callAsync();
|
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[4]).to.bignumber.eq(_params.cobbDouglasAlphaNumerator);
|
||||||
expect(actual[5]).to.bignumber.eq(_params.cobbDouglasAlphaDenominator);
|
expect(actual[5]).to.bignumber.eq(_params.cobbDouglasAlphaDenominator);
|
||||||
expect(actual[6]).to.eq(_params.wethProxyAddress);
|
expect(actual[6]).to.eq(_params.wethProxyAddress);
|
||||||
expect(actual[7]).to.eq(_params.ethVaultAddress);
|
expect(actual[7]).to.eq(_params.zrxVaultAddress);
|
||||||
expect(actual[8]).to.eq(_params.rewardVaultAddress);
|
|
||||||
expect(actual[9]).to.eq(_params.zrxVaultAddress);
|
|
||||||
return receipt;
|
return receipt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,43 +77,6 @@ blockchainTests('Configurable Parameters unit tests', env => {
|
|||||||
it('works if called by owner', async () => {
|
it('works if called by owner', async () => {
|
||||||
return setParamsAndAssertAsync({});
|
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
|
// tslint:enable:no-unnecessary-type-assertion
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ERC20Wrapper } from '@0x/contracts-asset-proxy';
|
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 { BigNumber } from '@0x/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
@ -46,8 +46,6 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
minimumPoolStake: new BigNumber(2),
|
minimumPoolStake: new BigNumber(2),
|
||||||
cobbDouglasAlphaNumerator: new BigNumber(1),
|
cobbDouglasAlphaNumerator: new BigNumber(1),
|
||||||
cobbDouglasAlphaDenominator: new BigNumber(6),
|
cobbDouglasAlphaDenominator: new BigNumber(6),
|
||||||
rewardVaultAddress: stakingApiWrapper.rewardVaultContract.address,
|
|
||||||
ethVaultAddress: stakingApiWrapper.ethVaultContract.address,
|
|
||||||
zrxVaultAddress: stakingApiWrapper.zrxVaultContract.address,
|
zrxVaultAddress: stakingApiWrapper.zrxVaultContract.address,
|
||||||
});
|
});
|
||||||
// setup stakers
|
// setup stakers
|
||||||
@ -75,47 +73,47 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
describe('Reward Simulation', () => {
|
describe('Reward Simulation', () => {
|
||||||
interface EndBalances {
|
interface EndBalances {
|
||||||
// staker 1
|
// staker 1
|
||||||
stakerRewardVaultBalance_1?: BigNumber;
|
stakerRewardBalance_1?: BigNumber;
|
||||||
stakerEthVaultBalance_1?: BigNumber;
|
stakerWethBalance_1?: BigNumber;
|
||||||
// staker 2
|
// staker 2
|
||||||
stakerRewardVaultBalance_2?: BigNumber;
|
stakerRewardBalance_2?: BigNumber;
|
||||||
stakerEthVaultBalance_2?: BigNumber;
|
stakerWethBalance_2?: BigNumber;
|
||||||
// operator
|
// operator
|
||||||
operatorEthVaultBalance?: BigNumber;
|
operatorWethBalance?: BigNumber;
|
||||||
// undivided balance in reward pool
|
// undivided balance in reward pool
|
||||||
poolRewardVaultBalance?: BigNumber;
|
poolRewardBalance?: BigNumber;
|
||||||
membersRewardVaultBalance?: BigNumber;
|
membersRewardBalance?: BigNumber;
|
||||||
}
|
}
|
||||||
const validateEndBalances = async (_expectedEndBalances: EndBalances): Promise<void> => {
|
const validateEndBalances = async (_expectedEndBalances: EndBalances): Promise<void> => {
|
||||||
const expectedEndBalances = {
|
const expectedEndBalances = {
|
||||||
// staker 1
|
// staker 1
|
||||||
stakerRewardVaultBalance_1:
|
stakerRewardBalance_1:
|
||||||
_expectedEndBalances.stakerRewardVaultBalance_1 !== undefined
|
_expectedEndBalances.stakerRewardBalance_1 !== undefined
|
||||||
? _expectedEndBalances.stakerRewardVaultBalance_1
|
? _expectedEndBalances.stakerRewardBalance_1
|
||||||
: ZERO,
|
: constants.ZERO_AMOUNT,
|
||||||
stakerEthVaultBalance_1:
|
stakerWethBalance_1:
|
||||||
_expectedEndBalances.stakerEthVaultBalance_1 !== undefined
|
_expectedEndBalances.stakerWethBalance_1 !== undefined
|
||||||
? _expectedEndBalances.stakerEthVaultBalance_1
|
? _expectedEndBalances.stakerWethBalance_1
|
||||||
: ZERO,
|
: constants.ZERO_AMOUNT,
|
||||||
// staker 2
|
// staker 2
|
||||||
stakerRewardVaultBalance_2:
|
stakerRewardBalance_2:
|
||||||
_expectedEndBalances.stakerRewardVaultBalance_2 !== undefined
|
_expectedEndBalances.stakerRewardBalance_2 !== undefined
|
||||||
? _expectedEndBalances.stakerRewardVaultBalance_2
|
? _expectedEndBalances.stakerRewardBalance_2
|
||||||
: ZERO,
|
: constants.ZERO_AMOUNT,
|
||||||
stakerEthVaultBalance_2:
|
stakerWethBalance_2:
|
||||||
_expectedEndBalances.stakerEthVaultBalance_2 !== undefined
|
_expectedEndBalances.stakerWethBalance_2 !== undefined
|
||||||
? _expectedEndBalances.stakerEthVaultBalance_2
|
? _expectedEndBalances.stakerWethBalance_2
|
||||||
: ZERO,
|
: constants.ZERO_AMOUNT,
|
||||||
// operator
|
// operator
|
||||||
operatorEthVaultBalance:
|
operatorWethBalance:
|
||||||
_expectedEndBalances.operatorEthVaultBalance !== undefined
|
_expectedEndBalances.operatorWethBalance !== undefined
|
||||||
? _expectedEndBalances.operatorEthVaultBalance
|
? _expectedEndBalances.operatorWethBalance
|
||||||
: ZERO,
|
: constants.ZERO_AMOUNT,
|
||||||
// undivided balance in reward pool
|
// undivided balance in reward pool
|
||||||
poolRewardVaultBalance:
|
poolRewardBalance:
|
||||||
_expectedEndBalances.poolRewardVaultBalance !== undefined
|
_expectedEndBalances.poolRewardBalance !== undefined
|
||||||
? _expectedEndBalances.poolRewardVaultBalance
|
? _expectedEndBalances.poolRewardBalance
|
||||||
: ZERO,
|
: constants.ZERO_AMOUNT,
|
||||||
};
|
};
|
||||||
const finalEndBalancesAsArray = await Promise.all([
|
const finalEndBalancesAsArray = await Promise.all([
|
||||||
// staker 1
|
// staker 1
|
||||||
@ -123,40 +121,40 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
poolId,
|
poolId,
|
||||||
stakers[0].getOwner(),
|
stakers[0].getOwner(),
|
||||||
),
|
),
|
||||||
stakingApiWrapper.ethVaultContract.balanceOf.callAsync(stakers[0].getOwner()),
|
stakingApiWrapper.wethContract.balanceOf.callAsync(stakers[0].getOwner()),
|
||||||
// staker 2
|
// staker 2
|
||||||
stakingApiWrapper.stakingContract.computeRewardBalanceOfDelegator.callAsync(
|
stakingApiWrapper.stakingContract.computeRewardBalanceOfDelegator.callAsync(
|
||||||
poolId,
|
poolId,
|
||||||
stakers[1].getOwner(),
|
stakers[1].getOwner(),
|
||||||
),
|
),
|
||||||
stakingApiWrapper.ethVaultContract.balanceOf.callAsync(stakers[1].getOwner()),
|
stakingApiWrapper.wethContract.balanceOf.callAsync(stakers[1].getOwner()),
|
||||||
// operator
|
// operator
|
||||||
stakingApiWrapper.ethVaultContract.balanceOf.callAsync(poolOperator.getOwner()),
|
stakingApiWrapper.wethContract.balanceOf.callAsync(poolOperator.getOwner()),
|
||||||
// undivided balance in reward pool
|
// undivided balance in reward pool
|
||||||
stakingApiWrapper.rewardVaultContract.balanceOf.callAsync(poolId),
|
stakingApiWrapper.stakingContract.rewardsByPoolId.callAsync(poolId),
|
||||||
]);
|
]);
|
||||||
expect(finalEndBalancesAsArray[0], 'stakerRewardVaultBalance_1').to.be.bignumber.equal(
|
expect(finalEndBalancesAsArray[0], 'stakerRewardBalance_1').to.be.bignumber.equal(
|
||||||
expectedEndBalances.stakerRewardVaultBalance_1,
|
expectedEndBalances.stakerRewardBalance_1,
|
||||||
);
|
);
|
||||||
expect(finalEndBalancesAsArray[1], 'stakerEthVaultBalance_1').to.be.bignumber.equal(
|
expect(finalEndBalancesAsArray[1], 'stakerWethBalance_1').to.be.bignumber.equal(
|
||||||
expectedEndBalances.stakerEthVaultBalance_1,
|
expectedEndBalances.stakerWethBalance_1,
|
||||||
);
|
);
|
||||||
expect(finalEndBalancesAsArray[2], 'stakerRewardVaultBalance_2').to.be.bignumber.equal(
|
expect(finalEndBalancesAsArray[2], 'stakerRewardBalance_2').to.be.bignumber.equal(
|
||||||
expectedEndBalances.stakerRewardVaultBalance_2,
|
expectedEndBalances.stakerRewardBalance_2,
|
||||||
);
|
);
|
||||||
expect(finalEndBalancesAsArray[3], 'stakerEthVaultBalance_2').to.be.bignumber.equal(
|
expect(finalEndBalancesAsArray[3], 'stakerWethBalance_2').to.be.bignumber.equal(
|
||||||
expectedEndBalances.stakerEthVaultBalance_2,
|
expectedEndBalances.stakerWethBalance_2,
|
||||||
);
|
);
|
||||||
expect(finalEndBalancesAsArray[4], 'operatorEthVaultBalance').to.be.bignumber.equal(
|
expect(finalEndBalancesAsArray[4], 'operatorWethBalance').to.be.bignumber.equal(
|
||||||
expectedEndBalances.operatorEthVaultBalance,
|
expectedEndBalances.operatorWethBalance,
|
||||||
);
|
);
|
||||||
expect(finalEndBalancesAsArray[5], 'poolRewardVaultBalance').to.be.bignumber.equal(
|
expect(finalEndBalancesAsArray[5], 'poolRewardBalance').to.be.bignumber.equal(
|
||||||
expectedEndBalances.poolRewardVaultBalance,
|
expectedEndBalances.poolRewardBalance,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const payProtocolFeeAndFinalize = async (_fee?: BigNumber) => {
|
const payProtocolFeeAndFinalize = async (_fee?: BigNumber) => {
|
||||||
const fee = _fee !== undefined ? _fee : ZERO;
|
const fee = _fee !== undefined ? _fee : constants.ZERO_AMOUNT;
|
||||||
if (!fee.eq(ZERO)) {
|
if (!fee.eq(constants.ZERO_AMOUNT)) {
|
||||||
await stakingApiWrapper.stakingContract.payProtocolFee.awaitTransactionSuccessAsync(
|
await stakingApiWrapper.stakingContract.payProtocolFee.awaitTransactionSuccessAsync(
|
||||||
poolOperator.getOwner(),
|
poolOperator.getOwner(),
|
||||||
takerAddress,
|
takerAddress,
|
||||||
@ -166,7 +164,6 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
}
|
}
|
||||||
await finalizer.finalizeAsync();
|
await finalizer.finalizeAsync();
|
||||||
};
|
};
|
||||||
const ZERO = new BigNumber(0);
|
|
||||||
it('Reward balance should be zero if not delegated', async () => {
|
it('Reward balance should be zero if not delegated', async () => {
|
||||||
// sanity balances - all zero
|
// sanity balances - all zero
|
||||||
await validateEndBalances({});
|
await validateEndBalances({});
|
||||||
@ -193,7 +190,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
await payProtocolFeeAndFinalize(reward);
|
await payProtocolFeeAndFinalize(reward);
|
||||||
// sanity check final balances - all zero
|
// sanity check final balances - all zero
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
operatorEthVaultBalance: reward,
|
operatorWethBalance: reward,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it(`Operator should receive entire reward if no delegators in their pool
|
it(`Operator should receive entire reward if no delegators in their pool
|
||||||
@ -206,7 +203,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
await payProtocolFeeAndFinalize(reward);
|
await payProtocolFeeAndFinalize(reward);
|
||||||
// sanity check final balances
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
operatorEthVaultBalance: reward,
|
operatorWethBalance: reward,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should give pool reward to delegator', async () => {
|
it('Should give pool reward to delegator', async () => {
|
||||||
@ -220,9 +217,9 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
await payProtocolFeeAndFinalize(reward);
|
await payProtocolFeeAndFinalize(reward);
|
||||||
// sanity check final balances
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: reward,
|
stakerRewardBalance_1: reward,
|
||||||
poolRewardVaultBalance: reward,
|
poolRewardBalance: reward,
|
||||||
membersRewardVaultBalance: reward,
|
membersRewardBalance: reward,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should split pool reward between delegators', async () => {
|
it('Should split pool reward between delegators', async () => {
|
||||||
@ -239,10 +236,10 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
await payProtocolFeeAndFinalize(reward);
|
await payProtocolFeeAndFinalize(reward);
|
||||||
// sanity check final balances
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: reward.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
|
stakerRewardBalance_1: reward.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
|
||||||
stakerRewardVaultBalance_2: reward.times(stakeAmounts[1]).dividedToIntegerBy(totalStakeAmount),
|
stakerRewardBalance_2: reward.times(stakeAmounts[1]).dividedToIntegerBy(totalStakeAmount),
|
||||||
poolRewardVaultBalance: reward,
|
poolRewardBalance: reward,
|
||||||
membersRewardVaultBalance: reward,
|
membersRewardBalance: reward,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should split pool reward between delegators, when they join in different epochs', async () => {
|
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);
|
await payProtocolFeeAndFinalize(reward);
|
||||||
// sanity check final balances
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: reward.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
|
stakerRewardBalance_1: reward.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
|
||||||
stakerRewardVaultBalance_2: reward.times(stakeAmounts[1]).dividedToIntegerBy(totalStakeAmount),
|
stakerRewardBalance_2: reward.times(stakeAmounts[1]).dividedToIntegerBy(totalStakeAmount),
|
||||||
poolRewardVaultBalance: reward,
|
poolRewardBalance: reward,
|
||||||
membersRewardVaultBalance: reward,
|
membersRewardBalance: reward,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should give pool reward to delegators only for the epoch during which they delegated', async () => {
|
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);
|
await payProtocolFeeAndFinalize(rewardForBothDelegators);
|
||||||
// sanity check final balances
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: rewardForOnlyFirstDelegator.plus(
|
stakerRewardBalance_1: rewardForOnlyFirstDelegator.plus(
|
||||||
rewardForBothDelegators.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
|
rewardForBothDelegators.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
|
||||||
),
|
),
|
||||||
stakerRewardVaultBalance_2: rewardForBothDelegators
|
stakerRewardBalance_2: rewardForBothDelegators
|
||||||
.times(stakeAmounts[1])
|
.times(stakeAmounts[1])
|
||||||
.dividedToIntegerBy(totalStakeAmount),
|
.dividedToIntegerBy(totalStakeAmount),
|
||||||
poolRewardVaultBalance: rewardForOnlyFirstDelegator.plus(rewardForBothDelegators),
|
poolRewardBalance: rewardForOnlyFirstDelegator.plus(rewardForBothDelegators),
|
||||||
membersRewardVaultBalance: rewardForOnlyFirstDelegator.plus(rewardForBothDelegators),
|
membersRewardBalance: rewardForOnlyFirstDelegator.plus(rewardForBothDelegators),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should split pool reward between delegators, over several consecutive epochs', async () => {
|
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
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: rewardForOnlyFirstDelegator.plus(
|
stakerRewardBalance_1: rewardForOnlyFirstDelegator.plus(
|
||||||
totalSharedRewards.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
|
totalSharedRewards.times(stakeAmounts[0]).dividedToIntegerBy(totalStakeAmount),
|
||||||
),
|
),
|
||||||
stakerRewardVaultBalance_2: totalSharedRewards
|
stakerRewardBalance_2: totalSharedRewards.times(stakeAmounts[1]).dividedToIntegerBy(totalStakeAmount),
|
||||||
.times(stakeAmounts[1])
|
poolRewardBalance: rewardForOnlyFirstDelegator.plus(totalSharedRewards),
|
||||||
.dividedToIntegerBy(totalStakeAmount),
|
membersRewardBalance: rewardForOnlyFirstDelegator.plus(totalSharedRewards),
|
||||||
poolRewardVaultBalance: rewardForOnlyFirstDelegator.plus(totalSharedRewards),
|
|
||||||
membersRewardVaultBalance: 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);
|
const stakeAmount = toBaseUnitAmount(4);
|
||||||
// first staker delegates (epoch 0)
|
// first staker delegates (epoch 0)
|
||||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
||||||
@ -358,7 +353,7 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
// earn reward
|
// earn reward
|
||||||
const reward = toBaseUnitAmount(10);
|
const reward = toBaseUnitAmount(10);
|
||||||
await payProtocolFeeAndFinalize(reward);
|
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(
|
await stakers[0].moveStakeAsync(
|
||||||
new StakeInfo(StakeStatus.Delegated, poolId),
|
new StakeInfo(StakeStatus.Delegated, poolId),
|
||||||
new StakeInfo(StakeStatus.Active),
|
new StakeInfo(StakeStatus.Active),
|
||||||
@ -366,11 +361,11 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
);
|
);
|
||||||
// sanity check final balances
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: ZERO,
|
stakerRewardBalance_1: constants.ZERO_AMOUNT,
|
||||||
stakerEthVaultBalance_1: reward,
|
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);
|
const stakeAmount = toBaseUnitAmount(4);
|
||||||
// first staker delegates (epoch 0)
|
// first staker delegates (epoch 0)
|
||||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
||||||
@ -383,8 +378,8 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
await stakers[0].stakeWithPoolAsync(poolId, stakeAmount);
|
||||||
// sanity check final balances
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: ZERO,
|
stakerRewardBalance_1: constants.ZERO_AMOUNT,
|
||||||
stakerEthVaultBalance_1: reward,
|
stakerWethBalance_1: reward,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should continue earning rewards after adding more stake and progressing several epochs', async () => {
|
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
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: rewardBeforeAddingMoreStake.plus(
|
stakerRewardBalance_1: rewardBeforeAddingMoreStake.plus(
|
||||||
totalRewardsAfterAddingMoreStake
|
totalRewardsAfterAddingMoreStake
|
||||||
.times(stakeAmounts[0])
|
.times(stakeAmounts[0])
|
||||||
.dividedBy(totalStake)
|
.dividedBy(totalStake)
|
||||||
.integerValue(BigNumber.ROUND_DOWN),
|
.integerValue(BigNumber.ROUND_DOWN),
|
||||||
),
|
),
|
||||||
stakerRewardVaultBalance_2: totalRewardsAfterAddingMoreStake
|
stakerRewardBalance_2: totalRewardsAfterAddingMoreStake
|
||||||
.times(stakeAmounts[1])
|
.times(stakeAmounts[1])
|
||||||
.dividedBy(totalStake)
|
.dividedBy(totalStake)
|
||||||
.integerValue(BigNumber.ROUND_DOWN),
|
.integerValue(BigNumber.ROUND_DOWN),
|
||||||
poolRewardVaultBalance: rewardBeforeAddingMoreStake.plus(totalRewardsAfterAddingMoreStake),
|
poolRewardBalance: rewardBeforeAddingMoreStake.plus(totalRewardsAfterAddingMoreStake),
|
||||||
membersRewardVaultBalance: rewardBeforeAddingMoreStake.plus(totalRewardsAfterAddingMoreStake),
|
membersRewardBalance: rewardBeforeAddingMoreStake.plus(totalRewardsAfterAddingMoreStake),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should stop collecting rewards after undelegating', async () => {
|
it('Should stop collecting rewards after undelegating', async () => {
|
||||||
@ -453,8 +448,8 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
|
|
||||||
// sanity check final balances
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerEthVaultBalance_1: rewardForDelegator,
|
stakerWethBalance_1: rewardForDelegator,
|
||||||
operatorEthVaultBalance: rewardNotForDelegator,
|
operatorWethBalance: rewardNotForDelegator,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should stop collecting rewards after undelegating, after several epochs', async () => {
|
it('Should stop collecting rewards after undelegating, after several epochs', async () => {
|
||||||
@ -488,8 +483,8 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
}
|
}
|
||||||
// sanity check final balances
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerEthVaultBalance_1: rewardForDelegator,
|
stakerWethBalance_1: rewardForDelegator,
|
||||||
operatorEthVaultBalance: totalRewardsNotForDelegator,
|
operatorWethBalance: totalRewardsNotForDelegator,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should collect fees correctly when leaving and returning to a pool', async () => {
|
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]);
|
await payProtocolFeeAndFinalize(rewardsForDelegator[1]);
|
||||||
// sanity check final balances
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: rewardsForDelegator[1],
|
stakerRewardBalance_1: rewardsForDelegator[1],
|
||||||
stakerEthVaultBalance_1: rewardsForDelegator[0],
|
stakerWethBalance_1: rewardsForDelegator[0],
|
||||||
operatorEthVaultBalance: rewardNotForDelegator,
|
operatorWethBalance: rewardNotForDelegator,
|
||||||
poolRewardVaultBalance: rewardsForDelegator[1],
|
poolRewardBalance: rewardsForDelegator[1],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('Should collect fees correctly when re-delegating after un-delegating', async () => {
|
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
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: ZERO,
|
stakerRewardBalance_1: constants.ZERO_AMOUNT,
|
||||||
stakerEthVaultBalance_1: rewardForDelegator,
|
stakerWethBalance_1: rewardForDelegator,
|
||||||
operatorEthVaultBalance: ZERO,
|
operatorWethBalance: constants.ZERO_AMOUNT,
|
||||||
poolRewardVaultBalance: ZERO,
|
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)
|
// first staker delegates (epoch 0)
|
||||||
const rewardForDelegator = toBaseUnitAmount(10);
|
const rewardForDelegator = toBaseUnitAmount(10);
|
||||||
const stakeAmount = toBaseUnitAmount(4);
|
const stakeAmount = toBaseUnitAmount(4);
|
||||||
@ -579,15 +574,15 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
await payProtocolFeeAndFinalize();
|
await payProtocolFeeAndFinalize();
|
||||||
// this should go to the delegator
|
// this should go to the delegator
|
||||||
await payProtocolFeeAndFinalize(rewardForDelegator);
|
await payProtocolFeeAndFinalize(rewardForDelegator);
|
||||||
await stakingApiWrapper.stakingContract.syncDelegatorRewards.awaitTransactionSuccessAsync(poolId, {
|
await stakingApiWrapper.stakingContract.withdrawDelegatorRewards.awaitTransactionSuccessAsync(poolId, {
|
||||||
from: stakers[0].getOwner(),
|
from: stakers[0].getOwner(),
|
||||||
});
|
});
|
||||||
// sanity check final balances
|
// sanity check final balances
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: ZERO,
|
stakerRewardBalance_1: constants.ZERO_AMOUNT,
|
||||||
stakerEthVaultBalance_1: rewardForDelegator,
|
stakerWethBalance_1: rewardForDelegator,
|
||||||
operatorEthVaultBalance: ZERO,
|
operatorWethBalance: constants.ZERO_AMOUNT,
|
||||||
poolRewardVaultBalance: ZERO,
|
poolRewardBalance: constants.ZERO_AMOUNT,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it(`payout should be based on stake at the time of rewards`, async () => {
|
it(`payout should be based on stake at the time of rewards`, async () => {
|
||||||
@ -607,11 +602,11 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
// finalize
|
// finalize
|
||||||
const reward = toBaseUnitAmount(10);
|
const reward = toBaseUnitAmount(10);
|
||||||
await payProtocolFeeAndFinalize(reward);
|
await payProtocolFeeAndFinalize(reward);
|
||||||
// Sync rewards to move the rewards into the EthVault.
|
// withdraw rewards
|
||||||
await staker.syncDelegatorRewardsAsync(poolId);
|
await staker.withdrawDelegatorRewardsAsync(poolId);
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: toBaseUnitAmount(0),
|
stakerRewardBalance_1: toBaseUnitAmount(0),
|
||||||
stakerEthVaultBalance_1: reward,
|
stakerWethBalance_1: reward,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it(`should split payout between two delegators when syncing rewards`, async () => {
|
it(`should split payout between two delegators when syncing rewards`, async () => {
|
||||||
@ -627,18 +622,18 @@ blockchainTests.resets('Testing Rewards', env => {
|
|||||||
// finalize
|
// finalize
|
||||||
const reward = toBaseUnitAmount(10);
|
const reward = toBaseUnitAmount(10);
|
||||||
await payProtocolFeeAndFinalize(reward);
|
await payProtocolFeeAndFinalize(reward);
|
||||||
// Sync rewards to move rewards from RewardVault into the EthVault.
|
// withdraw rewards
|
||||||
for (const [staker] of _.reverse(stakersAndStake)) {
|
for (const [staker] of _.reverse(stakersAndStake)) {
|
||||||
await staker.syncDelegatorRewardsAsync(poolId);
|
await staker.withdrawDelegatorRewardsAsync(poolId);
|
||||||
}
|
}
|
||||||
const expectedStakerRewards = stakeAmounts.map(n => reward.times(n).dividedToIntegerBy(totalStakeAmount));
|
const expectedStakerRewards = stakeAmounts.map(n => reward.times(n).dividedToIntegerBy(totalStakeAmount));
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: toBaseUnitAmount(0),
|
stakerRewardBalance_1: toBaseUnitAmount(0),
|
||||||
stakerRewardVaultBalance_2: toBaseUnitAmount(0),
|
stakerRewardBalance_2: toBaseUnitAmount(0),
|
||||||
stakerEthVaultBalance_1: expectedStakerRewards[0],
|
stakerWethBalance_1: expectedStakerRewards[0],
|
||||||
stakerEthVaultBalance_2: expectedStakerRewards[1],
|
stakerWethBalance_2: expectedStakerRewards[1],
|
||||||
poolRewardVaultBalance: new BigNumber(1), // Rounding error
|
poolRewardBalance: new BigNumber(1), // Rounding error
|
||||||
membersRewardVaultBalance: new BigNumber(1), // Rounding error
|
membersRewardBalance: new BigNumber(1), // Rounding error
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it(`delegator should not be credited payout twice by syncing rewards twice`, async () => {
|
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);
|
await payProtocolFeeAndFinalize(reward);
|
||||||
const expectedStakerRewards = stakeAmounts.map(n => reward.times(n).dividedToIntegerBy(totalStakeAmount));
|
const expectedStakerRewards = stakeAmounts.map(n => reward.times(n).dividedToIntegerBy(totalStakeAmount));
|
||||||
await validateEndBalances({
|
await validateEndBalances({
|
||||||
stakerRewardVaultBalance_1: expectedStakerRewards[0],
|
stakerRewardBalance_1: expectedStakerRewards[0],
|
||||||
stakerRewardVaultBalance_2: expectedStakerRewards[1],
|
stakerRewardBalance_2: expectedStakerRewards[1],
|
||||||
stakerEthVaultBalance_1: toBaseUnitAmount(0),
|
stakerWethBalance_1: toBaseUnitAmount(0),
|
||||||
stakerEthVaultBalance_2: toBaseUnitAmount(0),
|
stakerWethBalance_2: toBaseUnitAmount(0),
|
||||||
poolRewardVaultBalance: reward,
|
poolRewardBalance: reward,
|
||||||
membersRewardVaultBalance: reward,
|
membersRewardBalance: reward,
|
||||||
});
|
});
|
||||||
// First staker will sync rewards to get rewards transferred to EthVault.
|
// First staker will withdraw rewards.
|
||||||
const sneakyStaker = stakers[0];
|
const sneakyStaker = stakers[0];
|
||||||
const sneakyStakerExpectedEthVaultBalance = expectedStakerRewards[0];
|
const sneakyStakerExpectedWethBalance = expectedStakerRewards[0];
|
||||||
await sneakyStaker.syncDelegatorRewardsAsync(poolId);
|
await sneakyStaker.withdrawDelegatorRewardsAsync(poolId);
|
||||||
// Should have been credited the correct amount of rewards.
|
// 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(),
|
sneakyStaker.getOwner(),
|
||||||
);
|
);
|
||||||
expect(sneakyStakerEthVaultBalance, 'EthVault balance after first undelegate').to.bignumber.eq(
|
expect(sneakyStakerWethBalance, 'WETH balance after first undelegate').to.bignumber.eq(
|
||||||
sneakyStakerExpectedEthVaultBalance,
|
sneakyStakerExpectedWethBalance,
|
||||||
);
|
);
|
||||||
// Now he'll try to do it again to see if he gets credited twice.
|
// 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.
|
/// The total amount credited should remain the same.
|
||||||
sneakyStakerEthVaultBalance = await stakingApiWrapper.ethVaultContract.balanceOf.callAsync(
|
sneakyStakerWethBalance = await stakingApiWrapper.wethContract.balanceOf.callAsync(sneakyStaker.getOwner());
|
||||||
sneakyStaker.getOwner(),
|
expect(sneakyStakerWethBalance, 'WETH balance after second undelegate').to.bignumber.eq(
|
||||||
);
|
sneakyStakerExpectedWethBalance,
|
||||||
expect(sneakyStakerEthVaultBalance, 'EthVault balance after second undelegate').to.bignumber.eq(
|
|
||||||
sneakyStakerExpectedEthVaultBalance,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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('');
|
|
||||||
});
|
|
||||||
});
|
|
@ -16,8 +16,7 @@ import {
|
|||||||
artifacts,
|
artifacts,
|
||||||
TestDelegatorRewardsContract,
|
TestDelegatorRewardsContract,
|
||||||
TestDelegatorRewardsEvents,
|
TestDelegatorRewardsEvents,
|
||||||
TestDelegatorRewardsRecordDepositToEthVaultEventArgs as EthVaultDepositEventArgs,
|
TestDelegatorRewardsTransferEventArgs,
|
||||||
TestDelegatorRewardsRecordDepositToRewardVaultEventArgs as RewardVaultDepositEventArgs,
|
|
||||||
} from '../../src';
|
} from '../../src';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -57,7 +56,7 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
};
|
};
|
||||||
// Generate a deterministic operator address based on the poolId.
|
// Generate a deterministic operator address based on the poolId.
|
||||||
_opts.operator = poolIdToOperator(_opts.poolId);
|
_opts.operator = poolIdToOperator(_opts.poolId);
|
||||||
await testContract.depositStakingPoolRewards.awaitTransactionSuccessAsync(
|
await testContract.syncPoolRewards.awaitTransactionSuccessAsync(
|
||||||
_opts.poolId,
|
_opts.poolId,
|
||||||
_opts.operator,
|
_opts.operator,
|
||||||
new BigNumber(_opts.operatorReward),
|
new BigNumber(_opts.operatorReward),
|
||||||
@ -123,9 +122,8 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
return [_operatorReward, _membersReward];
|
return [_operatorReward, _membersReward];
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResultWithDeposits<T extends {}> = T & {
|
type ResultWithTransfers<T extends {}> = T & {
|
||||||
ethVaultDeposit: BigNumber;
|
delegatorTransfers: BigNumber;
|
||||||
rewardVaultDeposit: BigNumber;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface DelegateStakeOpts {
|
interface DelegateStakeOpts {
|
||||||
@ -136,7 +134,7 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
async function delegateStakeNowAsync(
|
async function delegateStakeNowAsync(
|
||||||
poolId: string,
|
poolId: string,
|
||||||
opts?: Partial<DelegateStakeOpts>,
|
opts?: Partial<DelegateStakeOpts>,
|
||||||
): Promise<ResultWithDeposits<DelegateStakeOpts>> {
|
): Promise<ResultWithTransfers<DelegateStakeOpts>> {
|
||||||
return delegateStakeAsync(poolId, opts, true);
|
return delegateStakeAsync(poolId, opts, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +142,7 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
poolId: string,
|
poolId: string,
|
||||||
opts?: Partial<DelegateStakeOpts>,
|
opts?: Partial<DelegateStakeOpts>,
|
||||||
now?: boolean,
|
now?: boolean,
|
||||||
): Promise<ResultWithDeposits<DelegateStakeOpts>> {
|
): Promise<ResultWithTransfers<DelegateStakeOpts>> {
|
||||||
const _opts = {
|
const _opts = {
|
||||||
delegator: randomAddress(),
|
delegator: randomAddress(),
|
||||||
stake: getRandomInteger(1, toBaseUnitAmount(10)),
|
stake: getRandomInteger(1, toBaseUnitAmount(10)),
|
||||||
@ -152,11 +150,10 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
};
|
};
|
||||||
const fn = now ? testContract.delegateStakeNow : testContract.delegateStake;
|
const fn = now ? testContract.delegateStakeNow : testContract.delegateStake;
|
||||||
const receipt = await fn.awaitTransactionSuccessAsync(_opts.delegator, poolId, new BigNumber(_opts.stake));
|
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 {
|
return {
|
||||||
..._opts,
|
..._opts,
|
||||||
ethVaultDeposit,
|
delegatorTransfers,
|
||||||
rewardVaultDeposit,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,42 +161,31 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
poolId: string,
|
poolId: string,
|
||||||
delegator: string,
|
delegator: string,
|
||||||
stake?: Numberish,
|
stake?: Numberish,
|
||||||
): Promise<ResultWithDeposits<{ stake: BigNumber }>> {
|
): Promise<ResultWithTransfers<{ stake: BigNumber }>> {
|
||||||
const _stake = new BigNumber(
|
const _stake = new BigNumber(
|
||||||
stake ||
|
stake ||
|
||||||
(await testContract.getStakeDelegatedToPoolByOwner.callAsync(delegator, poolId)).currentEpochBalance,
|
(await testContract.getStakeDelegatedToPoolByOwner.callAsync(delegator, poolId)).currentEpochBalance,
|
||||||
);
|
);
|
||||||
const receipt = await testContract.undelegateStake.awaitTransactionSuccessAsync(delegator, poolId, _stake);
|
const receipt = await testContract.undelegateStake.awaitTransactionSuccessAsync(delegator, poolId, _stake);
|
||||||
const [ethVaultDeposit, rewardVaultDeposit] = getDepositsFromLogs(receipt.logs, poolId, delegator);
|
const delegatorTransfers = getTransfersFromLogs(receipt.logs, delegator);
|
||||||
return {
|
return {
|
||||||
stake: _stake,
|
stake: _stake,
|
||||||
ethVaultDeposit,
|
delegatorTransfers,
|
||||||
rewardVaultDeposit,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDepositsFromLogs(logs: LogEntry[], poolId: string, delegator?: string): [BigNumber, BigNumber] {
|
function getTransfersFromLogs(logs: LogEntry[], delegator?: string): BigNumber {
|
||||||
let ethVaultDeposit = constants.ZERO_AMOUNT;
|
let delegatorTransfers = constants.ZERO_AMOUNT;
|
||||||
let rewardVaultDeposit = constants.ZERO_AMOUNT;
|
const transferArgs = filterLogsToArguments<TestDelegatorRewardsTransferEventArgs>(
|
||||||
const ethVaultDepositArgs = filterLogsToArguments<EthVaultDepositEventArgs>(
|
|
||||||
logs,
|
logs,
|
||||||
TestDelegatorRewardsEvents.RecordDepositToEthVault,
|
TestDelegatorRewardsEvents.Transfer,
|
||||||
);
|
);
|
||||||
for (const event of ethVaultDepositArgs) {
|
for (const event of transferArgs) {
|
||||||
if (event.owner === delegator) {
|
if (event._to === delegator) {
|
||||||
ethVaultDeposit = ethVaultDeposit.plus(event.amount);
|
delegatorTransfers = delegatorTransfers.plus(event._value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const rewardVaultDepositArgs = filterLogsToArguments<RewardVaultDepositEventArgs>(
|
return delegatorTransfers;
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function advanceEpochAsync(): Promise<number> {
|
async function advanceEpochAsync(): Promise<number> {
|
||||||
@ -216,16 +202,15 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
return testContract.computeRewardBalanceOfOperator.callAsync(poolId);
|
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);
|
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 receipt = await testContract.originalFinalizePool.awaitTransactionSuccessAsync(poolId);
|
||||||
const [ethVaultDeposit, rewardVaultDeposit] = getDepositsFromLogs(receipt.logs, poolId);
|
const delegatorTransfers = getTransfersFromLogs(receipt.logs, poolId);
|
||||||
return {
|
return {
|
||||||
ethVaultDeposit,
|
delegatorTransfers,
|
||||||
rewardVaultDeposit,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,8 +369,8 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
await advanceEpochAsync(); // epoch 2
|
await advanceEpochAsync(); // epoch 2
|
||||||
// rewards paid for stake in epoch 1.
|
// rewards paid for stake in epoch 1.
|
||||||
const { membersReward: reward } = await rewardPoolAsync({ poolId, membersStake: stake });
|
const { membersReward: reward } = await rewardPoolAsync({ poolId, membersStake: stake });
|
||||||
const { ethVaultDeposit: deposit } = await undelegateStakeAsync(poolId, delegator);
|
const { delegatorTransfers: withdrawal } = await undelegateStakeAsync(poolId, delegator);
|
||||||
assertRoughlyEquals(deposit, reward);
|
assertRoughlyEquals(withdrawal, reward);
|
||||||
const delegatorReward = await getDelegatorRewardBalanceAsync(poolId, delegator);
|
const delegatorReward = await getDelegatorRewardBalanceAsync(poolId, delegator);
|
||||||
expect(delegatorReward).to.bignumber.eq(0);
|
expect(delegatorReward).to.bignumber.eq(0);
|
||||||
});
|
});
|
||||||
@ -397,8 +382,8 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
await advanceEpochAsync(); // epoch 2
|
await advanceEpochAsync(); // epoch 2
|
||||||
// rewards paid for stake in epoch 1.
|
// rewards paid for stake in epoch 1.
|
||||||
const { membersReward: reward } = await rewardPoolAsync({ poolId, membersStake: stake });
|
const { membersReward: reward } = await rewardPoolAsync({ poolId, membersStake: stake });
|
||||||
const { ethVaultDeposit: deposit } = await undelegateStakeAsync(poolId, delegator);
|
const { delegatorTransfers: withdrawal } = await undelegateStakeAsync(poolId, delegator);
|
||||||
assertRoughlyEquals(deposit, reward);
|
assertRoughlyEquals(withdrawal, reward);
|
||||||
await delegateStakeAsync(poolId, { delegator, stake });
|
await delegateStakeAsync(poolId, { delegator, stake });
|
||||||
const delegatorReward = await getDelegatorRewardBalanceAsync(poolId, delegator);
|
const delegatorReward = await getDelegatorRewardBalanceAsync(poolId, delegator);
|
||||||
expect(delegatorReward).to.bignumber.eq(0);
|
expect(delegatorReward).to.bignumber.eq(0);
|
||||||
@ -448,7 +433,7 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
// Pay rewards for epoch 1.
|
// Pay rewards for epoch 1.
|
||||||
const { membersReward: reward1 } = await rewardPoolAsync({ poolId, membersStake: rewardStake });
|
const { membersReward: reward1 } = await rewardPoolAsync({ poolId, membersStake: rewardStake });
|
||||||
// add extra stake
|
// 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)
|
await advanceEpochAsync(); // epoch 3 (stake2 now active)
|
||||||
// Pay rewards for epoch 2.
|
// Pay rewards for epoch 2.
|
||||||
await advanceEpochAsync(); // epoch 4
|
await advanceEpochAsync(); // epoch 4
|
||||||
@ -459,7 +444,7 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
computeDelegatorRewards(reward1, stake1, rewardStake),
|
computeDelegatorRewards(reward1, stake1, rewardStake),
|
||||||
computeDelegatorRewards(reward2, totalStake, 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 () => {
|
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 () => {
|
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 poolId = hexRandom();
|
||||||
const { delegator, stake } = await delegateStakeAsync(poolId);
|
const { delegator, stake } = await delegateStakeAsync(poolId);
|
||||||
await advanceEpochAsync(); // epoch 1 (stake now active)
|
await advanceEpochAsync(); // epoch 1 (stake now active)
|
||||||
await advanceEpochAsync(); // epoch 2
|
await advanceEpochAsync(); // epoch 2
|
||||||
// rewards paid for stake in epoch 1
|
// rewards paid for stake in epoch 1
|
||||||
const { membersReward: reward } = await rewardPoolAsync({ poolId, membersStake: stake });
|
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);
|
const finalRewardBalance = await getDelegatorRewardBalanceAsync(poolId, delegator);
|
||||||
expect(deposit).to.bignumber.eq(reward);
|
expect(withdrawal).to.bignumber.eq(reward);
|
||||||
expect(finalRewardBalance).to.bignumber.eq(0);
|
expect(finalRewardBalance).to.bignumber.eq(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -697,7 +682,7 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
// touch the stake one last time
|
// touch the stake one last time
|
||||||
stakeResults.push(await touchStakeAsync(poolId, delegator));
|
stakeResults.push(await touchStakeAsync(poolId, delegator));
|
||||||
// Should only see deposits for epoch 2.
|
// 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);
|
const expectedReward = computeDelegatorRewards(reward, stake, rewardStake);
|
||||||
assertRoughlyEquals(BigNumber.sum(...allDeposits), expectedReward);
|
assertRoughlyEquals(BigNumber.sum(...allDeposits), expectedReward);
|
||||||
});
|
});
|
||||||
@ -725,7 +710,7 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
const { membersReward: reward2 } = await rewardPoolAsync({ poolId, membersStake: rewardStake });
|
const { membersReward: reward2 } = await rewardPoolAsync({ poolId, membersStake: rewardStake });
|
||||||
// touch the stake to claim rewards
|
// touch the stake to claim rewards
|
||||||
stakeResults.push(await touchStakeAsync(poolId, delegator));
|
stakeResults.push(await touchStakeAsync(poolId, delegator));
|
||||||
const allDeposits = stakeResults.map(r => r.ethVaultDeposit);
|
const allDeposits = stakeResults.map(r => r.delegatorTransfers);
|
||||||
const expectedReward = BigNumber.sum(
|
const expectedReward = BigNumber.sum(
|
||||||
computeDelegatorRewards(reward1, stake, rewardStake),
|
computeDelegatorRewards(reward1, stake, rewardStake),
|
||||||
computeDelegatorRewards(reward2, new BigNumber(stake).minus(unstake), 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
|
// rewards paid for stake in epoch 1
|
||||||
const { membersReward: reward } = await rewardPoolAsync({ poolId, membersStake: totalStake });
|
const { membersReward: reward } = await rewardPoolAsync({ poolId, membersStake: totalStake });
|
||||||
// delegator A will finalize and collect rewards by touching stake.
|
// delegator A will finalize and collect rewards by touching stake.
|
||||||
const { ethVaultDeposit: depositA } = await touchStakeAsync(poolId, delegatorA);
|
const { delegatorTransfers: withdrawalA } = await touchStakeAsync(poolId, delegatorA);
|
||||||
assertRoughlyEquals(depositA, computeDelegatorRewards(reward, stakeA, totalStake));
|
assertRoughlyEquals(withdrawalA, computeDelegatorRewards(reward, stakeA, totalStake));
|
||||||
// delegator B will collect rewards by touching stake
|
// delegator B will collect rewards by touching stake
|
||||||
const { ethVaultDeposit: depositB } = await touchStakeAsync(poolId, delegatorB);
|
const { delegatorTransfers: withdrawalB } = await touchStakeAsync(poolId, delegatorB);
|
||||||
assertRoughlyEquals(depositB, computeDelegatorRewards(reward, stakeB, totalStake));
|
assertRoughlyEquals(withdrawalB, computeDelegatorRewards(reward, stakeB, totalStake));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('delegator B collects correct rewards after delegator A finalizes', async () => {
|
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);
|
const totalRewards = BigNumber.sum(prevReward, unfinalizedReward);
|
||||||
// delegator A will finalize and collect rewards by touching stake.
|
// delegator A will finalize and collect rewards by touching stake.
|
||||||
const { ethVaultDeposit: depositA } = await touchStakeAsync(poolId, delegatorA);
|
const { delegatorTransfers: withdrawalA } = await touchStakeAsync(poolId, delegatorA);
|
||||||
assertRoughlyEquals(depositA, computeDelegatorRewards(totalRewards, stakeA, totalStake));
|
assertRoughlyEquals(withdrawalA, computeDelegatorRewards(totalRewards, stakeA, totalStake));
|
||||||
// delegator B will collect rewards by touching stake
|
// delegator B will collect rewards by touching stake
|
||||||
const { ethVaultDeposit: depositB } = await touchStakeAsync(poolId, delegatorB);
|
const { delegatorTransfers: withdrawalB } = await touchStakeAsync(poolId, delegatorB);
|
||||||
assertRoughlyEquals(depositB, computeDelegatorRewards(totalRewards, stakeB, totalStake));
|
assertRoughlyEquals(withdrawalB, computeDelegatorRewards(totalRewards, stakeB, totalStake));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('delegator A and B collect correct rewards after external finalization', async () => {
|
it('delegator A and B collect correct rewards after external finalization', async () => {
|
||||||
@ -793,11 +778,11 @@ blockchainTests.resets('delegator unit rewards', env => {
|
|||||||
// finalize
|
// finalize
|
||||||
await finalizePoolAsync(poolId);
|
await finalizePoolAsync(poolId);
|
||||||
// delegator A will collect rewards by touching stake.
|
// delegator A will collect rewards by touching stake.
|
||||||
const { ethVaultDeposit: depositA } = await touchStakeAsync(poolId, delegatorA);
|
const { delegatorTransfers: withdrawalA } = await touchStakeAsync(poolId, delegatorA);
|
||||||
assertRoughlyEquals(depositA, computeDelegatorRewards(totalRewards, stakeA, totalStake));
|
assertRoughlyEquals(withdrawalA, computeDelegatorRewards(totalRewards, stakeA, totalStake));
|
||||||
// delegator B will collect rewards by touching stake
|
// delegator B will collect rewards by touching stake
|
||||||
const { ethVaultDeposit: depositB } = await touchStakeAsync(poolId, delegatorB);
|
const { delegatorTransfers: withdrawalB } = await touchStakeAsync(poolId, delegatorB);
|
||||||
assertRoughlyEquals(depositB, computeDelegatorRewards(totalRewards, stakeB, totalStake));
|
assertRoughlyEquals(withdrawalB, computeDelegatorRewards(totalRewards, stakeB, totalStake));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -8,11 +8,9 @@ import * as _ from 'lodash';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
artifacts,
|
artifacts,
|
||||||
EthVaultContract,
|
|
||||||
IStakingEventsEpochEndedEventArgs,
|
IStakingEventsEpochEndedEventArgs,
|
||||||
IStakingEventsStakingPoolActivatedEventArgs,
|
IStakingEventsStakingPoolActivatedEventArgs,
|
||||||
ReadOnlyProxyContract,
|
ReadOnlyProxyContract,
|
||||||
StakingPoolRewardVaultContract,
|
|
||||||
StakingProxyContract,
|
StakingProxyContract,
|
||||||
TestCobbDouglasContract,
|
TestCobbDouglasContract,
|
||||||
TestStakingContract,
|
TestStakingContract,
|
||||||
@ -31,8 +29,6 @@ export class StakingApiWrapper {
|
|||||||
// The StakingProxy.sol contract as a StakingProxyContract
|
// The StakingProxy.sol contract as a StakingProxyContract
|
||||||
public stakingProxyContract: StakingProxyContract;
|
public stakingProxyContract: StakingProxyContract;
|
||||||
public zrxVaultContract: ZrxVaultContract;
|
public zrxVaultContract: ZrxVaultContract;
|
||||||
public ethVaultContract: EthVaultContract;
|
|
||||||
public rewardVaultContract: StakingPoolRewardVaultContract;
|
|
||||||
public zrxTokenContract: DummyERC20TokenContract;
|
public zrxTokenContract: DummyERC20TokenContract;
|
||||||
public wethContract: WETH9Contract;
|
public wethContract: WETH9Contract;
|
||||||
public cobbDouglasContract: TestCobbDouglasContract;
|
public cobbDouglasContract: TestCobbDouglasContract;
|
||||||
@ -122,8 +118,6 @@ export class StakingApiWrapper {
|
|||||||
new BigNumber(_params.cobbDouglasAlphaNumerator),
|
new BigNumber(_params.cobbDouglasAlphaNumerator),
|
||||||
new BigNumber(_params.cobbDouglasAlphaDenominator),
|
new BigNumber(_params.cobbDouglasAlphaDenominator),
|
||||||
_params.wethProxyAddress,
|
_params.wethProxyAddress,
|
||||||
_params.ethVaultAddress,
|
|
||||||
_params.rewardVaultAddress,
|
|
||||||
_params.zrxVaultAddress,
|
_params.zrxVaultAddress,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -144,8 +138,6 @@ export class StakingApiWrapper {
|
|||||||
'cobbDouglasAlphaNumerator',
|
'cobbDouglasAlphaNumerator',
|
||||||
'cobbDouglasAlphaDenominator',
|
'cobbDouglasAlphaDenominator',
|
||||||
'wethProxyAddress',
|
'wethProxyAddress',
|
||||||
'ethVaultAddress',
|
|
||||||
'rewardVaultAddress',
|
|
||||||
'zrxVaultAddress',
|
'zrxVaultAddress',
|
||||||
],
|
],
|
||||||
await this.stakingContract.getParams.callAsync(),
|
await this.stakingContract.getParams.callAsync(),
|
||||||
@ -180,16 +172,12 @@ export class StakingApiWrapper {
|
|||||||
stakingProxyContract: StakingProxyContract,
|
stakingProxyContract: StakingProxyContract,
|
||||||
stakingContract: TestStakingContract,
|
stakingContract: TestStakingContract,
|
||||||
zrxVaultContract: ZrxVaultContract,
|
zrxVaultContract: ZrxVaultContract,
|
||||||
ethVaultContract: EthVaultContract,
|
|
||||||
rewardVaultContract: StakingPoolRewardVaultContract,
|
|
||||||
zrxTokenContract: DummyERC20TokenContract,
|
zrxTokenContract: DummyERC20TokenContract,
|
||||||
wethContract: WETH9Contract,
|
wethContract: WETH9Contract,
|
||||||
cobbDouglasContract: TestCobbDouglasContract,
|
cobbDouglasContract: TestCobbDouglasContract,
|
||||||
) {
|
) {
|
||||||
this._web3Wrapper = env.web3Wrapper;
|
this._web3Wrapper = env.web3Wrapper;
|
||||||
this.zrxVaultContract = zrxVaultContract;
|
this.zrxVaultContract = zrxVaultContract;
|
||||||
this.ethVaultContract = ethVaultContract;
|
|
||||||
this.rewardVaultContract = rewardVaultContract;
|
|
||||||
this.zrxTokenContract = zrxTokenContract;
|
this.zrxTokenContract = zrxTokenContract;
|
||||||
this.wethContract = wethContract;
|
this.wethContract = wethContract;
|
||||||
this.cobbDouglasContract = cobbDouglasContract;
|
this.cobbDouglasContract = cobbDouglasContract;
|
||||||
@ -253,22 +241,6 @@ export async function deployAndConfigureContractsAsync(
|
|||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
artifacts,
|
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
|
// deploy zrx vault
|
||||||
const zrxVaultContract = await ZrxVaultContract.deployFrom0xArtifactAsync(
|
const zrxVaultContract = await ZrxVaultContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.ZrxVault,
|
artifacts.ZrxVault,
|
||||||
@ -287,8 +259,6 @@ export async function deployAndConfigureContractsAsync(
|
|||||||
stakingContract.address,
|
stakingContract.address,
|
||||||
readOnlyProxyContract.address,
|
readOnlyProxyContract.address,
|
||||||
erc20ProxyContract.address,
|
erc20ProxyContract.address,
|
||||||
ethVaultContract.address,
|
|
||||||
rewardVaultContract.address,
|
|
||||||
zrxVaultContract.address,
|
zrxVaultContract.address,
|
||||||
);
|
);
|
||||||
// deploy cobb douglas contract
|
// deploy cobb douglas contract
|
||||||
@ -303,18 +273,12 @@ export async function deployAndConfigureContractsAsync(
|
|||||||
await erc20ProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync(zrxVaultContract.address);
|
await erc20ProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync(zrxVaultContract.address);
|
||||||
// set staking proxy contract in zrx vault
|
// set staking proxy contract in zrx vault
|
||||||
await zrxVaultContract.setStakingProxy.awaitTransactionSuccessAsync(stakingProxyContract.address);
|
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(
|
return new StakingApiWrapper(
|
||||||
env,
|
env,
|
||||||
ownerAddress,
|
ownerAddress,
|
||||||
stakingProxyContract,
|
stakingProxyContract,
|
||||||
stakingContract,
|
stakingContract,
|
||||||
zrxVaultContract,
|
zrxVaultContract,
|
||||||
ethVaultContract,
|
|
||||||
rewardVaultContract,
|
|
||||||
zrxTokenContract,
|
zrxTokenContract,
|
||||||
wethContract,
|
wethContract,
|
||||||
cobbDouglasContract,
|
cobbDouglasContract,
|
||||||
|
@ -18,8 +18,6 @@ export const constants = {
|
|||||||
cobbDouglasAlphaNumerator: new BigNumber(1),
|
cobbDouglasAlphaNumerator: new BigNumber(1),
|
||||||
cobbDouglasAlphaDenominator: new BigNumber(2),
|
cobbDouglasAlphaDenominator: new BigNumber(2),
|
||||||
wethProxyAddress: randomAddress(),
|
wethProxyAddress: randomAddress(),
|
||||||
ethVaultAddress: randomAddress(),
|
|
||||||
rewardVaultAddress: randomAddress(),
|
|
||||||
zrxVaultAddress: randomAddress(),
|
zrxVaultAddress: randomAddress(),
|
||||||
},
|
},
|
||||||
PPM,
|
PPM,
|
||||||
|
@ -111,8 +111,6 @@ export class CumulativeRewardTrackingSimulation {
|
|||||||
this.getTestCumulativeRewardTrackingContract().address,
|
this.getTestCumulativeRewardTrackingContract().address,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
constants.NULL_ADDRESS,
|
|
||||||
);
|
);
|
||||||
const testLogs = await this._executeActionsAsync(testActions);
|
const testLogs = await this._executeActionsAsync(testActions);
|
||||||
CumulativeRewardTrackingSimulation._assertTestLogs(expectedTestLogs, testLogs);
|
CumulativeRewardTrackingSimulation._assertTestLogs(expectedTestLogs, testLogs);
|
||||||
|
@ -12,8 +12,6 @@ export interface StakingParams {
|
|||||||
cobbDouglasAlphaNumerator: Numberish;
|
cobbDouglasAlphaNumerator: Numberish;
|
||||||
cobbDouglasAlphaDenominator: Numberish;
|
cobbDouglasAlphaDenominator: Numberish;
|
||||||
wethProxyAddress: string;
|
wethProxyAddress: string;
|
||||||
ethVaultAddress: string;
|
|
||||||
rewardVaultAddress: string;
|
|
||||||
zrxVaultAddress: string;
|
zrxVaultAddress: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +101,7 @@ export interface StakeBalances {
|
|||||||
totalDelegatedStakeByPool: StakeBalanceByPool;
|
totalDelegatedStakeByPool: StakeBalanceByPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RewardVaultBalanceByPoolId {
|
export interface RewardBalanceByPoolId {
|
||||||
[key: string]: BigNumber;
|
[key: string]: BigNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,11 +3,8 @@
|
|||||||
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
|
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
|
||||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||||
"files": [
|
"files": [
|
||||||
"generated-artifacts/EthVault.json",
|
|
||||||
"generated-artifacts/IEthVault.json",
|
|
||||||
"generated-artifacts/IStaking.json",
|
"generated-artifacts/IStaking.json",
|
||||||
"generated-artifacts/IStakingEvents.json",
|
"generated-artifacts/IStakingEvents.json",
|
||||||
"generated-artifacts/IStakingPoolRewardVault.json",
|
|
||||||
"generated-artifacts/IStakingProxy.json",
|
"generated-artifacts/IStakingProxy.json",
|
||||||
"generated-artifacts/IStorage.json",
|
"generated-artifacts/IStorage.json",
|
||||||
"generated-artifacts/IStorageInit.json",
|
"generated-artifacts/IStorageInit.json",
|
||||||
@ -40,7 +37,6 @@
|
|||||||
"generated-artifacts/MixinVaultCore.json",
|
"generated-artifacts/MixinVaultCore.json",
|
||||||
"generated-artifacts/ReadOnlyProxy.json",
|
"generated-artifacts/ReadOnlyProxy.json",
|
||||||
"generated-artifacts/Staking.json",
|
"generated-artifacts/Staking.json",
|
||||||
"generated-artifacts/StakingPoolRewardVault.json",
|
|
||||||
"generated-artifacts/StakingProxy.json",
|
"generated-artifacts/StakingProxy.json",
|
||||||
"generated-artifacts/TestAssertStorageParams.json",
|
"generated-artifacts/TestAssertStorageParams.json",
|
||||||
"generated-artifacts/TestCobbDouglas.json",
|
"generated-artifacts/TestCobbDouglas.json",
|
||||||
@ -52,13 +48,11 @@
|
|||||||
"generated-artifacts/TestLibProxy.json",
|
"generated-artifacts/TestLibProxy.json",
|
||||||
"generated-artifacts/TestLibProxyReceiver.json",
|
"generated-artifacts/TestLibProxyReceiver.json",
|
||||||
"generated-artifacts/TestLibSafeDowncast.json",
|
"generated-artifacts/TestLibSafeDowncast.json",
|
||||||
"generated-artifacts/TestMixinParams.json",
|
|
||||||
"generated-artifacts/TestMixinVaultCore.json",
|
"generated-artifacts/TestMixinVaultCore.json",
|
||||||
"generated-artifacts/TestProtocolFees.json",
|
"generated-artifacts/TestProtocolFees.json",
|
||||||
"generated-artifacts/TestStaking.json",
|
"generated-artifacts/TestStaking.json",
|
||||||
"generated-artifacts/TestStakingNoWETH.json",
|
"generated-artifacts/TestStakingNoWETH.json",
|
||||||
"generated-artifacts/TestStakingProxy.json",
|
"generated-artifacts/TestStakingProxy.json",
|
||||||
"generated-artifacts/TestStorageLayout.json",
|
|
||||||
"generated-artifacts/ZrxVault.json"
|
"generated-artifacts/ZrxVault.json"
|
||||||
],
|
],
|
||||||
"exclude": ["./deploy/solc/solc_bin"]
|
"exclude": ["./deploy/solc/solc_bin"]
|
||||||
|
@ -25,8 +25,6 @@ export enum InvalidParamValueErrorCode {
|
|||||||
InvalidMaximumMakersInPool,
|
InvalidMaximumMakersInPool,
|
||||||
InvalidMinimumPoolStake,
|
InvalidMinimumPoolStake,
|
||||||
InvalidWethProxyAddress,
|
InvalidWethProxyAddress,
|
||||||
InvalidEthVaultAddress,
|
|
||||||
InvalidRewardVaultAddress,
|
|
||||||
InvalidZrxVaultAddress,
|
InvalidZrxVaultAddress,
|
||||||
InvalidEpochDuration,
|
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 {
|
export class InvalidStakeStatusError extends RevertError {
|
||||||
constructor(status?: BigNumber) {
|
constructor(status?: BigNumber) {
|
||||||
super('InvalidStakeStatusError', 'InvalidStakeStatusError(uint256 status)', { status });
|
super('InvalidStakeStatusError', 'InvalidStakeStatusError(uint256 status)', { status });
|
||||||
@ -247,7 +233,6 @@ export class PreviousEpochNotFinalizedError extends RevertError {
|
|||||||
const types = [
|
const types = [
|
||||||
AmountExceedsBalanceOfPoolError,
|
AmountExceedsBalanceOfPoolError,
|
||||||
BlockTimestampTooLowError,
|
BlockTimestampTooLowError,
|
||||||
EthVaultNotSetError,
|
|
||||||
ExchangeAddressAlreadyRegisteredError,
|
ExchangeAddressAlreadyRegisteredError,
|
||||||
ExchangeAddressNotRegisteredError,
|
ExchangeAddressNotRegisteredError,
|
||||||
InitializationError,
|
InitializationError,
|
||||||
@ -267,7 +252,6 @@ const types = [
|
|||||||
PoolExistenceError,
|
PoolExistenceError,
|
||||||
PreviousEpochNotFinalizedError,
|
PreviousEpochNotFinalizedError,
|
||||||
ProxyDestinationCannotBeNilError,
|
ProxyDestinationCannotBeNilError,
|
||||||
RewardVaultNotSetError,
|
|
||||||
WithdrawAmountExceedsMemberBalanceError,
|
WithdrawAmountExceedsMemberBalanceError,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user