Merge pull request #2592 from 0xProject/feat/zero-ex/transformer-deployer
Exchange Proxy: TransformerDeployer
This commit is contained in:
82
contracts/zero-ex/contracts/src/external/TransformerDeployer.sol
vendored
Normal file
82
contracts/zero-ex/contracts/src/external/TransformerDeployer.sol
vendored
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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-utils/contracts/src/v06/AuthorizableV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev A contract with a `die()` function.
|
||||||
|
interface IKillable {
|
||||||
|
function die() external;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Deployer contract for ERC20 transformers.
|
||||||
|
/// Only authorities may call `deploy()` and `kill()`.
|
||||||
|
contract TransformerDeployer is
|
||||||
|
AuthorizableV06
|
||||||
|
{
|
||||||
|
/// @dev Emitted when a contract is deployed via `deploy()`.
|
||||||
|
/// @param deployedAddress The address of the deployed contract.
|
||||||
|
/// @param nonce The deployment nonce.
|
||||||
|
/// @param sender The caller of `deploy()`.
|
||||||
|
event Deployed(address deployedAddress, uint256 nonce, address sender);
|
||||||
|
/// @dev Emitted when a contract is killed via `kill()`.
|
||||||
|
/// @param target The address of the contract being killed..
|
||||||
|
/// @param sender The caller of `kill()`.
|
||||||
|
event Killed(address target, address sender);
|
||||||
|
|
||||||
|
// @dev The current nonce of this contract.
|
||||||
|
uint256 public nonce = 1;
|
||||||
|
// @dev Mapping of deployed contract address to deployment nonce.
|
||||||
|
mapping (address => uint256) public toDeploymentNonce;
|
||||||
|
|
||||||
|
/// @dev Create this contract and register authorities.
|
||||||
|
constructor(address[] memory authorities) public {
|
||||||
|
for (uint256 i = 0; i < authorities.length; ++i) {
|
||||||
|
_addAuthorizedAddress(authorities[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Deploy a new contract. Only callable by an authority.
|
||||||
|
/// Any attached ETH will also be forwarded.
|
||||||
|
function deploy(bytes memory bytecode)
|
||||||
|
public
|
||||||
|
payable
|
||||||
|
onlyAuthorized
|
||||||
|
returns (address deployedAddress)
|
||||||
|
{
|
||||||
|
uint256 deploymentNonce = nonce;
|
||||||
|
nonce += 1;
|
||||||
|
assembly {
|
||||||
|
deployedAddress := create(callvalue(), add(bytecode, 32), mload(bytecode))
|
||||||
|
}
|
||||||
|
toDeploymentNonce[deployedAddress] = deploymentNonce;
|
||||||
|
emit Deployed(deployedAddress, deploymentNonce, msg.sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Call `die()` on a contract. Only callable by an authority.
|
||||||
|
function kill(IKillable target)
|
||||||
|
public
|
||||||
|
onlyAuthorized
|
||||||
|
{
|
||||||
|
target.die();
|
||||||
|
emit Killed(address(target), msg.sender);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 "../src/transformers/LibERC20Transformer.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestTransformerDeployerTransformer {
|
||||||
|
|
||||||
|
address payable public immutable deployer;
|
||||||
|
|
||||||
|
constructor() public payable {
|
||||||
|
deployer = msg.sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
modifier onlyDeployer() {
|
||||||
|
require(msg.sender == deployer, "TestTransformerDeployerTransformer/ONLY_DEPLOYER");
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
function die()
|
||||||
|
external
|
||||||
|
onlyDeployer
|
||||||
|
{
|
||||||
|
selfdestruct(deployer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDeployedByDeployer(uint32 nonce)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return LibERC20Transformer.getDeployedAddress(deployer, nonce) == address(this);
|
||||||
|
}
|
||||||
|
}
|
@@ -40,7 +40,7 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnable,ISimpleFunctionRegistry,ITokenSpender,ITransformERC20,FillQuoteTransformer,PayTakerTransformer,WethTransformer",
|
"publicInterfaceContracts": "ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnable,ISimpleFunctionRegistry,ITokenSpender,ITransformERC20,FillQuoteTransformer,PayTakerTransformer,WethTransformer",
|
||||||
"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/@(AllowanceTarget|Bootstrap|FillQuoteTransformer|FixinCommon|FlashWallet|FullMigration|IAllowanceTarget|IBootstrap|IERC20Transformer|IExchange|IFeature|IFlashWallet|IOwnable|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|ITokenSpender|ITransformERC20|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|Ownable|PayTakerTransformer|SimpleFunctionRegistry|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFullMigration|TestInitialMigration|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpender|TransformERC20|Transformer|WethTransformer|ZeroEx).json"
|
"abis": "./test/generated-artifacts/@(AllowanceTarget|Bootstrap|FillQuoteTransformer|FixinCommon|FlashWallet|FullMigration|IAllowanceTarget|IBootstrap|IERC20Transformer|IExchange|IFeature|IFlashWallet|IOwnable|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|ITokenSpender|ITransformERC20|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|Ownable|PayTakerTransformer|SimpleFunctionRegistry|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFullMigration|TestInitialMigration|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpender|TransformERC20|Transformer|TransformerDeployer|WethTransformer|ZeroEx).json"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@@ -57,6 +57,7 @@ import * as TestTokenSpender from '../test/generated-artifacts/TestTokenSpender.
|
|||||||
import * as TestTokenSpenderERC20Token from '../test/generated-artifacts/TestTokenSpenderERC20Token.json';
|
import * as TestTokenSpenderERC20Token from '../test/generated-artifacts/TestTokenSpenderERC20Token.json';
|
||||||
import * as TestTransformerBase from '../test/generated-artifacts/TestTransformerBase.json';
|
import * as TestTransformerBase from '../test/generated-artifacts/TestTransformerBase.json';
|
||||||
import * as TestTransformERC20 from '../test/generated-artifacts/TestTransformERC20.json';
|
import * as TestTransformERC20 from '../test/generated-artifacts/TestTransformERC20.json';
|
||||||
|
import * as TestTransformerDeployerTransformer from '../test/generated-artifacts/TestTransformerDeployerTransformer.json';
|
||||||
import * as TestTransformerHost from '../test/generated-artifacts/TestTransformerHost.json';
|
import * as TestTransformerHost from '../test/generated-artifacts/TestTransformerHost.json';
|
||||||
import * as TestWeth from '../test/generated-artifacts/TestWeth.json';
|
import * as TestWeth from '../test/generated-artifacts/TestWeth.json';
|
||||||
import * as TestWethTransformerHost from '../test/generated-artifacts/TestWethTransformerHost.json';
|
import * as TestWethTransformerHost from '../test/generated-artifacts/TestWethTransformerHost.json';
|
||||||
@@ -64,6 +65,7 @@ import * as TestZeroExFeature from '../test/generated-artifacts/TestZeroExFeatur
|
|||||||
import * as TokenSpender from '../test/generated-artifacts/TokenSpender.json';
|
import * as TokenSpender from '../test/generated-artifacts/TokenSpender.json';
|
||||||
import * as Transformer from '../test/generated-artifacts/Transformer.json';
|
import * as Transformer from '../test/generated-artifacts/Transformer.json';
|
||||||
import * as TransformERC20 from '../test/generated-artifacts/TransformERC20.json';
|
import * as TransformERC20 from '../test/generated-artifacts/TransformERC20.json';
|
||||||
|
import * as TransformerDeployer from '../test/generated-artifacts/TransformerDeployer.json';
|
||||||
import * as WethTransformer from '../test/generated-artifacts/WethTransformer.json';
|
import * as WethTransformer from '../test/generated-artifacts/WethTransformer.json';
|
||||||
import * as ZeroEx from '../test/generated-artifacts/ZeroEx.json';
|
import * as ZeroEx from '../test/generated-artifacts/ZeroEx.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
@@ -79,6 +81,7 @@ export const artifacts = {
|
|||||||
FlashWallet: FlashWallet as ContractArtifact,
|
FlashWallet: FlashWallet as ContractArtifact,
|
||||||
IAllowanceTarget: IAllowanceTarget as ContractArtifact,
|
IAllowanceTarget: IAllowanceTarget as ContractArtifact,
|
||||||
IFlashWallet: IFlashWallet as ContractArtifact,
|
IFlashWallet: IFlashWallet as ContractArtifact,
|
||||||
|
TransformerDeployer: TransformerDeployer as ContractArtifact,
|
||||||
Bootstrap: Bootstrap as ContractArtifact,
|
Bootstrap: Bootstrap as ContractArtifact,
|
||||||
IBootstrap: IBootstrap as ContractArtifact,
|
IBootstrap: IBootstrap as ContractArtifact,
|
||||||
IFeature: IFeature as ContractArtifact,
|
IFeature: IFeature as ContractArtifact,
|
||||||
@@ -124,6 +127,7 @@ export const artifacts = {
|
|||||||
TestTokenSpenderERC20Token: TestTokenSpenderERC20Token as ContractArtifact,
|
TestTokenSpenderERC20Token: TestTokenSpenderERC20Token as ContractArtifact,
|
||||||
TestTransformERC20: TestTransformERC20 as ContractArtifact,
|
TestTransformERC20: TestTransformERC20 as ContractArtifact,
|
||||||
TestTransformerBase: TestTransformerBase as ContractArtifact,
|
TestTransformerBase: TestTransformerBase as ContractArtifact,
|
||||||
|
TestTransformerDeployerTransformer: TestTransformerDeployerTransformer as ContractArtifact,
|
||||||
TestTransformerHost: TestTransformerHost as ContractArtifact,
|
TestTransformerHost: TestTransformerHost as ContractArtifact,
|
||||||
TestWeth: TestWeth as ContractArtifact,
|
TestWeth: TestWeth as ContractArtifact,
|
||||||
TestWethTransformerHost: TestWethTransformerHost as ContractArtifact,
|
TestWethTransformerHost: TestWethTransformerHost as ContractArtifact,
|
||||||
|
109
contracts/zero-ex/test/transformer_deployer_test.ts
Normal file
109
contracts/zero-ex/test/transformer_deployer_test.ts
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import { blockchainTests, constants, expect, randomAddress, verifyEventsFromLogs } from '@0x/contracts-test-utils';
|
||||||
|
import { AuthorizableRevertErrors, BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
|
import { artifacts } from './artifacts';
|
||||||
|
import {
|
||||||
|
TestTransformerDeployerTransformerContract,
|
||||||
|
TransformerDeployerContract,
|
||||||
|
TransformerDeployerEvents,
|
||||||
|
} from './wrappers';
|
||||||
|
|
||||||
|
blockchainTests.resets('TransformerDeployer', env => {
|
||||||
|
let owner: string;
|
||||||
|
let authority: string;
|
||||||
|
let deployer: TransformerDeployerContract;
|
||||||
|
const deployBytes = artifacts.TestTransformerDeployerTransformer.compilerOutput.evm.bytecode.object;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
[owner, authority] = await env.getAccountAddressesAsync();
|
||||||
|
deployer = await TransformerDeployerContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TransformerDeployer,
|
||||||
|
env.provider,
|
||||||
|
env.txDefaults,
|
||||||
|
artifacts,
|
||||||
|
[authority],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('deploy()', () => {
|
||||||
|
it('non-authority cannot call', async () => {
|
||||||
|
const nonAuthority = randomAddress();
|
||||||
|
const tx = deployer.deploy(deployBytes).callAsync({ from: nonAuthority });
|
||||||
|
return expect(tx).to.revertWith(new AuthorizableRevertErrors.SenderNotAuthorizedError(nonAuthority));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('authority can deploy', async () => {
|
||||||
|
const targetAddress = await deployer.deploy(deployBytes).callAsync({ from: authority });
|
||||||
|
const target = new TestTransformerDeployerTransformerContract(targetAddress, env.provider);
|
||||||
|
const receipt = await deployer.deploy(deployBytes).awaitTransactionSuccessAsync({ from: authority });
|
||||||
|
expect(await target.deployer().callAsync()).to.eq(deployer.address);
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[{ deployedAddress: targetAddress, nonce: new BigNumber(1), sender: authority }],
|
||||||
|
TransformerDeployerEvents.Deployed,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('authority can deploy with value', async () => {
|
||||||
|
const targetAddress = await deployer.deploy(deployBytes).callAsync({ from: authority, value: 1 });
|
||||||
|
const target = new TestTransformerDeployerTransformerContract(targetAddress, env.provider);
|
||||||
|
const receipt = await deployer
|
||||||
|
.deploy(deployBytes)
|
||||||
|
.awaitTransactionSuccessAsync({ from: authority, value: 1 });
|
||||||
|
expect(await target.deployer().callAsync()).to.eq(deployer.address);
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[{ deployedAddress: targetAddress, nonce: new BigNumber(1), sender: authority }],
|
||||||
|
TransformerDeployerEvents.Deployed,
|
||||||
|
);
|
||||||
|
expect(await env.web3Wrapper.getBalanceInWeiAsync(targetAddress)).to.bignumber.eq(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates nonce', async () => {
|
||||||
|
expect(await deployer.nonce().callAsync()).to.bignumber.eq(1);
|
||||||
|
await deployer.deploy(deployBytes).awaitTransactionSuccessAsync({ from: authority });
|
||||||
|
expect(await deployer.nonce().callAsync()).to.bignumber.eq(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('nonce can predict deployment address', async () => {
|
||||||
|
const nonce = await deployer.nonce().callAsync();
|
||||||
|
const targetAddress = await deployer.deploy(deployBytes).callAsync({ from: authority });
|
||||||
|
const target = new TestTransformerDeployerTransformerContract(targetAddress, env.provider);
|
||||||
|
await deployer.deploy(deployBytes).awaitTransactionSuccessAsync({ from: authority });
|
||||||
|
expect(await target.isDeployedByDeployer(nonce).callAsync()).to.eq(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can retrieve deployment nonce from contract address', async () => {
|
||||||
|
const nonce = await deployer.nonce().callAsync();
|
||||||
|
const targetAddress = await deployer.deploy(deployBytes).callAsync({ from: authority });
|
||||||
|
await deployer.deploy(deployBytes).awaitTransactionSuccessAsync({ from: authority });
|
||||||
|
expect(await deployer.toDeploymentNonce(targetAddress).callAsync()).to.bignumber.eq(nonce);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('kill()', () => {
|
||||||
|
let target: TestTransformerDeployerTransformerContract;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
const targetAddress = await deployer.deploy(deployBytes).callAsync({ from: authority });
|
||||||
|
target = new TestTransformerDeployerTransformerContract(targetAddress, env.provider);
|
||||||
|
await deployer.deploy(deployBytes).awaitTransactionSuccessAsync({ from: authority });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('authority cannot call', async () => {
|
||||||
|
const nonAuthority = randomAddress();
|
||||||
|
const tx = deployer.kill(target.address).callAsync({ from: nonAuthority });
|
||||||
|
return expect(tx).to.revertWith(new AuthorizableRevertErrors.SenderNotAuthorizedError(nonAuthority));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('authority can kill a contract', async () => {
|
||||||
|
const receipt = await deployer.kill(target.address).awaitTransactionSuccessAsync({ from: authority });
|
||||||
|
verifyEventsFromLogs(
|
||||||
|
receipt.logs,
|
||||||
|
[{ target: target.address, sender: authority }],
|
||||||
|
TransformerDeployerEvents.Killed,
|
||||||
|
);
|
||||||
|
return expect(env.web3Wrapper.getContractCodeAsync(target.address)).to.become(constants.NULL_BYTES);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -55,6 +55,7 @@ export * from '../test/generated-wrappers/test_token_spender';
|
|||||||
export * from '../test/generated-wrappers/test_token_spender_erc20_token';
|
export * from '../test/generated-wrappers/test_token_spender_erc20_token';
|
||||||
export * from '../test/generated-wrappers/test_transform_erc20';
|
export * from '../test/generated-wrappers/test_transform_erc20';
|
||||||
export * from '../test/generated-wrappers/test_transformer_base';
|
export * from '../test/generated-wrappers/test_transformer_base';
|
||||||
|
export * from '../test/generated-wrappers/test_transformer_deployer_transformer';
|
||||||
export * from '../test/generated-wrappers/test_transformer_host';
|
export * from '../test/generated-wrappers/test_transformer_host';
|
||||||
export * from '../test/generated-wrappers/test_weth';
|
export * from '../test/generated-wrappers/test_weth';
|
||||||
export * from '../test/generated-wrappers/test_weth_transformer_host';
|
export * from '../test/generated-wrappers/test_weth_transformer_host';
|
||||||
@@ -62,5 +63,6 @@ export * from '../test/generated-wrappers/test_zero_ex_feature';
|
|||||||
export * from '../test/generated-wrappers/token_spender';
|
export * from '../test/generated-wrappers/token_spender';
|
||||||
export * from '../test/generated-wrappers/transform_erc20';
|
export * from '../test/generated-wrappers/transform_erc20';
|
||||||
export * from '../test/generated-wrappers/transformer';
|
export * from '../test/generated-wrappers/transformer';
|
||||||
|
export * from '../test/generated-wrappers/transformer_deployer';
|
||||||
export * from '../test/generated-wrappers/weth_transformer';
|
export * from '../test/generated-wrappers/weth_transformer';
|
||||||
export * from '../test/generated-wrappers/zero_ex';
|
export * from '../test/generated-wrappers/zero_ex';
|
||||||
|
@@ -68,6 +68,7 @@
|
|||||||
"test/generated-artifacts/TestTokenSpenderERC20Token.json",
|
"test/generated-artifacts/TestTokenSpenderERC20Token.json",
|
||||||
"test/generated-artifacts/TestTransformERC20.json",
|
"test/generated-artifacts/TestTransformERC20.json",
|
||||||
"test/generated-artifacts/TestTransformerBase.json",
|
"test/generated-artifacts/TestTransformerBase.json",
|
||||||
|
"test/generated-artifacts/TestTransformerDeployerTransformer.json",
|
||||||
"test/generated-artifacts/TestTransformerHost.json",
|
"test/generated-artifacts/TestTransformerHost.json",
|
||||||
"test/generated-artifacts/TestWeth.json",
|
"test/generated-artifacts/TestWeth.json",
|
||||||
"test/generated-artifacts/TestWethTransformerHost.json",
|
"test/generated-artifacts/TestWethTransformerHost.json",
|
||||||
@@ -75,6 +76,7 @@
|
|||||||
"test/generated-artifacts/TokenSpender.json",
|
"test/generated-artifacts/TokenSpender.json",
|
||||||
"test/generated-artifacts/TransformERC20.json",
|
"test/generated-artifacts/TransformERC20.json",
|
||||||
"test/generated-artifacts/Transformer.json",
|
"test/generated-artifacts/Transformer.json",
|
||||||
|
"test/generated-artifacts/TransformerDeployer.json",
|
||||||
"test/generated-artifacts/WethTransformer.json",
|
"test/generated-artifacts/WethTransformer.json",
|
||||||
"test/generated-artifacts/ZeroEx.json"
|
"test/generated-artifacts/ZeroEx.json"
|
||||||
],
|
],
|
||||||
|
Reference in New Issue
Block a user