Lawrence Forman 2fce332ed7
ZeroEx: TransformERC20, TokenSpender (#2545)
* `@0x/contracts-utils`: Convert more 0.6 contracts

* `@0x/contracts-erc20`: Add solidity 0.6 contracts.

* `@0x/utils`: Add new `ZeroExRevertErrors` revert types

* `@0x/contracts-zero-ex`: Introduce the `TransformERC20` feature.

* `@0x/subproviders`: Update ganache-core.
`@0x/web3-wrapper`: Update ganache-core.

* `@0x/contracts-zero-ex`: Make `TokenSpender`'s puppet contract a distinct contract type and rename `getTokenSpenderPuppet()` to `getAllowanceTarget()`

* `@0x/zero-ex`: Rebase and use "slot" instead of "offset" language in storage buckets.

* `@0x/web3-wrapper`: Add `getAccountNonceAsync()` to `Web3Wrapper`

* `@0x/contracts-zero-ex`: Revamp TransformERC20.

* `@0x/contracts-zero-ex`: Remove `payable` from `IERC20Transformer.transform()` and disable hex capitalization linter rule because of prettier conflicts.

* `@0x/contracts-zero-ex`: Use `immutable` owner in `Puppet` instead of `Ownable`.

* `@x/utils`: Address review feedback.

* `@0x/contracts-zero-ex`: Address review feedback.

* `@0x/contracts-utils`: Address review feedback.

* `@0x/contracts-zero-ex`: Return deployment nonce in `transform()`.

* `@0x/contracts-zero-ex`: Finish returning deployment nonce in `transform()`.

* `@0x/contracts-zero-ex`: Fix doc-gen bug.

* `@0x/contracts-zero-ex`: Address review comments.

* `@0x/utils`: Add `NegativeTransformERC20OutputERror`

* `@0x/contracts-zero-ex`: Revert if the taker's output amount decreases.

Co-authored-by: Lawrence Forman <me@merklejerk.com>
2020-05-20 22:47:21 -04:00

129 lines
4.1 KiB
TypeScript

import { BaseContract } from '@0x/base-contract';
import { SupportedProvider } from '@0x/subproviders';
import { TxData } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
import {
FullMigrationContract,
InitialMigrationContract,
OwnableContract,
SimpleFunctionRegistryContract,
TokenSpenderContract,
TransformERC20Contract,
ZeroExContract,
} from '../wrappers';
// tslint:disable: completed-docs
export interface BootstrapFeatures {
registry: SimpleFunctionRegistryContract;
ownable: OwnableContract;
}
export async function deployBootstrapFeaturesAsync(
provider: SupportedProvider,
txDefaults: Partial<TxData>,
features: Partial<BootstrapFeatures> = {},
): Promise<BootstrapFeatures> {
return {
registry:
features.registry ||
(await SimpleFunctionRegistryContract.deployFrom0xArtifactAsync(
artifacts.SimpleFunctionRegistry,
provider,
txDefaults,
artifacts,
)),
ownable:
features.ownable ||
(await OwnableContract.deployFrom0xArtifactAsync(artifacts.Ownable, provider, txDefaults, artifacts)),
};
}
export async function initialMigrateAsync(
owner: string,
provider: SupportedProvider,
txDefaults: Partial<TxData>,
features: Partial<BootstrapFeatures> = {},
): Promise<ZeroExContract> {
const _features = await deployBootstrapFeaturesAsync(provider, txDefaults, features);
const migrator = await InitialMigrationContract.deployFrom0xArtifactAsync(
artifacts.InitialMigration,
provider,
txDefaults,
artifacts,
txDefaults.from as string,
);
const deployCall = migrator.deploy(owner, toFeatureAdddresses(_features));
const zeroEx = new ZeroExContract(await deployCall.callAsync(), provider, {});
await deployCall.awaitTransactionSuccessAsync();
return zeroEx;
}
export interface FullFeatures extends BootstrapFeatures {
tokenSpender: TokenSpenderContract;
transformERC20: TransformERC20Contract;
}
export interface FullMigrationOpts {
transformDeployer: string;
}
export async function deployFullFeaturesAsync(
provider: SupportedProvider,
txDefaults: Partial<TxData>,
features: Partial<FullFeatures> = {},
opts: Partial<FullMigrationOpts> = {},
): Promise<FullFeatures> {
return {
...(await deployBootstrapFeaturesAsync(provider, txDefaults)),
tokenSpender:
features.tokenSpender ||
(await TokenSpenderContract.deployFrom0xArtifactAsync(
artifacts.TokenSpender,
provider,
txDefaults,
artifacts,
)),
transformERC20:
features.transformERC20 ||
(await TransformERC20Contract.deployFrom0xArtifactAsync(
artifacts.TransformERC20,
provider,
txDefaults,
artifacts,
opts.transformDeployer || (txDefaults.from as string),
)),
};
}
export async function fullMigrateAsync(
owner: string,
provider: SupportedProvider,
txDefaults: Partial<TxData>,
features: Partial<FullFeatures> = {},
opts: Partial<FullMigrationOpts> = {},
): Promise<ZeroExContract> {
const _features = await deployFullFeaturesAsync(provider, txDefaults, features, opts);
const migrator = await FullMigrationContract.deployFrom0xArtifactAsync(
artifacts.FullMigration,
provider,
txDefaults,
artifacts,
txDefaults.from as string,
);
const deployCall = migrator.deploy(owner, toFeatureAdddresses(_features));
const zeroEx = new ZeroExContract(await deployCall.callAsync(), provider, {});
await deployCall.awaitTransactionSuccessAsync();
return zeroEx;
}
// tslint:disable:space-before-function-parent one-line
export function toFeatureAdddresses<T extends BootstrapFeatures | FullFeatures | (BootstrapFeatures & FullFeatures)>(
features: T,
): { [name in keyof T]: string } {
// TS can't figure this out.
return _.mapValues(features, (c: BaseContract) => c.address) as any;
}