diff --git a/contracts/integrations/contracts/test/TestFixinProtocolFeesIntegration.sol b/contracts/integrations/contracts/test/TestFixinProtocolFeesIntegration.sol index 173472f361..6030a1cfb2 100644 --- a/contracts/integrations/contracts/test/TestFixinProtocolFeesIntegration.sol +++ b/contracts/integrations/contracts/test/TestFixinProtocolFeesIntegration.sol @@ -19,6 +19,7 @@ pragma solidity ^0.6.5; import "@0x/contracts-zero-ex/contracts/test/TestFixinProtocolFees.sol"; +import "@0x/contracts-zero-ex/contracts/src/external/FeeCollectorController.sol"; contract TestFixinProtocolFeesIntegration is TestFixinProtocolFees { @@ -28,7 +29,11 @@ contract TestFixinProtocolFeesIntegration is TestFixinProtocolFees { uint32 protocolFeeMultiplier ) public - TestFixinProtocolFees(weth, staking, protocolFeeMultiplier) - { - } + TestFixinProtocolFees( + weth, + staking, + new FeeCollectorController(weth, staking), + protocolFeeMultiplier + ) + {} } diff --git a/contracts/integrations/package.json b/contracts/integrations/package.json index 74339ca32b..2b8712c2ff 100644 --- a/contracts/integrations/package.json +++ b/contracts/integrations/package.json @@ -1,6 +1,7 @@ { "name": "@0x/contracts-integrations", "version": "2.7.10", + "private": true, "engines": { "node": ">=6.12" }, diff --git a/contracts/zero-ex/CHANGELOG.json b/contracts/zero-ex/CHANGELOG.json index 9152a23c53..0ed15cff9e 100644 --- a/contracts/zero-ex/CHANGELOG.json +++ b/contracts/zero-ex/CHANGELOG.json @@ -57,6 +57,10 @@ { "note": "Add Crypto.com to `BridgeAdapter`", "pr": 43 + }, + { + "note": "Use `FeeCollectorController` contract for deploying `FeeCollector`s", + "pr": 59 } ] }, diff --git a/contracts/zero-ex/contracts/src/external/FeeCollectorController.sol b/contracts/zero-ex/contracts/src/external/FeeCollectorController.sol new file mode 100644 index 0000000000..7d8b982bc3 --- /dev/null +++ b/contracts/zero-ex/contracts/src/external/FeeCollectorController.sol @@ -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 + )); + } +} diff --git a/contracts/zero-ex/contracts/src/external/LibFeeCollector.sol b/contracts/zero-ex/contracts/src/external/LibFeeCollector.sol new file mode 100644 index 0000000000..d98530db80 --- /dev/null +++ b/contracts/zero-ex/contracts/src/external/LibFeeCollector.sol @@ -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 + )))); + } +} diff --git a/contracts/zero-ex/contracts/src/features/NativeOrdersFeature.sol b/contracts/zero-ex/contracts/src/features/NativeOrdersFeature.sol index fb529af11c..5687f6e97b 100644 --- a/contracts/zero-ex/contracts/src/features/NativeOrdersFeature.sol +++ b/contracts/zero-ex/contracts/src/features/NativeOrdersFeature.sol @@ -108,12 +108,13 @@ contract NativeOrdersFeature is address zeroExAddress, IEtherTokenV06 weth, IStaking staking, + FeeCollectorController feeCollectorController, uint32 protocolFeeMultiplier, bytes32 greedyTokensBloomFilter ) public FixinEIP712(zeroExAddress) - FixinProtocolFees(weth, staking, protocolFeeMultiplier) + FixinProtocolFees(weth, staking, feeCollectorController, protocolFeeMultiplier) FixinTokenSpender(greedyTokensBloomFilter) { // solhint-disable no-empty-blocks diff --git a/contracts/zero-ex/contracts/src/fixins/FixinProtocolFees.sol b/contracts/zero-ex/contracts/src/fixins/FixinProtocolFees.sol index 5cfbca010e..59b8c8ae53 100644 --- a/contracts/zero-ex/contracts/src/fixins/FixinProtocolFees.sol +++ b/contracts/zero-ex/contracts/src/fixins/FixinProtocolFees.sol @@ -21,13 +21,18 @@ pragma experimental ABIEncoderV2; import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; import "../external/FeeCollector.sol"; +import "../external/FeeCollectorController.sol"; +import "../external/LibFeeCollector.sol"; import "../vendor/v3/IStaking.sol"; /// @dev Helpers for collecting protocol fees. abstract contract FixinProtocolFees { + /// @dev The 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. bytes32 private immutable FEE_COLLECTOR_INIT_CODE_HASH; /// @dev The WETH token contract. @@ -38,11 +43,14 @@ abstract contract FixinProtocolFees { constructor( IEtherTokenV06 weth, IStaking staking, + FeeCollectorController feeCollectorController, uint32 protocolFeeMultiplier ) 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; STAKING = staking; PROTOCOL_FEE_MULTIPLIER = protocolFeeMultiplier; @@ -72,23 +80,11 @@ abstract contract FixinProtocolFees { function _transferFeesForPool(bytes32 poolId) internal { - 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); - } - + // This will create a FeeCollector contract (if necessary) and wrap + // fees for the pool ID. + FeeCollector feeCollector = + FEE_COLLECTOR_CONTROLLER.prepareFeeCollectorToPayFees(poolId); + // All fees in the fee collector should be in WETH now. uint256 bal = WETH.balanceOf(address(feeCollector)); if (bal > 1) { // Leave 1 wei behind to avoid high SSTORE cost of zero-->non-zero. @@ -106,14 +102,11 @@ abstract contract FixinProtocolFees { view returns (FeeCollector) { - // Compute the CREATE2 address for the fee collector. - address payable addr = address(uint256(keccak256(abi.encodePacked( - byte(0xff), - address(this), - poolId, // pool ID is salt - FEE_COLLECTOR_INIT_CODE_HASH - )))); - return FeeCollector(addr); + return FeeCollector(LibFeeCollector.getFeeCollectorAddress( + address(FEE_COLLECTOR_CONTROLLER), + FEE_COLLECTOR_INIT_CODE_HASH, + poolId + )); } /// @dev Get the cost of a single protocol fee. diff --git a/contracts/zero-ex/contracts/test/TestFeeCollectorController.sol b/contracts/zero-ex/contracts/test/TestFeeCollectorController.sol new file mode 100644 index 0000000000..b9a86e5035 --- /dev/null +++ b/contracts/zero-ex/contracts/test/TestFeeCollectorController.sol @@ -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; +} diff --git a/contracts/zero-ex/contracts/test/TestFixinProtocolFees.sol b/contracts/zero-ex/contracts/test/TestFixinProtocolFees.sol index b24081c65e..8365b1126f 100644 --- a/contracts/zero-ex/contracts/test/TestFixinProtocolFees.sol +++ b/contracts/zero-ex/contracts/test/TestFixinProtocolFees.sol @@ -27,10 +27,11 @@ contract TestFixinProtocolFees is constructor( IEtherTokenV06 weth, IStaking staking, + FeeCollectorController feeCollectorController, uint32 protocolFeeMultiplier ) public - FixinProtocolFees(weth, staking, protocolFeeMultiplier) + FixinProtocolFees(weth, staking, feeCollectorController, protocolFeeMultiplier) { // solhint-disalbe no-empty-blocks } diff --git a/contracts/zero-ex/contracts/test/TestMetaTransactionsNativeOrdersFeature.sol b/contracts/zero-ex/contracts/test/TestMetaTransactionsNativeOrdersFeature.sol index 6ba6992e7e..01aab57249 100644 --- a/contracts/zero-ex/contracts/test/TestMetaTransactionsNativeOrdersFeature.sol +++ b/contracts/zero-ex/contracts/test/TestMetaTransactionsNativeOrdersFeature.sol @@ -21,17 +21,23 @@ pragma experimental ABIEncoderV2; import "../src/features/NativeOrdersFeature.sol"; import "../src/features/IMetaTransactionsFeature.sol"; +import "./TestFeeCollectorController.sol"; contract TestMetaTransactionsNativeOrdersFeature is NativeOrdersFeature { - constructor( - ) + constructor() 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( LibNativeOrder.LimitOrder order, diff --git a/contracts/zero-ex/contracts/test/TestNativeOrdersFeature.sol b/contracts/zero-ex/contracts/test/TestNativeOrdersFeature.sol index d9ff51f618..349fe4e15f 100644 --- a/contracts/zero-ex/contracts/test/TestNativeOrdersFeature.sol +++ b/contracts/zero-ex/contracts/test/TestNativeOrdersFeature.sol @@ -2,6 +2,7 @@ pragma solidity ^0.6; pragma experimental ABIEncoderV2; import "../src/features/NativeOrdersFeature.sol"; +import "./TestFeeCollectorController.sol"; contract TestNativeOrdersFeature is NativeOrdersFeature @@ -10,6 +11,7 @@ contract TestNativeOrdersFeature is address zeroExAddress, IEtherTokenV06 weth, IStaking staking, + FeeCollectorController _feeCollectorController, // Unused but necessary for artifact compatibility. uint32 protocolFeeMultiplier, bytes32 greedyTokensBloomFilter ) @@ -18,6 +20,7 @@ contract TestNativeOrdersFeature is zeroExAddress, weth, staking, + FeeCollectorController(address(new TestFeeCollectorController())), protocolFeeMultiplier, greedyTokensBloomFilter ) diff --git a/contracts/zero-ex/package.json b/contracts/zero-ex/package.json index 0fdc327c0c..d8172490f0 100644 --- a/contracts/zero-ex/package.json +++ b/contracts/zero-ex/package.json @@ -40,9 +40,9 @@ "publish:private": "yarn build && gitpkg publish" }, "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": "./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": { "type": "git", diff --git a/contracts/zero-ex/src/artifacts.ts b/contracts/zero-ex/src/artifacts.ts index 922fc55d4f..fb7686ad60 100644 --- a/contracts/zero-ex/src/artifacts.ts +++ b/contracts/zero-ex/src/artifacts.ts @@ -7,6 +7,8 @@ import { ContractArtifact } from 'ethereum-types'; import * as AffiliateFeeTransformer from '../generated-artifacts/AffiliateFeeTransformer.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 FullMigration from '../generated-artifacts/FullMigration.json'; import * as IAllowanceTarget from '../generated-artifacts/IAllowanceTarget.json'; @@ -60,4 +62,6 @@ export const artifacts = { ILiquidityProviderFeature: ILiquidityProviderFeature as ContractArtifact, NativeOrdersFeature: NativeOrdersFeature as ContractArtifact, INativeOrdersFeature: INativeOrdersFeature as ContractArtifact, + FeeCollectorController: FeeCollectorController as ContractArtifact, + FeeCollector: FeeCollector as ContractArtifact, }; diff --git a/contracts/zero-ex/src/migration.ts b/contracts/zero-ex/src/migration.ts index a8c19ec84d..6843d89a98 100644 --- a/contracts/zero-ex/src/migration.ts +++ b/contracts/zero-ex/src/migration.ts @@ -7,6 +7,7 @@ import * as _ from 'lodash'; import { artifacts } from './artifacts'; import { ZERO_BYTES32 } from './constants'; import { + FeeCollectorControllerContract, FullMigrationContract, InitialMigrationContract, IZeroExContract, @@ -124,6 +125,7 @@ export interface FullFeatureArtifacts extends BootstrapFeatureArtifacts { signatureValidator: SimpleContractArtifact; metaTransactions: SimpleContractArtifact; nativeOrders: SimpleContractArtifact; + feeCollectorController: SimpleContractArtifact; } /** @@ -148,6 +150,7 @@ const DEFAULT_FULL_FEATURES_DEPLOY_CONFIG = { zeroExAddress: NULL_ADDRESS, wethAddress: NULL_ADDRESS, stakingAddress: NULL_ADDRESS, + feeCollectorController: NULL_ADDRESS, protocolFeeMultiplier: 70e3, greedyTokensBloomFilter: ZERO_BYTES32, }; @@ -158,6 +161,7 @@ const DEFAULT_FULL_FEATURES_ARTIFACTS = { signatureValidator: artifacts.SignatureValidatorFeature, metaTransactions: artifacts.MetaTransactionsFeature, nativeOrders: artifacts.NativeOrdersFeature, + feeCollectorController: artifacts.FeeCollectorController, }; /** @@ -175,6 +179,16 @@ export async function deployFullFeaturesAsync( ...DEFAULT_FULL_FEATURES_ARTIFACTS, ...featureArtifacts, }; + if (_config.feeCollectorController === NULL_ADDRESS) { + _config.feeCollectorController = (await FeeCollectorControllerContract.deployFrom0xArtifactAsync( + _featureArtifacts.feeCollectorController, + provider, + txDefaults, + artifacts, + _config.wethAddress, + _config.stakingAddress, + )).address; + } return { ...(await deployBootstrapFeaturesAsync(provider, txDefaults)), tokenSpender: @@ -222,6 +236,7 @@ export async function deployFullFeaturesAsync( _config.zeroExAddress, _config.wethAddress, _config.stakingAddress, + _config.feeCollectorController, _config.protocolFeeMultiplier, _config.greedyTokensBloomFilter, )).address, diff --git a/contracts/zero-ex/src/wrappers.ts b/contracts/zero-ex/src/wrappers.ts index 114a7455d5..459d44e197 100644 --- a/contracts/zero-ex/src/wrappers.ts +++ b/contracts/zero-ex/src/wrappers.ts @@ -5,6 +5,8 @@ */ export * from '../generated-wrappers/affiliate_fee_transformer'; 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/full_migration'; export * from '../generated-wrappers/i_allowance_target'; diff --git a/contracts/zero-ex/test/artifacts.ts b/contracts/zero-ex/test/artifacts.ts index 39e6e02669..9cfc5b4413 100644 --- a/contracts/zero-ex/test/artifacts.ts +++ b/contracts/zero-ex/test/artifacts.ts @@ -10,6 +10,7 @@ import * as AllowanceTarget from '../test/generated-artifacts/AllowanceTarget.js import * as BootstrapFeature from '../test/generated-artifacts/BootstrapFeature.json'; import * as BridgeAdapter from '../test/generated-artifacts/BridgeAdapter.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 FixinCommon from '../test/generated-artifacts/FixinCommon.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 LibCommonRichErrors from '../test/generated-artifacts/LibCommonRichErrors.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 LibMetaTransactionsRichErrors from '../test/generated-artifacts/LibMetaTransactionsRichErrors.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 TestCallTarget from '../test/generated-artifacts/TestCallTarget.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 TestFillQuoteTransformerExchange from '../test/generated-artifacts/TestFillQuoteTransformerExchange.json'; import * as TestFillQuoteTransformerHost from '../test/generated-artifacts/TestFillQuoteTransformerHost.json'; @@ -151,10 +154,12 @@ export const artifacts = { LibWalletRichErrors: LibWalletRichErrors as ContractArtifact, AllowanceTarget: AllowanceTarget as ContractArtifact, FeeCollector: FeeCollector as ContractArtifact, + FeeCollectorController: FeeCollectorController as ContractArtifact, FlashWallet: FlashWallet as ContractArtifact, IAllowanceTarget: IAllowanceTarget as ContractArtifact, IFlashWallet: IFlashWallet as ContractArtifact, ILiquidityProviderSandbox: ILiquidityProviderSandbox as ContractArtifact, + LibFeeCollector: LibFeeCollector as ContractArtifact, LiquidityProviderSandbox: LiquidityProviderSandbox as ContractArtifact, PermissionlessTransformerDeployer: PermissionlessTransformerDeployer as ContractArtifact, TransformerDeployer: TransformerDeployer as ContractArtifact, @@ -233,6 +238,7 @@ export const artifacts = { TestBridge: TestBridge as ContractArtifact, TestCallTarget: TestCallTarget as ContractArtifact, TestDelegateCaller: TestDelegateCaller as ContractArtifact, + TestFeeCollectorController: TestFeeCollectorController as ContractArtifact, TestFillQuoteTransformerBridge: TestFillQuoteTransformerBridge as ContractArtifact, TestFillQuoteTransformerExchange: TestFillQuoteTransformerExchange as ContractArtifact, TestFillQuoteTransformerHost: TestFillQuoteTransformerHost as ContractArtifact, diff --git a/contracts/zero-ex/test/protocol_fees_test.ts b/contracts/zero-ex/test/protocol_fees_test.ts index 5acb63bdb7..336a15eebe 100644 --- a/contracts/zero-ex/test/protocol_fees_test.ts +++ b/contracts/zero-ex/test/protocol_fees_test.ts @@ -2,7 +2,13 @@ import { blockchainTests, expect } from '@0x/contracts-test-utils'; import { AuthorizableRevertErrors, BigNumber, hexUtils } from '@0x/utils'; import { artifacts } from './artifacts'; -import { FeeCollectorContract, TestFixinProtocolFeesContract, TestStakingContract, TestWethContract } from './wrappers'; +import { + FeeCollectorContract, + FeeCollectorControllerContract, + TestFixinProtocolFeesContract, + TestStakingContract, + TestWethContract, +} from './wrappers'; blockchainTests.resets('ProtocolFees', env => { const FEE_MULTIPLIER = 70e3; @@ -11,6 +17,7 @@ blockchainTests.resets('ProtocolFees', env => { let protocolFees: TestFixinProtocolFeesContract; let staking: TestStakingContract; let weth: TestWethContract; + let feeCollectorController: FeeCollectorControllerContract; let singleFeeAmount: BigNumber; before(async () => { @@ -28,6 +35,14 @@ blockchainTests.resets('ProtocolFees', env => { artifacts, weth.address, ); + feeCollectorController = await FeeCollectorControllerContract.deployFrom0xArtifactAsync( + artifacts.FeeCollectorController, + env.provider, + env.txDefaults, + artifacts, + weth.address, + staking.address, + ); protocolFees = await TestFixinProtocolFeesContract.deployFrom0xArtifactAsync( artifacts.TestFixinProtocolFees, env.provider, @@ -35,6 +50,7 @@ blockchainTests.resets('ProtocolFees', env => { artifacts, weth.address, staking.address, + feeCollectorController.address, FEE_MULTIPLIER, ); singleFeeAmount = await protocolFees.getSingleProtocolFee().callAsync(); diff --git a/contracts/zero-ex/test/wrappers.ts b/contracts/zero-ex/test/wrappers.ts index 6c4860e97c..85398501ba 100644 --- a/contracts/zero-ex/test/wrappers.ts +++ b/contracts/zero-ex/test/wrappers.ts @@ -8,6 +8,7 @@ export * from '../test/generated-wrappers/allowance_target'; export * from '../test/generated-wrappers/bootstrap_feature'; export * from '../test/generated-wrappers/bridge_adapter'; 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/fixin_common'; 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_common_rich_errors'; 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_meta_transactions_rich_errors'; 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_call_target'; 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_exchange'; export * from '../test/generated-wrappers/test_fill_quote_transformer_host'; diff --git a/contracts/zero-ex/tsconfig.json b/contracts/zero-ex/tsconfig.json index 8c53a7269b..ed9e9567b2 100644 --- a/contracts/zero-ex/tsconfig.json +++ b/contracts/zero-ex/tsconfig.json @@ -5,6 +5,8 @@ "files": [ "generated-artifacts/AffiliateFeeTransformer.json", "generated-artifacts/BridgeAdapter.json", + "generated-artifacts/FeeCollector.json", + "generated-artifacts/FeeCollectorController.json", "generated-artifacts/FillQuoteTransformer.json", "generated-artifacts/FullMigration.json", "generated-artifacts/IAllowanceTarget.json", @@ -35,6 +37,7 @@ "test/generated-artifacts/BootstrapFeature.json", "test/generated-artifacts/BridgeAdapter.json", "test/generated-artifacts/FeeCollector.json", + "test/generated-artifacts/FeeCollectorController.json", "test/generated-artifacts/FillQuoteTransformer.json", "test/generated-artifacts/FixinCommon.json", "test/generated-artifacts/FixinEIP712.json", @@ -70,6 +73,7 @@ "test/generated-artifacts/LibBootstrap.json", "test/generated-artifacts/LibCommonRichErrors.json", "test/generated-artifacts/LibERC20Transformer.json", + "test/generated-artifacts/LibFeeCollector.json", "test/generated-artifacts/LibLiquidityProviderRichErrors.json", "test/generated-artifacts/LibMetaTransactionsRichErrors.json", "test/generated-artifacts/LibMetaTransactionsStorage.json", @@ -120,6 +124,7 @@ "test/generated-artifacts/TestBridge.json", "test/generated-artifacts/TestCallTarget.json", "test/generated-artifacts/TestDelegateCaller.json", + "test/generated-artifacts/TestFeeCollectorController.json", "test/generated-artifacts/TestFillQuoteTransformerBridge.json", "test/generated-artifacts/TestFillQuoteTransformerExchange.json", "test/generated-artifacts/TestFillQuoteTransformerHost.json", diff --git a/packages/contract-addresses/CHANGELOG.json b/packages/contract-addresses/CHANGELOG.json index a3365f8cdd..bbad62e22d 100644 --- a/packages/contract-addresses/CHANGELOG.json +++ b/packages/contract-addresses/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "5.5.0", + "changes": [ + { + "note": "Update ganache snapshot addresses", + "pr": 59 + } + ] + }, { "version": "5.4.0", "changes": [ diff --git a/packages/contract-addresses/addresses.json b/packages/contract-addresses/addresses.json index 2a67136840..52b9304e98 100644 --- a/packages/contract-addresses/addresses.json +++ b/packages/contract-addresses/addresses.json @@ -198,10 +198,10 @@ "exchangeProxyFlashWallet": "0xb9682a8e7920b431f1d412b8510f0077410c8faa", "exchangeProxyLiquidityProviderSandbox": "0x0000000000000000000000000000000000000000", "transformers": { - "wethTransformer": "0x7209185959d7227fb77274e1e88151d7c4c368d3", - "payTakerTransformer": "0x3f16ca81691dab9184cb4606c361d73c4fd2510a", - "affiliateFeeTransformer": "0x99356167edba8fbdc36959e3f5d0c43d1ba9c6db", - "fillQuoteTransformer": "0x45b3a72221e571017c0f0ec42189e11d149d0ace" + "wethTransformer": "0x3f16ca81691dab9184cb4606c361d73c4fd2510a", + "payTakerTransformer": "0x99356167edba8fbdc36959e3f5d0c43d1ba9c6db", + "affiliateFeeTransformer": "0x45b3a72221e571017c0f0ec42189e11d149d0ace", + "fillQuoteTransformer": "0xdd66c23e07b4d6925b6089b5fe6fc9e62941afe8" } } }