diff --git a/contracts/zero-ex/CHANGELOG.json b/contracts/zero-ex/CHANGELOG.json index 4d124051f1..7b7120ddef 100644 --- a/contracts/zero-ex/CHANGELOG.json +++ b/contracts/zero-ex/CHANGELOG.json @@ -49,6 +49,10 @@ { "note": "Remove calldata signing functionality", "pr": 51 + }, + { + "note": "Add a permissionless transformer deployer", + "pr": 55 } ] }, diff --git a/contracts/zero-ex/contracts/src/external/PermissionlessTransformerDeployer.sol b/contracts/zero-ex/contracts/src/external/PermissionlessTransformerDeployer.sol new file mode 100644 index 0000000000..0faa973dbf --- /dev/null +++ b/contracts/zero-ex/contracts/src/external/PermissionlessTransformerDeployer.sol @@ -0,0 +1,114 @@ +/* + + 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 Deployer contract for ERC20 transformers. +contract PermissionlessTransformerDeployer { + /// @dev Emitted when a contract is deployed via `deploy()`. + /// @param deployedAddress The address of the deployed contract. + /// @param salt The deployment salt. + /// @param sender The caller of `deploy()`. + event Deployed(address deployedAddress, bytes32 salt, address sender); + + // @dev Mapping of deployed contract address to the deployment salt. + mapping (address => bytes32) public toDeploymentSalt; + // @dev Mapping of deployed contract address to the init code hash. + mapping (address => bytes32) public toInitCodeHash; + + /// @dev Deploy a new contract. Any attached ETH will be forwarded. + function deploy(bytes memory bytecode, bytes32 salt) + public + payable + returns (address deployedAddress) + { + assembly { + deployedAddress := create2(callvalue(), add(bytecode, 32), mload(bytecode), salt) + } + require(deployedAddress != address(0), 'PermissionlessTransformerDeployer/DEPLOY_FAILED'); + require(isDelegateCallSafe(deployedAddress), 'PermissionlessTransformerDeployer/UNSAFE_CODE'); + toDeploymentSalt[deployedAddress] = salt; + toInitCodeHash[deployedAddress] = keccak256(bytecode); + emit Deployed(deployedAddress, salt, msg.sender); + } + + /// @dev Checks whether a given address is safe to be called via + /// delegatecall. A contract is considered unsafe if it includes any + /// of the following opcodes: CALLCODE, DELEGATECALL, SELFDESTRUCT, + /// CREATE, CREATE2, SLOAD, and STORE. This code is adapted from + /// https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/helpers/IndestructibleRegistry.sol + /// @param target The address to check. + /// @return True if the contract is considered safe for delegatecall. + function isDelegateCallSafe(address target) public view returns (bool) { + uint256 size; + assembly { size := extcodesize(target) } + require(size > 0, 'PermissionlessTransformerDeployer/NO_CODE'); + + bytes memory extcode = new bytes(size); + assembly { + extcodecopy(target, add(extcode, 32), 0, size) + } + + // Look for any reachable, impermissible opcodes. + bool reachable = true; + for (uint256 i = 0; i < extcode.length; i++) { + uint8 op = uint8(extcode[i]); + + // If the opcode is a PUSH, skip over the push data. + if (op > 95 && op < 128) { // pushN + i += (op - 95); + continue; + } + + if (reachable) { + // If execution is halted, mark subsequent opcodes unreachable. + if ( + op == 254 || // invalid + op == 243 || // return + op == 253 || // revert + op == 86 || // jump + op == 0 // stop + ) { + reachable = false; + continue; + } + + // If opcode is impermissible, contract is unsafe. + if ( + op == 242 || // callcode + op == 244 || // delegatecall + op == 255 || // selfdestruct + op == 240 || // create + op == 245 || // create2 + op == 84 || // sload + op == 85 // sstore + ) { + return false; + } + } else if (op == 91) { // jumpdest + // After a JUMPDEST, opcodes are reachable again. + reachable = true; + } + } + + return true; // No impermissible opcodes found. + } +} + diff --git a/contracts/zero-ex/contracts/test/TestPermissionlessTransformerDeployerSuicidal.sol b/contracts/zero-ex/contracts/test/TestPermissionlessTransformerDeployerSuicidal.sol new file mode 100644 index 0000000000..e9fe62e2d4 --- /dev/null +++ b/contracts/zero-ex/contracts/test/TestPermissionlessTransformerDeployerSuicidal.sol @@ -0,0 +1,27 @@ +/* + + 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; + + +contract TestPermissionlessTransformerDeployerSuicidal { + function kill() external { + selfdestruct(msg.sender); + } +} diff --git a/contracts/zero-ex/contracts/test/TestPermissionlessTransformerDeployerTransformer.sol b/contracts/zero-ex/contracts/test/TestPermissionlessTransformerDeployerTransformer.sol new file mode 100644 index 0000000000..80cc641eb6 --- /dev/null +++ b/contracts/zero-ex/contracts/test/TestPermissionlessTransformerDeployerTransformer.sol @@ -0,0 +1,36 @@ +/* + + 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 TestPermissionlessTransformerDeployerTransformer { + uint256 public constant CONSTRUCTOR_FAIL_VALUE = 3333; + address payable public immutable deployer; + + constructor() public payable { + deployer = msg.sender; + require( + msg.value != CONSTRUCTOR_FAIL_VALUE, + "TestTransformerDeployerTransformer/CONSTRUCTOR_FAIL" + ); + } +} diff --git a/contracts/zero-ex/package.json b/contracts/zero-ex/package.json index c02259c5b1..60ab991288 100644 --- a/contracts/zero-ex/package.json +++ b/contracts/zero-ex/package.json @@ -42,7 +42,7 @@ "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", "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|MixinCurve|MixinDodo|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinShell|MixinSushiswap|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|NativeOrdersFeature|OwnableFeature|PayTakerTransformer|SignatureValidatorFeature|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestNativeOrdersFeature|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|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|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" }, "repository": { "type": "git", diff --git a/contracts/zero-ex/test/artifacts.ts b/contracts/zero-ex/test/artifacts.ts index fae7064dac..8df2956935 100644 --- a/contracts/zero-ex/test/artifacts.ts +++ b/contracts/zero-ex/test/artifacts.ts @@ -88,6 +88,7 @@ import * as MixinZeroExBridge from '../test/generated-artifacts/MixinZeroExBridg import * as NativeOrdersFeature from '../test/generated-artifacts/NativeOrdersFeature.json'; import * as OwnableFeature from '../test/generated-artifacts/OwnableFeature.json'; import * as PayTakerTransformer from '../test/generated-artifacts/PayTakerTransformer.json'; +import * as PermissionlessTransformerDeployer from '../test/generated-artifacts/PermissionlessTransformerDeployer.json'; import * as SignatureValidatorFeature from '../test/generated-artifacts/SignatureValidatorFeature.json'; import * as SimpleFunctionRegistryFeature from '../test/generated-artifacts/SimpleFunctionRegistryFeature.json'; import * as TestBridge from '../test/generated-artifacts/TestBridge.json'; @@ -109,6 +110,8 @@ import * as TestMigrator from '../test/generated-artifacts/TestMigrator.json'; import * as TestMintableERC20Token from '../test/generated-artifacts/TestMintableERC20Token.json'; import * as TestMintTokenERC20Transformer from '../test/generated-artifacts/TestMintTokenERC20Transformer.json'; import * as TestNativeOrdersFeature from '../test/generated-artifacts/TestNativeOrdersFeature.json'; +import * as TestPermissionlessTransformerDeployerSuicidal from '../test/generated-artifacts/TestPermissionlessTransformerDeployerSuicidal.json'; +import * as TestPermissionlessTransformerDeployerTransformer from '../test/generated-artifacts/TestPermissionlessTransformerDeployerTransformer.json'; import * as TestRfqOriginRegistration from '../test/generated-artifacts/TestRfqOriginRegistration.json'; import * as TestSimpleFunctionRegistryFeatureImpl1 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json'; import * as TestSimpleFunctionRegistryFeatureImpl2 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json'; @@ -152,6 +155,7 @@ export const artifacts = { IFlashWallet: IFlashWallet as ContractArtifact, ILiquidityProviderSandbox: ILiquidityProviderSandbox as ContractArtifact, LiquidityProviderSandbox: LiquidityProviderSandbox as ContractArtifact, + PermissionlessTransformerDeployer: PermissionlessTransformerDeployer as ContractArtifact, TransformerDeployer: TransformerDeployer as ContractArtifact, BootstrapFeature: BootstrapFeature as ContractArtifact, IBootstrapFeature: IBootstrapFeature as ContractArtifact, @@ -243,6 +247,8 @@ export const artifacts = { TestMintTokenERC20Transformer: TestMintTokenERC20Transformer as ContractArtifact, TestMintableERC20Token: TestMintableERC20Token as ContractArtifact, TestNativeOrdersFeature: TestNativeOrdersFeature as ContractArtifact, + TestPermissionlessTransformerDeployerSuicidal: TestPermissionlessTransformerDeployerSuicidal as ContractArtifact, + TestPermissionlessTransformerDeployerTransformer: TestPermissionlessTransformerDeployerTransformer as ContractArtifact, TestRfqOriginRegistration: TestRfqOriginRegistration as ContractArtifact, TestSimpleFunctionRegistryFeatureImpl1: TestSimpleFunctionRegistryFeatureImpl1 as ContractArtifact, TestSimpleFunctionRegistryFeatureImpl2: TestSimpleFunctionRegistryFeatureImpl2 as ContractArtifact, diff --git a/contracts/zero-ex/test/permissionless_transformer_deployer_test.ts b/contracts/zero-ex/test/permissionless_transformer_deployer_test.ts new file mode 100644 index 0000000000..ef4ee76c36 --- /dev/null +++ b/contracts/zero-ex/test/permissionless_transformer_deployer_test.ts @@ -0,0 +1,102 @@ +import { blockchainTests, expect, verifyEventsFromLogs } from '@0x/contracts-test-utils'; +import { BigNumber, hexUtils } from '@0x/utils'; +import * as ethjs from 'ethereumjs-util'; + +import { artifacts } from './artifacts'; +import { + PermissionlessTransformerDeployerContract, + PermissionlessTransformerDeployerEvents, + TestPermissionlessTransformerDeployerTransformerContract, +} from './wrappers'; + +blockchainTests.resets('PermissionlessTransformerDeployer', env => { + let owner: string; + let sender: string; + let deployer: PermissionlessTransformerDeployerContract; + const deployBytes = artifacts.TestPermissionlessTransformerDeployerTransformer.compilerOutput.evm.bytecode.object; + + before(async () => { + [owner, sender] = await env.getAccountAddressesAsync(); + deployer = await PermissionlessTransformerDeployerContract.deployFrom0xArtifactAsync( + artifacts.PermissionlessTransformerDeployer, + env.provider, + env.txDefaults, + artifacts, + ); + }); + + describe('deploy()', () => { + it('can deploy safe contract', async () => { + const salt = hexUtils.random(); + const targetAddress = await deployer.deploy(deployBytes, salt).callAsync(); + const target = new TestPermissionlessTransformerDeployerTransformerContract(targetAddress, env.provider); + const receipt = await deployer.deploy(deployBytes, salt).awaitTransactionSuccessAsync({ from: sender }); + expect(await target.deployer().callAsync()).to.eq(deployer.address); + verifyEventsFromLogs( + receipt.logs, + [{ deployedAddress: targetAddress, salt, sender }], + PermissionlessTransformerDeployerEvents.Deployed, + ); + }); + + it('deploys at predictable address', async () => { + const salt = hexUtils.random(); + const targetAddress = await deployer.deploy(deployBytes, salt).callAsync(); + const initCodeHash = hexUtils.toHex(ethjs.sha3(deployBytes)); + const expectedAddress = hexUtils.slice( + hexUtils.toHex(ethjs.sha3(hexUtils.concat('0xFF', deployer.address, salt, initCodeHash))), + 12, + ); + + expect(targetAddress).to.eq(expectedAddress); + }); + + it('cannot deploy suicidal contract', async () => { + const suicidalDeployBytes = + artifacts.TestPermissionlessTransformerDeployerSuicidal.compilerOutput.evm.bytecode.object; + + const tx = deployer.deploy(suicidalDeployBytes, hexUtils.random()).awaitTransactionSuccessAsync(); + expect(tx).to.revertWith('PermissionlessTransformerDeployer/UNSAFE_CODE'); + }); + + it('can deploy safe contract with value', async () => { + const salt = hexUtils.random(); + const targetAddress = await deployer.deploy(deployBytes, salt).callAsync({ from: sender, value: 1 }); + const target = new TestPermissionlessTransformerDeployerTransformerContract(targetAddress, env.provider); + const receipt = await deployer + .deploy(deployBytes, salt) + .awaitTransactionSuccessAsync({ from: sender, value: 1 }); + expect(await target.deployer().callAsync()).to.eq(deployer.address); + verifyEventsFromLogs( + receipt.logs, + [{ deployedAddress: targetAddress, salt, sender }], + PermissionlessTransformerDeployerEvents.Deployed, + ); + expect(await env.web3Wrapper.getBalanceInWeiAsync(targetAddress)).to.bignumber.eq(1); + }); + + it('reverts if constructor throws', async () => { + const CONSTRUCTOR_FAIL_VALUE = new BigNumber(3333); + const tx = deployer + .deploy(deployBytes, hexUtils.random()) + .callAsync({ value: CONSTRUCTOR_FAIL_VALUE, from: sender }); + return expect(tx).to.revertWith('PermissionlessTransformerDeployer/DEPLOY_FAILED'); + }); + + it('can retrieve deployment salt from contract address', async () => { + const salt = hexUtils.random(); + const targetAddress = await deployer.deploy(deployBytes, salt).callAsync({ from: sender }); + await deployer.deploy(deployBytes, salt).awaitTransactionSuccessAsync({ from: sender }); + expect(await deployer.toDeploymentSalt(targetAddress).callAsync()).to.eq(salt); + }); + + it('can retrieve deployment init code hash from contract address', async () => { + const salt = hexUtils.random(); + const targetAddress = await deployer.deploy(deployBytes, salt).callAsync({ from: sender }); + await deployer.deploy(deployBytes, salt).awaitTransactionSuccessAsync({ from: sender }); + expect(hexUtils.toHex(await deployer.toInitCodeHash(targetAddress).callAsync())).to.eq( + hexUtils.toHex(ethjs.sha3(deployBytes)), + ); + }); + }); +}); diff --git a/contracts/zero-ex/test/wrappers.ts b/contracts/zero-ex/test/wrappers.ts index 706bd76d22..f39c8a14ca 100644 --- a/contracts/zero-ex/test/wrappers.ts +++ b/contracts/zero-ex/test/wrappers.ts @@ -86,6 +86,7 @@ export * from '../test/generated-wrappers/mixin_zero_ex_bridge'; export * from '../test/generated-wrappers/native_orders_feature'; export * from '../test/generated-wrappers/ownable_feature'; export * from '../test/generated-wrappers/pay_taker_transformer'; +export * from '../test/generated-wrappers/permissionless_transformer_deployer'; export * from '../test/generated-wrappers/signature_validator_feature'; export * from '../test/generated-wrappers/simple_function_registry_feature'; export * from '../test/generated-wrappers/test_bridge'; @@ -107,6 +108,8 @@ export * from '../test/generated-wrappers/test_migrator'; export * from '../test/generated-wrappers/test_mint_token_erc20_transformer'; export * from '../test/generated-wrappers/test_mintable_erc20_token'; export * from '../test/generated-wrappers/test_native_orders_feature'; +export * from '../test/generated-wrappers/test_permissionless_transformer_deployer_suicidal'; +export * from '../test/generated-wrappers/test_permissionless_transformer_deployer_transformer'; export * from '../test/generated-wrappers/test_rfq_origin_registration'; export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl1'; export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl2'; diff --git a/contracts/zero-ex/tsconfig.json b/contracts/zero-ex/tsconfig.json index 768b62b8ac..dddd09b753 100644 --- a/contracts/zero-ex/tsconfig.json +++ b/contracts/zero-ex/tsconfig.json @@ -113,6 +113,7 @@ "test/generated-artifacts/NativeOrdersFeature.json", "test/generated-artifacts/OwnableFeature.json", "test/generated-artifacts/PayTakerTransformer.json", + "test/generated-artifacts/PermissionlessTransformerDeployer.json", "test/generated-artifacts/SignatureValidatorFeature.json", "test/generated-artifacts/SimpleFunctionRegistryFeature.json", "test/generated-artifacts/TestBridge.json", @@ -134,6 +135,8 @@ "test/generated-artifacts/TestMintTokenERC20Transformer.json", "test/generated-artifacts/TestMintableERC20Token.json", "test/generated-artifacts/TestNativeOrdersFeature.json", + "test/generated-artifacts/TestPermissionlessTransformerDeployerSuicidal.json", + "test/generated-artifacts/TestPermissionlessTransformerDeployerTransformer.json", "test/generated-artifacts/TestRfqOriginRegistration.json", "test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json", "test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json",