diff --git a/contracts/staking/contracts/src/StakingProxy.sol b/contracts/staking/contracts/src/StakingProxy.sol index 43c2049ff4..9cfc7a8da1 100644 --- a/contracts/staking/contracts/src/StakingProxy.sol +++ b/contracts/staking/contracts/src/StakingProxy.sol @@ -35,13 +35,28 @@ contract StakingProxy is /// @param _stakingContract Staking contract to delegate calls to. /// @param _readOnlyProxy The address of the read only proxy. /// @param _wethProxyAddress The address that can transfer WETH for fees. - constructor(address _stakingContract, address _readOnlyProxy, address _wethProxyAddress) + /// @param _ethVaultAddress Address of the EthVault contract. + /// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract. + /// @param _zrxVaultAddress Address of the ZrxVault contract. + constructor( + address _stakingContract, + address _readOnlyProxy, + address _wethProxyAddress, + address _ethVaultAddress, + address _rewardVaultAddress, + address _zrxVaultAddress + ) public MixinStorage() { readOnlyProxy = _readOnlyProxy; - wethAssetProxy = IAssetProxy(_wethProxyAddress); - _attachStakingContract(_stakingContract); + _attachStakingContract( + _stakingContract, + _wethProxyAddress, + _ethVaultAddress, + _rewardVaultAddress, + _zrxVaultAddress + ); } /// @dev Delegates calls to the staking contract, if it is set. @@ -59,11 +74,27 @@ contract StakingProxy is /// @dev Attach a staking contract; future calls will be delegated to the staking contract. /// Note that this is callable only by this contract's owner. /// @param _stakingContract Address of staking contract. - function attachStakingContract(address _stakingContract) + /// @param _wethProxyAddress The address that can transfer WETH for fees. + /// @param _ethVaultAddress Address of the EthVault contract. + /// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract. + /// @param _zrxVaultAddress Address of the ZrxVault contract. + function attachStakingContract( + address _stakingContract, + address _wethProxyAddress, + address _ethVaultAddress, + address _rewardVaultAddress, + address _zrxVaultAddress + ) external onlyOwner { - _attachStakingContract(_stakingContract); + _attachStakingContract( + _stakingContract, + _wethProxyAddress, + _ethVaultAddress, + _rewardVaultAddress, + _zrxVaultAddress + ); } /// @dev Detach the current staking contract. @@ -132,13 +163,30 @@ contract StakingProxy is /// @dev Attach a staking contract; future calls will be delegated to the staking contract. /// @param _stakingContract Address of staking contract. - function _attachStakingContract(address _stakingContract) + /// @param _wethProxyAddress The address that can transfer WETH for fees. + /// @param _ethVaultAddress Address of the EthVault contract. + /// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract. + /// @param _zrxVaultAddress Address of the ZrxVault contract. + function _attachStakingContract( + address _stakingContract, + address _wethProxyAddress, + address _ethVaultAddress, + address _rewardVaultAddress, + address _zrxVaultAddress + ) private { stakingContract = readOnlyProxyCallee = _stakingContract; // Call `init()` on the staking contract to initialize storage. - (bool didInitSucceed, bytes memory initReturnData) = - _stakingContract.delegatecall(abi.encode(IStorageInit(0).init.selector)); + (bool didInitSucceed, bytes memory initReturnData) = _stakingContract.delegatecall( + abi.encodeWithSelector( + IStorageInit(0).init.selector, + _wethProxyAddress, + _ethVaultAddress, + _rewardVaultAddress, + _zrxVaultAddress + ) + ); if (!didInitSucceed) { assembly { revert(add(initReturnData, 0x20), mload(initReturnData)) } } diff --git a/contracts/staking/contracts/src/interfaces/IStakingEvents.sol b/contracts/staking/contracts/src/interfaces/IStakingEvents.sol index 194656e4b6..3bcafcdf07 100644 --- a/contracts/staking/contracts/src/interfaces/IStakingEvents.sol +++ b/contracts/staking/contracts/src/interfaces/IStakingEvents.sol @@ -60,13 +60,19 @@ interface IStakingEvents { /// @param maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool. /// @param cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor. /// @param cobbDouglasAlphaDenomintor Denominator for cobb douglas alpha factor. - event ParamsChanged( + /// @param ethVaultAddress Address of the EthVault contract. + /// @param rewardVaultAddress Address of the StakingPoolRewardVault contract. + /// @param zrxVaultAddress Address of the ZrxVault contract. + event ParamsSet( uint256 epochDurationInSeconds, uint32 rewardDelegatedStakeWeight, uint256 minimumPoolStake, uint256 maximumMakersInPool, uint256 cobbDouglasAlphaNumerator, - uint256 cobbDouglasAlphaDenomintor + uint256 cobbDouglasAlphaDenomintor, + address ethVaultAddress, + address rewardVaultAddress, + address zrxVaultAddress ); /// @dev Emitted by MixinScheduler when the timeLock period is changed. diff --git a/contracts/staking/contracts/src/interfaces/IStorageInit.sol b/contracts/staking/contracts/src/interfaces/IStorageInit.sol index e06fce9897..35e49c1a5d 100644 --- a/contracts/staking/contracts/src/interfaces/IStorageInit.sol +++ b/contracts/staking/contracts/src/interfaces/IStorageInit.sol @@ -22,5 +22,15 @@ pragma solidity ^0.5.9; interface IStorageInit { /// @dev Initialize storage owned by this contract. - function init() external; + /// @param _wethProxyAddress The address that can transfer WETH for fees. + /// @param _ethVaultAddress Address of the EthVault contract. + /// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract. + /// @param _zrxVaultAddress Address of the ZrxVault contract. + function init( + address _wethProxyAddress, + address _ethVaultAddress, + address _rewardVaultAddress, + address _zrxVaultAddress + ) + external; } diff --git a/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol b/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol index 3daf14c8cb..8c3721d813 100644 --- a/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol +++ b/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol @@ -41,7 +41,11 @@ library LibStakingRichErrors { enum InvalidParamValueErrorCode { InvalidCobbDouglasAlpha, InvalidRewardDelegatedStakeWeight, - InvalidMaximumMakersInPool + InvalidMaximumMakersInPool, + InvalidWethProxyAddress, + InvalidEthVaultAddress, + InvalidRewardVaultAddress, + InvalidZrxVaultAddress } enum MakerPoolAssignmentErrorCodes { diff --git a/contracts/staking/contracts/src/sys/MixinParams.sol b/contracts/staking/contracts/src/sys/MixinParams.sol index cd6fba21de..0c470feed7 100644 --- a/contracts/staking/contracts/src/sys/MixinParams.sol +++ b/contracts/staking/contracts/src/sys/MixinParams.sol @@ -21,6 +21,9 @@ pragma solidity ^0.5.9; import "@0x/contracts-utils/contracts/src/LibRichErrors.sol"; import "../immutable/MixinStorage.sol"; import "../interfaces/IStakingEvents.sol"; +import "../interfaces/IEthVault.sol"; +import "../interfaces/IStakingPoolRewardVault.sol"; +import "../interfaces/IZrxVault.sol"; import "../libs/LibStakingRichErrors.sol"; @@ -34,39 +37,37 @@ contract MixinParams is /// @param _minimumPoolStake Minimum amount of stake required in a pool to collect rewards. /// @param _maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool. /// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor. - /// @param _cobbDouglasAlphaDenomintor 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 _ethVaultAddress Address of the EthVault contract. + /// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract. + /// @param _zrxVaultAddress Address of the ZrxVault contract. function setParams( uint256 _epochDurationInSeconds, uint32 _rewardDelegatedStakeWeight, uint256 _minimumPoolStake, uint256 _maximumMakersInPool, uint32 _cobbDouglasAlphaNumerator, - uint32 _cobbDouglasAlphaDenomintor + uint32 _cobbDouglasAlphaDenominator, + address _wethProxyAddress, + address _ethVaultAddress, + address _rewardVaultAddress, + address _zrxVaultAddress ) external onlyOwner { - _assertValidRewardDelegatedStakeWeight(_rewardDelegatedStakeWeight); - _assertValidMaximumMakersInPool(_maximumMakersInPool); - _assertValidCobbDouglasAlpha( + _setParams( + _epochDurationInSeconds, + _rewardDelegatedStakeWeight, + _minimumPoolStake, + _maximumMakersInPool, _cobbDouglasAlphaNumerator, - _cobbDouglasAlphaDenomintor - ); - - epochDurationInSeconds = _epochDurationInSeconds; - rewardDelegatedStakeWeight = _rewardDelegatedStakeWeight; - minimumPoolStake = _minimumPoolStake; - maximumMakersInPool = _maximumMakersInPool; - cobbDouglasAlphaNumerator = _cobbDouglasAlphaNumerator; - cobbDouglasAlphaDenomintor = _cobbDouglasAlphaDenomintor; - - emit ParamsChanged( - epochDurationInSeconds, - rewardDelegatedStakeWeight, - minimumPoolStake, - maximumMakersInPool, - cobbDouglasAlphaNumerator, - cobbDouglasAlphaDenomintor + _cobbDouglasAlphaDenominator, + _wethProxyAddress, + _ethVaultAddress, + _rewardVaultAddress, + _zrxVaultAddress ); } @@ -76,7 +77,11 @@ contract MixinParams is /// @return _minimumPoolStake Minimum amount of stake required in a pool to collect rewards. /// @return _maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool. /// @return _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor. - /// @return _cobbDouglasAlphaDenomintor 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 _ethVaultAddress Address of the EthVault contract. + /// @return _rewardVaultAddress Address of the StakingPoolRewardVault contract. + /// @return _zrxVaultAddress Address of the ZrxVault contract. function getParams() external view @@ -86,7 +91,11 @@ contract MixinParams is uint256 _minimumPoolStake, uint256 _maximumMakersInPool, uint32 _cobbDouglasAlphaNumerator, - uint32 _cobbDouglasAlphaDenomintor + uint32 _cobbDouglasAlphaDenominator, + address _wethProxyAddress, + address _ethVaultAddress, + address _rewardVaultAddress, + address _zrxVaultAddress ) { _epochDurationInSeconds = epochDurationInSeconds; @@ -94,7 +103,11 @@ contract MixinParams is _minimumPoolStake = minimumPoolStake; _maximumMakersInPool = maximumMakersInPool; _cobbDouglasAlphaNumerator = cobbDouglasAlphaNumerator; - _cobbDouglasAlphaDenomintor = cobbDouglasAlphaDenomintor; + _cobbDouglasAlphaDenominator = cobbDouglasAlphaDenomintor; + _wethProxyAddress = address(wethAssetProxy); + _ethVaultAddress = address(ethVault); + _rewardVaultAddress = address(rewardVault); + _zrxVaultAddress = address(_zrxVaultAddress); } /// @dev Assert param values before initializing them. @@ -108,7 +121,11 @@ contract MixinParams is minimumPoolStake != 0 && maximumMakersInPool != 0 && cobbDouglasAlphaNumerator != 0 && - cobbDouglasAlphaDenomintor != 0 + cobbDouglasAlphaDenomintor != 0 && + address(wethAssetProxy) != NIL_ADDRESS && + address(ethVault) != NIL_ADDRESS && + address(rewardVault) != NIL_ADDRESS && + address(zrxVault) != NIL_ADDRESS ) { LibRichErrors.rrevert( LibStakingRichErrors.InitializationError( @@ -118,20 +135,105 @@ contract MixinParams is } } - /// @dev Initialize storage belonging to this mixin. - function _initMixinParams() + /// @dev Initialzize storage belonging to this mixin. + /// @param _wethProxyAddress The address that can transfer WETH for fees. + /// @param _ethVaultAddress Address of the EthVault contract. + /// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract. + /// @param _zrxVaultAddress Address of the ZrxVault contract. + function _initMixinParams( + address _wethProxyAddress, + address _ethVaultAddress, + address _rewardVaultAddress, + address _zrxVaultAddress + ) internal { // assert the current values before overwriting them. _assertMixinParamsBeforeInit(); // Set up defaults. - epochDurationInSeconds = 2 weeks; - rewardDelegatedStakeWeight = (90 * PPM_DENOMINATOR) / 100; // 90% - minimumPoolStake = 100 * MIN_TOKEN_VALUE; // 100 ZRX - maximumMakersInPool = 10; - cobbDouglasAlphaNumerator = 1; - cobbDouglasAlphaDenomintor = 2; + _epochDurationInSeconds = 2 weeks; + _rewardDelegatedStakeWeight = (90 * PPM_DENOMINATOR) / 100; // 90% + _minimumPoolStake = 100 * MIN_TOKEN_VALUE; // 100 ZRX + _maximumMakersInPool = 10; + _cobbDouglasAlphaNumerator = 1; + _cobbDouglasAlphaDenomintor = 2; + _setParams( + _epochDurationInSeconds, + _rewardDelegatedStakeWeight, + _minimumPoolStake, + _maximumMakersInPool, + _cobbDouglasAlphaNumerator, + _cobbDouglasAlphaDenomintor, + _wethProxyAddress, + _ethVaultAddress, + _rewardVaultAddress, + _zrxVaultAddress + ); + } + + /// @dev Set all configurable parameters at once. + /// @param _epochDurationInSeconds Minimum seconds between epochs. + /// @param _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm. + /// @param _minimumPoolStake Minimum amount of stake required in a pool to collect rewards. + /// @param _maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool. + /// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor. + /// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor. + /// @param _wethProxyAddress The address that can transfer WETH for fees. + /// @param _ethVaultAddress Address of the EthVault contract. + /// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract. + /// @param _zrxVaultAddress Address of the ZrxVault contract. + function _setParams( + uint256 _epochDurationInSeconds, + uint32 _rewardDelegatedStakeWeight, + uint256 _minimumPoolStake, + uint256 _maximumMakersInPool, + uint32 _cobbDouglasAlphaNumerator, + uint32 _cobbDouglasAlphaDenominator, + address _wethProxyAddress, + address _ethVaultAddress, + address _rewardVaultAddress, + address _zrxVaultAddress + ) + internal + { + _assertValidRewardDelegatedStakeWeight(_rewardDelegatedStakeWeight); + _assertValidMaximumMakersInPool(_maximumMakersInPool); + _assertValidCobbDouglasAlpha( + _cobbDouglasAlphaNumerator, + _cobbDouglasAlphaDenominator + ); + _assertValidAddresses( + _wethProxyAddress, + _ethVaultAddress, + _rewardVaultAddress, + _zrxVaultAddress + ); + // TODO: set boundaries on some of these params + + epochDurationInSeconds = _epochDurationInSeconds; + rewardDelegatedStakeWeight = _rewardDelegatedStakeWeight; + minimumPoolStake = _minimumPoolStake; + maximumMakersInPool = _maximumMakersInPool; + cobbDouglasAlphaNumerator = _cobbDouglasAlphaNumerator; + cobbDouglasAlphaDenomintor = _cobbDouglasAlphaDenominator; + wethAssetProxy = IAssetProxy(_wethProxyAddress); + ethVault = IEthVault(_ethVaultAddress); + rewardVault = IStakingPoolRewardVault(_rewardVaultAddress); + zrxVault = IZrxVault(_zrxVaultAddress); + + emit ParamsSet( + _epochDurationInSeconds, + _rewardDelegatedStakeWeight, + _minimumPoolStake, + _maximumMakersInPool, + _cobbDouglasAlphaNumerator, + _cobbDouglasAlphaDenominator, + _wethProxyAddress, + _ethVaultAddress, + _rewardVaultAddress, + _zrxVaultAddress + ); } /// @dev Asserts that cobb douglas alpha values are valid. @@ -184,4 +286,47 @@ contract MixinParams is )); } } + + /// @dev Asserts that passed in addresses are non-zero. + /// @param _wethProxyAddress The address that can transfer WETH for fees. + /// @param _ethVaultAddress Address of the EthVault contract. + /// @param _rewardVaultAddress Address of the StakingPoolRewardVault contract. + /// @param _zrxVaultAddress Address of the ZrxVault contract. + function _assertValidVaultAddresses( + address _wethProxyAddress, + address _ethVaultAddress, + address _rewardVaultAddress, + address _zrxVaultAddress + ) + private + pure + { + if (_wethProxyAddress == NIL_ADDRESS) { + LibRichErrors.rrevert( + LibStakingRichErrors.InvalidParamValueError( + LibStakingRichErrors.InvalidParamValueErrorCode.InvalidWethProxyAddress + )); + } + + if (_ethVaultAddress == NIL_ADDRESS) { + LibRichErrors.rrevert( + LibStakingRichErrors.InvalidParamValueError( + LibStakingRichErrors.InvalidParamValueErrorCode.InvalidEthVaultAddress + )); + } + + if (_rewardVaultAddress == NIL_ADDRESS) { + LibRichErrors.rrevert( + LibStakingRichErrors.InvalidParamValueError( + LibStakingRichErrors.InvalidParamValueErrorCode.InvalidRewardVaultAddress + )); + } + + if (_zrxVaultAddress == NIL_ADDRESS) { + LibRichErrors.rrevert( + LibStakingRichErrors.InvalidParamValueError( + LibStakingRichErrors.InvalidParamValueErrorCode.InvalidZrxVaultAddress + )); + } + } }