add tests for LiquidityProviderFeature
This commit is contained in:
parent
c6d738ed0c
commit
1c15ecacb0
@ -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,
|
||||
|
69
contracts/zero-ex/contracts/test/TestBridge.sol
Normal file
69
contracts/zero-ex/contracts/test/TestBridge.sol
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
);
|
||||
});
|
||||
describe('Swap', () => {
|
||||
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));
|
||||
});
|
||||
});
|
||||
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,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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';
|
||||
|
@ -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",
|
||||
|
@ -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'),
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user