Skip to content
This repository has been archived by the owner on Jul 9, 2021. It is now read-only.

Commit

Permalink
New staking mechanics: delay on entry opposed to exit
Browse files Browse the repository at this point in the history
  • Loading branch information
hysz committed Aug 31, 2019
1 parent a5996b3 commit d355356
Show file tree
Hide file tree
Showing 39 changed files with 1,381 additions and 1,521 deletions.
15 changes: 7 additions & 8 deletions contracts/staking/contracts/src/Staking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,15 @@
*/

pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;

import "./interfaces/IStaking.sol";
import "./fees/MixinExchangeManager.sol";
import "./stake/MixinZrxVault.sol";
import "./staking_pools/MixinStakingPoolRewardVault.sol";
import "./sys/MixinScheduler.sol";
import "./stake/MixinStakeBalances.sol";
import "./stake/MixinTimeLockedStake.sol";
import "./stake/MixinStake.sol";
import "./stake/MixinDelegatedStake.sol";
import "./staking_pools/MixinStakingPool.sol";
import "./fees/MixinExchangeFees.sol";
import "./staking_pools/MixinStakingPoolRewards.sol";
Expand All @@ -36,19 +35,19 @@ contract Staking is
IStaking,
IStakingEvents,
MixinDeploymentConstants,
Ownable,
MixinConstants,
MixinStorage,
MixinZrxVault,
MixinExchangeManager,
MixinScheduler,
MixinStakingPoolRewardVault,
MixinZrxVault,
MixinStakingPool,
MixinTimeLockedStake,
MixinStakeStorage,
MixinStakeBalances,
MixinStake,
MixinStakingPoolRewards,
MixinExchangeFees,
MixinDelegatedStake
MixinStake,
MixinStakingPool,
MixinExchangeFees
{
// this contract can receive ETH
// solhint-disable no-empty-blocks
Expand Down
28 changes: 22 additions & 6 deletions contracts/staking/contracts/src/fees/MixinExchangeFees.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;

import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
Expand Down Expand Up @@ -45,14 +46,17 @@ import "./MixinExchangeManager.sol";
contract MixinExchangeFees is
IStakingEvents,
MixinDeploymentConstants,
Ownable,
MixinConstants,
MixinStorage,
MixinZrxVault,
MixinExchangeManager,
MixinScheduler,
MixinStakingPoolRewardVault,
MixinStakingPool,
MixinTimeLockedStake,
MixinStakeBalances
MixinStakeStorage,
MixinStakeBalances,
MixinStakingPoolRewards,
MixinStakingPool
{
using LibSafeMath for uint256;

Expand Down Expand Up @@ -175,8 +179,8 @@ contract MixinExchangeFees is
bytes32 poolId = activePoolsThisEpoch[i];

// compute weighted stake
uint256 totalStakeDelegatedToPool = getTotalStakeDelegatedToPool(poolId);
uint256 stakeHeldByPoolOperator = getActivatedAndUndelegatedStake(getStakingPoolOperator(poolId));
uint256 totalStakeDelegatedToPool = getTotalStakeDelegatedToPool(poolId).current;
uint256 stakeHeldByPoolOperator = getActiveStake(getStakingPoolOperator(poolId)).current; // @TODO Update
uint256 weightedStake = stakeHeldByPoolOperator.safeAdd(
totalStakeDelegatedToPool
.safeMul(REWARD_PAYOUT_DELEGATED_STAKE_PERCENT_VALUE)
Expand All @@ -187,6 +191,7 @@ contract MixinExchangeFees is
activePools[i].poolId = poolId;
activePools[i].feesCollected = protocolFeesThisEpochByPool[poolId];
activePools[i].weightedStake = weightedStake;
activePools[i].delegatedStake = totalStakeDelegatedToPool;

// update cumulative amounts
totalFeesCollected = totalFeesCollected.safeAdd(activePools[i].feesCollected);
Expand Down Expand Up @@ -218,9 +223,20 @@ contract MixinExchangeFees is
);

// record reward in vault
_recordDepositInStakingPoolRewardVault(activePools[i].poolId, reward);
bool rewardForOperatorOnly = activePools[i].delegatedStake == 0;
(, uint256 poolPortion) = rewardVault.recordDepositFor(activePools[i].poolId, reward, rewardForOperatorOnly);
totalRewardsPaid = totalRewardsPaid.safeAdd(reward);

// sync cumulative rewards, if necessary.
if (poolPortion > 0) {
_recordRewardForDelegators(
activePools[i].poolId,
poolPortion,
activePools[i].delegatedStake,
currentEpoch
);
}

// clear state for gas refunds
protocolFeesThisEpochByPool[activePools[i].poolId] = 0;
activePoolsThisEpoch[i] = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import "../immutable/MixinStorage.sol";
contract MixinExchangeManager is
IStakingEvents,
MixinDeploymentConstants,
Ownable,
MixinConstants,
MixinStorage
{
Expand Down
2 changes: 2 additions & 0 deletions contracts/staking/contracts/src/immutable/MixinConstants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ contract MixinConstants is
uint64 constant internal INITIAL_EPOCH = 0;

uint64 constant internal INITIAL_TIMELOCK_PERIOD = INITIAL_EPOCH;

uint256 constant internal MIN_TOKEN_VALUE = 1000000000000000000; // 10**18
}
43 changes: 19 additions & 24 deletions contracts/staking/contracts/src/immutable/MixinStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@ pragma solidity ^0.5.9;
import "@0x/contracts-utils/contracts/src/Ownable.sol";
import "./MixinConstants.sol";
import "../interfaces/IZrxVault.sol";
import "../interfaces/IEthVault.sol";
import "../interfaces/IStakingPoolRewardVault.sol";
import "../interfaces/IStructs.sol";


// solhint-disable max-states-count
contract MixinStorage is
MixinDeploymentConstants,
MixinConstants,
Ownable
Ownable,
MixinConstants
{

constructor()
Expand All @@ -40,26 +41,23 @@ contract MixinStorage is
// address of staking contract
address internal stakingContract;

// mapping from Owner to Amount Staked
mapping (address => uint256) internal stakeByOwner;
// mapping from Owner to Amount of Active Stake
mapping (address => IStructs.DelayedBalance) internal activeStakeByOwner;

// mapping from Owner to Amount of Instactive Stake
mapping (address => uint256) internal activatedStakeByOwner;

// mapping from Owner to Amount TimeLocked
mapping (address => IStructs.TimeLock) internal timeLockedStakeByOwner;
// mapping from Owner to Amount of Inactive Stake
mapping (address => IStructs.DelayedBalance) internal inactiveStakeByOwner;

// mapping from Owner to Amount Delegated
mapping (address => uint256) internal delegatedStakeByOwner;
mapping (address => IStructs.DelayedBalance) internal delegatedStakeByOwner;

// mapping from Owner to Pool Id to Amount Delegated
mapping (address => mapping (bytes32 => uint256)) internal delegatedStakeToPoolByOwner;
mapping (address => mapping (bytes32 => IStructs.DelayedBalance)) internal delegatedStakeToPoolByOwner;

// mapping from Pool Id to Amount Delegated
mapping (bytes32 => uint256) internal delegatedStakeByPoolId;
mapping (bytes32 => IStructs.DelayedBalance) internal delegatedStakeByPoolId;

// total activated stake in the system
uint256 internal totalActivatedStake;
// mapping from Owner to Amount of Withdrawable Stake
mapping (address => uint256) internal withdrawableStakeByOwner;

// tracking Pool Id
bytes32 internal nextPoolId = INITIAL_POOL_ID;
Expand All @@ -80,30 +78,27 @@ contract MixinStorage is
// current epoch start time
uint256 internal currentEpochStartTimeInSeconds;

// current withdrawal period
uint256 internal currentTimeLockPeriod = INITIAL_TIMELOCK_PERIOD;

// current epoch start time
uint256 internal currentTimeLockPeriodStartEpoch = INITIAL_EPOCH;

// fees collected this epoch
mapping (bytes32 => uint256) internal protocolFeesThisEpochByPool;

// pools that were active in the current epoch
bytes32[] internal activePoolsThisEpoch;

// mapping from POol Id to Shadow Rewards
mapping (bytes32 => uint256) internal shadowRewardsByPoolId;
// reward ratios by epoch
mapping (bytes32 => mapping (uint256 => IStructs.Fraction)) internal cumulativeRewardsByPool;

// shadow balances by
mapping (address => mapping (bytes32 => uint256)) internal shadowRewardsInPoolByOwner;
mapping (bytes32 => uint256) internal cumulativeRewardsByPoolLastStored;

// registered 0x Exchange contracts
mapping (address => bool) internal validExchanges;

// ZRX vault
IZrxVault internal zrxVault;

// Rebate Vault
IEthVault internal ethVault;

// Rebate Vault
IStakingPoolRewardVault internal rewardVault;
}

71 changes: 71 additions & 0 deletions contracts/staking/contracts/src/interfaces/IEthVault.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
Copyright 2018 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 ETH from `owner` into the vault.
/// Note that only the Staking contract can call this.
/// Note that this can only be called when *not* in Catostrophic Failure mode.
/// @param owner of ETH Tokens.
function depositFor(address owner)
external
payable;

/// @dev Withdraw an `amount` of ETH to `msg.sender` from the vault.
/// Note that only the Staking contract can call this.
/// Note that this can only be called when *not* in Catostrophic Failure mode.
/// @param amount of ETH to withdraw.
function withdraw(uint256 amount)
external;

/// @dev Withdraw ALL ETH to `msg.sender` from the vault.
function withdrawAll()
external
returns (uint256);

/// @dev Returns the balance in ETH of the `owner`
/// @return Balance in ETH.
function balanceOf(address owner)
external
view
returns (uint256);
}
32 changes: 22 additions & 10 deletions contracts/staking/contracts/src/interfaces/IStakingEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,34 @@ pragma solidity ^0.5.9;

interface IStakingEvents {

/// @dev Emitted by MixinStake when new Stake is minted.
/// @param owner of Stake.
/// @param amount of Stake minted.
event StakeMinted(
address owner,
/// @dev Emitted by MixinStake when ZRX is staked.
/// @param owner of ZRX.
/// @param amount of ZRX staked.
event Stake(
address indexed owner,
uint256 amount
);

/// @dev Emitted by MixinStake when Stake is burned.
/// @param owner of Stake.
/// @param amount of Stake burned.
event StakeBurned(
address owner,
/// @dev Emitted by MixinStake when ZRX is unstaked.
/// @param owner of ZRX.
/// @param amount of ZRX unstaked.
event Unstake(
address indexed owner,
uint256 amount
);

/// @dev Emitted by MixinStake when ZRX is unstaked.
/// @param owner of ZRX.
/// @param amount of ZRX unstaked.
event MoveStake(
address indexed owner,
uint256 amount,
uint8 fromState,
bytes32 indexed fromPool,
uint8 toState,
bytes32 indexed toProol
);

/// @dev Emitted by MixinExchangeManager when an exchange is added.
/// @param exchangeAddress Address of new exchange.
event ExchangeAdded(
Expand Down
Loading

0 comments on commit d355356

Please sign in to comment.