Exchange tracking

This commit is contained in:
Greg Hysen 2019-06-06 23:01:17 -07:00
parent 938f4d2d9d
commit c57d17dc58
7 changed files with 159 additions and 4 deletions

View File

@ -25,6 +25,7 @@ import "./core/MixinPools.sol";
import "./core/MixinEpoch.sol";
import "./core/MixinRewards.sol";
import "./core/MixinFees.sol";
import "./core/MixinExchange.sol";
contract Staking is
@ -32,6 +33,7 @@ contract Staking is
//IStakingEvents,
MixinConstants,
MixinStorage,
MixinExchange,
MixinEpoch,
MixinRewards,
MixinStake,
@ -350,9 +352,17 @@ contract Staking is
}
///// FEES /////
modifier onlyExchange() {
require(
_isValidExchangeAddress(msg.sender),
"ONLY_CALLABLE_BY_EXCHANGE"
);
_;
}
function payProtocolFee(address makerAddress)
external
payable
onlyExchange
{
_payProtocolFee(makerAddress, msg.value);
}
@ -373,6 +383,29 @@ contract Staking is
return _getTotalProtocolFeesThisEpoch();
}
///// EXCHANGES /////
// @TODO - Only by 0x multi-sig
function isValidExchangeAddress(address addr)
external
view
returns (bool)
{
return _isValidExchangeAddress(addr);
}
function addExchangeAddress(address addr)
external
{
_addExchangeAddress(addr);
}
function removeExchangeAddress(address addr)
external
{
_removeExchangeAddress(addr);
}
///// SETTERS /////
function setZrxVault(address _zrxVault)

View File

@ -0,0 +1,68 @@
/*
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 "../immutable/MixinStorage.sol";
import "../immutable/MixinConstants.sol";
import "../interfaces/IStakingEvents.sol";
import "./MixinStakeBalances.sol";
import "./MixinEpoch.sol";
import "./MixinPools.sol";
contract MixinExchange is
SafeMath,
IStakingEvents,
MixinConstants,
MixinStorage
{
function _isValidExchangeAddress(address addr)
internal
view
returns (bool)
{
return validExchanges[addr];
}
function _addExchangeAddress(address addr)
internal
{
require(
!validExchanges[addr],
"EXCHANGE_ADDRESS_ALREADY_REGISTERED"
);
validExchanges[addr] = true;
emit ExchangeAdded(addr);
}
function _removeExchangeAddress(address addr)
internal
{
require(
validExchanges[addr],
"EXCHANGE_ADDRESS_NOT_REGISTERED"
);
validExchanges[addr] = false;
emit ExchangeRemoved(addr);
}
}

View File

@ -94,6 +94,9 @@ contract MixinStorage is
// shadow balances by
mapping (address => mapping (bytes32 => uint256)) shadowRewardsInPoolByOwner;
// registrered 0x exchanges
mapping (address => bool) validExchanges;
/*
// mapping from Owner to Pool Id to Amount Delegated

View File

@ -17,4 +17,12 @@ interface IStakingEvents {
address operatorAddress,
uint8 operatorShare
);
event ExchangeAdded(
address exchangeAddress
);
event ExchangeRemoved(
address exchangeAddress
);
}

View File

@ -525,7 +525,32 @@ describe('Staking Core', () => {
}
});
it.only('Protocol Fees', async () => {
it.only('Exchange Tracking', async () => {
// 1 try querying an invalid addresses
const invalidAddress = "0x0000000000000000000000000000000000000001";
const isInvalidAddressValid = await stakingWrapper.isValidExchangeAddressAsync(invalidAddress);
expect(isInvalidAddressValid).to.be.false();
// 2 add valid address
await stakingWrapper.addExchangeAddressAsync(exchange);
const isValidAddressValid = await stakingWrapper.isValidExchangeAddressAsync(exchange);
expect(isValidAddressValid).to.be.true();
// 3 try adding valid address again
await expectTransactionFailedAsync(
stakingWrapper.addExchangeAddressAsync(exchange),
RevertReason.ExchangeAddressAlreadyRegistered
);
// 4 remove valid address
await stakingWrapper.removeExchangeAddressAsync(exchange);
const isValidAddressStillValid = await stakingWrapper.isValidExchangeAddressAsync(exchange);
expect(isValidAddressStillValid).to.be.false();
// 5 try removing valid address again
await expectTransactionFailedAsync(
stakingWrapper.removeExchangeAddressAsync(exchange),
RevertReason.ExchangeAddressNotRegistered
);
});
it.skip('Protocol Fees', async () => {
///// 1 SETUP POOLS /////
const poolOperators = stakers.slice(0, 3);
const operatorShares = [39, 59, 43];

View File

@ -317,26 +317,41 @@ export class StakingWrapper {
const value = this.getStakingContract().getCurrentTimelockPeriod.getABIDecodedReturnData(returnData);
return value;
}
///// FEES /////
///// PROTOCOL FEES /////
public async payProtocolFeeAsync(makerAddress: string, amount: BigNumber): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().payProtocolFee.getABIEncodedTransactionData(makerAddress);
const txReceipt = await this._executeTransactionAsync(calldata, this._ownerAddres, amount);
return txReceipt;
}
public async getProtocolFeesThisEpochByPoolAsync(poolId: string): Promise<BigNumber> {
const calldata = this.getStakingContract().getProtocolFeesThisEpochByPool.getABIEncodedTransactionData(poolId);
const returnData = await this._callAsync(calldata);
const value = this.getStakingContract().getProtocolFeesThisEpochByPool.getABIDecodedReturnData(returnData);
return value;
}
public async getTotalProtocolFeesThisEpochAsync(): Promise<BigNumber> {
const calldata = this.getStakingContract().getTotalProtocolFeesThisEpoch.getABIEncodedTransactionData();
const returnData = await this._callAsync(calldata);
const value = this.getStakingContract().getTotalProtocolFeesThisEpoch.getABIDecodedReturnData(returnData);
return value;
}
///// EXCHANGES /////
public async isValidExchangeAddressAsync(exchangeAddress: string): Promise<Boolean> {
const calldata = this.getStakingContract().isValidExchangeAddress.getABIEncodedTransactionData(exchangeAddress);
const returnData = await this._callAsync(calldata);
const value = this.getStakingContract().isValidExchangeAddress.getABIDecodedReturnData(returnData);
return value;
}
public async addExchangeAddressAsync(exchangeAddress: string): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().addExchangeAddress.getABIEncodedTransactionData(exchangeAddress);
const txReceipt = await this._executeTransactionAsync(calldata, this._ownerAddres);
return txReceipt;
}
public async removeExchangeAddressAsync(exchangeAddress: string): Promise<TransactionReceiptWithDecodedLogs> {
const calldata = this.getStakingContract().removeExchangeAddress.getABIEncodedTransactionData(exchangeAddress);
const txReceipt = await this._executeTransactionAsync(calldata, this._ownerAddres);
return txReceipt;
}
/*
///// REWARDS /////

View File

@ -343,6 +343,9 @@ export enum RevertReason {
// Staking
OnlyCallableByPoolOperator = 'ONLY_CALLABLE_BY_POOL_OPERATOR',
MakerAddressAlreadyRegistered = 'MAKER_ADDRESS_ALREADY_REGISTERED',
OnlyCallableByExchange = 'ONLY_CALLABLE_BY_EXCHANGE',
ExchangeAddressAlreadyRegistered = 'EXCHANGE_ADDRESS_ALREADY_REGISTERED',
ExchangeAddressNotRegistered = 'EXCHANGE_ADDRESS_NOT_REGISTERED',
}
export enum StatusCodes {