Add WooFI support (#513)

* Add WooFI interface for sampling

* WooFi Sampler

* Add mixin

* Update bridge adapters

* fix some bugs

* update transformer_utils

* Add BSC support

* yarn prettier

* Capitalize WOOFI in bridge adapters

* Put rebateAddress in a constant, fixed some other stylistic errors

* bug fixes

* Updated CHANGELOGS & MD docs

* Publish

 - @0x/contracts-erc20@3.3.33
 - @0x/contracts-test-utils@5.4.24
 - @0x/contracts-treasury@1.4.16
 - @0x/contracts-utils@4.8.14
 - @0x/contracts-zero-ex@0.36.0
 - @0x/asset-swapper@16.64.0
 - @0x/contract-addresses@6.17.0
 - @0x/contract-wrappers@13.20.5
 - @0x/protocol-utils@11.16.0

* Update reference.mdx (#531)

Align with `DEFAULT_QUOTE_SLIPPAGE_PERCENTAGE` value from c74e31c219/src/constants.ts (L26)

* code cleanup

* remove deusdc curve pool from this pr

* Refactor PoolsCache (part 1) [TKR-500] (#525)

* Make _refreshPoolCacheIfRequiredAsync type-safe and remove Promise.all

* Factor out PoolsCache key logic into a function

* Use Map instead of object in PoolsCache and increase the default timeout

* Clean up PoolsCache and simplify its public interface

* Refactor PoolsCache (part 2) [TKR-500]  (#526)

* Introduce NoOpPoolsCache and use it in unsupported chains for BeethovenX

* Use `NoOpPoolsCache` for `CreamPoolsCache` and `BalancerPoolsCache` on unsupported chains

* Remove `getBidAskLiquidityForMakerTakerAssetPairAsync` (#528)

* Add transfer approval for quote token for multi-hops and fix buy sampler typo

* Use 0x gas api instead of eth gas station api [TKR-502] (#532)

* Use 0x gas api instead of eth gas station api

* Add integration test for `ProtocolFeeUtils`

* Update CHANGELOG.json

* Add polygon, fantom, avalanche support

* yarn prettier

* Updated CHANGELOGS & MD docs

* Publish

 - @0x/asset-swapper@16.65.0

* Remove references to `custom-no-magic-numbers` ts lint rule [TKR-484] (#533)

* Remove references to `custom-no-magic-numbers ts` lint rule

* Run prettier

* resolve Kyu's comments

* remove fqt change

* Add WooFI interface for sampling

* WooFi Sampler

* Add mixin

* Update bridge adapters

* fix some bugs

* update transformer_utils

* Add BSC support

* yarn prettier

* Capitalize WOOFI in bridge adapters

* Put rebateAddress in a constant, fixed some other stylistic errors

* bug fixes

* code cleanup

* remove deusdc curve pool from this pr

* Add transfer approval for quote token for multi-hops and fix buy sampler typo

* Add polygon, fantom, avalanche support

* yarn prettier

* resolve Kyu's comments

* remove fqt change

* merge types.ts

* WOOFi -> WOOFI

* fix lerna run lint

* Changelog

* nit changes

Co-authored-by: Github Actions <github-actions@github.com>
Co-authored-by: Pavel <51318041+pavel-bc@users.noreply.github.com>
Co-authored-by: Kyu <kyuhyun217@gmail.com>
This commit is contained in:
eobbad 2022-08-03 15:54:09 -04:00 committed by GitHub
parent d3d4a08f91
commit c12a10b96e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 421 additions and 5 deletions

View File

@ -30,6 +30,7 @@ import "./mixins/MixinAaveV2.sol";
import "./mixins/MixinNerve.sol"; import "./mixins/MixinNerve.sol";
import "./mixins/MixinPlatypus.sol"; import "./mixins/MixinPlatypus.sol";
import "./mixins/MixinUniswapV2.sol"; import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinWOOFi.sol";
import "./mixins/MixinZeroExBridge.sol"; import "./mixins/MixinZeroExBridge.sol";
contract AvalancheBridgeAdapter is contract AvalancheBridgeAdapter is
@ -42,6 +43,7 @@ contract AvalancheBridgeAdapter is
MixinNerve, MixinNerve,
MixinPlatypus, MixinPlatypus,
MixinUniswapV2, MixinUniswapV2,
MixinWOOFi,
MixinZeroExBridge MixinZeroExBridge
{ {
constructor(IEtherTokenV06 weth) constructor(IEtherTokenV06 weth)
@ -120,6 +122,14 @@ contract AvalancheBridgeAdapter is
sellAmount, sellAmount,
order.bridgeData order.bridgeData
); );
} else if (protocolId == BridgeProtocols.WOOFI) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeWOOFi(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) { } else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); } if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge( boughtAmount = _tradeZeroExBridge(

View File

@ -29,6 +29,7 @@ import "./mixins/MixinKyberDmm.sol";
import "./mixins/MixinMooniswap.sol"; import "./mixins/MixinMooniswap.sol";
import "./mixins/MixinNerve.sol"; import "./mixins/MixinNerve.sol";
import "./mixins/MixinUniswapV2.sol"; import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinWOOFi.sol";
import "./mixins/MixinZeroExBridge.sol"; import "./mixins/MixinZeroExBridge.sol";
contract BSCBridgeAdapter is contract BSCBridgeAdapter is
@ -40,6 +41,7 @@ contract BSCBridgeAdapter is
MixinMooniswap, MixinMooniswap,
MixinNerve, MixinNerve,
MixinUniswapV2, MixinUniswapV2,
MixinWOOFi,
MixinZeroExBridge MixinZeroExBridge
{ {
constructor(IEtherTokenV06 weth) constructor(IEtherTokenV06 weth)
@ -111,6 +113,14 @@ contract BSCBridgeAdapter is
sellAmount, sellAmount,
order.bridgeData order.bridgeData
); );
} else if (protocolId == BridgeProtocols.WOOFI) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeWOOFi(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) { } else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); } if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge( boughtAmount = _tradeZeroExBridge(

View File

@ -58,4 +58,5 @@ library BridgeProtocols {
uint128 internal constant BANCORV3 = 28; uint128 internal constant BANCORV3 = 28;
uint128 internal constant VELODROME = 29; uint128 internal constant VELODROME = 29;
uint128 internal constant SYNTHETIX = 30; uint128 internal constant SYNTHETIX = 30;
uint128 internal constant WOOFI = 31;
} }

View File

@ -28,6 +28,7 @@ import "./mixins/MixinCurve.sol";
import "./mixins/MixinCurveV2.sol"; import "./mixins/MixinCurveV2.sol";
import "./mixins/MixinNerve.sol"; import "./mixins/MixinNerve.sol";
import "./mixins/MixinUniswapV2.sol"; import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinWOOFi.sol";
import "./mixins/MixinZeroExBridge.sol"; import "./mixins/MixinZeroExBridge.sol";
contract FantomBridgeAdapter is contract FantomBridgeAdapter is
@ -38,6 +39,7 @@ contract FantomBridgeAdapter is
MixinCurveV2, MixinCurveV2,
MixinNerve, MixinNerve,
MixinUniswapV2, MixinUniswapV2,
MixinWOOFi,
MixinZeroExBridge MixinZeroExBridge
{ {
constructor(IEtherTokenV06 weth) constructor(IEtherTokenV06 weth)
@ -103,6 +105,14 @@ contract FantomBridgeAdapter is
sellAmount, sellAmount,
order.bridgeData order.bridgeData
); );
} else if (protocolId == BridgeProtocols.WOOFI) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeWOOFi(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) { } else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); } if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge( boughtAmount = _tradeZeroExBridge(

View File

@ -34,6 +34,7 @@ import "./mixins/MixinMStable.sol";
import "./mixins/MixinNerve.sol"; import "./mixins/MixinNerve.sol";
import "./mixins/MixinUniswapV2.sol"; import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinUniswapV3.sol"; import "./mixins/MixinUniswapV3.sol";
import "./mixins/MixinWOOFi.sol";
import "./mixins/MixinZeroExBridge.sol"; import "./mixins/MixinZeroExBridge.sol";
contract PolygonBridgeAdapter is contract PolygonBridgeAdapter is
@ -50,6 +51,7 @@ contract PolygonBridgeAdapter is
MixinNerve, MixinNerve,
MixinUniswapV2, MixinUniswapV2,
MixinUniswapV3, MixinUniswapV3,
MixinWOOFi,
MixinZeroExBridge MixinZeroExBridge
{ {
constructor(IEtherTokenV06 weth) constructor(IEtherTokenV06 weth)
@ -157,6 +159,14 @@ contract PolygonBridgeAdapter is
sellAmount, sellAmount,
order.bridgeData order.bridgeData
); );
} else if (protocolId == BridgeProtocols.WOOFI) {
if (dryRun) { return (0, true); }
boughtAmount = _tradeWOOFi(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.UNKNOWN) { } else if (protocolId == BridgeProtocols.UNKNOWN) {
if (dryRun) { return (0, true); } if (dryRun) { return (0, true); }
boughtAmount = _tradeZeroExBridge( boughtAmount = _tradeZeroExBridge(

View File

@ -0,0 +1,136 @@
// SPDX-License-Identifier: Apache-2.0
/*
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;
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";
import "../IBridgeAdapter.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
/// @dev WooFI pool interface.
interface IWooPP {
function quoteToken() external view returns (address);
function sellBase(
address baseToken,
uint256 baseAmount,
uint256 minQuoteAmount,
address to,
address rebateTo
) external returns (uint256 quoteAmount);
function sellQuote(
address baseToken,
uint256 quoteAmount,
uint256 minBaseAmount,
address to,
address rebateTo
) external returns (uint256 baseAmount);
/// @dev Query the amount for selling the base token amount.
/// @param baseToken the base token to sell
/// @param baseAmount the amount to sell
/// @return quoteAmount the swapped quote amount
function querySellBase(
address baseToken,
uint256 baseAmount
) external view returns (uint256 quoteAmount);
}
contract MixinWOOFi{
using LibERC20TokenV06 for IERC20TokenV06;
using LibERC20TokenV06 for IEtherTokenV06;
using LibSafeMathV06 for uint256;
address constant rebateAddress = 0xBfdcBB4C05843163F491C24f9c0019c510786304;
// /// @dev Swaps an exact amount of input tokens for as many output tokens as possible.
// /// @param _amountIn Amount of input tokens to send
// /// @param _minAmountOut The minimum amount of output tokens that must be received for the transaction not to revert.
// /// @param _tokenIn Input token
// /// @param _tokenOut Output token
// /// @param _to recipient of tokens
// /// @param pool WOOFi pool where the swap will happen
function _tradeWOOFi(
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
public
returns (uint256 boughtAmount)
{
(IWooPP _pool) = abi.decode(bridgeData, (IWooPP));
uint256 beforeBalance = buyToken.balanceOf(address(this));
sellToken.approveIfBelow(address(_pool), sellAmount);
_swap(
sellAmount,
address(sellToken),
address(buyToken),
_pool
);
boughtAmount = buyToken.balanceOf(address(this)).safeSub(beforeBalance);
}
function _swap(
uint _amountIn,
address _tokenIn,
address _tokenOut,
IWooPP pool
) internal {
address quoteToken = pool.quoteToken();
if (_tokenIn == quoteToken) {
pool.sellQuote(
_tokenOut,
_amountIn,
1,
address(this),
rebateAddress
);
} else if (_tokenOut == quoteToken) {
pool.sellBase(
_tokenIn,
_amountIn,
1,
address(this),
rebateAddress
);
} else {
uint256 quoteAmount = pool.sellBase(
_tokenIn,
_amountIn,
0,
address(this),
rebateAddress
);
IERC20TokenV06(pool.quoteToken()).approveIfBelow(address(pool), quoteAmount);
pool.sellQuote(
_tokenOut,
quoteAmount,
1,
address(this),
rebateAddress
);
}
}
}

View File

@ -43,7 +43,7 @@
"config": { "config": {
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature,OtcOrdersFeature,IOtcOrdersFeature,AvalancheBridgeAdapter,BSCBridgeAdapter,CeloBridgeAdapter,EthereumBridgeAdapter,FantomBridgeAdapter,OptimismBridgeAdapter,PolygonBridgeAdapter", "publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature,OtcOrdersFeature,IOtcOrdersFeature,AvalancheBridgeAdapter,BSCBridgeAdapter,CeloBridgeAdapter,EthereumBridgeAdapter,FantomBridgeAdapter,OptimismBridgeAdapter,PolygonBridgeAdapter",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(AbstractBridgeAdapter|AffiliateFeeTransformer|AvalancheBridgeAdapter|BSCBridgeAdapter|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeProtocols|CeloBridgeAdapter|CurveLiquidityProvider|ERC1155OrdersFeature|ERC165Feature|ERC721OrdersFeature|EthereumBridgeAdapter|FantomBridgeAdapter|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinERC1155Spender|FixinERC721Spender|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC1155OrdersFeature|IERC1155Token|IERC165Feature|IERC20Bridge|IERC20Transformer|IERC721OrdersFeature|IERC721Token|IFeature|IFeeRecipient|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|IPropertyValidator|ISimpleFunctionRegistryFeature|IStaking|ITakerCallback|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC1155OrdersStorage|LibERC20Transformer|LibERC721OrdersStorage|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNFTOrder|LibNFTOrdersRichErrors|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAaveV2|MixinBalancer|MixinBalancerV2|MixinBalancerV2Batch|MixinBancor|MixinBancorV3|MixinCompound|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinGMX|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinPlatypus|MixinShell|MixinSynthetix|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinVelodrome|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NFTOrders|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OptimismBridgeAdapter|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PolygonBridgeAdapter|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFeeRecipient|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC1155Token|TestMintableERC20Token|TestMintableERC721Token|TestMooniswap|TestNFTOrderPresigner|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestPropertyValidator|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json" "abis": "./test/generated-artifacts/@(AbstractBridgeAdapter|AffiliateFeeTransformer|AvalancheBridgeAdapter|BSCBridgeAdapter|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeProtocols|CeloBridgeAdapter|CurveLiquidityProvider|ERC1155OrdersFeature|ERC165Feature|ERC721OrdersFeature|EthereumBridgeAdapter|FantomBridgeAdapter|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinERC1155Spender|FixinERC721Spender|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC1155OrdersFeature|IERC1155Token|IERC165Feature|IERC20Bridge|IERC20Transformer|IERC721OrdersFeature|IERC721Token|IFeature|IFeeRecipient|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|IPropertyValidator|ISimpleFunctionRegistryFeature|IStaking|ITakerCallback|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC1155OrdersStorage|LibERC20Transformer|LibERC721OrdersStorage|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNFTOrder|LibNFTOrdersRichErrors|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinAaveV2|MixinBalancer|MixinBalancerV2|MixinBalancerV2Batch|MixinBancor|MixinBancorV3|MixinCompound|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinGMX|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinPlatypus|MixinShell|MixinSynthetix|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinVelodrome|MixinWOOFi|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NFTOrders|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OptimismBridgeAdapter|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PolygonBridgeAdapter|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFeeRecipient|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC1155Token|TestMintableERC20Token|TestMintableERC721Token|TestMooniswap|TestNFTOrderPresigner|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestPropertyValidator|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -129,6 +129,7 @@ import * as MixinUniswap from '../test/generated-artifacts/MixinUniswap.json';
import * as MixinUniswapV2 from '../test/generated-artifacts/MixinUniswapV2.json'; import * as MixinUniswapV2 from '../test/generated-artifacts/MixinUniswapV2.json';
import * as MixinUniswapV3 from '../test/generated-artifacts/MixinUniswapV3.json'; import * as MixinUniswapV3 from '../test/generated-artifacts/MixinUniswapV3.json';
import * as MixinVelodrome from '../test/generated-artifacts/MixinVelodrome.json'; import * as MixinVelodrome from '../test/generated-artifacts/MixinVelodrome.json';
import * as MixinWOOFi from '../test/generated-artifacts/MixinWOOFi.json';
import * as MixinZeroExBridge from '../test/generated-artifacts/MixinZeroExBridge.json'; import * as MixinZeroExBridge from '../test/generated-artifacts/MixinZeroExBridge.json';
import * as MooniswapLiquidityProvider from '../test/generated-artifacts/MooniswapLiquidityProvider.json'; import * as MooniswapLiquidityProvider from '../test/generated-artifacts/MooniswapLiquidityProvider.json';
import * as MultiplexFeature from '../test/generated-artifacts/MultiplexFeature.json'; import * as MultiplexFeature from '../test/generated-artifacts/MultiplexFeature.json';
@ -353,6 +354,7 @@ export const artifacts = {
MixinUniswapV2: MixinUniswapV2 as ContractArtifact, MixinUniswapV2: MixinUniswapV2 as ContractArtifact,
MixinUniswapV3: MixinUniswapV3 as ContractArtifact, MixinUniswapV3: MixinUniswapV3 as ContractArtifact,
MixinVelodrome: MixinVelodrome as ContractArtifact, MixinVelodrome: MixinVelodrome as ContractArtifact,
MixinWOOFi: MixinWOOFi as ContractArtifact,
MixinZeroExBridge: MixinZeroExBridge as ContractArtifact, MixinZeroExBridge: MixinZeroExBridge as ContractArtifact,
IERC1155Token: IERC1155Token as ContractArtifact, IERC1155Token: IERC1155Token as ContractArtifact,
IERC721Token: IERC721Token as ContractArtifact, IERC721Token: IERC721Token as ContractArtifact,

View File

@ -127,6 +127,7 @@ export * from '../test/generated-wrappers/mixin_uniswap';
export * from '../test/generated-wrappers/mixin_uniswap_v2'; export * from '../test/generated-wrappers/mixin_uniswap_v2';
export * from '../test/generated-wrappers/mixin_uniswap_v3'; export * from '../test/generated-wrappers/mixin_uniswap_v3';
export * from '../test/generated-wrappers/mixin_velodrome'; export * from '../test/generated-wrappers/mixin_velodrome';
export * from '../test/generated-wrappers/mixin_w_o_o_fi';
export * from '../test/generated-wrappers/mixin_zero_ex_bridge'; export * from '../test/generated-wrappers/mixin_zero_ex_bridge';
export * from '../test/generated-wrappers/mooniswap_liquidity_provider'; export * from '../test/generated-wrappers/mooniswap_liquidity_provider';
export * from '../test/generated-wrappers/multiplex_feature'; export * from '../test/generated-wrappers/multiplex_feature';

View File

@ -166,6 +166,7 @@
"test/generated-artifacts/MixinUniswapV2.json", "test/generated-artifacts/MixinUniswapV2.json",
"test/generated-artifacts/MixinUniswapV3.json", "test/generated-artifacts/MixinUniswapV3.json",
"test/generated-artifacts/MixinVelodrome.json", "test/generated-artifacts/MixinVelodrome.json",
"test/generated-artifacts/MixinWOOFi.json",
"test/generated-artifacts/MixinZeroExBridge.json", "test/generated-artifacts/MixinZeroExBridge.json",
"test/generated-artifacts/MooniswapLiquidityProvider.json", "test/generated-artifacts/MooniswapLiquidityProvider.json",
"test/generated-artifacts/MultiplexFeature.json", "test/generated-artifacts/MultiplexFeature.json",

View File

@ -1,4 +1,13 @@
[ [
{
"version": "16.66.0",
"changes": [
{
"note": "Add WOOFi support",
"pr": 513
}
]
},
{ {
"version": "16.65.0", "version": "16.65.0",
"changes": [ "changes": [

View File

@ -45,6 +45,7 @@ import "./UniswapSampler.sol";
import "./UniswapV2Sampler.sol"; import "./UniswapV2Sampler.sol";
import "./UniswapV3Sampler.sol"; import "./UniswapV3Sampler.sol";
import "./VelodromeSampler.sol"; import "./VelodromeSampler.sol";
import "./WooPPSampler.sol";
import "./UtilitySampler.sol"; import "./UtilitySampler.sol";
@ -74,6 +75,7 @@ contract ERC20BridgeSampler is
UniswapV2Sampler, UniswapV2Sampler,
UniswapV3Sampler, UniswapV3Sampler,
VelodromeSampler, VelodromeSampler,
WooPPSampler,
UtilitySampler UtilitySampler
{ {

View File

@ -0,0 +1,121 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./SamplerUtils.sol";
import "./ApproximateBuys.sol";
interface IWooPP {
/// @dev get the quote token address (immutable)
/// @return address of quote token
function quoteToken() external view returns (address);
/// @dev Query the amount for selling the base token amount.
/// @param baseToken the base token to sell
/// @param baseAmount the amount to sell
/// @return quoteAmount the swapped quote amount
function querySellBase(address baseToken, uint256 baseAmount) external view returns (uint256 quoteAmount);
/// @dev Query the amount for selling the quote token.
/// @param baseToken the base token to receive (buy)
/// @param quoteAmount the amount to sell
/// @return baseAmount the swapped base token amount
function querySellQuote(address baseToken, uint256 quoteAmount) external view returns (uint256 baseAmount);
}
contract WooPPSampler is SamplerUtils, ApproximateBuys{
function query(
uint amountIn,
address tokenIn,
address tokenOut,
address pool
) internal view returns (uint256 amountOut) {
if (amountIn == 0) {
return 0;
}
address quoteToken = IWooPP(pool).quoteToken();
if (tokenIn == quoteToken) {
amountOut = IWooPP(pool).querySellQuote(tokenOut, amountIn);
} else if (tokenOut == quoteToken) {
amountOut = IWooPP(pool).querySellBase(tokenIn, amountIn);
} else {
uint quoteAmount = IWooPP(pool).querySellBase(tokenIn, amountIn);
amountOut = IWooPP(pool).querySellQuote(tokenOut, quoteAmount);
}
}
/// @dev Sample sell quotes from WooFI.
/// @param pool Address of the pool we are sampling from
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample (sorted in ascending order).
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromWooPP(
address pool,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
makerTokenAmounts[i] = query(takerTokenAmounts[i], takerToken, makerToken, pool);
if (makerTokenAmounts[i] == 0) {
break;
}
}
}
/// @dev Sample buy quotes from WooFI.
/// @param pool Address of the pool we are sampling from
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token sell amount for each sample (sorted in ascending order).
/// @return takerTokenAmounts Taker amounts bought at each taker token
/// amount.
function sampleBuysFromWooPP(
address pool,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = _sampleApproximateBuys(
ApproximateBuyQuoteOpts({
takerTokenData: abi.encode(pool,takerToken, makerToken),
makerTokenData: abi.encode(pool, makerToken, takerToken),
getSellQuoteCallback: _sampleSellForApproximateBuyFromWoofi
}),
makerTokenAmounts
);
}
function _sampleSellForApproximateBuyFromWoofi(
bytes memory takerTokenData,
bytes memory makerTokenData,
uint256 sellAmount
) internal view returns (uint256) {
(address _pool, address _takerToken, address _makerToken) = abi.decode(takerTokenData, (address, address, address));
(bool success, bytes memory resultData) = address(this).staticcall(abi.encodeWithSelector(
this.sampleSellsFromWooPP.selector,
_pool,
_takerToken,
_makerToken,
_toSingleValueArray(sellAmount)
));
if(!success) {
return 0;
}
return abi.decode(resultData, (uint256[]))[0];
}
}

View File

@ -40,7 +40,7 @@
"config": { "config": {
"publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker", "publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BalancerV2BatchSampler|BalancerV2Common|BalancerV2Sampler|BancorSampler|BancorV3Sampler|CompoundSampler|CurveSampler|DODOSampler|DODOV2Sampler|ERC20BridgeSampler|FakeTaker|GMXSampler|IBalancer|IBalancerV2Vault|IBancor|IBancorV3|ICurve|IGMX|IMStable|IMooniswap|IMultiBridge|IPlatypus|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|LidoSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|NativeOrderSampler|PlatypusSampler|SamplerUtils|ShellSampler|SynthetixSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler|VelodromeSampler).json", "abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BalancerV2BatchSampler|BalancerV2Common|BalancerV2Sampler|BancorSampler|BancorV3Sampler|CompoundSampler|CurveSampler|DODOSampler|DODOV2Sampler|ERC20BridgeSampler|FakeTaker|GMXSampler|IBalancer|IBalancerV2Vault|IBancor|IBancorV3|ICurve|IGMX|IMStable|IMooniswap|IMultiBridge|IPlatypus|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|LidoSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|NativeOrderSampler|PlatypusSampler|SamplerUtils|ShellSampler|SynthetixSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler|VelodromeSampler|WooPPSampler).json",
"postpublish": { "postpublish": {
"assets": [] "assets": []
} }
@ -89,7 +89,8 @@
"graphql": "^15.4.0", "graphql": "^15.4.0",
"graphql-request": "^3.4.0", "graphql-request": "^3.4.0",
"heartbeats": "^5.0.1", "heartbeats": "^5.0.1",
"lodash": "^4.17.11" "lodash": "^4.17.11",
"msw": "^0.44.2"
}, },
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^5.8.0", "@0x/abi-gen": "^5.8.0",

View File

@ -35,6 +35,7 @@ import {
SynthetixFillData, SynthetixFillData,
UniswapV2FillData, UniswapV2FillData,
UniswapV3FillData, UniswapV3FillData,
WOOFiFillData,
} from './types'; } from './types';
// tslint:disable: no-bitwise // tslint:disable: no-bitwise
@ -154,6 +155,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.BiSwap, ERC20BridgeSource.BiSwap,
ERC20BridgeSource.MDex, ERC20BridgeSource.MDex,
ERC20BridgeSource.KnightSwap, ERC20BridgeSource.KnightSwap,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Polygon]: new SourceFilters([ [ChainId.Polygon]: new SourceFilters([
ERC20BridgeSource.SushiSwap, ERC20BridgeSource.SushiSwap,
@ -176,6 +178,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.UniswapV3, ERC20BridgeSource.UniswapV3,
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.MeshSwap, ERC20BridgeSource.MeshSwap,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Avalanche]: new SourceFilters([ [ChainId.Avalanche]: new SourceFilters([
ERC20BridgeSource.MultiHop, ERC20BridgeSource.MultiHop,
@ -189,6 +192,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.GMX, ERC20BridgeSource.GMX,
ERC20BridgeSource.Platypus, ERC20BridgeSource.Platypus,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Fantom]: new SourceFilters([ [ChainId.Fantom]: new SourceFilters([
ERC20BridgeSource.MultiHop, ERC20BridgeSource.MultiHop,
@ -202,6 +206,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.SushiSwap, ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.Yoshi, ERC20BridgeSource.Yoshi,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Celo]: new SourceFilters([ [ChainId.Celo]: new SourceFilters([
ERC20BridgeSource.UbeSwap, ERC20BridgeSource.UbeSwap,
@ -302,6 +307,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.BiSwap, ERC20BridgeSource.BiSwap,
ERC20BridgeSource.MDex, ERC20BridgeSource.MDex,
ERC20BridgeSource.KnightSwap, ERC20BridgeSource.KnightSwap,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Polygon]: new SourceFilters([ [ChainId.Polygon]: new SourceFilters([
ERC20BridgeSource.SushiSwap, ERC20BridgeSource.SushiSwap,
@ -324,6 +330,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.UniswapV3, ERC20BridgeSource.UniswapV3,
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.MeshSwap, ERC20BridgeSource.MeshSwap,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Avalanche]: new SourceFilters([ [ChainId.Avalanche]: new SourceFilters([
ERC20BridgeSource.MultiHop, ERC20BridgeSource.MultiHop,
@ -337,6 +344,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.GMX, ERC20BridgeSource.GMX,
ERC20BridgeSource.Platypus, ERC20BridgeSource.Platypus,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Fantom]: new SourceFilters([ [ChainId.Fantom]: new SourceFilters([
ERC20BridgeSource.MultiHop, ERC20BridgeSource.MultiHop,
@ -350,6 +358,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.SushiSwap, ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Synapse, ERC20BridgeSource.Synapse,
ERC20BridgeSource.Yoshi, ERC20BridgeSource.Yoshi,
ERC20BridgeSource.WOOFi,
]), ]),
[ChainId.Celo]: new SourceFilters([ [ChainId.Celo]: new SourceFilters([
ERC20BridgeSource.UbeSwap, ERC20BridgeSource.UbeSwap,
@ -542,6 +551,7 @@ export const BSC_TOKENS = {
pBTC: '0xed28a457a5a76596ac48d87c0f577020f6ea1c4c', pBTC: '0xed28a457a5a76596ac48d87c0f577020f6ea1c4c',
nUSD: '0x23b891e5c62e0955ae2bd185990103928ab817b3', nUSD: '0x23b891e5c62e0955ae2bd185990103928ab817b3',
BSW: '0x965F527D9159dCe6288a2219DB51fc6Eef120dD1', BSW: '0x965F527D9159dCe6288a2219DB51fc6Eef120dD1',
WOO: '0x4691937a7508860f876c9c0a2a617e7d9e945d4b',
}; };
export const POLYGON_TOKENS = { export const POLYGON_TOKENS = {
@ -561,6 +571,7 @@ export const POLYGON_TOKENS = {
WEXPOLY: '0x4c4bf319237d98a30a929a96112effa8da3510eb', WEXPOLY: '0x4c4bf319237d98a30a929a96112effa8da3510eb',
nUSD: '0xb6c473756050de474286bed418b77aeac39b02af', nUSD: '0xb6c473756050de474286bed418b77aeac39b02af',
ANY: '0x6aB6d61428fde76768D7b45D8BFeec19c6eF91A8', ANY: '0x6aB6d61428fde76768D7b45D8BFeec19c6eF91A8',
WOO: '0x1b815d120b3ef02039ee11dc2d33de7aa4a8c603',
}; };
export const AVALANCHE_TOKENS = { export const AVALANCHE_TOKENS = {
@ -587,6 +598,7 @@ export const AVALANCHE_TOKENS = {
UST: '0xb599c3590f42f8f995ecfa0f85d2980b76862fc1', UST: '0xb599c3590f42f8f995ecfa0f85d2980b76862fc1',
FRAX: '0xd24c2ad096400b6fbcd2ad8b24e7acbc21a1da64', FRAX: '0xd24c2ad096400b6fbcd2ad8b24e7acbc21a1da64',
YUSD: '0x111111111111ed1d73f860f57b2798b683f2d325', YUSD: '0x111111111111ed1d73f860f57b2798b683f2d325',
WOO: '0xabc9547b534519ff73921b1fba6e672b5f58d083',
}; };
export const CELO_TOKENS = { export const CELO_TOKENS = {
@ -646,6 +658,7 @@ export const FANTOM_TOKENS = {
gWBTC: '0x38aca5484b8603373acc6961ecd57a6a594510a3', gWBTC: '0x38aca5484b8603373acc6961ecd57a6a594510a3',
gCRV: '0x690754a168b022331caa2467207c61919b3f8a98', gCRV: '0x690754a168b022331caa2467207c61919b3f8a98',
gMIM: '0xc664fc7b8487a3e10824cda768c1d239f2403bbe', gMIM: '0xc664fc7b8487a3e10824cda768c1d239f2403bbe',
WOO: '0x6626c47c00f1d87902fc13eecfac3ed06d5e8d8a',
}; };
export const OPTIMISM_TOKENS = { export const OPTIMISM_TOKENS = {
@ -864,6 +877,16 @@ export const PLATYPUS_AVALANCHE_POOLS = {
sAVAX: '0x4658ea7e9960d6158a261104aaa160cc953bb6ba', sAVAX: '0x4658ea7e9960d6158a261104aaa160cc953bb6ba',
}; };
export const WOOFI_POOL_BY_CHAIN_ID = valueByChainId<string>(
{
[ChainId.BSC]: '0xbf365ce9cfcb2d5855521985e351ba3bcf77fd3f',
[ChainId.Fantom]: '0x9503e7517d3c5bc4f9e4a1c6ae4f8b33ac2546f2',
[ChainId.Avalanche]: '0x1df3009c57a8b143c6246149f00b090bce3b8f88',
[ChainId.Polygon]: '0x7400b665c8f4f3a951a99f1ee9872efb8778723d',
},
NULL_ADDRESS,
);
export const DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID = valueByChainId<string[]>( export const DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID = valueByChainId<string[]>(
{ {
[ChainId.Mainnet]: [ [ChainId.Mainnet]: [
@ -2645,7 +2668,19 @@ export const DEFAULT_GAS_SCHEDULE: Required<GasSchedule> = {
[ERC20BridgeSource.CheeseSwap]: uniswapV2CloneGasSchedule, [ERC20BridgeSource.CheeseSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.WaultSwap]: uniswapV2CloneGasSchedule, [ERC20BridgeSource.WaultSwap]: uniswapV2CloneGasSchedule,
[ERC20BridgeSource.ACryptos]: fillData => (fillData as CurveFillData).pool.gasSchedule, [ERC20BridgeSource.ACryptos]: fillData => (fillData as CurveFillData).pool.gasSchedule,
[ERC20BridgeSource.WOOFi]: (fillData?: FillData) => {
const woofiFillData = fillData as WOOFiFillData;
const quoteTokenAddresses = [BSC_TOKENS.USDT, AVALANCHE_TOKENS.nUSDC, FANTOM_TOKENS.USDC, POLYGON_TOKENS.USDC];
if (
quoteTokenAddresses.includes(woofiFillData.takerToken) ||
quoteTokenAddresses.includes(woofiFillData.makerToken)
) {
return 500e3;
} else {
return 100e4;
}
},
// //
// Polygon // Polygon
// //

View File

@ -43,6 +43,7 @@ import {
UniswapV3FillData, UniswapV3FillData,
UniswapV3PathAmount, UniswapV3PathAmount,
VelodromeFillData, VelodromeFillData,
WOOFiFillData,
} from './types'; } from './types';
// tslint:disable completed-docs // tslint:disable completed-docs
@ -213,6 +214,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
return encodeBridgeSourceId(BridgeProtocol.Velodrome, 'Velodrome'); return encodeBridgeSourceId(BridgeProtocol.Velodrome, 'Velodrome');
case ERC20BridgeSource.Synthetix: case ERC20BridgeSource.Synthetix:
return encodeBridgeSourceId(BridgeProtocol.Synthetix, 'Synthetix'); return encodeBridgeSourceId(BridgeProtocol.Synthetix, 'Synthetix');
case ERC20BridgeSource.WOOFi:
return encodeBridgeSourceId(BridgeProtocol.WOOFi, 'WOOFi');
default: default:
throw new Error(AggregationError.NoBridgeForSource); throw new Error(AggregationError.NoBridgeForSource);
} }
@ -402,6 +405,10 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
fillData.makerTokenSymbolBytes32, fillData.makerTokenSymbolBytes32,
]); ]);
break; break;
case ERC20BridgeSource.WOOFi:
const woofiFillData = (order as OptimizedMarketBridgeOrder<WOOFiFillData>).fillData;
bridgeData = encoder.encode([woofiFillData.poolAddress]);
break;
default: default:
throw new Error(AggregationError.NoBridgeForSource); throw new Error(AggregationError.NoBridgeForSource);
} }
@ -529,6 +536,7 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.Geist]: AbiEncoder.create('(address,address)'), [ERC20BridgeSource.Geist]: AbiEncoder.create('(address,address)'),
[ERC20BridgeSource.Velodrome]: AbiEncoder.create('(address,bool)'), [ERC20BridgeSource.Velodrome]: AbiEncoder.create('(address,bool)'),
[ERC20BridgeSource.Synthetix]: AbiEncoder.create('(address,bytes32,bytes32)'), [ERC20BridgeSource.Synthetix]: AbiEncoder.create('(address,bytes32,bytes32)'),
[ERC20BridgeSource.WOOFi]: AbiEncoder.create('(address)'),
}; };
function getFillTokenAmounts(fill: Fill, side: MarketOperation): [BigNumber, BigNumber] { function getFillTokenAmounts(fill: Fill, side: MarketOperation): [BigNumber, BigNumber] {

View File

@ -52,6 +52,7 @@ import {
UNISWAPV1_ROUTER_BY_CHAIN_ID, UNISWAPV1_ROUTER_BY_CHAIN_ID,
UNISWAPV3_CONFIG_BY_CHAIN_ID, UNISWAPV3_CONFIG_BY_CHAIN_ID,
VELODROME_ROUTER_BY_CHAIN_ID, VELODROME_ROUTER_BY_CHAIN_ID,
WOOFI_POOL_BY_CHAIN_ID,
ZERO_AMOUNT, ZERO_AMOUNT,
} from './constants'; } from './constants';
import { getGeistInfoForPair } from './geist_utils'; import { getGeistInfoForPair } from './geist_utils';
@ -99,6 +100,7 @@ import {
UniswapV2FillData, UniswapV2FillData,
UniswapV3FillData, UniswapV3FillData,
VelodromeFillData, VelodromeFillData,
WOOFiFillData,
} from './types'; } from './types';
/** /**
@ -1364,6 +1366,35 @@ export class SamplerOperations {
}, },
}); });
} }
public getWOOFiSellQuotes(
poolAddress: string,
takerToken: string,
makerToken: string,
makerFillAmounts: BigNumber[],
): SourceQuoteOperation<WOOFiFillData> {
return new SamplerContractOperation({
fillData: { poolAddress, takerToken, makerToken },
source: ERC20BridgeSource.WOOFi,
contract: this._samplerContract,
function: this._samplerContract.sampleSellsFromWooPP,
params: [poolAddress, takerToken, makerToken, makerFillAmounts],
});
}
public getWOOFiBuyQuotes(
poolAddress: string,
takerToken: string,
makerToken: string,
makerFillAmounts: BigNumber[],
): SourceQuoteOperation<WOOFiFillData> {
return new SamplerContractOperation({
fillData: { poolAddress, takerToken, makerToken },
source: ERC20BridgeSource.WOOFi,
contract: this._samplerContract,
function: this._samplerContract.sampleBuysFromWooPP,
params: [poolAddress, takerToken, makerToken, makerFillAmounts],
});
}
/** /**
* Returns the best price for the native token * Returns the best price for the native token
@ -1800,6 +1831,14 @@ export class SamplerOperations {
takerFillAmounts, takerFillAmounts,
); );
} }
case ERC20BridgeSource.WOOFi: {
return this.getWOOFiSellQuotes(
WOOFI_POOL_BY_CHAIN_ID[this.chainId],
takerToken,
makerToken,
takerFillAmounts,
);
}
default: default:
throw new Error(`Unsupported sell sample source: ${source}`); throw new Error(`Unsupported sell sample source: ${source}`);
} }
@ -2140,6 +2179,14 @@ export class SamplerOperations {
makerFillAmounts, makerFillAmounts,
); );
} }
case ERC20BridgeSource.WOOFi: {
return this.getWOOFiBuyQuotes(
WOOFI_POOL_BY_CHAIN_ID[this.chainId],
takerToken,
makerToken,
makerFillAmounts,
);
}
default: default:
throw new Error(`Unsupported buy sample source: ${source}`); throw new Error(`Unsupported buy sample source: ${source}`);
} }

View File

@ -69,6 +69,7 @@ export enum ERC20BridgeSource {
Synapse = 'Synapse', Synapse = 'Synapse',
BancorV3 = 'BancorV3', BancorV3 = 'BancorV3',
Synthetix = 'Synthetix', Synthetix = 'Synthetix',
WOOFi = 'WOOFi',
// BSC only // BSC only
PancakeSwap = 'PancakeSwap', PancakeSwap = 'PancakeSwap',
PancakeSwapV2 = 'PancakeSwap_V2', PancakeSwapV2 = 'PancakeSwap_V2',
@ -373,6 +374,12 @@ export interface PlatypusFillData extends FillData {
tokenAddressPath: string[]; tokenAddressPath: string[];
} }
export interface WOOFiFillData extends FillData {
poolAddress: string;
takerToken: string;
makerToken: string;
}
export interface VelodromeFillData extends FillData { export interface VelodromeFillData extends FillData {
router: string; router: string;
stable: boolean; stable: boolean;

View File

@ -51,6 +51,7 @@ import * as UniswapV2Sampler from '../test/generated-artifacts/UniswapV2Sampler.
import * as UniswapV3Sampler from '../test/generated-artifacts/UniswapV3Sampler.json'; import * as UniswapV3Sampler from '../test/generated-artifacts/UniswapV3Sampler.json';
import * as UtilitySampler from '../test/generated-artifacts/UtilitySampler.json'; import * as UtilitySampler from '../test/generated-artifacts/UtilitySampler.json';
import * as VelodromeSampler from '../test/generated-artifacts/VelodromeSampler.json'; import * as VelodromeSampler from '../test/generated-artifacts/VelodromeSampler.json';
import * as WooPPSampler from '../test/generated-artifacts/WooPPSampler.json';
export const artifacts = { export const artifacts = {
ApproximateBuys: ApproximateBuys as ContractArtifact, ApproximateBuys: ApproximateBuys as ContractArtifact,
BalanceChecker: BalanceChecker as ContractArtifact, BalanceChecker: BalanceChecker as ContractArtifact,
@ -84,6 +85,7 @@ export const artifacts = {
UniswapV3Sampler: UniswapV3Sampler as ContractArtifact, UniswapV3Sampler: UniswapV3Sampler as ContractArtifact,
UtilitySampler: UtilitySampler as ContractArtifact, UtilitySampler: UtilitySampler as ContractArtifact,
VelodromeSampler: VelodromeSampler as ContractArtifact, VelodromeSampler: VelodromeSampler as ContractArtifact,
WooPPSampler: WooPPSampler as ContractArtifact,
IBalancer: IBalancer as ContractArtifact, IBalancer: IBalancer as ContractArtifact,
IBalancerV2Vault: IBalancerV2Vault as ContractArtifact, IBalancerV2Vault: IBalancerV2Vault as ContractArtifact,
IBancor: IBancor as ContractArtifact, IBancor: IBancor as ContractArtifact,

View File

@ -49,3 +49,4 @@ export * from '../test/generated-wrappers/uniswap_v2_sampler';
export * from '../test/generated-wrappers/uniswap_v3_sampler'; export * from '../test/generated-wrappers/uniswap_v3_sampler';
export * from '../test/generated-wrappers/utility_sampler'; export * from '../test/generated-wrappers/utility_sampler';
export * from '../test/generated-wrappers/velodrome_sampler'; export * from '../test/generated-wrappers/velodrome_sampler';
export * from '../test/generated-wrappers/woo_p_p_sampler';

View File

@ -51,6 +51,7 @@
"test/generated-artifacts/UniswapV2Sampler.json", "test/generated-artifacts/UniswapV2Sampler.json",
"test/generated-artifacts/UniswapV3Sampler.json", "test/generated-artifacts/UniswapV3Sampler.json",
"test/generated-artifacts/UtilitySampler.json", "test/generated-artifacts/UtilitySampler.json",
"test/generated-artifacts/VelodromeSampler.json" "test/generated-artifacts/VelodromeSampler.json",
"test/generated-artifacts/WooPPSampler.json"
] ]
} }

View File

@ -141,6 +141,7 @@ export enum BridgeProtocol {
BancorV3, BancorV3,
Velodrome, Velodrome,
Synthetix, Synthetix,
WOOFi,
} }
// tslint:enable: enum-naming // tslint:enable: enum-naming