@0x:contracts-exchange Added the MixinProtocolFees contract

This commit is contained in:
Alex Towle
2019-08-21 14:46:35 -07:00
parent 05eb646848
commit bf3751fd9e
9 changed files with 215 additions and 6 deletions

View File

@@ -30,8 +30,8 @@ import "@0x/contracts-exchange-libs/contracts/src/LibExchangeRichErrors.sol";
import "@0x/contracts-staking/contracts/src/interfaces/IStaking.sol";
import "./interfaces/IExchangeCore.sol";
import "./MixinAssetProxyDispatcher.sol";
import "./MixinProtocolFees.sol";
import "./MixinSignatureValidator.sol";
import "./MixinStakingManager.sol";
contract MixinExchangeCore is
@@ -40,7 +40,7 @@ contract MixinExchangeCore is
IExchangeCore,
MixinAssetProxyDispatcher,
MixinSignatureValidator,
MixinStakingManager
MixinProtocolFees
{
using LibOrder for LibOrder.Order;
using LibSafeMath for uint256;

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;
import "@0x/contracts-utils/contracts/src/Ownable.sol";
import "./interfaces/IProtocolFees.sol";
contract MixinProtocolFees is
IProtocolFees,
Ownable
{
// The protocol fee multiplier -- the owner can update this field.
uint256 public protocolFeeMultiplier;
// The address of the registered protocolFeeCollector contract -- the owner can update this field.
address public protocolFeeCollector;
/// @dev Allows the owner to update the protocol fee multiplier.
/// @param updatedProtocolFeeMultiplier The updated protocol fee multiplier.
function updateProtocolFeeMultiplier(uint256 updatedProtocolFeeMultiplier)
external
onlyOwner
{
emit UpdatedProtocolFeeMultiplier(protocolFeeMultiplier, updatedProtocolFeeMultiplier);
protocolFeeMultiplier = updatedProtocolFeeMultiplier;
}
/// @dev Allows the owner to update the protocolFeeCollector address.
/// @param updatedProtocolFeeCollector The updated protocolFeeCollector contract address.
function updateProtocolFeeCollectorAddress(address updatedProtocolFeeCollector)
external
onlyOwner
{
emit UpdatedProtocolFeeCollectorAddress(protocolFeeCollector, updatedProtocolFeeCollector);
protocolFeeCollector = updatedProtocolFeeCollector;
}
}

View File

@@ -0,0 +1,39 @@
/*
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;
contract IProtocolFees {
// Logs updates to the protocol fee multiplier.
event UpdatedProtocolFeeMultiplier(uint256 oldProtocolFeeMultiplier, uint256 updatedProtocolFeeMultiplier);
// Logs updates to the protocolFeeCollector address.
event UpdatedProtocolFeeCollectorAddress(address oldProtocolFeeCollector, address updatedProtocolFeeCollector);
/// @dev Allows the owner to update the protocol fee multiplier.
/// @param updatedProtocolFeeMultiplier The updated protocol fee multiplier.
function updateProtocolFeeMultiplier(uint256 updatedProtocolFeeMultiplier)
external;
/// @dev Allows the owner to update the protocolFeeCollector address.
/// @param updatedProtocolFeeCollector The updated protocolFeeCollector contract address.
function updateProtocolFeeCollectorAddress(address updatedProtocolFeeCollector)
external;
}

View File

@@ -13,6 +13,7 @@ import * as IEIP1271Wallet from '../generated-artifacts/IEIP1271Wallet.json';
import * as IExchange from '../generated-artifacts/IExchange.json';
import * as IExchangeCore from '../generated-artifacts/IExchangeCore.json';
import * as IMatchOrders from '../generated-artifacts/IMatchOrders.json';
import * as IProtocolFees from '../generated-artifacts/IProtocolFees.json';
import * as ISignatureValidator from '../generated-artifacts/ISignatureValidator.json';
import * as IStakingManager from '../generated-artifacts/IStakingManager.json';
import * as ITransactions from '../generated-artifacts/ITransactions.json';
@@ -24,6 +25,7 @@ import * as LibExchangeRichErrorDecoder from '../generated-artifacts/LibExchange
import * as MixinAssetProxyDispatcher from '../generated-artifacts/MixinAssetProxyDispatcher.json';
import * as MixinExchangeCore from '../generated-artifacts/MixinExchangeCore.json';
import * as MixinMatchOrders from '../generated-artifacts/MixinMatchOrders.json';
import * as MixinProtocolFees from '../generated-artifacts/MixinProtocolFees.json';
import * as MixinSignatureValidator from '../generated-artifacts/MixinSignatureValidator.json';
import * as MixinStakingManager from '../generated-artifacts/MixinStakingManager.json';
import * as MixinTransactions from '../generated-artifacts/MixinTransactions.json';
@@ -45,6 +47,7 @@ export const artifacts = {
MixinAssetProxyDispatcher: MixinAssetProxyDispatcher as ContractArtifact,
MixinExchangeCore: MixinExchangeCore as ContractArtifact,
MixinMatchOrders: MixinMatchOrders as ContractArtifact,
MixinProtocolFees: MixinProtocolFees as ContractArtifact,
MixinSignatureValidator: MixinSignatureValidator as ContractArtifact,
MixinStakingManager: MixinStakingManager as ContractArtifact,
MixinTransactions: MixinTransactions as ContractArtifact,
@@ -56,6 +59,7 @@ export const artifacts = {
IExchange: IExchange as ContractArtifact,
IExchangeCore: IExchangeCore as ContractArtifact,
IMatchOrders: IMatchOrders as ContractArtifact,
IProtocolFees: IProtocolFees as ContractArtifact,
ISignatureValidator: ISignatureValidator as ContractArtifact,
IStakingManager: IStakingManager as ContractArtifact,
ITransactions: ITransactions as ContractArtifact,

View File

@@ -11,6 +11,7 @@ export * from '../generated-wrappers/i_e_i_p1271_wallet';
export * from '../generated-wrappers/i_exchange';
export * from '../generated-wrappers/i_exchange_core';
export * from '../generated-wrappers/i_match_orders';
export * from '../generated-wrappers/i_protocol_fees';
export * from '../generated-wrappers/i_signature_validator';
export * from '../generated-wrappers/i_staking_manager';
export * from '../generated-wrappers/i_transactions';
@@ -22,6 +23,7 @@ export * from '../generated-wrappers/lib_exchange_rich_error_decoder';
export * from '../generated-wrappers/mixin_asset_proxy_dispatcher';
export * from '../generated-wrappers/mixin_exchange_core';
export * from '../generated-wrappers/mixin_match_orders';
export * from '../generated-wrappers/mixin_protocol_fees';
export * from '../generated-wrappers/mixin_signature_validator';
export * from '../generated-wrappers/mixin_staking_manager';
export * from '../generated-wrappers/mixin_transactions';

View File

@@ -0,0 +1,110 @@
import { blockchainTests, constants, expect, LogDecoder } from '@0x/contracts-test-utils';
import { BigNumber, OwnableRevertErrors } from '@0x/utils';
import { LogWithDecodedArgs } from 'ethereum-types';
import {
artifacts,
ExchangeContract,
ExchangeUpdatedProtocolFeeCollectorAddressEventArgs,
ExchangeUpdatedProtocolFeeMultiplierEventArgs,
} from '../src';
blockchainTests.resets('MixinProtocolFees', env => {
let accounts: string[];
let exchange: ExchangeContract;
let logDecoder: LogDecoder;
let nonOwner: string;
let owner: string;
let protocolFeeCollector: string;
// The protocolFeeMultiplier that will be used to test the update functions.
const protocolFeeMultiplier = new BigNumber(15000);
before(async () => {
accounts = await env.web3Wrapper.getAvailableAddressesAsync();
owner = accounts[0];
nonOwner = accounts[1];
protocolFeeCollector = accounts[2];
// Update the from address of the txDefaults. This is the address that will become the owner.
env.txDefaults.from = owner;
// Deploy the exchange contract.
exchange = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange,
env.provider,
env.txDefaults,
{},
new BigNumber(1337),
);
// Configure the log decoder
logDecoder = new LogDecoder(env.web3Wrapper, artifacts);
});
blockchainTests.resets('updateProtocolFeeMultiplier', () => {
it('should revert if msg.sender != owner', async () => {
const expectedError = new OwnableRevertErrors.OnlyOwnerError(nonOwner, owner);
// Ensure that the transaction reverts with the expected rich error.
const tx = exchange.updateProtocolFeeCollectorAddress.sendTransactionAsync(protocolFeeCollector, {
from: nonOwner,
});
return expect(tx).to.revertWith(expectedError);
});
it('should succeed and emit an UpdatedProtocolFeeMultiplier event if msg.sender == owner', async () => {
// Call the `updateProtocolFeeMultiplier()` function and get the receipt.
const receipt = await logDecoder.getTxWithDecodedLogsAsync(
await exchange.updateProtocolFeeMultiplier.sendTransactionAsync(protocolFeeMultiplier, {
from: owner,
}),
);
// Verify that the protocolFeeCollector address was actually updated to the correct address.
const updated = await exchange.protocolFeeMultiplier.callAsync();
expect(updated).bignumber.to.be.eq(protocolFeeMultiplier);
// Ensure that the correct `UpdatedProtocolFeeCollectorAddress` event was logged.
// tslint:disable:no-unnecessary-type-assertion
const updatedEvent = receipt.logs[0] as LogWithDecodedArgs<ExchangeUpdatedProtocolFeeMultiplierEventArgs>;
expect(updatedEvent.event).to.be.eq('UpdatedProtocolFeeMultiplier');
expect(updatedEvent.args.oldProtocolFeeMultiplier).bignumber.to.be.eq(constants.ZERO_AMOUNT);
expect(updatedEvent.args.updatedProtocolFeeMultiplier).bignumber.to.be.eq(protocolFeeMultiplier);
});
});
blockchainTests.resets('updateProtocolFeeCollectorAddress', () => {
it('should revert if msg.sender != owner', async () => {
const expectedError = new OwnableRevertErrors.OnlyOwnerError(nonOwner, owner);
// Ensure that the transaction reverts with the expected rich error.
const tx = exchange.updateProtocolFeeCollectorAddress.sendTransactionAsync(protocolFeeCollector, {
from: nonOwner,
});
return expect(tx).to.revertWith(expectedError);
});
it('should succeed and emit an UpdatedProtocolFeeCollectorAddress event if msg.sender == owner', async () => {
// Call the `updateProtocolFeeCollectorAddress()` function and get the receipt.
const receipt = await logDecoder.getTxWithDecodedLogsAsync(
await exchange.updateProtocolFeeCollectorAddress.sendTransactionAsync(protocolFeeCollector, {
from: owner,
}),
);
// Verify that the protocolFeeCollector address was actually updated to the correct address.
const updated = await exchange.protocolFeeCollector.callAsync();
expect(updated).to.be.eq(protocolFeeCollector);
// Ensure that the correct `UpdatedProtocolFeeCollectorAddress` event was logged.
// tslint:disable:no-unnecessary-type-assertion
const updatedEvent = receipt.logs[0] as LogWithDecodedArgs<
ExchangeUpdatedProtocolFeeCollectorAddressEventArgs
>;
expect(updatedEvent.event).to.be.eq('UpdatedProtocolFeeCollectorAddress');
expect(updatedEvent.args.oldProtocolFeeCollector).to.be.eq(constants.NULL_ADDRESS);
expect(updatedEvent.args.updatedProtocolFeeCollector).to.be.eq(protocolFeeCollector);
});
});
});

View File

@@ -10,8 +10,7 @@ export const constants = {
ExchangeFunctionName.SimulateDispatchTransferFromCalls,
ExchangeFunctionName.TransferOwnership,
ExchangeFunctionName.UpdateProtocolFeeMultiplier,
ExchangeFunctionName.UpdateStakingAddress,
ExchangeFunctionName.UpdateWethAddress,
ExchangeFunctionName.UpdateProtocolFeeCollectorAddress,
],
SINGLE_FILL_FN_NAMES: [
ExchangeFunctionName.FillOrder,

View File

@@ -33,6 +33,5 @@ export enum ExchangeFunctionName {
SimulateDispatchTransferFromCalls = 'simulateDispatchTransferFromCalls',
TransferOwnership = 'transferOwnership',
UpdateProtocolFeeMultiplier = 'updateProtocolFeeMultiplier',
UpdateStakingAddress = 'updateStakingAddress',
UpdateWethAddress = 'updateWethAddress',
UpdateProtocolFeeCollectorAddress = 'updateProtocolFeeCollectorAddress',
}

View File

@@ -11,6 +11,7 @@
"generated-artifacts/IExchange.json",
"generated-artifacts/IExchangeCore.json",
"generated-artifacts/IMatchOrders.json",
"generated-artifacts/IProtocolFees.json",
"generated-artifacts/ISignatureValidator.json",
"generated-artifacts/IStakingManager.json",
"generated-artifacts/ITransactions.json",
@@ -22,6 +23,7 @@
"generated-artifacts/MixinAssetProxyDispatcher.json",
"generated-artifacts/MixinExchangeCore.json",
"generated-artifacts/MixinMatchOrders.json",
"generated-artifacts/MixinProtocolFees.json",
"generated-artifacts/MixinSignatureValidator.json",
"generated-artifacts/MixinStakingManager.json",
"generated-artifacts/MixinTransactions.json",