EP: FeeCollectorController (#59)

* `@0x/contracts-zero-ex`: Govern `FeeCollector`s through a separate `FeeCollectorController` contract.

* `@0x/contracts-integrations`: Fix broken EP protocol fees test.
`@0x/contracts-integrations`: Make this package private.

* `@0x/contract-addresses`: Update ganache snapshot addresses.

* Update contracts/zero-ex/contracts/src/external/FeeCollectorController.sol

Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com>

* Apply suggestions from code review

Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com>

* rebase

Co-authored-by: Lawrence Forman <me@merklejerk.com>
Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com>
This commit is contained in:
Lawrence Forman 2020-12-01 12:17:21 -05:00 committed by GitHub
parent 27e36b112e
commit 475b608338
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 280 additions and 43 deletions

View File

@ -19,6 +19,7 @@
pragma solidity ^0.6.5; pragma solidity ^0.6.5;
import "@0x/contracts-zero-ex/contracts/test/TestFixinProtocolFees.sol"; import "@0x/contracts-zero-ex/contracts/test/TestFixinProtocolFees.sol";
import "@0x/contracts-zero-ex/contracts/src/external/FeeCollectorController.sol";
contract TestFixinProtocolFeesIntegration is TestFixinProtocolFees { contract TestFixinProtocolFeesIntegration is TestFixinProtocolFees {
@ -28,7 +29,11 @@ contract TestFixinProtocolFeesIntegration is TestFixinProtocolFees {
uint32 protocolFeeMultiplier uint32 protocolFeeMultiplier
) )
public public
TestFixinProtocolFees(weth, staking, protocolFeeMultiplier) TestFixinProtocolFees(
{ weth,
} staking,
new FeeCollectorController(weth, staking),
protocolFeeMultiplier
)
{}
} }

View File

@ -1,6 +1,7 @@
{ {
"name": "@0x/contracts-integrations", "name": "@0x/contracts-integrations",
"version": "2.7.10", "version": "2.7.10",
"private": true,
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },

View File

@ -57,6 +57,10 @@
{ {
"note": "Add Crypto.com to `BridgeAdapter`", "note": "Add Crypto.com to `BridgeAdapter`",
"pr": 43 "pr": 43
},
{
"note": "Use `FeeCollectorController` contract for deploying `FeeCollector`s",
"pr": 59
} }
] ]
}, },

View File

