diff --git a/contracts/zero-ex/contracts/src/features/LiquidityProviderFeature.sol b/contracts/zero-ex/contracts/src/features/LiquidityProviderFeature.sol index 4c7cda1b4b..61bb080866 100644 --- a/contracts/zero-ex/contracts/src/features/LiquidityProviderFeature.sol +++ b/contracts/zero-ex/contracts/src/features/LiquidityProviderFeature.sol @@ -28,30 +28,12 @@ import "../errors/LibLiquidityProviderRichErrors.sol"; import "../fixins/FixinCommon.sol"; import "../migrations/LibMigrate.sol"; import "../storage/LibLiquidityProviderStorage.sol"; +import "../vendor/v3/IERC20Bridge.sol"; import "./IFeature.sol"; import "./ILiquidityProviderFeature.sol"; import "./ITokenSpenderFeature.sol"; -interface IERC20Bridge { - /// @dev Transfers `amount` of the ERC20 `tokenAddress` from `from` to `to`. - /// @param tokenAddress The address of the ERC20 token to transfer. - /// @param from Address to transfer asset from. - /// @param to Address to transfer asset to. - /// @param amount Amount of asset to transfer. - /// @param bridgeData Arbitrary asset data needed by the bridge contract. - /// @return success The magic bytes `0xdc1600f3` if successful. - function bridgeTransferFrom( - address tokenAddress, - address from, - address to, - uint256 amount, - bytes calldata bridgeData - ) - external - returns (bytes4 success); -} - contract LiquidityProviderFeature is IFeature, ILiquidityProviderFeature, diff --git a/contracts/zero-ex/contracts/test/TestBridge.sol b/contracts/zero-ex/contracts/test/TestBridge.sol new file mode 100644 index 0000000000..4f94594649 --- /dev/null +++ b/contracts/zero-ex/contracts/test/TestBridge.sol @@ -0,0 +1,69 @@ +/* + + 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-erc20/contracts/src/v06/IERC20TokenV06.sol"; +import "../src/vendor/v3/IERC20Bridge.sol"; + + +contract TestBridge is + IERC20Bridge +{ + IERC20TokenV06 public immutable xAsset; + IERC20TokenV06 public immutable yAsset; + + constructor(IERC20TokenV06 xAsset_, IERC20TokenV06 yAsset_) + public + { + xAsset = xAsset_; + yAsset = yAsset_; + } + + /// @dev Transfers `amount` of the ERC20 `tokenAddress` from `from` to `to`. + /// @param tokenAddress The address of the ERC20 token to transfer. + /// @param from Address to transfer asset from. + /// @param to Address to transfer asset to. + /// @param amount Amount of asset to transfer. + /// @param bridgeData Arbitrary asset data needed by the bridge contract. + /// @return success The magic bytes `0xdc1600f3` if successful. + function bridgeTransferFrom( + address tokenAddress, + address from, + address to, + uint256 amount, + bytes calldata bridgeData + ) + external + override + returns (bytes4 success) + { + IERC20TokenV06 takerToken = tokenAddress == address(xAsset) ? yAsset : xAsset; + uint256 takerTokenBalance = takerToken.balanceOf(address(this)); + emit ERC20BridgeTransfer( + address(takerToken), + tokenAddress, + takerTokenBalance, + amount, + from, + to + ); + return 0xdecaf000; + } +} diff --git a/contracts/zero-ex/package.json b/contracts/zero-ex/package.json index c4f9bbc6c7..55d941e368 100644 --- a/contracts/zero-ex/package.json +++ b/contracts/zero-ex/package.json @@ -41,7 +41,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", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", - "abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinReentrancyGuard|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|ILiquidityProviderFeature|IMetaTransactionsFeature|IOwnableFeature|ISignatureValidatorFeature|ISimpleFunctionRegistryFeature|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibLiquidityProviderRichErrors|LibLiquidityProviderStorage|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignatureRichErrors|LibSignedCallData|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LogMetadataTransformer|MetaTransactionsFeature|MixinAdapterAddresses|MixinBalancer|MixinCurve|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|OwnableFeature|PayTakerTransformer|SignatureValidatorFeature|SimpleFunctionRegistryFeature|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFullMigration|TestInitialMigration|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx).json" + "abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinReentrancyGuard|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|ILiquidityProviderFeature|IMetaTransactionsFeature|IOwnableFeature|ISignatureValidatorFeature|ISimpleFunctionRegistryFeature|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibLiquidityProviderRichErrors|LibLiquidityProviderStorage|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignatureRichErrors|LibSignedCallData|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LogMetadataTransformer|MetaTransactionsFeature|MixinAdapterAddresses|MixinBalancer|MixinCurve|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|OwnableFeature|PayTakerTransformer|SignatureValidatorFeature|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFullMigration|TestInitialMigration|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx).json" }, "repository": { "type": "git", diff --git a/contracts/zero-ex/test/artifacts.ts b/contracts/zero-ex/test/artifacts.ts index a2eb14facf..6de120b62e 100644 --- a/contracts/zero-ex/test/artifacts.ts +++ b/contracts/zero-ex/test/artifacts.ts @@ -75,6 +75,7 @@ import * as OwnableFeature from '../test/generated-artifacts/OwnableFeature.json import * as PayTakerTransformer from '../test/generated-artifacts/PayTakerTransformer.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'; import * as TestCallTarget from '../test/generated-artifacts/TestCallTarget.json'; import * as TestDelegateCaller from '../test/generated-artifacts/TestDelegateCaller.json'; import * as TestFillQuoteTransformerBridge from '../test/generated-artifacts/TestFillQuoteTransformerBridge.json'; @@ -182,6 +183,7 @@ export const artifacts = { IExchange: IExchange as ContractArtifact, IGasToken: IGasToken as ContractArtifact, ITestSimpleFunctionRegistryFeature: ITestSimpleFunctionRegistryFeature as ContractArtifact, + TestBridge: TestBridge as ContractArtifact, TestCallTarget: TestCallTarget as ContractArtifact, TestDelegateCaller: TestDelegateCaller as ContractArtifact, TestFillQuoteTransformerBridge: TestFillQuoteTransformerBridge as ContractArtifact, diff --git a/contracts/zero-ex/test/features/liquidity_provider_test.ts b/contracts/zero-ex/test/features/liquidity_provider_test.ts index 4c183456df..12fbfc0e9a 100644 --- a/contracts/zero-ex/test/features/liquidity_provider_test.ts +++ b/contracts/zero-ex/test/features/liquidity_provider_test.ts @@ -1,26 +1,28 @@ -import { - blockchainTests, - expect, - getRandomInteger, - randomAddress, - verifyEventsFromLogs, -} from '@0x/contracts-test-utils'; -import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/utils'; +import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20'; +import { blockchainTests, constants, expect, randomAddress, verifyEventsFromLogs } from '@0x/contracts-test-utils'; +import { BigNumber, OwnableRevertErrors, ZeroExRevertErrors } from '@0x/utils'; -import { IZeroExContract, TokenSpenderFeatureContract } from '../../src/wrappers'; +import { + IOwnableFeatureContract, + IZeroExContract, + LiquidityProviderFeatureContract, + TokenSpenderFeatureContract, +} from '../../src/wrappers'; import { artifacts } from '../artifacts'; import { abis } from '../utils/abis'; import { fullMigrateAsync } from '../utils/migration'; -import { TestTokenSpenderERC20TokenContract, TestTokenSpenderERC20TokenEvents } from '../wrappers'; +import { IERC20BridgeEvents, TestBridgeContract, TestWethContract } from '../wrappers'; -blockchainTests.resets('LiquidityProvider feature', env => { +blockchainTests('LiquidityProvider feature', env => { let zeroEx: IZeroExContract; - let feature: TokenSpenderFeatureContract; - let token: TestTokenSpenderERC20TokenContract; - let allowanceTarget: string; + let feature: LiquidityProviderFeatureContract; + let token: DummyERC20TokenContract; + let weth: TestWethContract; + let owner: string; + let taker: string; before(async () => { - const [owner] = await env.getAccountAddressesAsync(); + [owner, taker] = await env.getAccountAddressesAsync(); zeroEx = await fullMigrateAsync(owner, env.provider, env.txDefaults, { tokenSpender: (await TokenSpenderFeatureContract.deployFrom0xArtifactAsync( artifacts.TestTokenSpender, @@ -29,20 +31,220 @@ blockchainTests.resets('LiquidityProvider feature', env => { artifacts, )).address, }); - feature = new TokenSpenderFeatureContract(zeroEx.address, env.provider, env.txDefaults, abis); - token = await TestTokenSpenderERC20TokenContract.deployFrom0xArtifactAsync( - artifacts.TestTokenSpenderERC20Token, + const tokenSpender = new TokenSpenderFeatureContract(zeroEx.address, env.provider, env.txDefaults, abis); + const allowanceTarget = await tokenSpender.getAllowanceTarget().callAsync(); + + token = await DummyERC20TokenContract.deployFrom0xArtifactAsync( + erc20Artifacts.DummyERC20Token, + env.provider, + env.txDefaults, + erc20Artifacts, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ); + await token.setBalance(taker, constants.INITIAL_ERC20_BALANCE).awaitTransactionSuccessAsync(); + weth = await TestWethContract.deployFrom0xArtifactAsync( + artifacts.TestWeth, env.provider, env.txDefaults, artifacts, ); - allowanceTarget = await feature.getAllowanceTarget().callAsync(); - }); + await token + .approve(allowanceTarget, constants.INITIAL_ERC20_ALLOWANCE) + .awaitTransactionSuccessAsync({ from: taker }); + feature = new LiquidityProviderFeatureContract(zeroEx.address, env.provider, env.txDefaults, abis); + const featureImpl = await LiquidityProviderFeatureContract.deployFrom0xArtifactAsync( + artifacts.LiquidityProviderFeature, + env.provider, + env.txDefaults, + artifacts, + weth.address, + ); + await new IOwnableFeatureContract(zeroEx.address, env.provider, env.txDefaults, abis) + .migrate(featureImpl.address, featureImpl.migrate().getABIEncodedTransactionData(), owner) + .awaitTransactionSuccessAsync(); + }); describe('Registry', () => { - + it('`getLiquidityProviderForMarket` reverts if address is not set', async () => { + const [xAsset, yAsset] = [randomAddress(), randomAddress()]; + let tx = feature.getLiquidityProviderForMarket(xAsset, yAsset).awaitTransactionSuccessAsync(); + expect(tx).to.revertWith( + new ZeroExRevertErrors.LiquidityProvider.NoLiquidityProviderForMarketError(xAsset, yAsset), + ); + tx = feature.getLiquidityProviderForMarket(yAsset, xAsset).awaitTransactionSuccessAsync(); + return expect(tx).to.revertWith( + new ZeroExRevertErrors.LiquidityProvider.NoLiquidityProviderForMarketError(yAsset, xAsset), + ); + }); + it('can set/get a liquidity provider address for a given market', async () => { + const expectedAddress = randomAddress(); + await feature + .setLiquidityProviderForMarket(token.address, weth.address, expectedAddress) + .awaitTransactionSuccessAsync(); + let actualAddress = await feature.getLiquidityProviderForMarket(token.address, weth.address).callAsync(); + expect(actualAddress).to.equal(expectedAddress); + actualAddress = await feature.getLiquidityProviderForMarket(weth.address, token.address).callAsync(); + expect(actualAddress).to.equal(expectedAddress); + }); + it('can update a liquidity provider address for a given market', async () => { + const expectedAddress = randomAddress(); + await feature + .setLiquidityProviderForMarket(token.address, weth.address, expectedAddress) + .awaitTransactionSuccessAsync(); + let actualAddress = await feature.getLiquidityProviderForMarket(token.address, weth.address).callAsync(); + expect(actualAddress).to.equal(expectedAddress); + actualAddress = await feature.getLiquidityProviderForMarket(weth.address, token.address).callAsync(); + expect(actualAddress).to.equal(expectedAddress); + }); + it('can effectively remove a liquidity provider for a market by setting the address to 0', async () => { + await feature + .setLiquidityProviderForMarket(token.address, weth.address, constants.NULL_ADDRESS) + .awaitTransactionSuccessAsync(); + const tx = feature + .getLiquidityProviderForMarket(token.address, weth.address) + .awaitTransactionSuccessAsync(); + return expect(tx).to.revertWith( + new ZeroExRevertErrors.LiquidityProvider.NoLiquidityProviderForMarketError(token.address, weth.address), + ); + }); + it('reverts if non-owner attempts to set an address', async () => { + const tx = feature + .setLiquidityProviderForMarket(randomAddress(), randomAddress(), randomAddress()) + .awaitTransactionSuccessAsync({ from: taker }); + return expect(tx).to.revertWith(new OwnableRevertErrors.OnlyOwnerError(taker, owner)); + }); }); - describe('Swap', () => { + blockchainTests.resets('Swap', () => { + let liquidityProvider: TestBridgeContract; + const ETH_TOKEN_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'; + before(async () => { + liquidityProvider = await TestBridgeContract.deployFrom0xArtifactAsync( + artifacts.TestBridge, + env.provider, + env.txDefaults, + artifacts, + token.address, + weth.address, + ); + await feature + .setLiquidityProviderForMarket(token.address, weth.address, liquidityProvider.address) + .awaitTransactionSuccessAsync(); + }); + it('Cannot execute a swap for a market without a liquidity provider set', async () => { + const [xAsset, yAsset] = [randomAddress(), randomAddress()]; + const tx = feature + .sellToLiquidityProvider( + xAsset, + yAsset, + constants.NULL_ADDRESS, + constants.ONE_ETHER, + constants.ZERO_AMOUNT, + ) + .awaitTransactionSuccessAsync({ from: taker }); + return expect(tx).to.revertWith( + new ZeroExRevertErrors.LiquidityProvider.NoLiquidityProviderForMarketError(xAsset, yAsset), + ); + }); + it('Successfully executes an ERC20-ERC20 swap', async () => { + const tx = await feature + .sellToLiquidityProvider( + weth.address, + token.address, + constants.NULL_ADDRESS, + constants.ONE_ETHER, + constants.ZERO_AMOUNT, + ) + .awaitTransactionSuccessAsync({ from: taker }); + verifyEventsFromLogs( + tx.logs, + [ + { + inputToken: token.address, + outputToken: weth.address, + inputTokenAmount: constants.ONE_ETHER, + outputTokenAmount: constants.ZERO_AMOUNT, + from: constants.NULL_ADDRESS, + to: taker, + }, + ], + IERC20BridgeEvents.ERC20BridgeTransfer, + ); + }); + it('Reverts if cannot fulfill the minimum buy amount', async () => { + const minBuyAmount = new BigNumber(1); + const tx = feature + .sellToLiquidityProvider( + weth.address, + token.address, + constants.NULL_ADDRESS, + constants.ONE_ETHER, + minBuyAmount, + ) + .awaitTransactionSuccessAsync({ from: taker }); + return expect(tx).to.revertWith( + new ZeroExRevertErrors.LiquidityProvider.LiquidityProviderIncompleteSellError( + liquidityProvider.address, + weth.address, + token.address, + constants.ONE_ETHER, + constants.ZERO_AMOUNT, + minBuyAmount, + ), + ); + }); + it('Successfully executes an ETH-ERC20 swap', async () => { + const tx = await feature + .sellToLiquidityProvider( + token.address, + ETH_TOKEN_ADDRESS, + constants.NULL_ADDRESS, + constants.ONE_ETHER, + constants.ZERO_AMOUNT, + ) + .awaitTransactionSuccessAsync({ from: taker, value: constants.ONE_ETHER }); + verifyEventsFromLogs( + tx.logs, + [ + { + inputToken: weth.address, + outputToken: token.address, + inputTokenAmount: constants.ONE_ETHER, + outputTokenAmount: constants.ZERO_AMOUNT, + from: constants.NULL_ADDRESS, + to: taker, + }, + ], + IERC20BridgeEvents.ERC20BridgeTransfer, + ); + }); + it('Successfully executes an ERC20-ETH swap', async () => { + const tx = await feature + .sellToLiquidityProvider( + ETH_TOKEN_ADDRESS, + token.address, + constants.NULL_ADDRESS, + constants.ONE_ETHER, + constants.ZERO_AMOUNT, + ) + .awaitTransactionSuccessAsync({ from: taker }); + verifyEventsFromLogs( + tx.logs, + [ + { + inputToken: token.address, + outputToken: weth.address, + inputTokenAmount: constants.ONE_ETHER, + outputTokenAmount: constants.ZERO_AMOUNT, + from: constants.NULL_ADDRESS, + to: zeroEx.address, + }, + ], + IERC20BridgeEvents.ERC20BridgeTransfer, + ); + }); }); }); diff --git a/contracts/zero-ex/test/wrappers.ts b/contracts/zero-ex/test/wrappers.ts index 1aa12ac0c7..76dac9c6b4 100644 --- a/contracts/zero-ex/test/wrappers.ts +++ b/contracts/zero-ex/test/wrappers.ts @@ -73,6 +73,7 @@ export * from '../test/generated-wrappers/ownable_feature'; export * from '../test/generated-wrappers/pay_taker_transformer'; export * from '../test/generated-wrappers/signature_validator_feature'; export * from '../test/generated-wrappers/simple_function_registry_feature'; +export * from '../test/generated-wrappers/test_bridge'; export * from '../test/generated-wrappers/test_call_target'; export * from '../test/generated-wrappers/test_delegate_caller'; export * from '../test/generated-wrappers/test_fill_quote_transformer_bridge'; diff --git a/contracts/zero-ex/tsconfig.json b/contracts/zero-ex/tsconfig.json index 0f0163243e..4cc0fb27af 100644 --- a/contracts/zero-ex/tsconfig.json +++ b/contracts/zero-ex/tsconfig.json @@ -97,6 +97,7 @@ "test/generated-artifacts/PayTakerTransformer.json", "test/generated-artifacts/SignatureValidatorFeature.json", "test/generated-artifacts/SimpleFunctionRegistryFeature.json", + "test/generated-artifacts/TestBridge.json", "test/generated-artifacts/TestCallTarget.json", "test/generated-artifacts/TestDelegateCaller.json", "test/generated-artifacts/TestFillQuoteTransformerBridge.json", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 52c2565aa3..74c518ddc4 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -54,4 +54,5 @@ export const ZeroExRevertErrors = { Wallet: require('./revert_errors/zero-ex/wallet_revert_errors'), MetaTransactions: require('./revert_errors/zero-ex/meta_transaction_revert_errors'), SignatureValidator: require('./revert_errors/zero-ex/signature_validator_revert_errors'), + LiquidityProvider: require('./revert_errors/zero-ex/liquidity_provider_revert_errors'), }; diff --git a/packages/utils/src/revert_errors/zero-ex/liquidity_provider_revert_errors.ts b/packages/utils/src/revert_errors/zero-ex/liquidity_provider_revert_errors.ts new file mode 100644 index 0000000000..5adafe0127 --- /dev/null +++ b/packages/utils/src/revert_errors/zero-ex/liquidity_provider_revert_errors.ts @@ -0,0 +1,47 @@ +import { RevertError } from '../../revert_error'; +import { Numberish } from '../../types'; + +// tslint:disable:max-classes-per-file +export class LiquidityProviderIncompleteSellError extends RevertError { + constructor( + providerAddress?: string, + makerToken?: string, + takerToken?: string, + sellAmount?: Numberish, + boughtAmount?: Numberish, + minBuyAmount?: Numberish, + ) { + super( + 'LiquidityProviderIncompleteSellError', + 'LiquidityProviderIncompleteSellError(address providerAddress, address makerToken, address takerToken, uint256 sellAmount, uint256 boughtAmount, uint256 minBuyAmount)', + { + providerAddress, + makerToken, + takerToken, + sellAmount, + boughtAmount, + minBuyAmount, + }, + ); + } +} + +export class NoLiquidityProviderForMarketError extends RevertError { + constructor(xAsset?: string, yAsset?: string) { + super( + 'NoLiquidityProviderForMarketError', + 'NoLiquidityProviderForMarketError(address xAsset, address yAsset)', + { + xAsset, + yAsset, + }, + ); + } +} + +const types = [LiquidityProviderIncompleteSellError, NoLiquidityProviderForMarketError]; + +// Register the types we've defined. +for (const type of types) { + RevertError.registerType(type); +}