Split Storage Logic + Staking Logic Contracts

This commit is contained in:
Greg Hysen
2019-05-31 14:58:02 -07:00
parent c6192ea953
commit 6a902eff56
13 changed files with 401 additions and 6 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 "./core/MixinStorage.sol";
import "./interfaces/IStakingProxy.sol";
contract StakingProxy is
IStakingProxy,
MixinStorage
{
address constant NIL_ADDRESS = 0x0000000000000000000000000000000000000000;
constructor(address _stakingContract)
public
{
stakingContract = _stakingContract;
}
function ()
external
payable
{
address _stakingContract = stakingContract;
if (_stakingContract == NIL_ADDRESS) {
return;
}
assembly {
// copy calldata to memory
calldatacopy(
0x0,
0x0,
calldatasize()
)
// delegate call into staking contract
let success := delegatecall(
gas, // forward all gas
_stakingContract, // calling staking contract
0x0, // start of input (calldata)
calldatasize(), // length of input (calldata)
0x0, // write output over input
0 // length of output is unknown
)
// copy return data to memory
returndatacopy(
0x0,
0x0,
returndatasize()
)
// rethrow any exceptions
if iszero(success) {
revert(0, returndatasize())
}
// return call results
return(0, returndatasize())
}
}
function attachStakingContract(address _stakingContract)
external
//ownerOnly
{
stakingContract = _stakingContract;
}
function detachStakingContract()
external
//ownerOnly
{
stakingContract = NIL_ADDRESS;
}
}

View File

@@ -0,0 +1,153 @@
/*
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 "../libs/LibZrxToken.sol";
import "@0x/contracts-utils/contracts/src/SafeMath.sol";
import "./MixinStorage.sol";
import "../interfaces/IStakingEvents.sol";
contract MixinStake is
SafeMath,
IStakingEvents,
MixinStorage
{
using LibZrxToken for uint256;
// default maker id that stake is delegated to
bytes32 constant internal NIL_MAKER_ID = 0x0;
function _stake(uint256 amount)
internal
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);
// emit stake event
emit StakeMinted(
msg.sender,
amountOfStakeToMint
);
// return amount of stake minted
return amountOfStakeToMint;
}
function _unstake(uint256 amount)
internal
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);
// emit stake event
emit StakeMinted(
msg.sender,
amountOfStakeToBurn
);
// return amount of stake minted
return amountOfStakeToBurn;
}
function _delegateStake(bytes32 makerId, uint256 amount)
internal
returns (uint256)
{
uint256 amountOfStakeToDelegate = amount._roundDownToNearestWholeToken();
}
// returns
function _undelegateStake(bytes32 makerId, uint256 amount)
internal
returns (uint256)
{
}
function _undelegateStake(bytes32 makerId)
internal
returns (uint256)
{
address owner = msg.sender;
uint256 delegatedStakeBalance = _getStakeDelegatedByOwner(owner, makerId);
_undelegateStake(makerId, delegatedStakeBalance);
}
function _stakeAndDelegate(bytes32 makerId, uint256 amount)
internal
returns (uint256 amountOfStakeDelegated)
{
// mint stake
uint256 amountOfStakeMinted = _stake(amount);
// delegate stake to maker
amountOfStakeDelegated = _delegateStake(makerId, amountOfStakeMinted);
return amountOfStakeDelegated;
}
function _getStakeDelegatedByOwner(address owner, bytes32 makerId)
internal
returns (uint256)
{
return delegatedStake[owner][makerId];
}
function _getTotalStakeDelegatedByOwner(address owner)
internal
returns (uint256)
{
return _safeSub(
totalStake[owner],
delegatedStake[owner][NIL_MAKER_ID]
);
}
function _getTotalStakeDelegatedToMaker(bytes32 makerId)
internal
returns (uint256)
{
return totalDelegatedStake[makerId];
}
function _getStakeBalance(address owner)
internal
view
returns (uint256)
{
return totalStake[owner];
}
}

View File

@@ -0,0 +1,43 @@
/*
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";
contract MixinStorage {
// address of staking contract
address stakingContract;
// 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;
// mapping from Maker Id to Amount of Delegated Staked
mapping (bytes32 => uint256) totalDelegatedStake;
// ZRX vault
IVault zrxVault;
// Rebate Vault
IVault rebateVault;
}

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;
interface IStaking
{
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,14 @@
interface IStakingEvents {
event StakeMinted(
address owner,
uint256 amount
);
event StakeBurned(
address owner,
uint256 amount
);
}

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;
interface IStakingProxy
{
/*function attachStakingContract(address stakingContract) external;
function detachStakingContract() external;
function () external payable;*/
}

View File

@@ -0,0 +1,24 @@
/*
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 MakerRegistry {
}

View File

@@ -93,7 +93,7 @@ export class StakingWrapper {
txDefaults,
);
}
private async _executeTransaction(calldata: string, from: string): Promise<TransactionReceiptWithDecodedLogs> {
private async _executeTransactionAsync(calldata: string, from: string): Promise<TransactionReceiptWithDecodedLogs> {
const txData = {
from,
to: this.getStakingProxyContract().address,
@@ -105,20 +105,33 @@ export class StakingWrapper {
);
return txReceipt;
}
private async _callAsync(calldata: string, from: string): Promise<any> {
const txData = {
from,
to: this.getStakingProxyContract().address,
data: calldata,
gas: 3000000
}
const returnValue = await this._web3Wrapper.callAsync(txData);
return returnValue;
}
public async stake(holder: string, amount: BigNumber): Promise<BigNumber> {
const calldata = await this.getStakingContract().stake.getABIEncodedTransactionData(amount);
const txReceipt = await this._executeTransaction(calldata, holder);
const calldata = this.getStakingContract().stake.getABIEncodedTransactionData(amount);
const txReceipt = await this._executeTransactionAsync(calldata, holder);
const stakeMintedLog = this._logDecoder.decodeLogOrThrow(txReceipt.logs[1]);
const stakeMinted = (stakeMintedLog as any).args.amount;
return stakeMinted;
}
public async unstake(holder: string, amount: BigNumber): Promise<BigNumber> {
const stakeBurned = await this.getStakingContract().unstake.callAsync(amount, {from: holder});
await this.getStakingContract().unstake.awaitTransactionSuccessAsync(amount, {from: holder});
const calldata = this.getStakingContract().unstake.getABIEncodedTransactionData(amount);
const txReceipt = await this._executeTransactionAsync(calldata, holder);
const stakeBurnedLog = this._logDecoder.decodeLogOrThrow(txReceipt.logs[1]);
const stakeBurned = (stakeBurnedLog as any).args.amount;
return stakeBurned;
}
public async getStakeBalance(holder: string): Promise<BigNumber> {
const balance = await this.getStakingContract().getStakeBalance.callAsync(holder);
const calldata = this.getStakingContract().getStakeBalance.getABIEncodedTransactionData(holder);
const balance = await this._callAsync(calldata, holder);
return balance;
}
public async getZrxVaultBalance(holder: string): Promise<BigNumber> {