@0x/contracts-staking: Updating tests and making the contracts testable.

This commit is contained in:
Lawrence Forman
2019-09-21 23:50:34 -04:00
parent 3ad7728a0e
commit 6a29654d7d
18 changed files with 283 additions and 348 deletions

View File

@@ -192,24 +192,23 @@ contract MixinExchangeFees is
private
view
{
if (protocolFeePaid != 0) {
return;
if (protocolFeePaid == 0) {
LibRichErrors.rrevert(
LibStakingRichErrors.InvalidProtocolFeePaymentError(
LibStakingRichErrors.ProtocolFeePaymentErrorCodes.ZeroProtocolFeePaid,
protocolFeePaid,
msg.value
)
);
}
if (msg.value == protocolFeePaid || msg.value == 0) {
return;
if (msg.value != protocolFeePaid && msg.value != 0) {
LibRichErrors.rrevert(
LibStakingRichErrors.InvalidProtocolFeePaymentError(
LibStakingRichErrors.ProtocolFeePaymentErrorCodes.MismatchedFeeAndPayment,
protocolFeePaid,
msg.value
)
);
}
LibRichErrors.rrevert(
LibStakingRichErrors.InvalidProtocolFeePaymentError(
protocolFeePaid == 0 ?
LibStakingRichErrors
.ProtocolFeePaymentErrorCodes
.ZeroProtocolFeePaid :
LibStakingRichErrors
.ProtocolFeePaymentErrorCodes
.MismatchedFeeAndPayment,
protocolFeePaid,
msg.value
)
);
}
}

View File

@@ -26,20 +26,6 @@ import "../interfaces/IStructs.sol";
/// cyclical dependencies.
contract MixinAbstract {
/// @dev Computes the reward owed to a pool during finalization.
/// Does nothing if the pool is already finalized.
/// @param poolId The pool's ID.
/// @return totalReward The total reward owed to a pool.
/// @return membersStake The total stake for all non-operator members in
/// this pool.
function _getUnfinalizedPoolRewards(bytes32 poolId)
internal
view
returns (
uint256 totalReward,
uint256 membersStake
);
/// @dev Instantly finalizes a single pool that was active in the previous
/// epoch, crediting it rewards and sending those rewards to the reward
/// and eth vault. This can be called by internal functions that need
@@ -57,4 +43,18 @@ contract MixinAbstract {
uint256 membersReward,
uint256 membersStake
);
/// @dev Computes the reward owed to a pool during finalization.
/// Does nothing if the pool is already finalized.
/// @param poolId The pool's ID.
/// @return totalReward The total reward owed to a pool.
/// @return membersStake The total stake for all non-operator members in
/// this pool.
function _getUnfinalizedPoolRewards(bytes32 poolId)
internal
view
returns (
uint256 totalReward,
uint256 membersStake
);
}

View File

@@ -248,7 +248,7 @@ contract MixinFinalizer is
IEtherToken weth = IEtherToken(_getWETHAddress());
uint256 ethBalance = address(this).balance;
if (ethBalance != 0) {
weth.deposit.value((address(this).balance));
weth.deposit.value((address(this).balance))();
}
balance = weth.balanceOf(address(this));
return balance;

View File

@@ -235,7 +235,7 @@ contract MixinParams is
address[2] memory oldSpenders,
address[2] memory newSpenders
)
private
internal
{
IEtherToken weth = IEtherToken(_getWETHAddress());
// Grant new allowances.

View File

@@ -21,7 +21,6 @@ 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 "../immutable/MixinDeploymentConstants.sol";
import "./MixinVaultCore.sol";
@@ -29,15 +28,21 @@ import "./MixinVaultCore.sol";
contract EthVault is
IEthVault,
IVaultCore,
MixinDeploymentConstants,
Ownable,
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()`.
@@ -49,7 +54,7 @@ contract EthVault is
onlyStakingProxy
{
// Transfer WETH from the staking contract into this contract.
IEtherToken(_getWETHAddress()).transferFrom(msg.sender, address(this), amount);
weth.transferFrom(msg.sender, address(this), amount);
// Credit the owner.
_balances[owner] = _balances[owner].safeAdd(amount);
emit EthDepositedIntoVault(msg.sender, owner, amount);
@@ -97,7 +102,7 @@ contract EthVault is
_balances[owner] = _balances[owner].safeSub(amount);
// withdraw WETH to owner
IEtherToken(_getWETHAddress()).transfer(msg.sender, amount);
weth.transfer(msg.sender, amount);
// notify
emit EthWithdrawnFromVault(msg.sender, owner, amount);

View File

@@ -26,22 +26,27 @@ import "../libs/LibStakingRichErrors.sol";
import "../libs/LibSafeDowncast.sol";
import "./MixinVaultCore.sol";
import "../interfaces/IStakingPoolRewardVault.sol";
import "../immutable/MixinDeploymentConstants.sol";
/// @dev This vault manages staking pool rewards.
contract StakingPoolRewardVault is
IStakingPoolRewardVault,
IVaultCore,
MixinDeploymentConstants,
Ownable,
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()`.
@@ -53,7 +58,7 @@ contract StakingPoolRewardVault is
onlyStakingProxy
{
// Transfer WETH from the staking contract into this contract.
IEtherToken(_getWETHAddress()).transferFrom(msg.sender, address(this), amount);
weth.transferFrom(msg.sender, address(this), amount);
// Credit the pool.
_balanceByPoolId[poolId] = _balanceByPoolId[poolId].safeAdd(amount);
emit EthDepositedIntoVault(msg.sender, poolId, amount);
@@ -73,7 +78,7 @@ contract StakingPoolRewardVault is
onlyStakingProxy
{
_balanceByPoolId[poolId] = _balanceByPoolId[poolId].safeSub(amount);
IEtherToken(_getWETHAddress()).transfer(to, amount);
weth.transfer(to, amount);
emit PoolRewardTransferred(
poolId,
to,

View File

@@ -21,6 +21,7 @@ pragma experimental ABIEncoderV2;
import "./TestStaking.sol";
// solhint-disable no-empty-blocks
contract TestCumulativeRewardTracking is
TestStaking
{
@@ -39,7 +40,8 @@ contract TestCumulativeRewardTracking is
uint256 epoch
);
// solhint-disable-next-line no-empty-blocks
constructor(address wethAddress) public TestStaking(wethAddress) {}
function init(address, address, address payable, address) public {}
function _forceSetCumulativeReward(

View File

@@ -0,0 +1,54 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "../src/interfaces/IEthVault.sol";
import "../src/interfaces/IStakingPoolRewardVault.sol";
import "../src/sys/MixinParams.sol";
// solhint-disable no-empty-blocks
contract TestMixinParams is
MixinParams
{
event WETHApprove(address spender, uint256 amount);
/// @dev Sets the eth and reward vault addresses.
function setVaultAddresses(
address ethVaultAddress,
address rewardVaultAddress
)
external
{
ethVault = IEthVault(ethVaultAddress);
rewardVault = IStakingPoolRewardVault(rewardVaultAddress);
}
/// @dev WETH `approve()` function that just logs events.
function approve(address spender, uint256 amount) external returns (bool) {
emit WETHApprove(spender, amount);
}
/// @dev Overridden return this contract's address.
function _getWETHAddress() internal view returns (address) {
return address(this);
}
}

View File

@@ -21,11 +21,11 @@ pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
import "../src/interfaces/IStructs.sol";
import "../src/Staking.sol";
import "./TestStakingNoWETH.sol";
contract TestProtocolFees is
Staking
TestStakingNoWETH
{
struct TestPool {
uint256 operatorStake;
@@ -33,13 +33,22 @@ contract TestProtocolFees is
mapping(address => bool) isMaker;
}
event ERC20ProxyTransferFrom(
bytes assetData,
address from,
address to,
uint256 amount
);
mapping(bytes32 => TestPool) private _testPools;
mapping(address => bytes32) private _makersToTestPoolIds;
constructor(address exchangeAddress, address wethProxyAddress) public {
constructor(address exchangeAddress) public {
init(
wethProxyAddress,
address(1), // vault addresses must be non-zero
// Use this contract as the ERC20Proxy.
address(this),
// vault addresses must be non-zero
address(1),
address(1),
address(1)
);
@@ -81,6 +90,18 @@ contract TestProtocolFees is
}
}
/// @dev The ERC20Proxy `transferFrom()` function.
function transferFrom(
bytes calldata assetData,
address from,
address to,
uint256 amount
)
external
{
emit ERC20ProxyTransferFrom(assetData, from, to, amount);
}
/// @dev Overridden to use test pools.
function getStakingPoolIdOfMaker(address makerAddress)
public

View File

@@ -25,23 +25,17 @@ import "../src/Staking.sol";
contract TestStaking is
Staking
{
address internal _wethAddress;
address public testWethAddress;
constructor(address wethAddress) public {
_wethAddress = wethAddress;
testWethAddress = wethAddress;
}
/// @dev Overridden to avoid hard-coded WETH.
function getTotalBalance()
external
view
returns (uint256 totalBalance)
{
totalBalance = address(this).balance;
}
/// @dev Overridden to use _wethAddress;
/// @dev Overridden to use testWethAddress;
function _getWETHAddress() internal view returns (address) {
return _wethAddress;
// `testWethAddress` will not be set on the proxy this contract is
// attached to, so we need to access the storage of the deployed
// instance of this contract.
return TestStaking(address(uint160(stakingContract))).testWethAddress();
}
}

View File

@@ -17,28 +17,28 @@
*/
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/ERC20Proxy.sol";
import "../src/Staking.sol";
contract TestProtocolFeesERC20Proxy is
ERC20Proxy
// solhint-disable no-empty-blocks
/// @dev A version of the staking contract with WETH-related functions
/// overridden to do nothing.
contract TestStakingNoWETH is
Staking
{
event TransferFromCalled(
bytes assetData,
address from,
address to,
uint256 amount
);
function transferFrom(
bytes calldata assetData,
address from,
address to,
uint256 amount
function _transferWETHAllownces(
address[2] memory oldSpenders,
address[2] memory newSpenders
)
external
internal
{}
function _wrapBalanceToWETHAndGetBalance()
internal
returns (uint256 balance)
{
emit TransferFromCalled(assetData, from, to, amount);
return address(this).balance;
}
}