protocol/contracts/zero-ex/tests/utils/DeployZeroEx.sol
Andy 38665ffc86
Migrate the multiplex tests to foundry (#655)
* add some tests for multiplex using foundry

* remove try/catch from multiplex foundry tests

* refactor multiplex forge tests

* fix broken import, remove dead code

---------

Co-authored-by: Patrick Dowell <patrick.dowell@gmail.com>
2023-02-22 19:16:48 -05:00

333 lines
16 KiB
Solidity

// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2023 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;
pragma experimental ABIEncoderV2;
import "forge-std/Test.sol";
import "src/IZeroEx.sol";
import "src/ZeroEx.sol";
import "src/migrations/InitialMigration.sol";
import "src/features/OwnableFeature.sol";
import "src/features/SimpleFunctionRegistryFeature.sol";
import "src/features/NativeOrdersFeature.sol";
import "src/features/BatchFillNativeOrdersFeature.sol";
import "src/features/FundRecoveryFeature.sol";
import "src/features/TransformERC20Feature.sol";
import "src/features/OtcOrdersFeature.sol";
import "src/features/MetaTransactionsFeature.sol";
import "src/features/nft_orders/ERC1155OrdersFeature.sol";
import "src/features/nft_orders/ERC721OrdersFeature.sol";
import "src/features/UniswapFeature.sol";
import "src/features/UniswapV3Feature.sol";
import "src/features/multiplex/MultiplexFeature.sol";
import "src/external/TransformerDeployer.sol";
import "src/external/FeeCollectorController.sol";
import "src/external/LiquidityProviderSandbox.sol";
import "src/transformers/WethTransformer.sol";
import "src/transformers/FillQuoteTransformer.sol";
import "src/transformers/PayTakerTransformer.sol";
import "src/transformers/AffiliateFeeTransformer.sol";
import "src/transformers/PositiveSlippageFeeTransformer.sol";
import "src/transformers/bridges/IBridgeAdapter.sol";
import "src/transformers/bridges/EthereumBridgeAdapter.sol";
import "@0x/contracts-erc20/src/IEtherToken.sol";
import "@0x/contracts-erc20/src/v06/WETH9V06.sol";
contract DeployZeroEx is Test {
ZeroEx public ZERO_EX = ZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF);
IZeroEx public IZERO_EX = IZeroEx(address(ZERO_EX));
address VANITY_DEPLOYER_ADDRESS = 0xe750ad66DE350F8110E305fb78Ec6A9f594445E3;
/* solhint-disable max-line-length */
bytes deployerBytecode =
hex"608060405234801561001057600080fd5b506040516103da3803806103da83398101604081905261002f91610077565b8060405161003c9061006a565b610046919061011f565b604051809103906000f080158015610062573d6000803e3d6000fd5b505050610198565b6101f5806101e583390190565b600060208284031215610088578081fd5b81516001600160401b038082111561009e578283fd5b818401915084601f8301126100b1578283fd5b8151818111156100c3576100c3610182565b604051601f8201601f19908116603f011681019083821181831017156100eb576100eb610182565b81604052828152876020848701011115610103578586fd5b610114836020830160208801610152565b979650505050505050565b600060208252825180602084015261013e816040850160208701610152565b601f01601f19169190910160400192915050565b60005b8381101561016d578181015183820152602001610155565b8381111561017c576000848401525b50505050565b634e487b7160e01b600052604160045260246000fd5b603f806101a66000396000f3fe6080604052600080fdfea26469706673582212201bd8b1a777b100d67435ca4bb0b2fdccb13a2c2dde019b227bb553ff9a95bd4464736f6c63430008020033608060405234801561001057600080fd5b506040516101f53803806101f583398101604081905261002f916100c9565b60008151602083016000f090506001600160a01b0381166100865760405162461bcd60e51b815260206004820152600d60248201526c1111541313d657d19052531151609a1b604482015260640160405180910390fd5b6040516001600160a01b03821681527ff40fcec21964ffb566044d083b4073f29f7f7929110ea19e1b3ebe375d89055e9060200160405180910390a150506101a8565b600060208083850312156100db578182fd5b82516001600160401b03808211156100f1578384fd5b818501915085601f830112610104578384fd5b81518181111561011657610116610192565b604051601f8201601f19908116603f0116810190838211818310171561013e5761013e610192565b816040528281528886848701011115610155578687fd5b8693505b828410156101765784840186015181850187015292850192610159565b8284111561018657868684830101525b98975050505050505050565b634e487b7160e01b600052604160045260246000fd5b603f806101b66000396000f3fe6080604052600080fdfea2646970667358221220fbca036a163ed7f008cefa7c834d98d25109a456a051d41d9c89d55d7185d12b64736f6c63430008020033";
/* solhint-enable max-line-length */
address[] transformerSigners = [address(this)];
bool isDeployed = false;
struct Features {
NativeOrdersFeature nativeOrdersFeature;
BatchFillNativeOrdersFeature batchFillNativeOrdersFeature;
OtcOrdersFeature otcOrdersFeature;
UniswapFeature uniswapFeature;
UniswapV3Feature uniswapV3Feature;
FundRecoveryFeature fundRecoveryFeature;
TransformERC20Feature transformERC20Feature;
MetaTransactionsFeature metaTransactionsFeature;
ERC1155OrdersFeature erc1155OrdersFeature;
ERC721OrdersFeature erc721OrdersFeature;
MultiplexFeature multiplexFeature;
}
struct Transformers {
FillQuoteTransformer fillQuoteTransformer;
WethTransformer wethTransformer;
AffiliateFeeTransformer affiliateFeeTransformer;
PayTakerTransformer payTakerTransformer;
}
struct ZeroExDeployed {
IZeroEx zeroEx;
TransformerDeployer transformerDeployer;
FeeCollectorController feeCollectorController;
IStaking staking; // address(0)
Features features;
Transformers transformers;
IEtherToken weth;
}
ZeroExDeployed ZERO_EX_DEPLOYED;
struct ZeroExDeployConfiguration {
address uniswapFactory;
address sushiswapFactory;
address uniswapV3Factory;
bytes32 uniswapPairInitCodeHash;
bytes32 sushiswapPairInitCodeHash;
bytes32 uniswapV3PoolInitCodeHash;
bool logDeployed;
}
ZeroExDeployConfiguration ZERO_EX_DEPLOY_CONFIG;
constructor(ZeroExDeployConfiguration memory configuration) public {
ZERO_EX_DEPLOY_CONFIG = configuration;
}
function getDeployedZeroEx() public returns (ZeroExDeployed memory) {
if (!isDeployed) {
deployZeroEx();
}
return ZERO_EX_DEPLOYED;
}
function logDeployedZeroEx() public {
emit log_string("--- Deployed ZeroEx ---");
emit log_named_address("ZeroEx", address(ZERO_EX));
emit log_named_address("TransformerDeployer", address(ZERO_EX_DEPLOYED.transformerDeployer));
emit log_named_address("FeeCollectorController", address(ZERO_EX_DEPLOYED.feeCollectorController));
emit log_named_address("Staking", address(ZERO_EX_DEPLOYED.staking));
emit log_string("----- Features -----");
emit log_named_address("NativeOrdersFeature", address(ZERO_EX_DEPLOYED.features.nativeOrdersFeature));
emit log_named_address(
"BatchFillNativeOrdersFeature",
address(ZERO_EX_DEPLOYED.features.batchFillNativeOrdersFeature)
);
emit log_named_address("OtcOrdersFeature", address(ZERO_EX_DEPLOYED.features.otcOrdersFeature));
emit log_named_address("UniswapFeature", address(ZERO_EX_DEPLOYED.features.uniswapFeature));
emit log_named_address("UniswapV3Feature", address(ZERO_EX_DEPLOYED.features.uniswapV3Feature));
emit log_named_address("FundRecoveryFeature", address(ZERO_EX_DEPLOYED.features.fundRecoveryFeature));
emit log_named_address("MetaTransactionsFeature", address(ZERO_EX_DEPLOYED.features.metaTransactionsFeature));
emit log_named_address("ERC1155OrdersFeature", address(ZERO_EX_DEPLOYED.features.erc1155OrdersFeature));
emit log_named_address("ERC721OrdersFeature", address(ZERO_EX_DEPLOYED.features.erc721OrdersFeature));
emit log_named_address("TransformERC20Feature", address(ZERO_EX_DEPLOYED.features.transformERC20Feature));
emit log_named_address("MultiplexFeature", address(ZERO_EX_DEPLOYED.features.multiplexFeature));
emit log_string("----- Transformers -----");
emit log_named_address("FillQuoteTransformer", address(ZERO_EX_DEPLOYED.transformers.fillQuoteTransformer));
emit log_named_address("WethTransformer", address(ZERO_EX_DEPLOYED.transformers.wethTransformer));
emit log_named_address(
"AffiliateFeeTransformer",
address(ZERO_EX_DEPLOYED.transformers.affiliateFeeTransformer)
);
emit log_named_address("PayTakerTransformer", address(ZERO_EX_DEPLOYED.transformers.payTakerTransformer));
emit log_string("----- Other -----");
emit log_named_address("WETH", address(ZERO_EX_DEPLOYED.weth));
}
function deployZeroEx() public returns (ZeroExDeployed memory) {
if (isDeployed) {
return ZERO_EX_DEPLOYED;
}
ZERO_EX_DEPLOYED.weth = IEtherToken(address(new WETH9V06()));
InitialMigration initialMigration = new InitialMigration(address(this));
// Append the required ZeroEx constructor arguments (address bootstrapper)
bytes memory zeroExDeploycode = abi.encodePacked(type(ZeroEx).creationCode, abi.encode(initialMigration));
// Append the required deployer code constructor arguments (bytes initCode)
bytes memory deployerDeploycode = abi.encodePacked(deployerBytecode, abi.encode(zeroExDeploycode));
// HERE BE DRAGONS, feel free to ignore this for now
// We want to deploy the ZeroEx contract, at 0xDef1C0ded9bec7F1a1670819833240f027b25EfF
// We use a special mechanism to deploy the ZeroEx contract.
// Must occur from this address as the first transaction
// The address is technically emitted in an event, but we know we did it correctly
//│ │ ├─ emit topic 0: 0xf40fcec21964ffb566044d083b4073f29f7f7929110ea19e1b3ebe375d89055e
//│ │ │ data: 0x000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff
hoax(VANITY_DEPLOYER_ADDRESS);
assembly {
pop(create(0, add(deployerDeploycode, 0x20), mload(deployerDeploycode)))
}
// Staking = address(0);
ZERO_EX_DEPLOYED.staking = IStaking(address(0));
ZERO_EX_DEPLOYED.transformerDeployer = new TransformerDeployer(transformerSigners);
ZERO_EX_DEPLOYED.feeCollectorController = new FeeCollectorController(
IEtherToken(ZERO_EX_DEPLOYED.weth),
IStaking(ZERO_EX_DEPLOYED.staking)
);
// Features
ZERO_EX_DEPLOYED.features.transformERC20Feature = new TransformERC20Feature();
ZERO_EX_DEPLOYED.features.nativeOrdersFeature = new NativeOrdersFeature(
address(ZERO_EX), // EP address
ZERO_EX_DEPLOYED.weth,
ZERO_EX_DEPLOYED.staking,
ZERO_EX_DEPLOYED.feeCollectorController, // feeCollectorController address
uint32(0) // protocolFeeMultiplier
);
ZERO_EX_DEPLOYED.features.batchFillNativeOrdersFeature = new BatchFillNativeOrdersFeature(address(ZERO_EX));
ZERO_EX_DEPLOYED.features.otcOrdersFeature = new OtcOrdersFeature(address(ZERO_EX), ZERO_EX_DEPLOYED.weth);
ZERO_EX_DEPLOYED.features.uniswapFeature = new UniswapFeature(ZERO_EX_DEPLOYED.weth);
ZERO_EX_DEPLOYED.features.uniswapV3Feature = new UniswapV3Feature(
ZERO_EX_DEPLOYED.weth,
ZERO_EX_DEPLOY_CONFIG.uniswapV3Factory,
ZERO_EX_DEPLOY_CONFIG.uniswapV3PoolInitCodeHash
);
ZERO_EX_DEPLOYED.features.fundRecoveryFeature = new FundRecoveryFeature();
ZERO_EX_DEPLOYED.features.metaTransactionsFeature = new MetaTransactionsFeature(address(ZERO_EX));
ZERO_EX_DEPLOYED.features.erc1155OrdersFeature = new ERC1155OrdersFeature(
address(ZERO_EX),
ZERO_EX_DEPLOYED.weth
);
ZERO_EX_DEPLOYED.features.erc721OrdersFeature = new ERC721OrdersFeature(
address(ZERO_EX),
ZERO_EX_DEPLOYED.weth
);
ZERO_EX_DEPLOYED.features.multiplexFeature = new MultiplexFeature(
address(ZERO_EX),
ZERO_EX_DEPLOYED.weth,
new LiquidityProviderSandbox(address(ZERO_EX)),
ZERO_EX_DEPLOY_CONFIG.uniswapFactory,
ZERO_EX_DEPLOY_CONFIG.sushiswapFactory,
ZERO_EX_DEPLOY_CONFIG.uniswapPairInitCodeHash,
ZERO_EX_DEPLOY_CONFIG.sushiswapPairInitCodeHash
);
initialMigration.initializeZeroEx(
payable(address(this)),
ZERO_EX,
InitialMigration.BootstrapFeatures({
registry: new SimpleFunctionRegistryFeature(),
ownable: new OwnableFeature()
})
);
IZERO_EX.migrate(
address(ZERO_EX_DEPLOYED.features.batchFillNativeOrdersFeature),
abi.encodeWithSelector(BatchFillNativeOrdersFeature.migrate.selector),
address(this)
);
IZERO_EX.migrate(
address(ZERO_EX_DEPLOYED.features.transformERC20Feature),
abi.encodeWithSelector(
TransformERC20Feature.migrate.selector,
address(ZERO_EX_DEPLOYED.transformerDeployer)
),
address(this)
);
IZERO_EX.migrate(
address(ZERO_EX_DEPLOYED.features.nativeOrdersFeature),
abi.encodeWithSelector(NativeOrdersFeature.migrate.selector),
address(this)
);
IZERO_EX.migrate(
address(ZERO_EX_DEPLOYED.features.otcOrdersFeature),
abi.encodeWithSelector(OtcOrdersFeature.migrate.selector),
address(this)
);
IZERO_EX.migrate(
address(ZERO_EX_DEPLOYED.features.uniswapFeature),
abi.encodeWithSelector(UniswapFeature.migrate.selector),
address(this)
);
IZERO_EX.migrate(
address(ZERO_EX_DEPLOYED.features.uniswapV3Feature),
abi.encodeWithSelector(UniswapV3Feature.migrate.selector),
address(this)
);
IZERO_EX.migrate(
address(ZERO_EX_DEPLOYED.features.fundRecoveryFeature),
abi.encodeWithSelector(FundRecoveryFeature.migrate.selector),
address(this)
);
IZERO_EX.migrate(
address(ZERO_EX_DEPLOYED.features.metaTransactionsFeature),
abi.encodeWithSelector(MetaTransactionsFeature.migrate.selector),
address(this)
);
IZERO_EX.migrate(
address(ZERO_EX_DEPLOYED.features.erc1155OrdersFeature),
abi.encodeWithSelector(ERC1155OrdersFeature.migrate.selector),
address(this)
);
IZERO_EX.migrate(
address(ZERO_EX_DEPLOYED.features.erc721OrdersFeature),
abi.encodeWithSelector(ERC721OrdersFeature.migrate.selector),
address(this)
);
IZERO_EX.migrate(
address(ZERO_EX_DEPLOYED.features.multiplexFeature),
abi.encodeWithSelector(MultiplexFeature.migrate.selector),
address(this)
);
// Transformers
ZERO_EX_DEPLOYED.transformers.wethTransformer = WethTransformer(
ZERO_EX_DEPLOYED.transformerDeployer.deploy(
abi.encodePacked(
// Deploy the WethTransformer code
type(WethTransformer).creationCode,
// WethTransformer takes WETH address as a constructor argument
abi.encode(address(ZERO_EX_DEPLOYED.weth))
)
)
);
// Deploy the FQT, NOTE: No bridge adapter in tests
ZERO_EX_DEPLOYED.transformers.fillQuoteTransformer = FillQuoteTransformer(
ZERO_EX_DEPLOYED.transformerDeployer.deploy(
abi.encodePacked(
// Deploy the FQT code
type(FillQuoteTransformer).creationCode,
// FQT takes a BridgeAdapter and ZeroEx
abi.encode(
address(0), // Note: No BridgeAdapter in tests
INativeOrdersFeature(address(ZERO_EX))
)
)
)
);
ZERO_EX_DEPLOYED.transformers.affiliateFeeTransformer = AffiliateFeeTransformer(
ZERO_EX_DEPLOYED.transformerDeployer.deploy(type(AffiliateFeeTransformer).creationCode)
);
ZERO_EX_DEPLOYED.transformers.payTakerTransformer = PayTakerTransformer(
ZERO_EX_DEPLOYED.transformerDeployer.deploy(type(PayTakerTransformer).creationCode)
);
ZERO_EX_DEPLOYED.zeroEx = IZERO_EX;
isDeployed = true;
if (ZERO_EX_DEPLOY_CONFIG.logDeployed) {
logDeployedZeroEx();
}
return ZERO_EX_DEPLOYED;
}
}