From c0cb78bb3fdba40f22c9b6c20332f8cdcb11a716 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 3 Sep 2019 20:31:26 -0700 Subject: [PATCH] Improving readability of staking --- .../staking/contracts/src/StakingProxy.sol | 2 +- .../contracts/src/fees/MixinExchangeFees.sol | 7 +- .../src/fees/MixinExchangeManager.sol | 2 +- .../src/immutable/MixinConstants.sol | 4 +- .../immutable/MixinDeploymentConstants.sol | 2 +- .../contracts/src/immutable/MixinStorage.sol | 8 +-- .../contracts/src/interfaces/IEthVault.sol | 2 +- .../interfaces/IStakingPoolRewardVault.sol | 4 +- .../src/interfaces/IStakingProxy.sol | 2 +- .../contracts/src/interfaces/IStructs.sol | 2 +- .../contracts/src/interfaces/IVaultCore.sol | 2 +- .../contracts/src/interfaces/IWallet.sol | 2 +- .../contracts/src/interfaces/IZrxVault.sol | 2 +- .../contracts/src/libs/LibEIP712Hash.sol | 2 +- .../contracts/src/libs/LibSafeDowncast.sol | 2 +- .../src/libs/LibSignatureValidator.sol | 2 +- .../contracts/src/stake/MixinStake.sol | 38 ++++++----- .../src/stake/MixinStakeBalances.sol | 2 +- .../contracts/src/stake/MixinStakeStorage.sol | 2 +- .../contracts/src/stake/MixinZrxVault.sol | 2 +- .../src/staking_pools/MixinEthVault.sol | 2 +- .../src/staking_pools/MixinStakingPool.sol | 2 +- .../MixinStakingPoolRewardVault.sol | 7 +- .../staking_pools/MixinStakingPoolRewards.sol | 13 ++-- .../contracts/src/sys/MixinScheduler.sol | 2 +- .../staking/contracts/src/vaults/EthVault.sol | 11 ++-- .../contracts/src/vaults/MixinVaultCore.sol | 2 +- .../src/vaults/StakingPoolRewardVault.sol | 12 ++-- .../staking/contracts/src/vaults/ZrxVault.sol | 2 +- .../contracts/test/TestStorageLayout.sol | 9 ++- .../staking/test/utils/staking_wrapper.ts | 31 ++++----- .../utils/contracts/src/LibFractions.sol | 66 +++++++++++++++++++ contracts/utils/contracts/src/LibSafeMath.sol | 60 +---------------- contracts/utils/package.json | 2 +- contracts/utils/src/artifacts.ts | 2 + contracts/utils/src/wrappers.ts | 1 + contracts/utils/tsconfig.json | 1 + 37 files changed, 170 insertions(+), 146 deletions(-) create mode 100644 contracts/utils/contracts/src/LibFractions.sol diff --git a/contracts/staking/contracts/src/StakingProxy.sol b/contracts/staking/contracts/src/StakingProxy.sol index 7a4cb4e7bb..b3d283381d 100644 --- a/contracts/staking/contracts/src/StakingProxy.sol +++ b/contracts/staking/contracts/src/StakingProxy.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/fees/MixinExchangeFees.sol b/contracts/staking/contracts/src/fees/MixinExchangeFees.sol index e7791a8cbe..fe5c467d32 100644 --- a/contracts/staking/contracts/src/fees/MixinExchangeFees.sol +++ b/contracts/staking/contracts/src/fees/MixinExchangeFees.sol @@ -256,8 +256,11 @@ contract MixinExchangeFees is ); // record reward in vault - bool rewardForOperatorOnly = activePools[i].delegatedStake == 0; - (, uint256 poolPortion) = rewardVault.recordDepositFor(activePools[i].poolId, reward, rewardForOperatorOnly); + (, uint256 poolPortion) = rewardVault.recordDepositFor( + activePools[i].poolId, + reward, + activePools[i].delegatedStake == 0 // true -> reward is for operator only + ); totalRewardsPaid = totalRewardsPaid.safeAdd(reward); // sync cumulative rewards, if necessary. diff --git a/contracts/staking/contracts/src/fees/MixinExchangeManager.sol b/contracts/staking/contracts/src/fees/MixinExchangeManager.sol index f026c7dcbf..5b3808833d 100644 --- a/contracts/staking/contracts/src/fees/MixinExchangeManager.sol +++ b/contracts/staking/contracts/src/fees/MixinExchangeManager.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/immutable/MixinConstants.sol b/contracts/staking/contracts/src/immutable/MixinConstants.sol index 15d56ccfce..f3e89cbf71 100644 --- a/contracts/staking/contracts/src/immutable/MixinConstants.sol +++ b/contracts/staking/contracts/src/immutable/MixinConstants.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. @@ -42,5 +42,5 @@ contract MixinConstants is uint64 constant internal INITIAL_TIMELOCK_PERIOD = INITIAL_EPOCH; - uint256 constant internal MIN_TOKEN_VALUE = 1000000000000000000; // 10**18 + uint256 constant internal MIN_TOKEN_VALUE = 10**18; } diff --git a/contracts/staking/contracts/src/immutable/MixinDeploymentConstants.sol b/contracts/staking/contracts/src/immutable/MixinDeploymentConstants.sol index 33ce6debcd..bb199ff6ee 100644 --- a/contracts/staking/contracts/src/immutable/MixinDeploymentConstants.sol +++ b/contracts/staking/contracts/src/immutable/MixinDeploymentConstants.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/immutable/MixinStorage.sol b/contracts/staking/contracts/src/immutable/MixinStorage.sol index e2572d46bc..1533271b63 100644 --- a/contracts/staking/contracts/src/immutable/MixinStorage.sol +++ b/contracts/staking/contracts/src/immutable/MixinStorage.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. @@ -92,13 +92,13 @@ contract MixinStorage is // registered 0x Exchange contracts mapping (address => bool) internal validExchanges; - // ZRX vault + // ZRX vault (stores staked ZRX) IZrxVault internal zrxVault; - // Rebate Vault + // ETH Vault (stores eth balances of stakers and pool operators) IEthVault internal ethVault; - // Rebate Vault + // Rebate Vault (stores rewards for pools before they are moved to the eth vault on a per-user basis) IStakingPoolRewardVault internal rewardVault; // Numerator for cobb douglas alpha factor. diff --git a/contracts/staking/contracts/src/interfaces/IEthVault.sol b/contracts/staking/contracts/src/interfaces/IEthVault.sol index d672c9fa04..8867557b65 100644 --- a/contracts/staking/contracts/src/interfaces/IEthVault.sol +++ b/contracts/staking/contracts/src/interfaces/IEthVault.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/interfaces/IStakingPoolRewardVault.sol b/contracts/staking/contracts/src/interfaces/IStakingPoolRewardVault.sol index 91a0a9bcd0..00e52e68ba 100644 --- a/contracts/staking/contracts/src/interfaces/IStakingPoolRewardVault.sol +++ b/contracts/staking/contracts/src/interfaces/IStakingPoolRewardVault.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. @@ -109,7 +109,7 @@ interface IStakingPoolRewardVault { returns ( uint256 operatorPortion, uint256 delegatorsPortion - ); + ); /// @dev Withdraw some amount in ETH of an operator's reward. /// Note that this is only callable by the staking contract, and when diff --git a/contracts/staking/contracts/src/interfaces/IStakingProxy.sol b/contracts/staking/contracts/src/interfaces/IStakingProxy.sol index 2f9cb1b2dd..15952ebb6a 100644 --- a/contracts/staking/contracts/src/interfaces/IStakingProxy.sol +++ b/contracts/staking/contracts/src/interfaces/IStakingProxy.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/interfaces/IStructs.sol b/contracts/staking/contracts/src/interfaces/IStructs.sol index 45af164f50..fbae07e3a4 100644 --- a/contracts/staking/contracts/src/interfaces/IStructs.sol +++ b/contracts/staking/contracts/src/interfaces/IStructs.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/interfaces/IVaultCore.sol b/contracts/staking/contracts/src/interfaces/IVaultCore.sol index b9ba9369ef..91ab394dd4 100644 --- a/contracts/staking/contracts/src/interfaces/IVaultCore.sol +++ b/contracts/staking/contracts/src/interfaces/IVaultCore.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/interfaces/IWallet.sol b/contracts/staking/contracts/src/interfaces/IWallet.sol index 0db690b29b..c57faecb61 100644 --- a/contracts/staking/contracts/src/interfaces/IWallet.sol +++ b/contracts/staking/contracts/src/interfaces/IWallet.sol @@ -1,5 +1,5 @@ /* - Copyright 2018 ZeroEx Intl. + 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 diff --git a/contracts/staking/contracts/src/interfaces/IZrxVault.sol b/contracts/staking/contracts/src/interfaces/IZrxVault.sol index 4fd2c514e4..7c19a50843 100644 --- a/contracts/staking/contracts/src/interfaces/IZrxVault.sol +++ b/contracts/staking/contracts/src/interfaces/IZrxVault.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/libs/LibEIP712Hash.sol b/contracts/staking/contracts/src/libs/LibEIP712Hash.sol index 252fe854a2..13e12f2c0e 100644 --- a/contracts/staking/contracts/src/libs/LibEIP712Hash.sol +++ b/contracts/staking/contracts/src/libs/LibEIP712Hash.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/libs/LibSafeDowncast.sol b/contracts/staking/contracts/src/libs/LibSafeDowncast.sol index 7ed787aac7..c7ce8793ba 100644 --- a/contracts/staking/contracts/src/libs/LibSafeDowncast.sol +++ b/contracts/staking/contracts/src/libs/LibSafeDowncast.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/libs/LibSignatureValidator.sol b/contracts/staking/contracts/src/libs/LibSignatureValidator.sol index 7e2e4bb469..91f6fbb0ef 100644 --- a/contracts/staking/contracts/src/libs/LibSignatureValidator.sol +++ b/contracts/staking/contracts/src/libs/LibSignatureValidator.sol @@ -1,5 +1,5 @@ /* - Copyright 2018 ZeroEx Intl. + 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 diff --git a/contracts/staking/contracts/src/stake/MixinStake.sol b/contracts/staking/contracts/src/stake/MixinStake.sol index ed18700184..a9d719dad6 100644 --- a/contracts/staking/contracts/src/stake/MixinStake.sol +++ b/contracts/staking/contracts/src/stake/MixinStake.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. @@ -104,7 +104,11 @@ contract MixinStake is /// @param from state to move stake out of. /// @param to state to move stake into. /// @param amount of stake to move. - function moveStake(IStructs.StakeStateInfo calldata from, IStructs.StakeStateInfo calldata to, uint256 amount) + function moveStake( + IStructs.StakeStateInfo calldata from, + IStructs.StakeStateInfo calldata to, + uint256 amount + ) external { // sanity check - do nothing if moving stake between the same state @@ -140,8 +144,8 @@ contract MixinStake is : 0; // execute move - IStructs.DelayedBalance storage fromPtr = _getBalancePtrFromState(from); - IStructs.DelayedBalance storage toPtr = _getBalancePtrFromState(to); + IStructs.DelayedBalance storage fromPtr = _getBalancePtrFromState(from.state); + IStructs.DelayedBalance storage toPtr = _getBalancePtrFromState(to.state); _moveStake(fromPtr, toPtr, amount); // update withdrawable field, if necessary @@ -160,9 +164,9 @@ contract MixinStake is ); } - /// @dev Delegates an owners stake to a staking pool. + /// @dev Delegates a owners stake to a staking pool. /// @param poolId Id of pool to delegate to. - /// @param owner of stake to delegate. + /// @param owner who wants to delegate. /// @param amount of stake to delegate. function _delegateStake( bytes32 poolId, @@ -172,23 +176,23 @@ contract MixinStake is private { // transfer any rewards from the transient pool vault to the eth vault; - // this must be done before we can modify the staker's portion of the delegator pool. + // this must be done before we can modify the owner's portion of the delegator pool. _transferDelegatorsAccumulatedRewardsToEthVault(poolId, owner); // sync cumulative rewards that we'll need for future computations _syncCumulativeRewardsNeededByDelegator(poolId, currentEpoch); - // decrement how much stake the owner has delegated to the input pool + // increment how much stake the owner has delegated to the input pool _incrementBalance(delegatedStakeToPoolByOwner[owner][poolId], amount); // increment how much stake has been delegated to pool _incrementBalance(delegatedStakeByPoolId[poolId], amount); } - /// @dev Delegates an owners stake to a staking pool. - /// @param poolId Id of pool to delegate to. - /// @param owner of stake to delegate. - /// @param amount of stake to delegate. + /// @dev Un-Delegates a owners stake from a staking pool. + /// @param poolId Id of pool to un-delegate to. + /// @param owner who wants to un-delegate. + /// @param amount of stake to un-delegate. function _undelegateStake( bytes32 poolId, address payable owner, @@ -197,7 +201,7 @@ contract MixinStake is private { // transfer any rewards from the transient pool vault to the eth vault; - // this must be done before we can modify the staker's portion of the delegator pool. + // this must be done before we can modify the owner's portion of the delegator pool. _transferDelegatorsAccumulatedRewardsToEthVault(poolId, owner); // sync cumulative rewards that we'll need for future computations @@ -213,17 +217,17 @@ contract MixinStake is /// @dev Returns a storage pointer to a user's stake in a given state. /// @param state of user's stake to lookup. /// @return a storage pointer to the corresponding stake stake - function _getBalancePtrFromState(IStructs.StakeStateInfo memory state) + function _getBalancePtrFromState(IStructs.StakeState state) private returns (IStructs.DelayedBalance storage) { // lookup state address owner = msg.sender; - if (state.state == IStructs.StakeState.ACTIVE) { + if (state == IStructs.StakeState.ACTIVE) { return activeStakeByOwner[owner]; - } else if (state.state == IStructs.StakeState.INACTIVE) { + } else if (state == IStructs.StakeState.INACTIVE) { return inactiveStakeByOwner[owner]; - } else if (state.state == IStructs.StakeState.DELEGATED) { + } else if (state == IStructs.StakeState.DELEGATED) { return delegatedStakeByOwner[owner]; } diff --git a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol index 17ca5ad8c9..e467a80b73 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol index ca0900ba24..8ec7dbebdd 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/stake/MixinZrxVault.sol b/contracts/staking/contracts/src/stake/MixinZrxVault.sol index 7421741530..9cf434aaa8 100644 --- a/contracts/staking/contracts/src/stake/MixinZrxVault.sol +++ b/contracts/staking/contracts/src/stake/MixinZrxVault.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/staking_pools/MixinEthVault.sol b/contracts/staking/contracts/src/staking_pools/MixinEthVault.sol index 4c1e771bac..9359efb68e 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinEthVault.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinEthVault.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol index e386668a3f..5ed2bb86be 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewardVault.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewardVault.sol index aeeff77ea5..fb7c03ad2d 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewardVault.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewardVault.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. @@ -86,10 +86,11 @@ contract MixinStakingPoolRewardVault is ) internal { + IStakingPoolRewardVault _rewardVault = rewardVault; require( - address(rewardVault) != NIL_ADDRESS, + address(_rewardVault) != NIL_ADDRESS, "REWARD_VAULT_NOT_SET" ); - rewardVault.transferMemberBalanceToEthVault(poolId, member, amount); + _rewardVault.transferMemberBalanceToEthVault(poolId, member, amount); } } diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol index abeb52a21b..fa2dd55b75 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. @@ -19,6 +19,7 @@ pragma solidity ^0.5.9; pragma experimental ABIEncoderV2; +import "@0x/contracts-utils/contracts/src/LibFractions.sol"; import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "../immutable/MixinStorage.sol"; import "../immutable/MixinConstants.sol"; @@ -44,11 +45,11 @@ contract MixinStakingPoolRewards is /// @dev Computes the reward balance in ETH of a specific member of a pool. /// @param poolId Unique id of pool. /// @param member The member of the pool. - /// @return Balance in ETH. + /// @return totalReward Balance in ETH. function computeRewardBalanceOfDelegator(bytes32 poolId, address member) public view - returns (uint256) + returns (uint256 totalReward) { // cache some values to reduce sloads IStructs.DelayedBalance memory delegatedStake = delegatedStakeToPoolByOwner[member][poolId]; @@ -83,7 +84,7 @@ contract MixinStakingPoolRewards is : 0; // compute the total reward - uint256 totalReward = rewardsAccumulatedDuringLastStoredEpoch.safeAdd(rewardsAccumulatedAfterLastStoredEpoch); + totalReward = rewardsAccumulatedDuringLastStoredEpoch.safeAdd(rewardsAccumulatedAfterLastStoredEpoch); return totalReward; } @@ -179,7 +180,7 @@ contract MixinStakingPoolRewards is IStructs.Fraction memory mostRecentCumulativeRewards = cumulativeRewardsByPoolPtr[cumulativeRewardsLastStored]; // compute new cumulative reward - (uint256 numerator, uint256 denominator) = LibSafeMath.addFractions( + (uint256 numerator, uint256 denominator) = LibFractions.addFractions( mostRecentCumulativeRewards.numerator, mostRecentCumulativeRewards.denominator, reward, @@ -218,7 +219,7 @@ contract MixinStakingPoolRewards is { IStructs.Fraction memory beginRatio = cumulativeRewardsByPool[poolId][beginEpoch]; IStructs.Fraction memory endRatio = cumulativeRewardsByPool[poolId][endEpoch]; - uint256 reward = LibSafeMath.scaleFractionalDifference( + uint256 reward = LibFractions.scaleFractionalDifference( endRatio.numerator, endRatio.denominator, beginRatio.numerator, diff --git a/contracts/staking/contracts/src/sys/MixinScheduler.sol b/contracts/staking/contracts/src/sys/MixinScheduler.sol index 522893a4a1..85c4ee7614 100644 --- a/contracts/staking/contracts/src/sys/MixinScheduler.sol +++ b/contracts/staking/contracts/src/sys/MixinScheduler.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/vaults/EthVault.sol b/contracts/staking/contracts/src/vaults/EthVault.sol index cc70745a0b..9625ed3ba9 100644 --- a/contracts/staking/contracts/src/vaults/EthVault.sol +++ b/contracts/staking/contracts/src/vaults/EthVault.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. @@ -37,8 +37,9 @@ contract EthVault is mapping (address => uint256) internal balances; /// @dev Constructor. - // solhint-disable-next-line no-empty-blocks - constructor() public {} + constructor() + public + {} // solhint-disable-line no-empty-blocks /// @dev Deposit an `amount` of ETH from `owner` into the vault. /// Note that only the Staking contract can call this. @@ -69,11 +70,11 @@ contract EthVault is /// @dev Withdraw ALL ETH to `msg.sender` from the vault. function withdrawAll() external - returns (uint256) + returns (uint256 totalBalance) { // get total balance address payable owner = msg.sender; - uint256 totalBalance = balances[owner]; + totalBalance = balances[owner]; // withdraw ETH to owner _withdrawFrom(owner, totalBalance); diff --git a/contracts/staking/contracts/src/vaults/MixinVaultCore.sol b/contracts/staking/contracts/src/vaults/MixinVaultCore.sol index cfb915b445..a50f578d9e 100644 --- a/contracts/staking/contracts/src/vaults/MixinVaultCore.sol +++ b/contracts/staking/contracts/src/vaults/MixinVaultCore.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/src/vaults/StakingPoolRewardVault.sol b/contracts/staking/contracts/src/vaults/StakingPoolRewardVault.sol index a7ada15637..2e6ff2b5c6 100644 --- a/contracts/staking/contracts/src/vaults/StakingPoolRewardVault.sol +++ b/contracts/staking/contracts/src/vaults/StakingPoolRewardVault.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. @@ -121,8 +121,9 @@ contract StakingPoolRewardVault is } // sanity check on eth vault + IEthVault _ethVault = ethVault; require( - address(ethVault) != address(0), + address(_ethVault) != address(0), "ETH_VAULT_NOT_SET" ); @@ -137,7 +138,7 @@ contract StakingPoolRewardVault is // update balance and transfer `amount` in ETH to staking contract balanceByPoolId[poolId].operatorBalance = operatorBalance.safeSub(amount).downcastToUint96(); - ethVault.depositFor.value(amount)(operator); + _ethVault.depositFor.value(amount)(operator); // notify emit RewardWithdrawnForOperator(poolId, amount); @@ -157,8 +158,9 @@ contract StakingPoolRewardVault is onlyStakingContract { // sanity check on eth vault + IEthVault _ethVault = ethVault; require( - address(ethVault) != address(0), + address(_ethVault) != address(0), "ETH_VAULT_NOT_SET" ); @@ -173,7 +175,7 @@ contract StakingPoolRewardVault is // update balance and transfer `amount` in ETH to staking contract balanceByPoolId[poolId].membersBalance = membersBalance.safeSub(amount).downcastToUint96(); - ethVault.depositFor.value(amount)(member); + _ethVault.depositFor.value(amount)(member); // notify emit RewardWithdrawnForMember(poolId, amount); diff --git a/contracts/staking/contracts/src/vaults/ZrxVault.sol b/contracts/staking/contracts/src/vaults/ZrxVault.sol index 74807c5630..898f03d987 100644 --- a/contracts/staking/contracts/src/vaults/ZrxVault.sol +++ b/contracts/staking/contracts/src/vaults/ZrxVault.sol @@ -1,6 +1,6 @@ /* - Copyright 2018 ZeroEx Intl. + 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. diff --git a/contracts/staking/contracts/test/TestStorageLayout.sol b/contracts/staking/contracts/test/TestStorageLayout.sol index 4ddcbbaa63..a0bf09ad57 100644 --- a/contracts/staking/contracts/test/TestStorageLayout.sol +++ b/contracts/staking/contracts/test/TestStorageLayout.sol @@ -2,7 +2,7 @@ /* - Copyright 2018 ZeroEx Intl. + 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. @@ -42,6 +42,11 @@ contract TestStorageLayout is 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() } @@ -108,4 +113,4 @@ contract TestStorageLayout is slot := add(slot, 1) } } -} \ No newline at end of file +} diff --git a/contracts/staking/test/utils/staking_wrapper.ts b/contracts/staking/test/utils/staking_wrapper.ts index 61770df8b2..4d717d78d1 100644 --- a/contracts/staking/test/utils/staking_wrapper.ts +++ b/contracts/staking/test/utils/staking_wrapper.ts @@ -203,21 +203,27 @@ export class StakingWrapper { } public async moveStakeAsync( owner: string, - fromState: { + _fromState: { state: number, poolId?: string }, - toState: { + _toState: { state: number, poolId?: string }, amount: BigNumber, ): Promise { - fromState.poolId = fromState.poolId !== undefined ? fromState.poolId : constants.NIL_POOL_ID; - toState.poolId = fromState.poolId !== undefined ? toState.poolId : constants.NIL_POOL_ID; + const fromState = { + state: _fromState.state, + poolId: _fromState.poolId !== undefined ? _fromState.poolId : constants.NIL_POOL_ID + }; + const toState = { + state: _toState.state, + poolId: _toState.poolId !== undefined ? _toState.poolId : constants.NIL_POOL_ID + }; const calldata = this.getStakingContract().moveStake.getABIEncodedTransactionData( - fromState as any, - toState as any, + fromState, + toState, amount, ); const txReceipt = await this._executeTransactionAsync(calldata, owner); @@ -364,19 +370,6 @@ export class StakingWrapper { return signedStakingPoolApproval; } ///// EPOCHS ///// - - /* - public async testFinalizefees(rewards: {reward: BigNumber, poolId: string}[]): Promise { - await this.fastForwardToNextEpochAsync(); - const totalRewards = _.sumBy(rewards, (v: any) => {return v.reward.toNumber();}); - const calldata = this.getStakingContract().testFinalizeFees.getABIEncodedTransactionData(rewards); - const txReceipt = await this._executeTransactionAsync(calldata, undefined, new BigNumber(totalRewards), true); - return txReceipt; - } - */ - - - public async goToNextEpochAsync(): Promise { const calldata = this.getStakingContract().finalizeFees.getABIEncodedTransactionData(); const txReceipt = await this._executeTransactionAsync(calldata, undefined, new BigNumber(0), true); diff --git a/contracts/utils/contracts/src/LibFractions.sol b/contracts/utils/contracts/src/LibFractions.sol new file mode 100644 index 0000000000..caccd63591 --- /dev/null +++ b/contracts/utils/contracts/src/LibFractions.sol @@ -0,0 +1,66 @@ +pragma solidity ^0.5.9; + +import "./LibSafeMath.sol"; + + +library LibFractions { + + using LibSafeMath for uint256; + + /// @dev Safely adds two fractions `n1/d1 + n2/d2` + /// @param n1 numerator of `1` + /// @param d1 denominator of `1` + /// @param n2 numerator of `2` + /// @param d2 denominator of `2` + /// @return numerator of sum + /// @return denominator of sum + function addFractions( + uint256 n1, + uint256 d1, + uint256 n2, + uint256 d2 + ) + internal + pure + returns ( + uint256 numerator, + uint256 denominator + ) + { + numerator = n1 + .safeMul(d2) + .safeAdd(n2.safeMul(d1)); + + denominator = d1.safeMul(d2); + return (numerator, denominator); + } + + /// @dev Safely scales the difference between two fractions. + /// @param n1 numerator of `1` + /// @param d1 denominator of `1` + /// @param n2 numerator of `2` + /// @param d2 denominator of `2` + /// @param s scalar to multiply by difference. + /// @return result = `s * (n1/d1 - n2/d2)`. + function scaleFractionalDifference( + uint256 n1, + uint256 d1, + uint256 n2, + uint256 d2, + uint256 s + ) + internal + pure + returns (uint256 result) + { + uint256 numerator = n1 + .safeMul(d2) + .safeSub(n2.safeMul(d1)); + + uint256 tmp = numerator.safeDiv(d2); + result = s + .safeMul(tmp) + .safeDiv(d1); + return result; + } +} diff --git a/contracts/utils/contracts/src/LibSafeMath.sol b/contracts/utils/contracts/src/LibSafeMath.sol index 0f5860cb7b..4dea8bf10a 100644 --- a/contracts/utils/contracts/src/LibSafeMath.sol +++ b/contracts/utils/contracts/src/LibSafeMath.sol @@ -6,6 +6,8 @@ import "./LibSafeMathRichErrors.sol"; library LibSafeMath { + using LibSafeMath for uint256; + function safeMul(uint256 a, uint256 b) internal pure @@ -87,62 +89,4 @@ library LibSafeMath { { return a < b ? a : b; } - - /// @dev Safely adds two fractions `n1/d1 + n2/d2` - /// @param n1 numerator of `1` - /// @param d1 denominator of `1` - /// @param n2 numerator of `2` - /// @param d2 denominator of `2` - /// @return numerator of sum - /// @return denominator of sum - function addFractions( - uint256 n1, - uint256 d1, - uint256 n2, - uint256 d2 - ) - internal - pure - returns ( - uint256 numerator, - uint256 denominator - ) - { - numerator = safeAdd( - safeMul(n1, d2), - safeMul(n2, d1) - ); - denominator = safeMul(d1, d2); - return (numerator, denominator); - } - - /// @dev Safely scales the difference two fractions. - /// @param n1 numerator of `1` - /// @param d1 denominator of `1` - /// @param n2 numerator of `2` - /// @param d2 denominator of `2` - /// @param s scalar to multiply by difference. - /// @return result = `s * (n1/d1 - n2/d2)`. - function scaleFractionalDifference( - uint256 n1, - uint256 d1, - uint256 n2, - uint256 d2, - uint256 s - ) - internal - pure - returns (uint256) - { - uint256 numerator = safeSub( - safeMul(n1, d2), - safeMul(n2, d1) - ); - uint256 tmp = safeDiv(numerator, d2); - uint256 result = safeDiv( - safeMul(s, tmp), - d1 - ); - return result; - } } diff --git a/contracts/utils/package.json b/contracts/utils/package.json index 80096fe2c8..77432a9b28 100644 --- a/contracts/utils/package.json +++ b/contracts/utils/package.json @@ -36,7 +36,7 @@ }, "config": { "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", - "abis": "./generated-artifacts/@(Authorizable|IAuthorizable|IOwnable|LibAddress|LibAddressArray|LibAddressArrayRichErrors|LibAuthorizableRichErrors|LibBytes|LibBytesRichErrors|LibEIP1271|LibEIP712|LibOwnableRichErrors|LibReentrancyGuardRichErrors|LibRichErrors|LibSafeMath|LibSafeMathRichErrors|Ownable|ReentrancyGuard|Refundable|SafeMath|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibRichErrors|TestLogDecoding|TestLogDecodingDownstream|TestOwnable|TestReentrancyGuard|TestRefundable|TestRefundableReceiver|TestSafeMath).json" + "abis": "./generated-artifacts/@(Authorizable|IAuthorizable|IOwnable|LibAddress|LibAddressArray|LibAddressArrayRichErrors|LibAuthorizableRichErrors|LibBytes|LibBytesRichErrors|LibEIP1271|LibEIP712|LibFractions|LibOwnableRichErrors|LibReentrancyGuardRichErrors|LibRichErrors|LibSafeMath|LibSafeMathRichErrors|Ownable|ReentrancyGuard|Refundable|SafeMath|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibRichErrors|TestLogDecoding|TestLogDecodingDownstream|TestOwnable|TestReentrancyGuard|TestRefundable|TestRefundableReceiver|TestSafeMath).json" }, "repository": { "type": "git", diff --git a/contracts/utils/src/artifacts.ts b/contracts/utils/src/artifacts.ts index 9d0a7c8831..47a2d61628 100644 --- a/contracts/utils/src/artifacts.ts +++ b/contracts/utils/src/artifacts.ts @@ -16,6 +16,7 @@ import * as LibBytes from '../generated-artifacts/LibBytes.json'; import * as LibBytesRichErrors from '../generated-artifacts/LibBytesRichErrors.json'; import * as LibEIP1271 from '../generated-artifacts/LibEIP1271.json'; import * as LibEIP712 from '../generated-artifacts/LibEIP712.json'; +import * as LibFractions from '../generated-artifacts/LibFractions.json'; import * as LibOwnableRichErrors from '../generated-artifacts/LibOwnableRichErrors.json'; import * as LibReentrancyGuardRichErrors from '../generated-artifacts/LibReentrancyGuardRichErrors.json'; import * as LibRichErrors from '../generated-artifacts/LibRichErrors.json'; @@ -47,6 +48,7 @@ export const artifacts = { LibBytesRichErrors: LibBytesRichErrors as ContractArtifact, LibEIP1271: LibEIP1271 as ContractArtifact, LibEIP712: LibEIP712 as ContractArtifact, + LibFractions: LibFractions as ContractArtifact, LibOwnableRichErrors: LibOwnableRichErrors as ContractArtifact, LibReentrancyGuardRichErrors: LibReentrancyGuardRichErrors as ContractArtifact, LibRichErrors: LibRichErrors as ContractArtifact, diff --git a/contracts/utils/src/wrappers.ts b/contracts/utils/src/wrappers.ts index a14f4d30f0..78edd2ddec 100644 --- a/contracts/utils/src/wrappers.ts +++ b/contracts/utils/src/wrappers.ts @@ -14,6 +14,7 @@ export * from '../generated-wrappers/lib_bytes'; export * from '../generated-wrappers/lib_bytes_rich_errors'; export * from '../generated-wrappers/lib_e_i_p1271'; export * from '../generated-wrappers/lib_e_i_p712'; +export * from '../generated-wrappers/lib_fractions'; export * from '../generated-wrappers/lib_ownable_rich_errors'; export * from '../generated-wrappers/lib_reentrancy_guard_rich_errors'; export * from '../generated-wrappers/lib_rich_errors'; diff --git a/contracts/utils/tsconfig.json b/contracts/utils/tsconfig.json index deb1b76698..13059711d1 100644 --- a/contracts/utils/tsconfig.json +++ b/contracts/utils/tsconfig.json @@ -14,6 +14,7 @@ "generated-artifacts/LibBytesRichErrors.json", "generated-artifacts/LibEIP1271.json", "generated-artifacts/LibEIP712.json", + "generated-artifacts/LibFractions.json", "generated-artifacts/LibOwnableRichErrors.json", "generated-artifacts/LibReentrancyGuardRichErrors.json", "generated-artifacts/LibRichErrors.json",