Mooniswap LP (#143)
* `@0x/asset-swapper`: Fix compiler error on `ILiquidityProvider` call `@0x/protocol-utils`: Add VIP utils. * `@0x/asset-swapper`: Clean up curve VIP integration * `@0x/contracts-zero-ex`: Add `MooniswapLiquidityProvider`. `@0x/asset-swapper`: Add Mooniswap "vip" to EP quote consumer. * rebase and prettier * fix linter error * `@0x/contracts-zero-ex`: Add `MooniswapLiquidityProvider` tests. * review feedback * `@0x/contracts-zero-ex`: Emit `LiquidityProviderFill` events in LPs * `@0x/asset-swapper`: Fix compilation error * `@0x/asset-swapper`: Add EP gas overhead to Curve and Mooni LP bridge routes * `@0x/asset-swapper`: Remove consumer gas overhead for LP VIPs * `@0x/contracts-zero-ex`: Add more params to `LiquidityProviderFill` event * `@0x/contracts-zero-ex`: Address review comments. * `@0x/asset-swapper`: Update deployed Curve and Mooni LPs Co-authored-by: Lawrence Forman <me@merklejerk.com>
This commit is contained in:
@@ -1,4 +1,17 @@
|
||||
[
|
||||
{
|
||||
"version": "0.20.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add `MooniswapLiquidityProvider`",
|
||||
"pr": 143
|
||||
},
|
||||
{
|
||||
"note": "Emit `LiquidityProviderFill` event in `CurveLiquidityProvider`",
|
||||
"pr": 143
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.19.0",
|
||||
"changes": [
|
||||
|
||||
@@ -75,7 +75,8 @@ contract CurveLiquidityProvider is
|
||||
inputToken,
|
||||
outputToken,
|
||||
minBuyAmount,
|
||||
abi.decode(auxiliaryData, (CurveData))
|
||||
abi.decode(auxiliaryData, (CurveData)),
|
||||
recipient
|
||||
);
|
||||
// Every pool contract currently checks this but why not.
|
||||
require(boughtAmount >= minBuyAmount, "CurveLiquidityProvider/UNDERBOUGHT");
|
||||
@@ -109,7 +110,8 @@ contract CurveLiquidityProvider is
|
||||
LibERC20Transformer.ETH_TOKEN,
|
||||
outputToken,
|
||||
minBuyAmount,
|
||||
abi.decode(auxiliaryData, (CurveData))
|
||||
abi.decode(auxiliaryData, (CurveData)),
|
||||
recipient
|
||||
);
|
||||
// Every pool contract currently checks this but why not.
|
||||
require(boughtAmount >= minBuyAmount, "CurveLiquidityProvider/UNDERBOUGHT");
|
||||
@@ -141,7 +143,8 @@ contract CurveLiquidityProvider is
|
||||
inputToken,
|
||||
LibERC20Transformer.ETH_TOKEN,
|
||||
minBuyAmount,
|
||||
abi.decode(auxiliaryData, (CurveData))
|
||||
abi.decode(auxiliaryData, (CurveData)),
|
||||
recipient
|
||||
);
|
||||
// Every pool contract currently checks this but why not.
|
||||
require(boughtAmount >= minBuyAmount, "CurveLiquidityProvider/UNDERBOUGHT");
|
||||
@@ -169,7 +172,8 @@ contract CurveLiquidityProvider is
|
||||
IERC20TokenV06 inputToken,
|
||||
IERC20TokenV06 outputToken,
|
||||
uint256 minBuyAmount,
|
||||
CurveData memory data
|
||||
CurveData memory data,
|
||||
address recipient // Only used to log event.
|
||||
)
|
||||
private
|
||||
returns (uint256 boughtAmount)
|
||||
@@ -204,5 +208,16 @@ contract CurveLiquidityProvider is
|
||||
boughtAmount = LibERC20Transformer
|
||||
.getTokenBalanceOf(outputToken, address(this));
|
||||
}
|
||||
|
||||
emit LiquidityProviderFill(
|
||||
inputToken,
|
||||
outputToken,
|
||||
sellAmount,
|
||||
boughtAmount,
|
||||
bytes32("Curve"),
|
||||
address(data.curveAddress),
|
||||
msg.sender,
|
||||
recipient
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
|
||||
Copyright 2021 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/errors/LibRichErrorsV06.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
|
||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
|
||||
import "../transformers/LibERC20Transformer.sol";
|
||||
import "../vendor/ILiquidityProvider.sol";
|
||||
import "../vendor/IMooniswapPool.sol";
|
||||
|
||||
|
||||
contract MooniswapLiquidityProvider is
|
||||
ILiquidityProvider
|
||||
{
|
||||
using LibERC20TokenV06 for IERC20TokenV06;
|
||||
using LibSafeMathV06 for uint256;
|
||||
using LibRichErrorsV06 for bytes;
|
||||
|
||||
IEtherTokenV06 private immutable WETH;
|
||||
|
||||
constructor(IEtherTokenV06 weth) public {
|
||||
WETH = weth;
|
||||
}
|
||||
|
||||
/// @dev This contract must be payable because takers can transfer funds
|
||||
/// in prior to calling the swap function.
|
||||
receive() external payable {}
|
||||
|
||||
/// @dev Trades `inputToken` for `outputToken`. The amount of `inputToken`
|
||||
/// to sell must be transferred to the contract prior to calling this
|
||||
/// function to trigger the trade.
|
||||
/// @param inputToken The token being sold.
|
||||
/// @param outputToken The token being bought.
|
||||
/// @param recipient The recipient of the bought tokens.
|
||||
/// @param minBuyAmount The minimum acceptable amount of `outputToken` to buy.
|
||||
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
|
||||
/// @return boughtAmount The amount of `outputToken` bought.
|
||||
function sellTokenForToken(
|
||||
IERC20TokenV06 inputToken,
|
||||
IERC20TokenV06 outputToken,
|
||||
address recipient,
|
||||
uint256 minBuyAmount,
|
||||
bytes calldata auxiliaryData
|
||||
)
|
||||
external
|
||||
override
|
||||
returns (uint256 boughtAmount)
|
||||
{
|
||||
require(
|
||||
!LibERC20Transformer.isTokenETH(inputToken)
|
||||
&& !LibERC20Transformer.isTokenETH(outputToken)
|
||||
&& inputToken != outputToken,
|
||||
"MooniswapLiquidityProvider/INVALID_ARGS"
|
||||
);
|
||||
boughtAmount = _executeSwap(
|
||||
inputToken,
|
||||
outputToken,
|
||||
minBuyAmount,
|
||||
abi.decode(auxiliaryData, (IMooniswapPool)),
|
||||
recipient
|
||||
);
|
||||
outputToken.compatTransfer(recipient, boughtAmount);
|
||||
}
|
||||
|
||||
/// @dev Trades ETH for token. ETH must either be attached to this function
|
||||
/// call or sent to the contract prior to calling this function to
|
||||
/// trigger the trade.
|
||||
/// @param outputToken The token being bought.
|
||||
/// @param recipient The recipient of the bought tokens.
|
||||
/// @param minBuyAmount The minimum acceptable amount of `outputToken` to buy.
|
||||
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
|
||||
/// @return boughtAmount The amount of `outputToken` bought.
|
||||
function sellEthForToken(
|
||||
IERC20TokenV06 outputToken,
|
||||
address recipient,
|
||||
uint256 minBuyAmount,
|
||||
bytes calldata auxiliaryData
|
||||
)
|
||||
external
|
||||
payable
|
||||
override
|
||||
returns (uint256 boughtAmount)
|
||||
{
|
||||
require(
|
||||
!LibERC20Transformer.isTokenETH(outputToken),
|
||||
"MooniswapLiquidityProvider/INVALID_ARGS"
|
||||
);
|
||||
boughtAmount = _executeSwap(
|
||||
LibERC20Transformer.ETH_TOKEN,
|
||||
outputToken,
|
||||
minBuyAmount,
|
||||
abi.decode(auxiliaryData, (IMooniswapPool)),
|
||||
recipient
|
||||
);
|
||||
outputToken.compatTransfer(recipient, boughtAmount);
|
||||
}
|
||||
|
||||
/// @dev Trades token for ETH. The token must be sent to the contract prior
|
||||
/// to calling this function to trigger the trade.
|
||||
/// @param inputToken The token being sold.
|
||||
/// @param recipient The recipient of the bought tokens.
|
||||
/// @param minBuyAmount The minimum acceptable amount of ETH to buy.
|
||||
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
|
||||
/// @return boughtAmount The amount of ETH bought.
|
||||
function sellTokenForEth(
|
||||
IERC20TokenV06 inputToken,
|
||||
address payable recipient,
|
||||
uint256 minBuyAmount,
|
||||
bytes calldata auxiliaryData
|
||||
)
|
||||
external
|
||||
override
|
||||
returns (uint256 boughtAmount)
|
||||
{
|
||||
require(
|
||||
!LibERC20Transformer.isTokenETH(inputToken),
|
||||
"MooniswapLiquidityProvider/INVALID_ARGS"
|
||||
);
|
||||
boughtAmount = _executeSwap(
|
||||
inputToken,
|
||||
LibERC20Transformer.ETH_TOKEN,
|
||||
minBuyAmount,
|
||||
abi.decode(auxiliaryData, (IMooniswapPool)),
|
||||
recipient
|
||||
);
|
||||
recipient.call{value: boughtAmount}("");
|
||||
}
|
||||
|
||||
/// @dev Quotes the amount of `outputToken` that would be obtained by
|
||||
/// selling `sellAmount` of `inputToken`.
|
||||
function getSellQuote(
|
||||
IERC20TokenV06 /* inputToken */,
|
||||
IERC20TokenV06 /* outputToken */,
|
||||
uint256 /* sellAmount */
|
||||
)
|
||||
external
|
||||
view
|
||||
override
|
||||
returns (uint256)
|
||||
{
|
||||
revert("MooniswapLiquidityProvider/NOT_IMPLEMENTED");
|
||||
}
|
||||
|
||||
/// @dev Perform the swap against the curve pool. Handles any combination of
|
||||
/// tokens
|
||||
function _executeSwap(
|
||||
IERC20TokenV06 inputToken,
|
||||
IERC20TokenV06 outputToken,
|
||||
uint256 minBuyAmount,
|
||||
IMooniswapPool pool,
|
||||
address recipient // Only used to log event
|
||||
)
|
||||
private
|
||||
returns (uint256 boughtAmount)
|
||||
{
|
||||
uint256 sellAmount =
|
||||
LibERC20Transformer.getTokenBalanceOf(inputToken, address(this));
|
||||
uint256 ethValue = 0;
|
||||
if (inputToken == WETH) {
|
||||
// Selling WETH. Unwrap to ETH.
|
||||
require(!_isTokenEthLike(outputToken), 'MooniswapLiquidityProvider/ETH_TO_ETH');
|
||||
WETH.withdraw(sellAmount);
|
||||
ethValue = sellAmount;
|
||||
} else if (LibERC20Transformer.isTokenETH(inputToken)) {
|
||||
// Selling ETH directly.
|
||||
ethValue = sellAmount;
|
||||
require(!_isTokenEthLike(outputToken), 'MooniswapLiquidityProvider/ETH_TO_ETH');
|
||||
} else {
|
||||
// Selling a regular ERC20.
|
||||
require(inputToken != outputToken, 'MooniswapLiquidityProvider/SAME_TOKEN');
|
||||
inputToken.approveIfBelow(address(pool), sellAmount);
|
||||
}
|
||||
|
||||
boughtAmount = pool.swap{value: ethValue}(
|
||||
_isTokenEthLike(inputToken) ? IERC20TokenV06(0) : inputToken,
|
||||
_isTokenEthLike(outputToken) ? IERC20TokenV06(0) : outputToken,
|
||||
sellAmount,
|
||||
minBuyAmount,
|
||||
address(0)
|
||||
);
|
||||
|
||||
if (outputToken == WETH) {
|
||||
WETH.deposit{value: boughtAmount}();
|
||||
}
|
||||
|
||||
emit LiquidityProviderFill(
|
||||
inputToken,
|
||||
outputToken,
|
||||
sellAmount,
|
||||
boughtAmount,
|
||||
bytes32("Mooniswap"),
|
||||
address(pool),
|
||||
msg.sender,
|
||||
recipient
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Check if a token is ETH or WETH.
|
||||
function _isTokenEthLike(IERC20TokenV06 token)
|
||||
private
|
||||
view
|
||||
returns (bool isEthOrWeth)
|
||||
{
|
||||
return LibERC20Transformer.isTokenETH(token) || token == WETH;
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,28 @@ import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||
|
||||
interface ILiquidityProvider {
|
||||
|
||||
/// @dev An optional event an LP can emit for each fill against a source.
|
||||
/// @param inputToken The input token.
|
||||
/// @param outputToken The output token.
|
||||
/// @param inputTokenAmount How much input token was sold.
|
||||
/// @param outputTokenAmount How much output token was bought.
|
||||
/// @param sourceId A bytes32 encoded ascii source ID. E.g., `bytes32('Curve')`/
|
||||
/// @param sourceAddress An optional address associated with the source (e.g, a curve pool).
|
||||
/// @param sourceId A bytes32 encoded ascii source ID. E.g., `bytes32('Curve')`/
|
||||
/// @param sourceAddress An optional address associated with the source (e.g, a curve pool).
|
||||
/// @param sender The caller of the LP.
|
||||
/// @param recipient The recipient of the output tokens.
|
||||
event LiquidityProviderFill(
|
||||
IERC20TokenV06 inputToken,
|
||||
IERC20TokenV06 outputToken,
|
||||
uint256 inputTokenAmount,
|
||||
uint256 outputTokenAmount,
|
||||
bytes32 sourceId,
|
||||
address sourceAddress,
|
||||
address sender,
|
||||
address recipient
|
||||
);
|
||||
|
||||
/// @dev Trades `inputToken` for `outputToken`. The amount of `inputToken`
|
||||
/// to sell must be transferred to the contract prior to calling this
|
||||
/// function to trigger the trade.
|
||||
|
||||
41
contracts/zero-ex/contracts/src/vendor/IMooniswapPool.sol
vendored
Normal file
41
contracts/zero-ex/contracts/src/vendor/IMooniswapPool.sol
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/*
|
||||
|
||||
Copyright 2021 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/LibERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
|
||||
|
||||
/// @dev Moooniswap pool interface.
|
||||
interface IMooniswapPool {
|
||||
|
||||
function swap(
|
||||
IERC20TokenV06 sellToken,
|
||||
IERC20TokenV06 buyToken,
|
||||
uint256 sellAmount,
|
||||
uint256 minBoughtAmount,
|
||||
address referrer
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns (uint256 boughtAmount);
|
||||
}
|
||||
79
contracts/zero-ex/contracts/test/TestMooniswap.sol
Normal file
79
contracts/zero-ex/contracts/test/TestMooniswap.sol
Normal file
@@ -0,0 +1,79 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
|
||||
Copyright 2021 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 "./TestMintableERC20Token.sol";
|
||||
|
||||
contract TestMooniswap {
|
||||
|
||||
event MooniswapCalled(
|
||||
uint256 value,
|
||||
IERC20TokenV06 sellToken,
|
||||
IERC20TokenV06 buyToken,
|
||||
uint256 sellAmount,
|
||||
uint256 minBuyAmount,
|
||||
address referral
|
||||
);
|
||||
|
||||
uint256 public nextBuyAmount;
|
||||
|
||||
function setNextBoughtAmount(uint256 amt)
|
||||
external
|
||||
payable
|
||||
{
|
||||
nextBuyAmount = amt;
|
||||
}
|
||||
|
||||
function swap(
|
||||
IERC20TokenV06 sellToken,
|
||||
TestMintableERC20Token buyToken,
|
||||
uint256 sellAmount,
|
||||
uint256 minBuyAmount,
|
||||
address referral
|
||||
)
|
||||
external
|
||||
payable
|
||||
returns(uint256 boughtAmount)
|
||||
{
|
||||
emit MooniswapCalled(
|
||||
msg.value,
|
||||
sellToken,
|
||||
IERC20TokenV06(address(buyToken)),
|
||||
sellAmount,
|
||||
minBuyAmount,
|
||||
referral
|
||||
);
|
||||
boughtAmount = nextBuyAmount;
|
||||
nextBuyAmount = 0;
|
||||
require(boughtAmount >= minBuyAmount, 'UNDERBOUGHT');
|
||||
if (sellToken != IERC20TokenV06(0)) {
|
||||
sellToken.transferFrom(msg.sender, address(this), sellAmount);
|
||||
} else {
|
||||
require(sellAmount == msg.value, 'NOT_ENOUGH_ETH');
|
||||
}
|
||||
if (address(buyToken) == address(0)) {
|
||||
msg.sender.transfer(boughtAmount);
|
||||
} else {
|
||||
buyToken.mint(msg.sender, boughtAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@
|
||||
"config": {
|
||||
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITokenSpenderFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,TokenSpenderFeature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|BridgeSource|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|INativeOrdersFeature|IOwnableFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinShell|MixinSushiswap|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|NativeOrdersFeature|OwnableFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|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"
|
||||
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BootstrapFeature|BridgeAdapter|BridgeSource|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IAllowanceTarget|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|INativeOrdersFeature|IOwnableFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinShell|MixinSushiswap|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|MooniswapLiquidityProvider|NativeOrdersFeature|OwnableFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestMooniswap|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",
|
||||
|
||||
@@ -32,6 +32,7 @@ import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvi
|
||||
import * as ILiquidityProviderFeature from '../test/generated-artifacts/ILiquidityProviderFeature.json';
|
||||
import * as ILiquidityProviderSandbox from '../test/generated-artifacts/ILiquidityProviderSandbox.json';
|
||||
import * as IMetaTransactionsFeature from '../test/generated-artifacts/IMetaTransactionsFeature.json';
|
||||
import * as IMooniswapPool from '../test/generated-artifacts/IMooniswapPool.json';
|
||||
import * as INativeOrdersFeature from '../test/generated-artifacts/INativeOrdersFeature.json';
|
||||
import * as InitialMigration from '../test/generated-artifacts/InitialMigration.json';
|
||||
import * as IOwnableFeature from '../test/generated-artifacts/IOwnableFeature.json';
|
||||
@@ -88,6 +89,7 @@ import * as MixinSushiswap from '../test/generated-artifacts/MixinSushiswap.json
|
||||
import * as MixinUniswap from '../test/generated-artifacts/MixinUniswap.json';
|
||||
import * as MixinUniswapV2 from '../test/generated-artifacts/MixinUniswapV2.json';
|
||||
import * as MixinZeroExBridge from '../test/generated-artifacts/MixinZeroExBridge.json';
|
||||
import * as MooniswapLiquidityProvider from '../test/generated-artifacts/MooniswapLiquidityProvider.json';
|
||||
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';
|
||||
@@ -114,6 +116,7 @@ import * as TestMetaTransactionsTransformERC20Feature from '../test/generated-ar
|
||||
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 TestMooniswap from '../test/generated-artifacts/TestMooniswap.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';
|
||||
@@ -191,6 +194,7 @@ export const artifacts = {
|
||||
FixinReentrancyGuard: FixinReentrancyGuard as ContractArtifact,
|
||||
FixinTokenSpender: FixinTokenSpender as ContractArtifact,
|
||||
CurveLiquidityProvider: CurveLiquidityProvider as ContractArtifact,
|
||||
MooniswapLiquidityProvider: MooniswapLiquidityProvider as ContractArtifact,
|
||||
FullMigration: FullMigration as ContractArtifact,
|
||||
InitialMigration: InitialMigration as ContractArtifact,
|
||||
LibBootstrap: LibBootstrap as ContractArtifact,
|
||||
@@ -233,6 +237,7 @@ export const artifacts = {
|
||||
MixinUniswapV2: MixinUniswapV2 as ContractArtifact,
|
||||
MixinZeroExBridge: MixinZeroExBridge as ContractArtifact,
|
||||
ILiquidityProvider: ILiquidityProvider as ContractArtifact,
|
||||
IMooniswapPool: IMooniswapPool as ContractArtifact,
|
||||
IERC20Bridge: IERC20Bridge as ContractArtifact,
|
||||
IStaking: IStaking as ContractArtifact,
|
||||
ITestSimpleFunctionRegistryFeature: ITestSimpleFunctionRegistryFeature as ContractArtifact,
|
||||
@@ -256,6 +261,7 @@ export const artifacts = {
|
||||
TestMigrator: TestMigrator as ContractArtifact,
|
||||
TestMintTokenERC20Transformer: TestMintTokenERC20Transformer as ContractArtifact,
|
||||
TestMintableERC20Token: TestMintableERC20Token as ContractArtifact,
|
||||
TestMooniswap: TestMooniswap as ContractArtifact,
|
||||
TestNativeOrdersFeature: TestNativeOrdersFeature as ContractArtifact,
|
||||
TestPermissionlessTransformerDeployerSuicidal: TestPermissionlessTransformerDeployerSuicidal as ContractArtifact,
|
||||
TestPermissionlessTransformerDeployerTransformer: TestPermissionlessTransformerDeployerTransformer as ContractArtifact,
|
||||
|
||||
@@ -291,4 +291,32 @@ blockchainTests.resets('CurveLiquidityProvider feature', env => {
|
||||
const call = lp.sellEthForToken(ETH_TOKEN_ADDRESS, RECIPIENT, BUY_AMOUNT, encodeCurveData());
|
||||
return expect(call.callAsync()).to.revertWith('CurveLiquidityProvider/INVALID_ARGS');
|
||||
});
|
||||
|
||||
it('emits a LiquidityProviderFill event', async () => {
|
||||
await fundProviderContractAsync(SELL_TOKEN_COIN_IDX);
|
||||
const call = lp.sellTokenForToken(
|
||||
sellToken.address,
|
||||
buyToken.address,
|
||||
RECIPIENT,
|
||||
BUY_AMOUNT,
|
||||
encodeCurveData(),
|
||||
);
|
||||
const { logs } = await call.awaitTransactionSuccessAsync();
|
||||
verifyEventsFromLogs(
|
||||
logs,
|
||||
[
|
||||
{
|
||||
inputToken: sellToken.address,
|
||||
outputToken: buyToken.address,
|
||||
inputTokenAmount: SELL_AMOUNT,
|
||||
outputTokenAmount: BUY_AMOUNT,
|
||||
sourceId: hexUtils.rightPad(hexUtils.toHex(Buffer.from('Curve'))),
|
||||
sourceAddress: testCurve.address,
|
||||
sender: taker,
|
||||
recipient: RECIPIENT,
|
||||
},
|
||||
],
|
||||
'LiquidityProviderFill',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
289
contracts/zero-ex/test/liqudity-providers/mooniswap_test.ts
Normal file
289
contracts/zero-ex/test/liqudity-providers/mooniswap_test.ts
Normal file
@@ -0,0 +1,289 @@
|
||||
import { blockchainTests, constants, expect, getRandomInteger, verifyEventsFromLogs } from '@0x/contracts-test-utils';
|
||||
import { BigNumber, hexUtils } from '@0x/utils';
|
||||
|
||||
import { artifacts } from '../artifacts';
|
||||
import {
|
||||
MooniswapLiquidityProviderContract,
|
||||
TestMintableERC20TokenContract,
|
||||
TestMooniswapContract,
|
||||
TestWethContract,
|
||||
} from '../wrappers';
|
||||
|
||||
blockchainTests.resets('MooniswapLiquidityProvider feature', env => {
|
||||
let lp: MooniswapLiquidityProviderContract;
|
||||
let sellToken: TestMintableERC20TokenContract;
|
||||
let buyToken: TestMintableERC20TokenContract;
|
||||
let weth: TestWethContract;
|
||||
let testMooniswap: TestMooniswapContract;
|
||||
let owner: string;
|
||||
let taker: string;
|
||||
let mooniswapData: string;
|
||||
const RECIPIENT = hexUtils.random(20);
|
||||
const ETH_TOKEN_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
|
||||
const { NULL_ADDRESS, ZERO_AMOUNT } = constants;
|
||||
const SELL_AMOUNT = getRandomInteger('1e18', '10e18');
|
||||
const BUY_AMOUNT = getRandomInteger('1e18', '10e18');
|
||||
|
||||
before(async () => {
|
||||
[owner, taker] = await env.getAccountAddressesAsync();
|
||||
[sellToken, buyToken] = await Promise.all(
|
||||
new Array(2)
|
||||
.fill(0)
|
||||
.map(async () =>
|
||||
TestMintableERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestMintableERC20Token,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
),
|
||||
),
|
||||
);
|
||||
weth = await TestWethContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestWeth,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
testMooniswap = await TestMooniswapContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestMooniswap,
|
||||
env.provider,
|
||||
{ ...env.txDefaults },
|
||||
artifacts,
|
||||
);
|
||||
lp = await MooniswapLiquidityProviderContract.deployFrom0xArtifactAsync(
|
||||
artifacts.MooniswapLiquidityProvider,
|
||||
env.provider,
|
||||
{ ...env.txDefaults, from: taker },
|
||||
artifacts,
|
||||
weth.address,
|
||||
);
|
||||
mooniswapData = hexUtils.leftPad(testMooniswap.address);
|
||||
});
|
||||
|
||||
async function prepareNextSwapFundsAsync(
|
||||
sellTokenAddress: string,
|
||||
sellAmount: BigNumber,
|
||||
buyTokenAddress: string,
|
||||
buyAmount: BigNumber,
|
||||
): Promise<void> {
|
||||
if (sellTokenAddress.toLowerCase() === weth.address.toLowerCase()) {
|
||||
await weth.deposit().awaitTransactionSuccessAsync({
|
||||
from: taker,
|
||||
value: sellAmount,
|
||||
});
|
||||
await weth.transfer(lp.address, sellAmount).awaitTransactionSuccessAsync({ from: taker });
|
||||
} else if (sellTokenAddress.toLowerCase() === sellToken.address.toLowerCase()) {
|
||||
await sellToken.mint(lp.address, sellAmount).awaitTransactionSuccessAsync();
|
||||
} else {
|
||||
await await env.web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await env.web3Wrapper.sendTransactionAsync({
|
||||
to: lp.address,
|
||||
from: taker,
|
||||
value: sellAmount,
|
||||
}),
|
||||
);
|
||||
}
|
||||
await testMooniswap.setNextBoughtAmount(buyAmount).awaitTransactionSuccessAsync({
|
||||
value: buyTokenAddress.toLowerCase() === ETH_TOKEN_ADDRESS.toLowerCase() ? buyAmount : ZERO_AMOUNT,
|
||||
});
|
||||
}
|
||||
|
||||
it('can swap ERC20->ERC20', async () => {
|
||||
await prepareNextSwapFundsAsync(sellToken.address, SELL_AMOUNT, buyToken.address, BUY_AMOUNT);
|
||||
const call = lp.sellTokenForToken(sellToken.address, buyToken.address, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
const boughtAmount = await call.callAsync();
|
||||
const { logs } = await call.awaitTransactionSuccessAsync();
|
||||
expect(boughtAmount).to.bignumber.eq(BUY_AMOUNT);
|
||||
expect(await buyToken.balanceOf(RECIPIENT).callAsync()).to.bignumber.eq(BUY_AMOUNT);
|
||||
verifyEventsFromLogs(
|
||||
logs,
|
||||
[
|
||||
{
|
||||
value: ZERO_AMOUNT,
|
||||
sellToken: sellToken.address,
|
||||
buyToken: buyToken.address,
|
||||
sellAmount: SELL_AMOUNT,
|
||||
minBuyAmount: BUY_AMOUNT,
|
||||
referral: NULL_ADDRESS,
|
||||
},
|
||||
],
|
||||
'MooniswapCalled',
|
||||
);
|
||||
});
|
||||
|
||||
it('can swap ERC20->ETH', async () => {
|
||||
await prepareNextSwapFundsAsync(sellToken.address, SELL_AMOUNT, ETH_TOKEN_ADDRESS, BUY_AMOUNT);
|
||||
const call = lp.sellTokenForEth(sellToken.address, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
const boughtAmount = await call.callAsync();
|
||||
const { logs } = await call.awaitTransactionSuccessAsync();
|
||||
expect(boughtAmount).to.bignumber.eq(BUY_AMOUNT);
|
||||
expect(await env.web3Wrapper.getBalanceInWeiAsync(RECIPIENT)).to.bignumber.eq(BUY_AMOUNT);
|
||||
verifyEventsFromLogs(
|
||||
logs,
|
||||
[
|
||||
{
|
||||
value: ZERO_AMOUNT,
|
||||
sellToken: sellToken.address,
|
||||
buyToken: NULL_ADDRESS,
|
||||
sellAmount: SELL_AMOUNT,
|
||||
minBuyAmount: BUY_AMOUNT,
|
||||
referral: NULL_ADDRESS,
|
||||
},
|
||||
],
|
||||
'MooniswapCalled',
|
||||
);
|
||||
});
|
||||
|
||||
it('can swap ETH->ERC20', async () => {
|
||||
await prepareNextSwapFundsAsync(ETH_TOKEN_ADDRESS, SELL_AMOUNT, buyToken.address, BUY_AMOUNT);
|
||||
const call = lp.sellEthForToken(buyToken.address, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
const boughtAmount = await call.callAsync();
|
||||
const { logs } = await call.awaitTransactionSuccessAsync();
|
||||
expect(boughtAmount).to.bignumber.eq(BUY_AMOUNT);
|
||||
expect(await buyToken.balanceOf(RECIPIENT).callAsync()).to.bignumber.eq(BUY_AMOUNT);
|
||||
verifyEventsFromLogs(
|
||||
logs,
|
||||
[
|
||||
{
|
||||
value: SELL_AMOUNT,
|
||||
sellToken: NULL_ADDRESS,
|
||||
buyToken: buyToken.address,
|
||||
sellAmount: SELL_AMOUNT,
|
||||
minBuyAmount: BUY_AMOUNT,
|
||||
referral: NULL_ADDRESS,
|
||||
},
|
||||
],
|
||||
'MooniswapCalled',
|
||||
);
|
||||
});
|
||||
|
||||
it('can swap ETH->ERC20 with attached ETH', async () => {
|
||||
await testMooniswap.setNextBoughtAmount(BUY_AMOUNT).awaitTransactionSuccessAsync();
|
||||
const call = lp.sellEthForToken(buyToken.address, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
const boughtAmount = await call.callAsync({ value: SELL_AMOUNT });
|
||||
const { logs } = await call.awaitTransactionSuccessAsync({ value: SELL_AMOUNT });
|
||||
expect(boughtAmount).to.bignumber.eq(BUY_AMOUNT);
|
||||
expect(await buyToken.balanceOf(RECIPIENT).callAsync()).to.bignumber.eq(BUY_AMOUNT);
|
||||
verifyEventsFromLogs(
|
||||
logs,
|
||||
[
|
||||
{
|
||||
value: SELL_AMOUNT,
|
||||
sellToken: NULL_ADDRESS,
|
||||
buyToken: buyToken.address,
|
||||
sellAmount: SELL_AMOUNT,
|
||||
minBuyAmount: BUY_AMOUNT,
|
||||
referral: NULL_ADDRESS,
|
||||
},
|
||||
],
|
||||
'MooniswapCalled',
|
||||
);
|
||||
});
|
||||
|
||||
it('can swap ERC20->WETH', async () => {
|
||||
await prepareNextSwapFundsAsync(
|
||||
sellToken.address,
|
||||
SELL_AMOUNT,
|
||||
ETH_TOKEN_ADDRESS, // Mooni contract holds ETH.
|
||||
BUY_AMOUNT,
|
||||
);
|
||||
const call = lp.sellTokenForToken(sellToken.address, weth.address, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
const boughtAmount = await call.callAsync();
|
||||
const { logs } = await call.awaitTransactionSuccessAsync();
|
||||
expect(boughtAmount).to.bignumber.eq(BUY_AMOUNT);
|
||||
expect(await sellToken.balanceOf(testMooniswap.address).callAsync()).to.bignumber.eq(SELL_AMOUNT);
|
||||
expect(await weth.balanceOf(RECIPIENT).callAsync()).to.bignumber.eq(BUY_AMOUNT);
|
||||
verifyEventsFromLogs(
|
||||
logs,
|
||||
[
|
||||
{
|
||||
value: ZERO_AMOUNT,
|
||||
sellToken: sellToken.address,
|
||||
buyToken: NULL_ADDRESS,
|
||||
sellAmount: SELL_AMOUNT,
|
||||
minBuyAmount: BUY_AMOUNT,
|
||||
referral: NULL_ADDRESS,
|
||||
},
|
||||
],
|
||||
'MooniswapCalled',
|
||||
);
|
||||
});
|
||||
|
||||
it('can swap WETH->ERC20', async () => {
|
||||
await prepareNextSwapFundsAsync(weth.address, SELL_AMOUNT, buyToken.address, BUY_AMOUNT);
|
||||
const call = lp.sellTokenForToken(weth.address, buyToken.address, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
const boughtAmount = await call.callAsync();
|
||||
const { logs } = await call.awaitTransactionSuccessAsync();
|
||||
expect(boughtAmount).to.bignumber.eq(BUY_AMOUNT);
|
||||
expect(await env.web3Wrapper.getBalanceInWeiAsync(testMooniswap.address)).to.bignumber.eq(SELL_AMOUNT);
|
||||
expect(await buyToken.balanceOf(RECIPIENT).callAsync()).to.bignumber.eq(BUY_AMOUNT);
|
||||
verifyEventsFromLogs(
|
||||
logs,
|
||||
[
|
||||
{
|
||||
value: SELL_AMOUNT,
|
||||
sellToken: NULL_ADDRESS,
|
||||
buyToken: buyToken.address,
|
||||
sellAmount: SELL_AMOUNT,
|
||||
minBuyAmount: BUY_AMOUNT,
|
||||
referral: NULL_ADDRESS,
|
||||
},
|
||||
],
|
||||
'MooniswapCalled',
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if pool reverts', async () => {
|
||||
await prepareNextSwapFundsAsync(sellToken.address, SELL_AMOUNT, buyToken.address, BUY_AMOUNT);
|
||||
await testMooniswap.setNextBoughtAmount(BUY_AMOUNT.minus(1)).awaitTransactionSuccessAsync();
|
||||
const call = lp.sellTokenForToken(sellToken.address, buyToken.address, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
return expect(call.callAsync()).to.revertWith('UNDERBOUGHT');
|
||||
});
|
||||
|
||||
it('reverts if ERC20->ERC20 is the same token', async () => {
|
||||
const call = lp.sellTokenForToken(sellToken.address, sellToken.address, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
return expect(call.callAsync()).to.revertWith('MooniswapLiquidityProvider/INVALID_ARGS');
|
||||
});
|
||||
|
||||
it('reverts if ERC20->ERC20 receives an ETH input token', async () => {
|
||||
const call = lp.sellTokenForToken(ETH_TOKEN_ADDRESS, buyToken.address, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
return expect(call.callAsync()).to.revertWith('MooniswapLiquidityProvider/INVALID_ARGS');
|
||||
});
|
||||
|
||||
it('reverts if ERC20->ERC20 receives an ETH output token', async () => {
|
||||
const call = lp.sellTokenForToken(sellToken.address, ETH_TOKEN_ADDRESS, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
return expect(call.callAsync()).to.revertWith('MooniswapLiquidityProvider/INVALID_ARGS');
|
||||
});
|
||||
|
||||
it('reverts if ERC20->ETH receives an ETH input token', async () => {
|
||||
const call = lp.sellTokenForEth(ETH_TOKEN_ADDRESS, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
return expect(call.callAsync()).to.revertWith('MooniswapLiquidityProvider/INVALID_ARGS');
|
||||
});
|
||||
|
||||
it('reverts if ETH->ERC20 receives an ETH output token', async () => {
|
||||
const call = lp.sellEthForToken(ETH_TOKEN_ADDRESS, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
return expect(call.callAsync()).to.revertWith('MooniswapLiquidityProvider/INVALID_ARGS');
|
||||
});
|
||||
|
||||
it('emits a LiquidityProviderFill event', async () => {
|
||||
await prepareNextSwapFundsAsync(sellToken.address, SELL_AMOUNT, buyToken.address, BUY_AMOUNT);
|
||||
const call = lp.sellTokenForToken(sellToken.address, buyToken.address, RECIPIENT, BUY_AMOUNT, mooniswapData);
|
||||
const { logs } = await call.awaitTransactionSuccessAsync();
|
||||
verifyEventsFromLogs(
|
||||
logs,
|
||||
[
|
||||
{
|
||||
inputToken: sellToken.address,
|
||||
outputToken: buyToken.address,
|
||||
inputTokenAmount: SELL_AMOUNT,
|
||||
outputTokenAmount: BUY_AMOUNT,
|
||||
sourceId: hexUtils.rightPad(hexUtils.toHex(Buffer.from('Mooniswap'))),
|
||||
sourceAddress: testMooniswap.address,
|
||||
sender: taker,
|
||||
recipient: RECIPIENT,
|
||||
},
|
||||
],
|
||||
'LiquidityProviderFill',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -30,6 +30,7 @@ export * from '../test/generated-wrappers/i_liquidity_provider';
|
||||
export * from '../test/generated-wrappers/i_liquidity_provider_feature';
|
||||
export * from '../test/generated-wrappers/i_liquidity_provider_sandbox';
|
||||
export * from '../test/generated-wrappers/i_meta_transactions_feature';
|
||||
export * from '../test/generated-wrappers/i_mooniswap_pool';
|
||||
export * from '../test/generated-wrappers/i_native_orders_feature';
|
||||
export * from '../test/generated-wrappers/i_ownable_feature';
|
||||
export * from '../test/generated-wrappers/i_simple_function_registry_feature';
|
||||
@@ -86,6 +87,7 @@ export * from '../test/generated-wrappers/mixin_sushiswap';
|
||||
export * from '../test/generated-wrappers/mixin_uniswap';
|
||||
export * from '../test/generated-wrappers/mixin_uniswap_v2';
|
||||
export * from '../test/generated-wrappers/mixin_zero_ex_bridge';
|
||||
export * from '../test/generated-wrappers/mooniswap_liquidity_provider';
|
||||
export * from '../test/generated-wrappers/native_orders_feature';
|
||||
export * from '../test/generated-wrappers/ownable_feature';
|
||||
export * from '../test/generated-wrappers/pay_taker_transformer';
|
||||
@@ -112,6 +114,7 @@ export * from '../test/generated-wrappers/test_meta_transactions_transform_erc20
|
||||
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_mooniswap';
|
||||
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';
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"test/generated-artifacts/ILiquidityProviderFeature.json",
|
||||
"test/generated-artifacts/ILiquidityProviderSandbox.json",
|
||||
"test/generated-artifacts/IMetaTransactionsFeature.json",
|
||||
"test/generated-artifacts/IMooniswapPool.json",
|
||||
"test/generated-artifacts/INativeOrdersFeature.json",
|
||||
"test/generated-artifacts/IOwnableFeature.json",
|
||||
"test/generated-artifacts/ISimpleFunctionRegistryFeature.json",
|
||||
@@ -116,6 +117,7 @@
|
||||
"test/generated-artifacts/MixinUniswap.json",
|
||||
"test/generated-artifacts/MixinUniswapV2.json",
|
||||
"test/generated-artifacts/MixinZeroExBridge.json",
|
||||
"test/generated-artifacts/MooniswapLiquidityProvider.json",
|
||||
"test/generated-artifacts/NativeOrdersFeature.json",
|
||||
"test/generated-artifacts/OwnableFeature.json",
|
||||
"test/generated-artifacts/PayTakerTransformer.json",
|
||||
@@ -142,6 +144,7 @@
|
||||
"test/generated-artifacts/TestMigrator.json",
|
||||
"test/generated-artifacts/TestMintTokenERC20Transformer.json",
|
||||
"test/generated-artifacts/TestMintableERC20Token.json",
|
||||
"test/generated-artifacts/TestMooniswap.json",
|
||||
"test/generated-artifacts/TestNativeOrdersFeature.json",
|
||||
"test/generated-artifacts/TestPermissionlessTransformerDeployerSuicidal.json",
|
||||
"test/generated-artifacts/TestPermissionlessTransformerDeployerTransformer.json",
|
||||
|
||||
Reference in New Issue
Block a user