@ -0,0 +1,92 @@
/*
Copyright 2020 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.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
import "../vendor/v3/IStaking.sol";
import "./FeeCollector.sol";
import "./LibFeeCollector.sol";
/// @dev A contract that manages `FeeCollector` contracts.
contract FeeCollectorController {
/// @dev Hash of the fee collector init code.
bytes32 public immutable FEE_COLLECTOR_INIT_CODE_HASH;
/// @dev The WETH contract.
IEtherTokenV06 private immutable WETH;
/// @dev The staking contract.
IStaking private immutable STAKING;
constructor(
IEtherTokenV06 weth,
IStaking staking
)
public
{
FEE_COLLECTOR_INIT_CODE_HASH = keccak256(type(FeeCollector).creationCode);
WETH = weth;
STAKING = staking;
}
/// @dev Deploy (if needed) a `FeeCollector` contract for `poolId`
/// and wrap its ETH into WETH. Anyone may call this.
/// @param poolId The pool ID associated with the staking pool.
/// @return feeCollector The `FeeCollector` contract instance.
function prepareFeeCollectorToPayFees(bytes32 poolId)
external
returns (FeeCollector feeCollector)
{
feeCollector = getFeeCollector(poolId);
uint256 codeSize;
assembly {
codeSize := extcodesize(feeCollector)
}
if (codeSize == 0) {
// Create and initialize the contract if necessary.
new FeeCollector{salt: bytes32(poolId)}();
feeCollector.initialize(WETH, STAKING, poolId);
}
if (address(feeCollector).balance > 1) {
feeCollector.convertToWeth(WETH);
}
return feeCollector;
}
/// @dev Get the `FeeCollector` contract for a given pool ID. The contract
/// will not actually exist until `prepareFeeCollectorToPayFees()`
/// has been called once.
/// @param poolId The pool ID associated with the staking pool.
/// @return feeCollector The `FeeCollector` contract instance.
function getFeeCollector(bytes32 poolId)
public
view
returns (FeeCollector feeCollector)
{
return FeeCollector(LibFeeCollector.getFeeCollectorAddress(
address(this),
FEE_COLLECTOR_INIT_CODE_HASH,
poolId
));
}
}

View File

@ -0,0 +1,43 @@
/*
Copyright 2020 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.6.5;
pragma experimental ABIEncoderV2;
/// @dev Helpers for computing `FeeCollector` contract addresses.
library LibFeeCollector {
/// @dev Compute the CREATE2 address for a fee collector.
/// @param controller The address of the `FeeCollectorController` contract.
/// @param initCodeHash The init code hash of the `FeeCollector` contract.
/// @param poolId The fee collector's pool ID.
function getFeeCollectorAddress(address controller, bytes32 initCodeHash, bytes32 poolId)
internal
pure
returns (address payable feeCollectorAddress)
{
// Compute the CREATE2 address for the fee collector.
return address(uint256(keccak256(abi.encodePacked(
byte(0xff),
controller,
poolId, // pool ID is salt
initCodeHash
))));
}
}

View File

@ -108,12 +108,13 @@ contract NativeOrdersFeature is
address zeroExAddress, address zeroExAddress,
IEtherTokenV06 weth, IEtherTokenV06 weth,
IStaking staking, IStaking staking,
FeeCollectorController feeCollectorController,
uint32 protocolFeeMultiplier, uint32 protocolFeeMultiplier,
bytes32 greedyTokensBloomFilter bytes32 greedyTokensBloomFilter
) )
public public
FixinEIP712(zeroExAddress) FixinEIP712(zeroExAddress)
FixinProtocolFees(weth, staking, protocolFeeMultiplier) FixinProtocolFees(weth, staking, feeCollectorController, protocolFeeMultiplier)
FixinTokenSpender(greedyTokensBloomFilter) FixinTokenSpender(greedyTokensBloomFilter)
{ {
// solhint-disable no-empty-blocks // solhint-disable no-empty-blocks

View File

@ -21,13 +21,18 @@ pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
import "../external/FeeCollector.sol"; import "../external/FeeCollector.sol";
import "../external/FeeCollectorController.sol";
import "../external/LibFeeCollector.sol";
import "../vendor/v3/IStaking.sol"; import "../vendor/v3/IStaking.sol";
/// @dev Helpers for collecting protocol fees. /// @dev Helpers for collecting protocol fees.
abstract contract FixinProtocolFees { abstract contract FixinProtocolFees {
/// @dev The protocol fee multiplier. /// @dev The protocol fee multiplier.
uint32 public immutable PROTOCOL_FEE_MULTIPLIER; uint32 public immutable PROTOCOL_FEE_MULTIPLIER;
/// @dev The `FeeCollectorController` contract.
FeeCollectorController private immutable FEE_COLLECTOR_CONTROLLER;
/// @dev Hash of the fee collector init code. /// @dev Hash of the fee collector init code.
bytes32 private immutable FEE_COLLECTOR_INIT_CODE_HASH; bytes32 private immutable FEE_COLLECTOR_INIT_CODE_HASH;
/// @dev The WETH token contract. /// @dev The WETH token contract.
@ -38,11 +43,14 @@ abstract contract FixinProtocolFees {
constructor( constructor(
IEtherTokenV06 weth, IEtherTokenV06 weth,
IStaking staking, IStaking staking,
FeeCollectorController feeCollectorController,
uint32 protocolFeeMultiplier uint32 protocolFeeMultiplier
) )
internal internal
{ {
FEE_COLLECTOR_INIT_CODE_HASH = keccak256(type(FeeCollector).creationCode); FEE_COLLECTOR_CONTROLLER = feeCollectorController;
FEE_COLLECTOR_INIT_CODE_HASH =
feeCollectorController.FEE_COLLECTOR_INIT_CODE_HASH();
WETH = weth; WETH = weth;
STAKING = staking; STAKING = staking;
PROTOCOL_FEE_MULTIPLIER = protocolFeeMultiplier; PROTOCOL_FEE_MULTIPLIER = protocolFeeMultiplier;
@ -72,23 +80,11 @@ abstract contract FixinProtocolFees {
function _transferFeesForPool(bytes32 poolId) function _transferFeesForPool(bytes32 poolId)
internal internal
{ {
FeeCollector feeCollector = _getFeeCollector(poolId); // This will create a FeeCollector contract (if necessary) and wrap
// fees for the pool ID.
uint256 codeSize; FeeCollector feeCollector =
assembly { FEE_COLLECTOR_CONTROLLER.prepareFeeCollectorToPayFees(poolId);
codeSize := extcodesize(feeCollector) // All fees in the fee collector should be in WETH now.
}
if (codeSize == 0) {
// Create and initialize the contract if necessary.
new FeeCollector{salt: bytes32(poolId)}();
feeCollector.initialize(WETH, STAKING, poolId);
}
if (address(feeCollector).balance > 1) {
feeCollector.convertToWeth(WETH);
}
uint256 bal = WETH.balanceOf(address(feeCollector)); uint256 bal = WETH.balanceOf(address(feeCollector));
if (bal > 1) { if (bal > 1) {
// Leave 1 wei behind to avoid high SSTORE cost of zero-->non-zero. // Leave 1 wei behind to avoid high SSTORE cost of zero-->non-zero.
@ -106,14 +102,11 @@ abstract contract FixinProtocolFees {
view view
returns (FeeCollector) returns (FeeCollector)
{ {
// Compute the CREATE2 address for the fee collector. return FeeCollector(LibFeeCollector.getFeeCollectorAddress(
address payable addr = address(uint256(keccak256(abi.encodePacked( address(FEE_COLLECTOR_CONTROLLER),
byte(0xff), FEE_COLLECTOR_INIT_CODE_HASH,
address(this), poolId
poolId, // pool ID is salt ));
FEE_COLLECTOR_INIT_CODE_HASH
))));
return FeeCollector(addr);
} }
/// @dev Get the cost of a single protocol fee. /// @dev Get the cost of a single protocol fee.

View File

@ -0,0 +1,28 @@
/*
Copyright 2020 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.6.5;
pragma experimental ABIEncoderV2;
/// @dev FeeCollectorControllerContract-like contract with a null init code hash.
// Does not implement anything else, so finalization will fail.
contract TestFeeCollectorController {
bytes32 public FEE_COLLECTOR_INIT_CODE_HASH = 0;
}

View File

@ -27,10 +27,11 @@ contract TestFixinProtocolFees is
constructor( constructor(
IEtherTokenV06 weth, IEtherTokenV06 weth,
IStaking staking, IStaking staking,
FeeCollectorController feeCollectorController,
uint32 protocolFeeMultiplier uint32 protocolFeeMultiplier
) )
public public
FixinProtocolFees(weth, staking, protocolFeeMultiplier) FixinProtocolFees(weth, staking, feeCollectorController, protocolFeeMultiplier)
{ {
// solhint-disalbe no-empty-blocks // solhint-disalbe no-empty-blocks
} }

View File

@ -21,17 +21,23 @@ pragma experimental ABIEncoderV2;
import "../src/features/NativeOrdersFeature.sol"; import "../src/features/NativeOrdersFeature.sol";
import "../src/features/IMetaTransactionsFeature.sol"; import "../src/features/IMetaTransactionsFeature.sol";
import "./TestFeeCollectorController.sol";
contract TestMetaTransactionsNativeOrdersFeature is contract TestMetaTransactionsNativeOrdersFeature is
NativeOrdersFeature NativeOrdersFeature
{ {
constructor( constructor()
)
public public
NativeOrdersFeature(address(0), IEtherTokenV06(0), IStaking(0), 0, bytes32(0)) NativeOrdersFeature(
{ address(0),
} IEtherTokenV06(0),
IStaking(0),
FeeCollectorController(address(new TestFeeCollectorController())),
0,
bytes32(0)
)
{}
event FillLimitOrderCalled( event FillLimitOrderCalled(
LibNativeOrder.LimitOrder order, LibNativeOrder.LimitOrder order,

View File

@ -2,6 +2,7 @@ pragma solidity ^0.6;
pragma experimental ABIEncoderV2; pragma experimental ABIEncoderV2;
import "../src/features/NativeOrdersFeature.sol"; import "../src/features/NativeOrdersFeature.sol";
import "./TestFeeCollectorController.sol";
contract TestNativeOrdersFeature is contract TestNativeOrdersFeature is
NativeOrdersFeature NativeOrdersFeature
@ -10,6 +11,7 @@ contract TestNativeOrdersFeature is
address zeroExAddress, address zeroExAddress,
IEtherTokenV06 weth, IEtherTokenV06 weth,
IStaking staking, IStaking staking,
FeeCollectorController _feeCollectorController, // Unused but necessary for artifact compatibility.
uint32 protocolFeeMultiplier, uint32 protocolFeeMultiplier,
bytes32 greedyTokensBloomFilter bytes32 greedyTokensBloomFilter
) )
@ -18,6 +20,7 @@ contract TestNativeOrdersFeature is
zeroExAddress, zeroExAddress,
weth, weth,
staking, staking,
FeeCollectorController(address(new TestFeeCollectorController())),
protocolFeeMultiplier, protocolFeeMultiplier,
greedyTokensBloomFilter greedyTokensBloomFilter
) )

View File

@ -40,9 +40,9 @@
"publish:private": "yarn build && gitpkg publish" "publish:private": "yarn build && gitpkg publish"
}, },
"config": { "config": {
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITokenSpenderFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,TokenSpenderFeature,AffiliateFeeTransformer,SignatureValidatorFeature,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature", "publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITokenSpenderFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,TokenSpenderFeature,AffiliateFeeTransformer,SignatureValidatorFeature,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|FeeCollector|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|INativeOrdersFeature|IOwnableFeature|ISignatureValidatorFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOrderHash|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAdapterAddresses|MixinBalancer|MixinCryptoCom|MixinCurve|MixinDodo|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinShell|MixinSushiswap|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|NativeOrdersFeature|OwnableFeature|PayTakerTransformer|PermissionlessTransformerDeployer|SignatureValidatorFeature|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestNativeOrdersFeature|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json" "abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|INativeOrdersFeature|IOwnableFeature|ISignatureValidatorFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOrderHash|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAdapterAddresses|MixinBalancer|MixinCryptoCom|MixinCurve|MixinDodo|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinShell|MixinSushiswap|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|NativeOrdersFeature|OwnableFeature|PayTakerTransformer|PermissionlessTransformerDeployer|SignatureValidatorFeature|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestNativeOrdersFeature|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -7,6 +7,8 @@ import { ContractArtifact } from 'ethereum-types';
import * as AffiliateFeeTransformer from '../generated-artifacts/AffiliateFeeTransformer.json'; import * as AffiliateFeeTransformer from '../generated-artifacts/AffiliateFeeTransformer.json';
import * as BridgeAdapter from '../generated-artifacts/BridgeAdapter.json'; import * as BridgeAdapter from '../generated-artifacts/BridgeAdapter.json';
import * as FeeCollector from '../generated-artifacts/FeeCollector.json';
import * as FeeCollectorController from '../generated-artifacts/FeeCollectorController.json';
import * as FillQuoteTransformer from '../generated-artifacts/FillQuoteTransformer.json'; import * as FillQuoteTransformer from '../generated-artifacts/FillQuoteTransformer.json';
import * as FullMigration from '../generated-artifacts/FullMigration.json'; import * as FullMigration from '../generated-artifacts/FullMigration.json';
import * as IAllowanceTarget from '../generated-artifacts/IAllowanceTarget.json'; import * as IAllowanceTarget from '../generated-artifacts/IAllowanceTarget.json';
@ -60,4 +62,6 @@ export const artifacts = {
ILiquidityProviderFeature: ILiquidityProviderFeature as ContractArtifact, ILiquidityProviderFeature: ILiquidityProviderFeature as ContractArtifact,
NativeOrdersFeature: NativeOrdersFeature as ContractArtifact, NativeOrdersFeature: NativeOrdersFeature as ContractArtifact,
INativeOrdersFeature: INativeOrdersFeature as ContractArtifact, INativeOrdersFeature: INativeOrdersFeature as ContractArtifact,
FeeCollectorController: FeeCollectorController as ContractArtifact,
FeeCollector: FeeCollector as ContractArtifact,
}; };

View File

@ -7,6 +7,7 @@ import * as _ from 'lodash';
import { artifacts } from './artifacts'; import { artifacts } from './artifacts';
import { ZERO_BYTES32 } from './constants'; import { ZERO_BYTES32 } from './constants';
import { import {
FeeCollectorControllerContract,
FullMigrationContract, FullMigrationContract,
InitialMigrationContract, InitialMigrationContract,
IZeroExContract, IZeroExContract,
@ -124,6 +125,7 @@ export interface FullFeatureArtifacts extends BootstrapFeatureArtifacts {
signatureValidator: SimpleContractArtifact; signatureValidator: SimpleContractArtifact;
metaTransactions: SimpleContractArtifact; metaTransactions: SimpleContractArtifact;
nativeOrders: SimpleContractArtifact; nativeOrders: SimpleContractArtifact;
feeCollectorController: SimpleContractArtifact;
} }
/** /**
@ -148,6 +150,7 @@ const DEFAULT_FULL_FEATURES_DEPLOY_CONFIG = {
zeroExAddress: NULL_ADDRESS, zeroExAddress: NULL_ADDRESS,
wethAddress: NULL_ADDRESS, wethAddress: NULL_ADDRESS,
stakingAddress: NULL_ADDRESS, stakingAddress: NULL_ADDRESS,
feeCollectorController: NULL_ADDRESS,
protocolFeeMultiplier: 70e3, protocolFeeMultiplier: 70e3,
greedyTokensBloomFilter: ZERO_BYTES32, greedyTokensBloomFilter: ZERO_BYTES32,
}; };
@ -158,6 +161,7 @@ const DEFAULT_FULL_FEATURES_ARTIFACTS = {
signatureValidator: artifacts.SignatureValidatorFeature, signatureValidator: artifacts.SignatureValidatorFeature,
metaTransactions: artifacts.MetaTransactionsFeature, metaTransactions: artifacts.MetaTransactionsFeature,
nativeOrders: artifacts.NativeOrdersFeature, nativeOrders: artifacts.NativeOrdersFeature,
feeCollectorController: artifacts.FeeCollectorController,
}; };
/** /**
@ -175,6 +179,16 @@ export async function deployFullFeaturesAsync(
...DEFAULT_FULL_FEATURES_ARTIFACTS, ...DEFAULT_FULL_FEATURES_ARTIFACTS,
...featureArtifacts, ...featureArtifacts,
}; };
if (_config.feeCollectorController === NULL_ADDRESS) {
_config.feeCollectorController = (await FeeCollectorControllerContract.deployFrom0xArtifactAsync(
_featureArtifacts.feeCollectorController,
provider,
txDefaults,
artifacts,
_config.wethAddress,
_config.stakingAddress,
)).address;
}
return { return {
...(await deployBootstrapFeaturesAsync(provider, txDefaults)), ...(await deployBootstrapFeaturesAsync(provider, txDefaults)),
tokenSpender: tokenSpender:
@ -222,6 +236,7 @@ export async function deployFullFeaturesAsync(
_config.zeroExAddress, _config.zeroExAddress,
_config.wethAddress, _config.wethAddress,
_config.stakingAddress, _config.stakingAddress,
_config.feeCollectorController,
_config.protocolFeeMultiplier, _config.protocolFeeMultiplier,
_config.greedyTokensBloomFilter, _config.greedyTokensBloomFilter,
)).address, )).address,

View File

@ -5,6 +5,8 @@
*/ */
export * from '../generated-wrappers/affiliate_fee_transformer'; export * from '../generated-wrappers/affiliate_fee_transformer';
export * from '../generated-wrappers/bridge_adapter'; export * from '../generated-wrappers/bridge_adapter';
export * from '../generated-wrappers/fee_collector';
export * from '../generated-wrappers/fee_collector_controller';
export * from '../generated-wrappers/fill_quote_transformer'; export * from '../generated-wrappers/fill_quote_transformer';
export * from '../generated-wrappers/full_migration'; export * from '../generated-wrappers/full_migration';
export * from '../generated-wrappers/i_allowance_target'; export * from '../generated-wrappers/i_allowance_target';

