protocol/contracts/zero-ex/src/migration.ts
Lawrence Forman 475b608338
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>
2020-12-01 12:17:21 -05:00

280 lines
8.9 KiB
TypeScript

import { SupportedProvider } from '@0x/subproviders';
import { SimpleContractArtifact } from '@0x/types';
import { NULL_ADDRESS } from '@0x/utils';
import { TxData } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { ZERO_BYTES32 } from './constants';
import {
FeeCollectorControllerContract,
FullMigrationContract,
InitialMigrationContract,
IZeroExContract,
MetaTransactionsFeatureContract,
NativeOrdersFeatureContract,
OwnableFeatureContract,
SignatureValidatorFeatureContract,
SimpleFunctionRegistryFeatureContract,
TokenSpenderFeatureContract,
TransformERC20FeatureContract,
ZeroExContract,
} from './wrappers';
// tslint:disable: completed-docs
/**
* Addresses of minimum features for a deployment of the Exchange Proxy.
*/
export interface BootstrapFeatures {
registry: string;
ownable: string;
}
/**
* Artifacts to use when deploying bootstrap features.
*/
export interface BootstrapFeatureArtifacts {
registry: SimpleContractArtifact;
ownable: SimpleContractArtifact;
}
const DEFAULT_BOOTSTRAP_FEATURE_ARTIFACTS = {
registry: artifacts.SimpleFunctionRegistryFeature,
ownable: artifacts.OwnableFeature,
};
/**
* Deploy the minimum features of the Exchange Proxy.
*/
export async function deployBootstrapFeaturesAsync(
provider: SupportedProvider,
txDefaults: Partial<TxData>,
features: Partial<BootstrapFeatures> = {},
featureArtifacts: Partial<BootstrapFeatureArtifacts> = {},
): Promise<BootstrapFeatures> {
const _featureArtifacts = {
...DEFAULT_BOOTSTRAP_FEATURE_ARTIFACTS,
...featureArtifacts,
};
return {
registry:
features.registry ||
(await SimpleFunctionRegistryFeatureContract.deployFrom0xArtifactAsync(
_featureArtifacts.registry,
provider,
txDefaults,
artifacts,
)).address,
ownable:
features.ownable ||
(await OwnableFeatureContract.deployFrom0xArtifactAsync(
_featureArtifacts.ownable,
provider,
txDefaults,
artifacts,
)).address,
};
}
/**
* Migrate an instance of the Exchange proxy with minimum viable features.
*/
export async function initialMigrateAsync(
owner: string,
provider: SupportedProvider,
txDefaults: Partial<TxData>,
features: Partial<BootstrapFeatures> = {},
): Promise<ZeroExContract> {
const migrator = await InitialMigrationContract.deployFrom0xArtifactAsync(
artifacts.InitialMigration,
provider,
txDefaults,
artifacts,
txDefaults.from as string,
);
const zeroEx = await ZeroExContract.deployFrom0xArtifactAsync(
artifacts.ZeroEx,
provider,
txDefaults,
artifacts,
migrator.address,
);
const _features = await deployBootstrapFeaturesAsync(provider, txDefaults, features);
await migrator.initializeZeroEx(owner, zeroEx.address, _features).awaitTransactionSuccessAsync();
return zeroEx;
}
/**
* Addresses of features for a full deployment of the Exchange Proxy.
*/
export interface FullFeatures extends BootstrapFeatures {
tokenSpender: string;
transformERC20: string;
signatureValidator: string;
metaTransactions: string;
nativeOrders: string;
}
/**
* Artifacts to use when deploying full features.
*/
export interface FullFeatureArtifacts extends BootstrapFeatureArtifacts {
tokenSpender: SimpleContractArtifact;
transformERC20: SimpleContractArtifact;
signatureValidator: SimpleContractArtifact;
metaTransactions: SimpleContractArtifact;
nativeOrders: SimpleContractArtifact;
feeCollectorController: SimpleContractArtifact;
}
/**
* Configuration for deploying full features..
*/
export interface FullFeaturesDeployConfig {
zeroExAddress: string;
wethAddress: string;
stakingAddress: string;
protocolFeeMultiplier: number;
greedyTokensBloomFilter: string;
}
/**
* Configuration options for a full migration of the Exchange Proxy.
*/
export interface FullMigrationConfig extends FullFeaturesDeployConfig {
transformerDeployer?: string;
}
const DEFAULT_FULL_FEATURES_DEPLOY_CONFIG = {
zeroExAddress: NULL_ADDRESS,
wethAddress: NULL_ADDRESS,
stakingAddress: NULL_ADDRESS,
feeCollectorController: NULL_ADDRESS,
protocolFeeMultiplier: 70e3,
greedyTokensBloomFilter: ZERO_BYTES32,
};
const DEFAULT_FULL_FEATURES_ARTIFACTS = {
tokenSpender: artifacts.TokenSpenderFeature,
transformERC20: artifacts.TransformERC20Feature,
signatureValidator: artifacts.SignatureValidatorFeature,
metaTransactions: artifacts.MetaTransactionsFeature,
nativeOrders: artifacts.NativeOrdersFeature,
feeCollectorController: artifacts.FeeCollectorController,
};
/**
* Deploy all the features for a full Exchange Proxy.
*/
export async function deployFullFeaturesAsync(
provider: SupportedProvider,
txDefaults: Partial<TxData>,
config: Partial<FullFeaturesDeployConfig> = {},
features: Partial<FullFeatures> = {},
featureArtifacts: Partial<FullFeatureArtifacts> = {},
): Promise<FullFeatures> {
const _config = { ...DEFAULT_FULL_FEATURES_DEPLOY_CONFIG, ...config };
const _featureArtifacts = {
...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:
features.tokenSpender ||
(await TokenSpenderFeatureContract.deployFrom0xArtifactAsync(
_featureArtifacts.tokenSpender,
provider,
txDefaults,
artifacts,
)).address,
transformERC20:
features.transformERC20 ||
(await TransformERC20FeatureContract.deployFrom0xArtifactAsync(
_featureArtifacts.transformERC20,
provider,
txDefaults,
artifacts,
_config.greedyTokensBloomFilter,
)).address,
signatureValidator:
features.signatureValidator ||
(await SignatureValidatorFeatureContract.deployFrom0xArtifactAsync(
_featureArtifacts.signatureValidator,
provider,
txDefaults,
artifacts,
)).address,
metaTransactions:
features.metaTransactions ||
(await MetaTransactionsFeatureContract.deployFrom0xArtifactAsync(
_featureArtifacts.metaTransactions,
provider,
txDefaults,
artifacts,
_config.zeroExAddress,
_config.greedyTokensBloomFilter,
)).address,
nativeOrders:
features.nativeOrders ||
(await NativeOrdersFeatureContract.deployFrom0xArtifactAsync(
_featureArtifacts.nativeOrders,
provider,
txDefaults,
artifacts,
_config.zeroExAddress,
_config.wethAddress,
_config.stakingAddress,
_config.feeCollectorController,
_config.protocolFeeMultiplier,
_config.greedyTokensBloomFilter,
)).address,
};
}
/**
* Deploy a fully featured instance of the Exchange Proxy.
*/
export async function fullMigrateAsync(
owner: string,
provider: SupportedProvider,
txDefaults: Partial<TxData>,
features: Partial<FullFeatures> = {},
config: Partial<FullMigrationConfig> = {},
featureArtifacts: Partial<FullFeatureArtifacts> = {},
): Promise<IZeroExContract> {
const migrator = await FullMigrationContract.deployFrom0xArtifactAsync(
artifacts.FullMigration,
provider,
txDefaults,
artifacts,
txDefaults.from as string,
);
const zeroEx = await ZeroExContract.deployFrom0xArtifactAsync(
artifacts.ZeroEx,
provider,
txDefaults,
artifacts,
await migrator.getBootstrapper().callAsync(),
);
const _config = { ...config, zeroExAddress: zeroEx.address };
const _features = await deployFullFeaturesAsync(provider, txDefaults, _config, features, featureArtifacts);
const migrateOpts = {
transformerDeployer: txDefaults.from as string,
..._config,
};
await migrator.migrateZeroEx(owner, zeroEx.address, _features, migrateOpts).awaitTransactionSuccessAsync();
return new IZeroExContract(zeroEx.address, provider, txDefaults);
}