Implemented staking logic and ZRX vault

This commit is contained in:
Greg Hysen
2019-05-20 15:18:54 -07:00
parent 7407890deb
commit 3517dd2741
21 changed files with 446 additions and 8 deletions

View File

@@ -0,0 +1,94 @@
/*
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.5;
import "./interfaces/IStake.sol";
import "./mixins/MStake.sol";
import "./interfaces/IVault.sol";
import "./libs/LibZrxToken.sol";
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
contract MixinStake is
MStake,
IStake,
SafeMath
{
using LibZrxToken for uint256;
// default maker id that stake is delegated to
bytes32 constant internal NIL_MAKER_ID = 0x0;
// mapping from Staker to Maker Id to Amount Staked
mapping (address => mapping (bytes32 => uint256)) delegatedStake;
// mapping from Staker to Maker Id to Amount Staked
mapping (address => uint256) totalStake;
// ZRX vault
IVault zrxVault;
constructor(address _zrxVault) public {
zrxVault = IVault(_zrxVault);
}
function stake(uint256 amount)
external
returns (uint256)
{
// sanitize input - can only stake whole tokens
uint256 amountOfStakeToMint = amount.roundDownToNearestWholeToken();
// deposit equivalent amount of ZRX into vault
zrxVault.depositFrom(msg.sender, amountOfStakeToMint);
// mint stake
totalStake[msg.sender] = _safeAdd(totalStake[msg.sender], amountOfStakeToMint);
delegatedStake[msg.sender][NIL_MAKER_ID] = _safeAdd(delegatedStake[msg.sender][NIL_MAKER_ID], amountOfStakeToMint);
// return amount of stake minted
return amountOfStakeToMint;
}
function unstake(uint256 amount)
external
returns (uint256)
{
// sanitize input - can only stake whole tokens
uint256 amountOfStakeToBurn = amount.roundDownToNearestWholeToken();
// burn stake
totalStake[msg.sender] = _safeSub(totalStake[msg.sender], amountOfStakeToBurn);
delegatedStake[msg.sender][NIL_MAKER_ID] = _safeSub(delegatedStake[msg.sender][NIL_MAKER_ID], amountOfStakeToBurn);
// withdraw equivalent amount of ZRX from vault
zrxVault.withdrawFrom(msg.sender, amountOfStakeToBurn);
// return amount of stake minted
return amountOfStakeToBurn;
}
function getStakeBalance(address owner)
external
view
returns (uint256)
{
return totalStake[owner];
}
}

View File

@@ -18,9 +18,15 @@
pragma solidity ^0.5.9;
import "./IStaking.sol";
import "./MixinStake.sol";
contract Staking is IStaking {
contract Staking is
MixinStake
{
constructor(address zrxVault)
public
MixinStake(zrxVault)
{}
}

View File

@@ -0,0 +1,42 @@
/*
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.5;
contract IAssetProxy {
/// @dev Transfers assets. Either succeeds or throws.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer.
function transferFrom(
bytes calldata assetData,
address from,
address to,
uint256 amount
)
external;
/// @dev Gets the proxy id associated with the proxy address.
/// @return Proxy id.
function getProxyId()
external
pure
returns (bytes4);
}

View File

@@ -0,0 +1,27 @@
/*
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.5;
contract IStake
{
function stake(uint256 amount) external returns (uint256);
function unstake(uint256 amount) external returns (uint256);
function getStakeBalance(address owner) external view returns (uint256);
}

View File

@@ -0,0 +1,31 @@
/*
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.5;
interface IVault {
function depositFrom(address owner, uint256 amount) external;
function withdrawFrom(address owner, uint256 amount) external;
function withdrawAllFrom(address owner) external returns (uint256);
function balanceOf(address owner) external view returns (uint256);
}

View File

@@ -0,0 +1,33 @@
/*
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.5;
library LibZrxToken {
uint256 constant internal TOKEN_MULTIPLIER = 10**18;
function roundDownToNearestWholeToken(uint256 value)
public
pure
returns (uint256)
{
return (value / TOKEN_MULTIPLIER) * TOKEN_MULTIPLIER;
}
}

View File

@@ -19,6 +19,8 @@
pragma solidity ^0.5.9;
interface IStaking {
contract MStake
{
}

View File

@@ -0,0 +1,66 @@
/*
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.5;
import "@0x/contracts-utils/contracts/src/Authorizable.sol";
contract MixinVaultCore is
Authorizable
{
address internal stakingContractAddress;
bool internal isInCatostrophicFailure;
constructor(address _stakingContractAddress) public {
stakingContractAddress = _stakingContractAddress;
isInCatostrophicFailure = false;
}
modifier onlyStakingContract {
require(
msg.sender == stakingContractAddress,
"ONLY_CALLABLE_BY_STAKING_CONTRACT"
);
_;
}
modifier onlyInCatostrophicFailure {
require(
isInCatostrophicFailure,
"ONLY_CALLABLE_IN_CATOSTROPHIC_FAILURE"
);
_;
}
function setStakingContractAddrsess(address _stakingContractAddress)
external
onlyOwner
{
stakingContractAddress = _stakingContractAddress;
}
function enterCatostrophicFailure()
external
onlyOwner
{
isInCatostrophicFailure = true;
}
}

View File

@@ -0,0 +1,119 @@
/*
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.5;
import "../interfaces/IVault.sol";
import "../interfaces/IAssetProxy.sol";
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
import "./MixinVaultCore.sol";
contract ZrxVault is
IVault,
SafeMath,
MixinVaultCore
{
// mapping from Owner to ZRX balance
mapping (address => uint256) internal balances;
IAssetProxy internal erc20Proxy;
bytes internal zrxAssetData;
constructor(address _erc20ProxyAddress, bytes memory _zrxAssetData) public {
erc20Proxy = IAssetProxy(_erc20ProxyAddress);
zrxAssetData = _zrxAssetData;
}
function setErc20Proxy(address _erc20ProxyAddress)
external
onlyOwner
{
erc20Proxy = IAssetProxy(_erc20ProxyAddress);
}
function setZrxAssetData(bytes calldata _zrxAssetData)
external
onlyOwner
{
zrxAssetData = _zrxAssetData;
}
function depositFrom(address owner, uint256 amount)
external
onlyStakingContract
{
// deposit ZRX from owner
erc20Proxy.transferFrom(
zrxAssetData,
address(this),
owner,
amount
);
// update balance
balances[owner] = _safeAdd(balances[owner], amount);
}
function withdrawFrom(address owner, uint256 amount)
external
onlyStakingContract
{
_withdrawFrom(owner, amount);
}
function withdrawAllFrom(address owner)
external
onlyInCatostrophicFailure
returns (uint256)
{
// get total balance
uint256 totalBalance = balances[owner];
// withdraw ZRX to owner
_withdrawFrom(owner, totalBalance);
return totalBalance;
}
function _withdrawFrom(address owner, uint256 amount)
internal
{
// withdraw ZRX to owner
erc20Proxy.transferFrom(
zrxAssetData,
address(this),
owner,
amount
);
// update balance
// note that this call will revert if trying to withdraw more
// than the current balance
balances[owner] = _safeSub(balances[owner], amount);
}
function balanceOf(address owner)
external
view
returns (uint256)
{
return balances[owner];
}
}

View File

@@ -35,7 +35,7 @@
"compile:truffle": "truffle compile"
},
"config": {
"abis": "./generated-artifacts/@(IStaking|Staking).json",
"abis": "./generated-artifacts/@(LibZrxToken|MixinStake|MixinVaultCore|Staking|ZrxVault).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
},
"repository": {

View File

@@ -5,6 +5,15 @@
*/
import { ContractArtifact } from 'ethereum-types';
import * as IStaking from '../generated-artifacts/IStaking.json';
import * as LibZrxToken from '../generated-artifacts/LibZrxToken.json';
import * as MixinStake from '../generated-artifacts/MixinStake.json';
import * as MixinVaultCore from '../generated-artifacts/MixinVaultCore.json';
import * as Staking from '../generated-artifacts/Staking.json';
export const artifacts = { IStaking: IStaking as ContractArtifact, Staking: Staking as ContractArtifact };
import * as ZrxVault from '../generated-artifacts/ZrxVault.json';
export const artifacts = {
MixinStake: MixinStake as ContractArtifact,
Staking: Staking as ContractArtifact,
LibZrxToken: LibZrxToken as ContractArtifact,
MixinVaultCore: MixinVaultCore as ContractArtifact,
ZrxVault: ZrxVault as ContractArtifact,
};

View File

@@ -3,5 +3,8 @@
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/i_staking';
export * from '../generated-wrappers/lib_zrx_token';
export * from '../generated-wrappers/mixin_stake';
export * from '../generated-wrappers/mixin_vault_core';
export * from '../generated-wrappers/staking';
export * from '../generated-wrappers/zrx_vault';

View File

@@ -2,6 +2,12 @@
"extends": "../../tsconfig",
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
"files": ["generated-artifacts/IStaking.json", "generated-artifacts/Staking.json"],
"files": [
"generated-artifacts/LibZrxToken.json",
"generated-artifacts/MixinStake.json",
"generated-artifacts/MixinVaultCore.json",
"generated-artifacts/Staking.json",
"generated-artifacts/ZrxVault.json"
],
"exclude": ["./deploy/solc/solc_bin"]
}