View File

@ -10,6 +10,7 @@ import * as AllowanceTarget from '../test/generated-artifacts/AllowanceTarget.js
import * as BootstrapFeature from '../test/generated-artifacts/BootstrapFeature.json'; import * as BootstrapFeature from '../test/generated-artifacts/BootstrapFeature.json';
import * as BridgeAdapter from '../test/generated-artifacts/BridgeAdapter.json'; import * as BridgeAdapter from '../test/generated-artifacts/BridgeAdapter.json';
import * as FeeCollector from '../test/generated-artifacts/FeeCollector.json'; import * as FeeCollector from '../test/generated-artifacts/FeeCollector.json';
import * as FeeCollectorController from '../test/generated-artifacts/FeeCollectorController.json';
import * as FillQuoteTransformer from '../test/generated-artifacts/FillQuoteTransformer.json'; import * as FillQuoteTransformer from '../test/generated-artifacts/FillQuoteTransformer.json';
import * as FixinCommon from '../test/generated-artifacts/FixinCommon.json'; import * as FixinCommon from '../test/generated-artifacts/FixinCommon.json';
import * as FixinEIP712 from '../test/generated-artifacts/FixinEIP712.json'; import * as FixinEIP712 from '../test/generated-artifacts/FixinEIP712.json';
@ -45,6 +46,7 @@ import * as IZeroEx from '../test/generated-artifacts/IZeroEx.json';
import * as LibBootstrap from '../test/generated-artifacts/LibBootstrap.json'; import * as LibBootstrap from '../test/generated-artifacts/LibBootstrap.json';
import * as LibCommonRichErrors from '../test/generated-artifacts/LibCommonRichErrors.json'; import * as LibCommonRichErrors from '../test/generated-artifacts/LibCommonRichErrors.json';
import * as LibERC20Transformer from '../test/generated-artifacts/LibERC20Transformer.json'; import * as LibERC20Transformer from '../test/generated-artifacts/LibERC20Transformer.json';
import * as LibFeeCollector from '../test/generated-artifacts/LibFeeCollector.json';
import * as LibLiquidityProviderRichErrors from '../test/generated-artifacts/LibLiquidityProviderRichErrors.json'; import * as LibLiquidityProviderRichErrors from '../test/generated-artifacts/LibLiquidityProviderRichErrors.json';
import * as LibMetaTransactionsRichErrors from '../test/generated-artifacts/LibMetaTransactionsRichErrors.json'; import * as LibMetaTransactionsRichErrors from '../test/generated-artifacts/LibMetaTransactionsRichErrors.json';
import * as LibMetaTransactionsStorage from '../test/generated-artifacts/LibMetaTransactionsStorage.json'; import * as LibMetaTransactionsStorage from '../test/generated-artifacts/LibMetaTransactionsStorage.json';
@ -95,6 +97,7 @@ import * as SimpleFunctionRegistryFeature from '../test/generated-artifacts/Simp
import * as TestBridge from '../test/generated-artifacts/TestBridge.json'; import * as TestBridge from '../test/generated-artifacts/TestBridge.json';
import * as TestCallTarget from '../test/generated-artifacts/TestCallTarget.json'; import * as TestCallTarget from '../test/generated-artifacts/TestCallTarget.json';
import * as TestDelegateCaller from '../test/generated-artifacts/TestDelegateCaller.json'; import * as TestDelegateCaller from '../test/generated-artifacts/TestDelegateCaller.json';
import * as TestFeeCollectorController from '../test/generated-artifacts/TestFeeCollectorController.json';
import * as TestFillQuoteTransformerBridge from '../test/generated-artifacts/TestFillQuoteTransformerBridge.json'; import * as TestFillQuoteTransformerBridge from '../test/generated-artifacts/TestFillQuoteTransformerBridge.json';
import * as TestFillQuoteTransformerExchange from '../test/generated-artifacts/TestFillQuoteTransformerExchange.json'; import * as TestFillQuoteTransformerExchange from '../test/generated-artifacts/TestFillQuoteTransformerExchange.json';
import * as TestFillQuoteTransformerHost from '../test/generated-artifacts/TestFillQuoteTransformerHost.json'; import * as TestFillQuoteTransformerHost from '../test/generated-artifacts/TestFillQuoteTransformerHost.json';
@ -151,10 +154,12 @@ export const artifacts = {
LibWalletRichErrors: LibWalletRichErrors as ContractArtifact, LibWalletRichErrors: LibWalletRichErrors as ContractArtifact,
AllowanceTarget: AllowanceTarget as ContractArtifact, AllowanceTarget: AllowanceTarget as ContractArtifact,
FeeCollector: FeeCollector as ContractArtifact, FeeCollector: FeeCollector as ContractArtifact,
FeeCollectorController: FeeCollectorController as ContractArtifact,
FlashWallet: FlashWallet as ContractArtifact, FlashWallet: FlashWallet as ContractArtifact,
IAllowanceTarget: IAllowanceTarget as ContractArtifact, IAllowanceTarget: IAllowanceTarget as ContractArtifact,
IFlashWallet: IFlashWallet as ContractArtifact, IFlashWallet: IFlashWallet as ContractArtifact,
ILiquidityProviderSandbox: ILiquidityProviderSandbox as ContractArtifact, ILiquidityProviderSandbox: ILiquidityProviderSandbox as ContractArtifact,
LibFeeCollector: LibFeeCollector as ContractArtifact,
LiquidityProviderSandbox: LiquidityProviderSandbox as ContractArtifact, LiquidityProviderSandbox: LiquidityProviderSandbox as ContractArtifact,
PermissionlessTransformerDeployer: PermissionlessTransformerDeployer as ContractArtifact, PermissionlessTransformerDeployer: PermissionlessTransformerDeployer as ContractArtifact,
TransformerDeployer: TransformerDeployer as ContractArtifact, TransformerDeployer: TransformerDeployer as ContractArtifact,
@ -233,6 +238,7 @@ export const artifacts = {
TestBridge: TestBridge as ContractArtifact, TestBridge: TestBridge as ContractArtifact,
TestCallTarget: TestCallTarget as ContractArtifact, TestCallTarget: TestCallTarget as ContractArtifact,
TestDelegateCaller: TestDelegateCaller as ContractArtifact, TestDelegateCaller: TestDelegateCaller as ContractArtifact,
TestFeeCollectorController: TestFeeCollectorController as ContractArtifact,
TestFillQuoteTransformerBridge: TestFillQuoteTransformerBridge as ContractArtifact, TestFillQuoteTransformerBridge: TestFillQuoteTransformerBridge as ContractArtifact,
TestFillQuoteTransformerExchange: TestFillQuoteTransformerExchange as ContractArtifact, TestFillQuoteTransformerExchange: TestFillQuoteTransformerExchange as ContractArtifact,
TestFillQuoteTransformerHost: TestFillQuoteTransformerHost as ContractArtifact, TestFillQuoteTransformerHost: TestFillQuoteTransformerHost as ContractArtifact,

View File

@ -2,7 +2,13 @@ import { blockchainTests, expect } from '@0x/contracts-test-utils';
import { AuthorizableRevertErrors, BigNumber, hexUtils } from '@0x/utils'; import { AuthorizableRevertErrors, BigNumber, hexUtils } from '@0x/utils';
import { artifacts } from './artifacts'; import { artifacts } from './artifacts';
import { FeeCollectorContract, TestFixinProtocolFeesContract, TestStakingContract, TestWethContract } from './wrappers'; import {
FeeCollectorContract,
FeeCollectorControllerContract,
TestFixinProtocolFeesContract,
TestStakingContract,
TestWethContract,
} from './wrappers';
blockchainTests.resets('ProtocolFees', env => { blockchainTests.resets('ProtocolFees', env => {
const FEE_MULTIPLIER = 70e3; const FEE_MULTIPLIER = 70e3;
@ -11,6 +17,7 @@ blockchainTests.resets('ProtocolFees', env => {
let protocolFees: TestFixinProtocolFeesContract; let protocolFees: TestFixinProtocolFeesContract;
let staking: TestStakingContract; let staking: TestStakingContract;
let weth: TestWethContract; let weth: TestWethContract;
let feeCollectorController: FeeCollectorControllerContract;
let singleFeeAmount: BigNumber; let singleFeeAmount: BigNumber;
before(async () => { before(async () => {
@ -28,6 +35,14 @@ blockchainTests.resets('ProtocolFees', env => {
artifacts, artifacts,
weth.address, weth.address,
); );
feeCollectorController = await FeeCollectorControllerContract.deployFrom0xArtifactAsync(
artifacts.FeeCollectorController,
env.provider,
env.txDefaults,
artifacts,
weth.address,
staking.address,
);
protocolFees = await TestFixinProtocolFeesContract.deployFrom0xArtifactAsync( protocolFees = await TestFixinProtocolFeesContract.deployFrom0xArtifactAsync(
artifacts.TestFixinProtocolFees, artifacts.TestFixinProtocolFees,
env.provider, env.provider,
@ -35,6 +50,7 @@ blockchainTests.resets('ProtocolFees', env => {
artifacts, artifacts,
weth.address, weth.address,
staking.address, staking.address,
feeCollectorController.address,
FEE_MULTIPLIER, FEE_MULTIPLIER,
); );
singleFeeAmount = await protocolFees.getSingleProtocolFee().callAsync(); singleFeeAmount = await protocolFees.getSingleProtocolFee().callAsync();

View File

@ -8,6 +8,7 @@ export * from '../test/generated-wrappers/allowance_target';
export * from '../test/generated-wrappers/bootstrap_feature'; export * from '../test/generated-wrappers/bootstrap_feature';
export * from '../test/generated-wrappers/bridge_adapter'; export * from '../test/generated-wrappers/bridge_adapter';
export * from '../test/generated-wrappers/fee_collector'; export * from '../test/generated-wrappers/fee_collector';
export * from '../test/generated-wrappers/fee_collector_controller';
export * from '../test/generated-wrappers/fill_quote_transformer'; export * from '../test/generated-wrappers/fill_quote_transformer';
export * from '../test/generated-wrappers/fixin_common'; export * from '../test/generated-wrappers/fixin_common';
export * from '../test/generated-wrappers/fixin_e_i_p712'; export * from '../test/generated-wrappers/fixin_e_i_p712';
@ -43,6 +44,7 @@ export * from '../test/generated-wrappers/initial_migration';
export * from '../test/generated-wrappers/lib_bootstrap'; export * from '../test/generated-wrappers/lib_bootstrap';
export * from '../test/generated-wrappers/lib_common_rich_errors'; export * from '../test/generated-wrappers/lib_common_rich_errors';
export * from '../test/generated-wrappers/lib_erc20_transformer'; export * from '../test/generated-wrappers/lib_erc20_transformer';
export * from '../test/generated-wrappers/lib_fee_collector';
export * from '../test/generated-wrappers/lib_liquidity_provider_rich_errors'; export * from '../test/generated-wrappers/lib_liquidity_provider_rich_errors';
export * from '../test/generated-wrappers/lib_meta_transactions_rich_errors'; export * from '../test/generated-wrappers/lib_meta_transactions_rich_errors';
export * from '../test/generated-wrappers/lib_meta_transactions_storage'; export * from '../test/generated-wrappers/lib_meta_transactions_storage';
@ -93,6 +95,7 @@ export * from '../test/generated-wrappers/simple_function_registry_feature';
export * from '../test/generated-wrappers/test_bridge'; export * from '../test/generated-wrappers/test_bridge';
export * from '../test/generated-wrappers/test_call_target'; export * from '../test/generated-wrappers/test_call_target';
export * from '../test/generated-wrappers/test_delegate_caller'; export * from '../test/generated-wrappers/test_delegate_caller';
export * from '../test/generated-wrappers/test_fee_collector_controller';
export * from '../test/generated-wrappers/test_fill_quote_transformer_bridge'; export * from '../test/generated-wrappers/test_fill_quote_transformer_bridge';
export * from '../test/generated-wrappers/test_fill_quote_transformer_exchange'; export * from '../test/generated-wrappers/test_fill_quote_transformer_exchange';
export * from '../test/generated-wrappers/test_fill_quote_transformer_host'; export * from '../test/generated-wrappers/test_fill_quote_transformer_host';

View File

@ -5,6 +5,8 @@
"files": [ "files": [
"generated-artifacts/AffiliateFeeTransformer.json", "generated-artifacts/AffiliateFeeTransformer.json",
"generated-artifacts/BridgeAdapter.json", "generated-artifacts/BridgeAdapter.json",
"generated-artifacts/FeeCollector.json",
"generated-artifacts/FeeCollectorController.json",
"generated-artifacts/FillQuoteTransformer.json", "generated-artifacts/FillQuoteTransformer.json",
"generated-artifacts/FullMigration.json", "generated-artifacts/FullMigration.json",
"generated-artifacts/IAllowanceTarget.json", "generated-artifacts/IAllowanceTarget.json",
@ -35,6 +37,7 @@
"test/generated-artifacts/BootstrapFeature.json", "test/generated-artifacts/BootstrapFeature.json",
"test/generated-artifacts/BridgeAdapter.json", "test/generated-artifacts/BridgeAdapter.json",
"test/generated-artifacts/FeeCollector.json", "test/generated-artifacts/FeeCollector.json",
"test/generated-artifacts/FeeCollectorController.json",
"test/generated-artifacts/FillQuoteTransformer.json", "test/generated-artifacts/FillQuoteTransformer.json",
"test/generated-artifacts/FixinCommon.json", "test/generated-artifacts/FixinCommon.json",
"test/generated-artifacts/FixinEIP712.json", "test/generated-artifacts/FixinEIP712.json",
@ -70,6 +73,7 @@
"test/generated-artifacts/LibBootstrap.json", "test/generated-artifacts/LibBootstrap.json",
"test/generated-artifacts/LibCommonRichErrors.json", "test/generated-artifacts/LibCommonRichErrors.json",
"test/generated-artifacts/LibERC20Transformer.json", "test/generated-artifacts/LibERC20Transformer.json",
"test/generated-artifacts/LibFeeCollector.json",
"test/generated-artifacts/LibLiquidityProviderRichErrors.json", "test/generated-artifacts/LibLiquidityProviderRichErrors.json",
"test/generated-artifacts/LibMetaTransactionsRichErrors.json", "test/generated-artifacts/LibMetaTransactionsRichErrors.json",
"test/generated-artifacts/LibMetaTransactionsStorage.json", "test/generated-artifacts/LibMetaTransactionsStorage.json",
@ -120,6 +124,7 @@
"test/generated-artifacts/TestBridge.json", "test/generated-artifacts/TestBridge.json",
"test/generated-artifacts/TestCallTarget.json", "test/generated-artifacts/TestCallTarget.json",
"test/generated-artifacts/TestDelegateCaller.json", "test/generated-artifacts/TestDelegateCaller.json",
"test/generated-artifacts/TestFeeCollectorController.json",
"test/generated-artifacts/TestFillQuoteTransformerBridge.json", "test/generated-artifacts/TestFillQuoteTransformerBridge.json",
"test/generated-artifacts/TestFillQuoteTransformerExchange.json", "test/generated-artifacts/TestFillQuoteTransformerExchange.json",
"test/generated-artifacts/TestFillQuoteTransformerHost.json", "test/generated-artifacts/TestFillQuoteTransformerHost.json",

View File

@ -1,4 +1,13 @@
[ [
{
"version": "5.5.0",
"changes": [
{
"note": "Update ganache snapshot addresses",
"pr": 59
}
]
},
{ {
"version": "5.4.0", "version": "5.4.0",
"changes": [ "changes": [

View File

@ -198,10 +198,10 @@
"exchangeProxyFlashWallet": "0xb9682a8e7920b431f1d412b8510f0077410c8faa", "exchangeProxyFlashWallet": "0xb9682a8e7920b431f1d412b8510f0077410c8faa",
"exchangeProxyLiquidityProviderSandbox": "0x0000000000000000000000000000000000000000", "exchangeProxyLiquidityProviderSandbox": "0x0000000000000000000000000000000000000000",
"transformers": { "transformers": {
"wethTransformer": "0x7209185959d7227fb77274e1e88151d7c4c368d3", "wethTransformer": "0x3f16ca81691dab9184cb4606c361d73c4fd2510a",
"payTakerTransformer": "0x3f16ca81691dab9184cb4606c361d73c4fd2510a", "payTakerTransformer": "0x99356167edba8fbdc36959e3f5d0c43d1ba9c6db",
"affiliateFeeTransformer": "0x99356167edba8fbdc36959e3f5d0c43d1ba9c6db", "affiliateFeeTransformer": "0x45b3a72221e571017c0f0ec42189e11d149d0ace",
"fillQuoteTransformer": "0x45b3a72221e571017c0f0ec42189e11d149d0ace" "fillQuoteTransformer": "0xdd66c23e07b4d6925b6089b5fe6fc9e62941afe8"
} }
} }
} }