Maker PSM integration [TKR-2] (#150)

* ADDS basic boilerplate for PSM bridge WIP

* ADDS integrate the MakerPSM mixin and fix incorrect naming

* fix: take into account PSM fee when buying USDC from PSM

* feat: intial stab at a PSM sampler WIP

* feat: integrate MakerPsm into AS WIP

* refactor: get VAT contract address from PSM instead of passing it in

* fix: hardcode PSM Gemtoken to USDC

* fix: remove passing in authGem, get from PSM contract instead

* fix: use constant modified to avoid using storage variables

* fix: incorrect num decimals after multiplication in sampler

* fix: PSM buy sampling

* fix: use fillData to estimate gas schedule

* Rebased on latest development

* Guard and use latest Curve LiquidityProvider

* `@0x/contract-addresses`: Redeploy FQT on mainnet and ropsten

Co-authored-by: Jacob Evans <jacob@dekz.net>
Co-authored-by: Lawrence Forman <lawrence@0xproject.com>
This commit is contained in:
Kim Persson 2021-04-01 21:45:06 +02:00 committed by GitHub
parent 164a5d44d9
commit 3adfcdffa8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 568 additions and 24 deletions

View File

@ -30,6 +30,7 @@ import "./mixins/MixinCryptoCom.sol";
import "./mixins/MixinDodo.sol"; import "./mixins/MixinDodo.sol";
import "./mixins/MixinDodoV2.sol"; import "./mixins/MixinDodoV2.sol";
import "./mixins/MixinKyber.sol"; import "./mixins/MixinKyber.sol";
import "./mixins/MixinMakerPSM.sol";
import "./mixins/MixinMooniswap.sol"; import "./mixins/MixinMooniswap.sol";
import "./mixins/MixinMStable.sol"; import "./mixins/MixinMStable.sol";
import "./mixins/MixinNerve.sol"; import "./mixins/MixinNerve.sol";
@ -49,6 +50,7 @@ contract BridgeAdapter is
MixinDodo, MixinDodo,
MixinDodoV2, MixinDodoV2,
MixinKyber, MixinKyber,
MixinMakerPSM,
MixinMooniswap, MixinMooniswap,
MixinMStable, MixinMStable,
MixinNerve, MixinNerve,
@ -68,6 +70,7 @@ contract BridgeAdapter is
MixinDodo() MixinDodo()
MixinDodoV2() MixinDodoV2()
MixinKyber(weth) MixinKyber(weth)
MixinMakerPSM()
MixinMooniswap(weth) MixinMooniswap(weth)
MixinMStable() MixinMStable()
MixinNerve() MixinNerve()
@ -123,6 +126,13 @@ contract BridgeAdapter is
sellAmount, sellAmount,
order.bridgeData order.bridgeData
); );
} else if (protocolId == BridgeProtocols.MAKERPSM) {
boughtAmount = _tradeMakerPsm(
sellToken,
buyToken,
sellAmount,
order.bridgeData
);
} else if (protocolId == BridgeProtocols.MOONISWAP) { } else if (protocolId == BridgeProtocols.MOONISWAP) {
boughtAmount = _tradeMooniswap( boughtAmount = _tradeMooniswap(
sellToken, sellToken,

View File

@ -43,4 +43,5 @@ library BridgeProtocols {
uint128 internal constant BANCOR = 13; uint128 internal constant BANCOR = 13;
uint128 internal constant COFIX = 14; uint128 internal constant COFIX = 14;
uint128 internal constant NERVE = 15; uint128 internal constant NERVE = 15;
uint128 internal constant MAKERPSM = 16;
} }

View File

@ -0,0 +1,114 @@
// 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-utils/contracts/src/v06/LibSafeMathV06.sol";
interface IPSM {
// @dev Get the fee for selling USDC to DAI in PSM
// @return tin toll in [wad]
function tin() external view returns (uint256);
// @dev Get the fee for selling DAI to USDC in PSM
// @return tout toll out [wad]
function tout() external view returns (uint256);
// @dev Get the address of the PSM state Vat
// @return address of the Vat
function vat() external view returns (address);
// @dev Get the address of the underlying vault powering PSM
// @return address of gemJoin contract
function gemJoin() external view returns (address);
// @dev Sell USDC for DAI
// @param usr The address of the account trading USDC for DAI.
// @param gemAmt The amount of USDC to sell in USDC base units
function sellGem(
address usr,
uint256 gemAmt
) external;
// @dev Buy USDC for DAI
// @param usr The address of the account trading DAI for USDC
// @param gemAmt The amount of USDC to buy in USDC base units
function buyGem(
address usr,
uint256 gemAmt
) external;
}
contract MixinMakerPSM {
using LibERC20TokenV06 for IERC20TokenV06;
using LibSafeMathV06 for uint256;
struct MakerPsmBridgeData {
address psmAddress;
address gemTokenAddres;
}
// Maker units
// wad: fixed point decimal with 18 decimals (for basic quantities, e.g. balances)
uint256 constant private WAD = 10 ** 18;
// ray: fixed point decimal with 27 decimals (for precise quantites, e.g. ratios)
uint256 constant private RAY = 10 ** 27;
// rad: fixed point decimal with 45 decimals (result of integer multiplication with a wad and a ray)
uint256 constant private RAD = 10 ** 45;
// See https://github.com/makerdao/dss/blob/master/DEVELOPING.md
function _tradeMakerPsm(
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
// Decode the bridge data.
MakerPsmBridgeData memory data = abi.decode(bridgeData, (MakerPsmBridgeData));
uint256 beforeBalance = buyToken.balanceOf(address(this));
IPSM psm = IPSM(data.psmAddress);
if (address(sellToken) == data.gemTokenAddres) {
sellToken.approveIfBelow(
psm.gemJoin(),
sellAmount
);
psm.sellGem(address(this), sellAmount);
} else if (address(buyToken) == data.gemTokenAddres) {
uint256 feeDivisor = WAD.safeAdd(psm.tout()); // eg. 1.001 * 10 ** 18 with 0.1% fee [tout is in wad];
uint256 buyTokenBaseUnit = uint256(10) ** uint256(buyToken.decimals());
uint256 gemAmount = sellAmount.safeMul(buyTokenBaseUnit).safeDiv(feeDivisor);
sellToken.approveIfBelow(
data.psmAddress,
sellAmount
);
psm.buyGem(address(this), gemAmount);
}
return buyToken.balanceOf(address(this)).safeSub(beforeBalance);
}
}

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,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature", "publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature",
"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/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinMStable|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OwnableFeature|PancakeSwapFeature|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|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json" "abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OwnableFeature|PancakeSwapFeature|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|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -13,7 +13,6 @@ import * as FeeCollector from '../generated-artifacts/FeeCollector.json';
import * as FeeCollectorController from '../generated-artifacts/FeeCollectorController.json'; import * as FeeCollectorController from '../generated-artifacts/FeeCollectorController.json';
import * as FillQuoteTransformer from '../generated-artifacts/FillQuoteTransformer.json'; import * as FillQuoteTransformer from '../generated-artifacts/FillQuoteTransformer.json';
import * as FullMigration from '../generated-artifacts/FullMigration.json'; import * as FullMigration from '../generated-artifacts/FullMigration.json';
import * as IAllowanceTarget from '../generated-artifacts/IAllowanceTarget.json';
import * as IBatchFillNativeOrdersFeature from '../generated-artifacts/IBatchFillNativeOrdersFeature.json'; import * as IBatchFillNativeOrdersFeature from '../generated-artifacts/IBatchFillNativeOrdersFeature.json';
import * as IERC20Transformer from '../generated-artifacts/IERC20Transformer.json'; import * as IERC20Transformer from '../generated-artifacts/IERC20Transformer.json';
import * as IFlashWallet from '../generated-artifacts/IFlashWallet.json'; import * as IFlashWallet from '../generated-artifacts/IFlashWallet.json';
@ -43,7 +42,6 @@ export const artifacts = {
FullMigration: FullMigration as ContractArtifact, FullMigration: FullMigration as ContractArtifact,
InitialMigration: InitialMigration as ContractArtifact, InitialMigration: InitialMigration as ContractArtifact,
IFlashWallet: IFlashWallet as ContractArtifact, IFlashWallet: IFlashWallet as ContractArtifact,
IAllowanceTarget: IAllowanceTarget as ContractArtifact,
IERC20Transformer: IERC20Transformer as ContractArtifact, IERC20Transformer: IERC20Transformer as ContractArtifact,
IOwnableFeature: IOwnableFeature as ContractArtifact, IOwnableFeature: IOwnableFeature as ContractArtifact,
ISimpleFunctionRegistryFeature: ISimpleFunctionRegistryFeature as ContractArtifact, ISimpleFunctionRegistryFeature: ISimpleFunctionRegistryFeature as ContractArtifact,

View File

@ -11,7 +11,6 @@ export * from '../generated-wrappers/fee_collector';
export * from '../generated-wrappers/fee_collector_controller'; export * from '../generated-wrappers/fee_collector_controller';
export * from '../generated-wrappers/fill_quote_transformer'; export * from '../generated-wrappers/fill_quote_transformer';
export * from '../generated-wrappers/full_migration'; export * from '../generated-wrappers/full_migration';
export * from '../generated-wrappers/i_allowance_target';
export * from '../generated-wrappers/i_batch_fill_native_orders_feature'; export * from '../generated-wrappers/i_batch_fill_native_orders_feature';
export * from '../generated-wrappers/i_erc20_transformer'; export * from '../generated-wrappers/i_erc20_transformer';
export * from '../generated-wrappers/i_flash_wallet'; export * from '../generated-wrappers/i_flash_wallet';

View File

@ -83,6 +83,7 @@ import * as MixinCurve from '../test/generated-artifacts/MixinCurve.json';
import * as MixinDodo from '../test/generated-artifacts/MixinDodo.json'; import * as MixinDodo from '../test/generated-artifacts/MixinDodo.json';
import * as MixinDodoV2 from '../test/generated-artifacts/MixinDodoV2.json'; import * as MixinDodoV2 from '../test/generated-artifacts/MixinDodoV2.json';
import * as MixinKyber from '../test/generated-artifacts/MixinKyber.json'; import * as MixinKyber from '../test/generated-artifacts/MixinKyber.json';
import * as MixinMakerPSM from '../test/generated-artifacts/MixinMakerPSM.json';
import * as MixinMooniswap from '../test/generated-artifacts/MixinMooniswap.json'; import * as MixinMooniswap from '../test/generated-artifacts/MixinMooniswap.json';
import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json'; import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json';
import * as MixinNerve from '../test/generated-artifacts/MixinNerve.json'; import * as MixinNerve from '../test/generated-artifacts/MixinNerve.json';
@ -241,6 +242,7 @@ export const artifacts = {
MixinDodoV2: MixinDodoV2 as ContractArtifact, MixinDodoV2: MixinDodoV2 as ContractArtifact,
MixinKyber: MixinKyber as ContractArtifact, MixinKyber: MixinKyber as ContractArtifact,
MixinMStable: MixinMStable as ContractArtifact, MixinMStable: MixinMStable as ContractArtifact,
MixinMakerPSM: MixinMakerPSM as ContractArtifact,
MixinMooniswap: MixinMooniswap as ContractArtifact, MixinMooniswap: MixinMooniswap as ContractArtifact,
MixinNerve: MixinNerve as ContractArtifact, MixinNerve: MixinNerve as ContractArtifact,
MixinOasis: MixinOasis as ContractArtifact, MixinOasis: MixinOasis as ContractArtifact,

View File

@ -82,6 +82,7 @@ export * from '../test/generated-wrappers/mixin_dodo';
export * from '../test/generated-wrappers/mixin_dodo_v2'; export * from '../test/generated-wrappers/mixin_dodo_v2';
export * from '../test/generated-wrappers/mixin_kyber'; export * from '../test/generated-wrappers/mixin_kyber';
export * from '../test/generated-wrappers/mixin_m_stable'; export * from '../test/generated-wrappers/mixin_m_stable';
export * from '../test/generated-wrappers/mixin_maker_p_s_m';
export * from '../test/generated-wrappers/mixin_mooniswap'; export * from '../test/generated-wrappers/mixin_mooniswap';
export * from '../test/generated-wrappers/mixin_nerve'; export * from '../test/generated-wrappers/mixin_nerve';
export * from '../test/generated-wrappers/mixin_oasis'; export * from '../test/generated-wrappers/mixin_oasis';

View File

@ -11,7 +11,6 @@
"generated-artifacts/FeeCollectorController.json", "generated-artifacts/FeeCollectorController.json",
"generated-artifacts/FillQuoteTransformer.json", "generated-artifacts/FillQuoteTransformer.json",
"generated-artifacts/FullMigration.json", "generated-artifacts/FullMigration.json",
"generated-artifacts/IAllowanceTarget.json",
"generated-artifacts/IBatchFillNativeOrdersFeature.json", "generated-artifacts/IBatchFillNativeOrdersFeature.json",
"generated-artifacts/IERC20Transformer.json", "generated-artifacts/IERC20Transformer.json",
"generated-artifacts/IFlashWallet.json", "generated-artifacts/IFlashWallet.json",
@ -114,6 +113,7 @@
"test/generated-artifacts/MixinDodoV2.json", "test/generated-artifacts/MixinDodoV2.json",
"test/generated-artifacts/MixinKyber.json", "test/generated-artifacts/MixinKyber.json",
"test/generated-artifacts/MixinMStable.json", "test/generated-artifacts/MixinMStable.json",
"test/generated-artifacts/MixinMakerPSM.json",
"test/generated-artifacts/MixinMooniswap.json", "test/generated-artifacts/MixinMooniswap.json",
"test/generated-artifacts/MixinNerve.json", "test/generated-artifacts/MixinNerve.json",
"test/generated-artifacts/MixinOasis.json", "test/generated-artifacts/MixinOasis.json",

View File

@ -28,6 +28,7 @@ import "./DODOV2Sampler.sol";
import "./Eth2DaiSampler.sol"; import "./Eth2DaiSampler.sol";
import "./KyberSampler.sol"; import "./KyberSampler.sol";
import "./LiquidityProviderSampler.sol"; import "./LiquidityProviderSampler.sol";
import "./MakerPSMSampler.sol";
import "./MultiBridgeSampler.sol"; import "./MultiBridgeSampler.sol";
import "./MStableSampler.sol"; import "./MStableSampler.sol";
import "./MooniswapSampler.sol"; import "./MooniswapSampler.sol";
@ -48,6 +49,7 @@ contract ERC20BridgeSampler is
Eth2DaiSampler, Eth2DaiSampler,
KyberSampler, KyberSampler,
LiquidityProviderSampler, LiquidityProviderSampler,
MakerPSMSampler,
MStableSampler, MStableSampler,
MooniswapSampler, MooniswapSampler,
MultiBridgeSampler, MultiBridgeSampler,

View File

@ -0,0 +1,267 @@
// 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;
pragma experimental ABIEncoderV2;
import "./SamplerUtils.sol";
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
interface IPSM {
// @dev Get the fee for selling USDC to DAI in PSM
// @return tin toll in [wad]
function tin() external view returns (uint256);
// @dev Get the fee for selling DAI to USDC in PSM
// @return tout toll out [wad]
function tout() external view returns (uint256);
// @dev Get the address of the PSM state Vat
// @return address of the Vat
function vat() external view returns (address);
// @dev Get the address of the underlying vault powering PSM
// @return address of gemJoin contract
function gemJoin() external view returns (address);
// @dev Get the address of DAI
// @return address of DAI contract
function dai() external view returns (address);
// @dev Sell USDC for DAI
// @param usr The address of the account trading USDC for DAI.
// @param gemAmt The amount of USDC to sell in USDC base units
function sellGem(
address usr,
uint256 gemAmt
) external;
// @dev Buy USDC for DAI
// @param usr The address of the account trading DAI for USDC
// @param gemAmt The amount of USDC to buy in USDC base units
function buyGem(
address usr,
uint256 gemAmt
) external;
}
interface IVAT {
// @dev Get a collateral type by identifier
// @param ilkIdentifier bytes32 identifier. Example: ethers.utils.formatBytes32String("PSM-USDC-A")
// @return ilk
// @return ilk.Art Total Normalised Debt in wad
// @return ilk.rate Accumulated Rates in ray
// @return ilk.spot Price with Safety Margin in ray
// @return ilk.line Debt Ceiling in rad
// @return ilk.dust Urn Debt Floor in rad
function ilks(
bytes32 ilkIdentifier
) external view returns (
uint256 Art,
uint256 rate,
uint256 spot,
uint256 line,
uint256 dust
);
}
contract MakerPSMSampler is
SamplerUtils
{
using LibSafeMathV06 for uint256;
/// @dev Information about which PSM module to use
struct MakerPsmInfo {
address psmAddress;
bytes32 ilkIdentifier;
address gemTokenAddress;
}
/// @dev Gas limit for MakerPsm calls.
uint256 constant private MAKER_PSM_CALL_GAS = 300e3; // 300k
// Maker units
// wad: fixed point decimal with 18 decimals (for basic quantities, e.g. balances)
uint256 constant private WAD = 10 ** 18;
// ray: fixed point decimal with 27 decimals (for precise quantites, e.g. ratios)
uint256 constant private RAY = 10 ** 27;
// rad: fixed point decimal with 45 decimals (result of integer multiplication with a wad and a ray)
uint256 constant private RAD = 10 ** 45;
// See https://github.com/makerdao/dss/blob/master/DEVELOPING.m
/// @dev Sample sell quotes from Maker PSM
function sampleSellsFromMakerPsm(
MakerPsmInfo memory psmInfo,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
)
public
view
returns (uint256[] memory makerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
IPSM psm = IPSM(psmInfo.psmAddress);
IVAT vat = IVAT(psm.vat());
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
if (makerToken != psm.dai() && takerToken != psm.dai()) {
return makerTokenAmounts;
}
for (uint256 i = 0; i < numSamples; i++) {
uint256 buyAmount = _samplePSMSell(psmInfo, makerToken, takerToken, takerTokenAmounts[i], psm, vat);
if (buyAmount == 0) {
break;
}
makerTokenAmounts[i] = buyAmount;
}
}
function sampleBuysFromMakerPsm(
MakerPsmInfo memory psmInfo,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
)
public
view
returns (uint256[] memory takerTokenAmounts)
{
_assertValidPair(makerToken, takerToken);
IPSM psm = IPSM(psmInfo.psmAddress);
IVAT vat = IVAT(psm.vat());
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
if (makerToken != psm.dai() && takerToken != psm.dai()) {
return takerTokenAmounts;
}
for (uint256 i = 0; i < numSamples; i++) {
uint256 sellAmount = _samplePSMBuy(psmInfo, makerToken, takerToken, makerTokenAmounts[i], psm, vat);
if (sellAmount == 0) {
break;
}
takerTokenAmounts[i] = sellAmount;
}
}
function _samplePSMSell(MakerPsmInfo memory psmInfo, address makerToken, address takerToken, uint256 takerTokenAmount, IPSM psm, IVAT vat)
private
view
returns (uint256)
{
(uint256 totalDebtInWad,,, uint256 debtCeilingInRad, uint256 debtFloorInRad) = vat.ilks(psmInfo.ilkIdentifier);
uint256 gemTokenBaseUnit = uint256(1e6);
if (takerToken == psmInfo.gemTokenAddress) {
// Simulate sellGem
// Selling USDC to the PSM, increasing the total debt
// Convert USDC 6 decimals to 18 decimals [wad]
uint256 takerTokenAmountInWad = takerTokenAmount.safeMul(1e12);
uint256 newTotalDebtInRad = totalDebtInWad.safeAdd(takerTokenAmountInWad).safeMul(RAY);
// PSM is too full to fit
if (newTotalDebtInRad >= debtCeilingInRad) {
return 0;
}
uint256 feeInWad = takerTokenAmountInWad.safeMul(psm.tin()).safeDiv(WAD);
uint256 makerTokenAmountInWad = takerTokenAmountInWad.safeSub(feeInWad);
return makerTokenAmountInWad;
} else if (makerToken == psmInfo.gemTokenAddress) {
// Simulate buyGem
// Buying USDC from the PSM, decreasing the total debt
// Selling DAI for USDC, already in 18 decimals [wad]
uint256 takerTokenAmountInWad = takerTokenAmount;
if (takerTokenAmountInWad > totalDebtInWad) {
return 0;
}
uint256 newTotalDebtInRad = totalDebtInWad.safeSub(takerTokenAmountInWad).safeMul(RAY);
// PSM is empty, not enough USDC to buy from it
if (newTotalDebtInRad <= debtFloorInRad) {
return 0;
}
uint256 feeDivisorInWad = WAD.safeAdd(psm.tout()); // eg. 1.001 * 10 ** 18 with 0.1% tout;
uint256 makerTokenAmountInGemTokenBaseUnits = takerTokenAmountInWad.safeMul(gemTokenBaseUnit).safeDiv(feeDivisorInWad);
return makerTokenAmountInGemTokenBaseUnits;
}
return 0;
}
function _samplePSMBuy(MakerPsmInfo memory psmInfo, address makerToken, address takerToken, uint256 makerTokenAmount, IPSM psm, IVAT vat)
private
view
returns (uint256)
{
(uint256 totalDebtInWad,,, uint256 debtCeilingInRad, uint256 debtFloorInRad) = vat.ilks(psmInfo.ilkIdentifier);
if (takerToken == psmInfo.gemTokenAddress) {
// Simulate sellGem
// Selling USDC to the PSM, increasing the total debt
uint256 makerTokenAmountInWad = makerTokenAmount;
uint256 feeDivisorInWad = WAD.safeSub(psm.tin()); // eg. 0.999 * 10 ** 18 with 0.1% tin;
uint256 takerTokenAmountInWad = makerTokenAmountInWad.safeMul(WAD).safeDiv(feeDivisorInWad);
uint256 newTotalDebtInRad = totalDebtInWad.safeAdd(takerTokenAmountInWad).safeMul(RAY);
// PSM is too full to fit
if (newTotalDebtInRad >= debtCeilingInRad) {
return 0;
}
uint256 takerTokenAmountInGemInGemBaseUnits = (takerTokenAmountInWad.safeDiv(1e12)).safeAdd(1); // Add 1 to deal with cut off decimals converting to lower decimals
return takerTokenAmountInGemInGemBaseUnits;
} else if (makerToken == psmInfo.gemTokenAddress) {
// Simulate buyGem
// Buying USDC from the PSM, decreasing the total debt
uint256 makerTokenAmountInWad = makerTokenAmount.safeMul(1e12);
uint256 feeMultiplierInWad = WAD.safeAdd(psm.tout()); // eg. 1.001 * 10 ** 18 with 0.1% tout;
uint256 takerTokenAmountInWad = makerTokenAmountInWad.safeMul(feeMultiplierInWad).safeDiv(WAD);
if (takerTokenAmountInWad > totalDebtInWad) {
return 0;
}
uint256 newTotalDebtInRad = totalDebtInWad.safeSub(takerTokenAmountInWad).safeMul(RAY);
// PSM is empty, not enough USDC to buy
if (newTotalDebtInRad <= debtFloorInRad) {
return 0;
}
return takerTokenAmountInWad;
}
return 0;
}
}

View File

@ -38,7 +38,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|BancorSampler|CurveSampler|DODOSampler|DODOV2Sampler|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|FakeTaker|IBalancer|IBancor|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UtilitySampler).json", "abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BancorSampler|CurveSampler|DODOSampler|DODOV2Sampler|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|FakeTaker|IBalancer|IBancor|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UtilitySampler).json",
"postpublish": { "postpublish": {
"assets": [] "assets": []
} }
@ -77,6 +77,7 @@
"@ethersproject/address": "^5.0.1", "@ethersproject/address": "^5.0.1",
"@ethersproject/contracts": "^5.0.1", "@ethersproject/contracts": "^5.0.1",
"@ethersproject/providers": "^5.0.4", "@ethersproject/providers": "^5.0.4",
"@ethersproject/strings": "^5.0.10",
"axios": "^0.21.1", "axios": "^0.21.1",
"axios-mock-adapter": "^1.19.0", "axios-mock-adapter": "^1.19.0",
"cream-sor": "^0.3.3", "cream-sor": "^0.3.3",

View File

@ -1,6 +1,7 @@
import { ChainId } from '@0x/contract-addresses'; import { ChainId } from '@0x/contract-addresses';
import { FillQuoteTransformerOrderType } from '@0x/protocol-utils'; import { FillQuoteTransformerOrderType } from '@0x/protocol-utils';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { formatBytes32String } from '@ethersproject/strings';
import { TokenAdjacencyGraphBuilder } from '../token_adjacency_graph_builder'; import { TokenAdjacencyGraphBuilder } from '../token_adjacency_graph_builder';
@ -18,7 +19,9 @@ import {
KyberSamplerOpts, KyberSamplerOpts,
LiquidityProviderFillData, LiquidityProviderFillData,
LiquidityProviderRegistry, LiquidityProviderRegistry,
MakerPsmFillData,
MultiHopFillData, MultiHopFillData,
PsmInfo,
TokenAdjacencyGraph, TokenAdjacencyGraph,
UniswapV2FillData, UniswapV2FillData,
} from './types'; } from './types';
@ -78,6 +81,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.LiquidityProvider, ERC20BridgeSource.LiquidityProvider,
ERC20BridgeSource.CryptoCom, ERC20BridgeSource.CryptoCom,
ERC20BridgeSource.Linkswap, ERC20BridgeSource.Linkswap,
ERC20BridgeSource.MakerPsm,
]), ]),
[ChainId.Ropsten]: new SourceFilters([ERC20BridgeSource.Native]), [ChainId.Ropsten]: new SourceFilters([ERC20BridgeSource.Native]),
[ChainId.Rinkeby]: new SourceFilters([ERC20BridgeSource.Native]), [ChainId.Rinkeby]: new SourceFilters([ERC20BridgeSource.Native]),
@ -127,6 +131,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.LiquidityProvider, ERC20BridgeSource.LiquidityProvider,
ERC20BridgeSource.CryptoCom, ERC20BridgeSource.CryptoCom,
ERC20BridgeSource.Linkswap, ERC20BridgeSource.Linkswap,
ERC20BridgeSource.MakerPsm,
]), ]),
[ChainId.Ropsten]: new SourceFilters([ERC20BridgeSource.Native]), [ChainId.Ropsten]: new SourceFilters([ERC20BridgeSource.Native]),
[ChainId.Rinkeby]: new SourceFilters([ERC20BridgeSource.Native]), [ChainId.Rinkeby]: new SourceFilters([ERC20BridgeSource.Native]),
@ -698,12 +703,28 @@ export const MAX_DODOV2_POOLS_QUERIED = 3;
export const CURVE_LIQUIDITY_PROVIDER_BY_CHAIN_ID = valueByChainId<string>( export const CURVE_LIQUIDITY_PROVIDER_BY_CHAIN_ID = valueByChainId<string>(
{ {
[ChainId.Mainnet]: '0x7a6F6a048fE2Dc1397ABa0bf7879d3eacF371C53', [ChainId.Mainnet]: '0x561b94454b65614ae3db0897b74303f4acf7cc75',
[ChainId.Ropsten]: '0xAa213dcDFbF104e08cbAeC3d1628eD197553AfCc', [ChainId.Ropsten]: '0xae241c6fc7f28f6dc0cb58b4112ba7f63fcaf5e2',
}, },
NULL_ADDRESS, NULL_ADDRESS,
); );
export const MAKER_PSM_INFO_BY_CHAIN_ID = valueByChainId<PsmInfo>(
{
[ChainId.Mainnet]: {
// Currently only USDC is supported
gemTokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
ilkIdentifier: formatBytes32String('PSM-USDC-A'),
psmAddress: '0x89b78cfa322f6c5de0abceecab66aee45393cc5a',
},
},
{
gemTokenAddress: NULL_ADDRESS,
ilkIdentifier: NULL_BYTES,
psmAddress: NULL_ADDRESS,
},
);
export const MOONISWAP_LIQUIDITY_PROVIDER_BY_CHAIN_ID = valueByChainId<string>( export const MOONISWAP_LIQUIDITY_PROVIDER_BY_CHAIN_ID = valueByChainId<string>(
{ {
[ChainId.Mainnet]: '0xa2033d6ba88756ce6a87584d69dc87bda9a4f889', [ChainId.Mainnet]: '0xa2033d6ba88756ce6a87584d69dc87bda9a4f889',
@ -776,7 +797,7 @@ export const BAKERYSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = { export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
[ERC20BridgeSource.Native]: fillData => { [ERC20BridgeSource.Native]: fillData => {
// TODO jacob re-order imports so there is no circular rependency with SignedNativeOrder // TODO jacob re-order imports so there is no circular rependency with SignedNativeOrder
const nativeFillData = fillData as ({ type: FillQuoteTransformerOrderType }); const nativeFillData = fillData as { type: FillQuoteTransformerOrderType };
return nativeFillData && nativeFillData.type === FillQuoteTransformerOrderType.Limit return nativeFillData && nativeFillData.type === FillQuoteTransformerOrderType.Limit
? PROTOCOL_FEE_MULTIPLIER.plus(100e3).toNumber() ? PROTOCOL_FEE_MULTIPLIER.plus(100e3).toNumber()
: // TODO jacob revisit wth v4 LimitOrders : // TODO jacob revisit wth v4 LimitOrders
@ -863,6 +884,16 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
[ERC20BridgeSource.Balancer]: () => 120e3, [ERC20BridgeSource.Balancer]: () => 120e3,
[ERC20BridgeSource.Cream]: () => 120e3, [ERC20BridgeSource.Cream]: () => 120e3,
[ERC20BridgeSource.MStable]: () => 700e3, [ERC20BridgeSource.MStable]: () => 700e3,
[ERC20BridgeSource.MakerPsm]: (fillData?: FillData) => {
const psmFillData = fillData as MakerPsmFillData;
// TODO(kimpers): update with more accurate numbers after allowances have been set
if (psmFillData.takerToken === psmFillData.gemTokenAddress) {
return psmFillData.isSellOperation ? 389e3 : 423e3;
} else {
return 444e3;
}
},
[ERC20BridgeSource.Mooniswap]: () => 130e3, [ERC20BridgeSource.Mooniswap]: () => 130e3,
[ERC20BridgeSource.Swerve]: () => 150e3, [ERC20BridgeSource.Swerve]: () => 150e3,
[ERC20BridgeSource.Nerve]: () => 150e3, [ERC20BridgeSource.Nerve]: () => 150e3,

View File

@ -16,6 +16,7 @@ import {
GenericRouterFillData, GenericRouterFillData,
KyberFillData, KyberFillData,
LiquidityProviderFillData, LiquidityProviderFillData,
MakerPsmFillData,
MooniswapFillData, MooniswapFillData,
MultiHopFillData, MultiHopFillData,
NativeCollapsedFill, NativeCollapsedFill,
@ -91,6 +92,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
case ERC20BridgeSource.LiquidityProvider: case ERC20BridgeSource.LiquidityProvider:
// "LiquidityProvider" is too long to encode (17 characters). // "LiquidityProvider" is too long to encode (17 characters).
return encodeBridgeSourceId(BridgeProtocol.Unknown, 'LP'); return encodeBridgeSourceId(BridgeProtocol.Unknown, 'LP');
case ERC20BridgeSource.MakerPsm:
return encodeBridgeSourceId(BridgeProtocol.MakerPsm, 'MakerPsm');
case ERC20BridgeSource.Mooniswap: case ERC20BridgeSource.Mooniswap:
return encodeBridgeSourceId(BridgeProtocol.Mooniswap, 'Mooniswap'); return encodeBridgeSourceId(BridgeProtocol.Mooniswap, 'Mooniswap');
case ERC20BridgeSource.MStable: case ERC20BridgeSource.MStable:
@ -216,6 +219,10 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
const mStableFillData = (order as OptimizedMarketBridgeOrder<GenericRouterFillData>).fillData; const mStableFillData = (order as OptimizedMarketBridgeOrder<GenericRouterFillData>).fillData;
bridgeData = encoder.encode([mStableFillData.router]); bridgeData = encoder.encode([mStableFillData.router]);
break; break;
case ERC20BridgeSource.MakerPsm:
const psmFillData = (order as OptimizedMarketBridgeOrder<MakerPsmFillData>).fillData;
bridgeData = encoder.encode([psmFillData.psmAddress, psmFillData.gemTokenAddress]);
break;
default: default:
throw new Error(AggregationError.NoBridgeForSource); throw new Error(AggregationError.NoBridgeForSource);
} }
@ -255,6 +262,10 @@ const curveEncoder = AbiEncoder.create([
{ name: 'fromTokenIdx', type: 'int128' }, { name: 'fromTokenIdx', type: 'int128' },
{ name: 'toTokenIdx', type: 'int128' }, { name: 'toTokenIdx', type: 'int128' },
]); ]);
const makerPsmEncoder = AbiEncoder.create([
{ name: 'psmAddress', type: 'address' },
{ name: 'gemTokenAddress', type: 'address' },
]);
const routerAddressPathEncoder = AbiEncoder.create('(address,address[])'); const routerAddressPathEncoder = AbiEncoder.create('(address,address[])');
const tokenAddressEncoder = AbiEncoder.create([{ name: 'tokenAddress', type: 'address' }]); const tokenAddressEncoder = AbiEncoder.create([{ name: 'tokenAddress', type: 'address' }]);
@ -302,6 +313,8 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.Balancer]: poolEncoder, [ERC20BridgeSource.Balancer]: poolEncoder,
[ERC20BridgeSource.Cream]: poolEncoder, [ERC20BridgeSource.Cream]: poolEncoder,
[ERC20BridgeSource.Uniswap]: poolEncoder, [ERC20BridgeSource.Uniswap]: poolEncoder,
// Custom integrations
[ERC20BridgeSource.MakerPsm]: makerPsmEncoder,
// BSC // BSC
[ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder, [ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.BakerySwap]: routerAddressPathEncoder, [ERC20BridgeSource.BakerySwap]: routerAddressPathEncoder,

View File

@ -25,6 +25,7 @@ import {
KYBER_CONFIG_BY_CHAIN_ID, KYBER_CONFIG_BY_CHAIN_ID,
LINKSWAP_ROUTER_BY_CHAIN_ID, LINKSWAP_ROUTER_BY_CHAIN_ID,
LIQUIDITY_PROVIDER_REGISTRY, LIQUIDITY_PROVIDER_REGISTRY,
MAKER_PSM_INFO_BY_CHAIN_ID,
MAX_UINT256, MAX_UINT256,
MOONISWAP_REGISTRIES_BY_CHAIN_ID, MOONISWAP_REGISTRIES_BY_CHAIN_ID,
MSTABLE_ROUTER_BY_CHAIN_ID, MSTABLE_ROUTER_BY_CHAIN_ID,
@ -57,8 +58,10 @@ import {
KyberSamplerOpts, KyberSamplerOpts,
LiquidityProviderFillData, LiquidityProviderFillData,
LiquidityProviderRegistry, LiquidityProviderRegistry,
MakerPsmFillData,
MooniswapFillData, MooniswapFillData,
MultiHopFillData, MultiHopFillData,
PsmInfo,
ShellFillData, ShellFillData,
SourceQuoteOperation, SourceQuoteOperation,
TokenAdjacencyGraph, TokenAdjacencyGraph,
@ -857,6 +860,46 @@ export class SamplerOperations {
}); });
} }
public getMakerPsmSellQuotes(
psmInfo: PsmInfo,
makerToken: string,
takerToken: string,
takerFillAmounts: BigNumber[],
): SourceQuoteOperation<MakerPsmFillData> {
return new SamplerContractOperation({
source: ERC20BridgeSource.MakerPsm,
fillData: {
isSellOperation: true,
takerToken,
makerToken,
...psmInfo,
},
contract: this._samplerContract,
function: this._samplerContract.sampleSellsFromMakerPsm,
params: [psmInfo, takerToken, makerToken, takerFillAmounts],
});
}
public getMakerPsmBuyQuotes(
psmInfo: PsmInfo,
makerToken: string,
takerToken: string,
makerFillAmounts: BigNumber[],
): SourceQuoteOperation<MakerPsmFillData> {
return new SamplerContractOperation({
source: ERC20BridgeSource.MakerPsm,
fillData: {
isSellOperation: false,
takerToken,
makerToken,
...psmInfo,
},
contract: this._samplerContract,
function: this._samplerContract.sampleBuysFromMakerPsm,
params: [psmInfo, takerToken, makerToken, makerFillAmounts],
});
}
public getMedianSellRate( public getMedianSellRate(
sources: ERC20BridgeSource[], sources: ERC20BridgeSource[],
makerToken: string, makerToken: string,
@ -1118,6 +1161,12 @@ export class SamplerOperations {
ERC20BridgeSource.Linkswap, ERC20BridgeSource.Linkswap,
), ),
); );
case ERC20BridgeSource.MakerPsm:
const psmInfo = MAKER_PSM_INFO_BY_CHAIN_ID[this.chainId];
if (!isValidAddress(psmInfo.psmAddress)) {
return [];
}
return this.getMakerPsmSellQuotes(psmInfo, makerToken, takerToken, takerFillAmounts);
default: default:
throw new Error(`Unsupported sell sample source: ${source}`); throw new Error(`Unsupported sell sample source: ${source}`);
} }
@ -1298,6 +1347,12 @@ export class SamplerOperations {
ERC20BridgeSource.Linkswap, ERC20BridgeSource.Linkswap,
), ),
); );
case ERC20BridgeSource.MakerPsm:
const psmInfo = MAKER_PSM_INFO_BY_CHAIN_ID[this.chainId];
if (!isValidAddress(psmInfo.psmAddress)) {
return [];
}
return this.getMakerPsmBuyQuotes(psmInfo, makerToken, takerToken, makerFillAmounts);
default: default:
throw new Error(`Unsupported buy sample source: ${source}`); throw new Error(`Unsupported buy sample source: ${source}`);
} }

View File

@ -47,6 +47,7 @@ export enum ERC20BridgeSource {
Balancer = 'Balancer', Balancer = 'Balancer',
Cream = 'CREAM', Cream = 'CREAM',
Bancor = 'Bancor', Bancor = 'Bancor',
MakerPsm = 'MakerPsm',
MStable = 'mStable', MStable = 'mStable',
Mooniswap = 'Mooniswap', Mooniswap = 'Mooniswap',
MultiHop = 'MultiHop', MultiHop = 'MultiHop',
@ -96,6 +97,15 @@ export interface CurveInfo {
metaToken: string | undefined; metaToken: string | undefined;
} }
/**
* Configuration for a specific PSM vault
*/
export interface PsmInfo {
psmAddress: string;
ilkIdentifier: string;
gemTokenAddress: string;
}
// Internal `fillData` field for `Fill` objects. // Internal `fillData` field for `Fill` objects.
export interface FillData {} export interface FillData {}
@ -165,6 +175,14 @@ export interface MultiHopFillData extends FillData {
secondHopSource: SourceQuoteOperation; secondHopSource: SourceQuoteOperation;
intermediateToken: string; intermediateToken: string;
} }
export interface MakerPsmExtendedData {
isSellOperation: boolean;
takerToken: string;
}
export type MakerPsmFillData = FillData & MakerPsmExtendedData & PsmInfo;
export interface HopInfo { export interface HopInfo {
sourceIndex: BigNumber; sourceIndex: BigNumber;
returnData: string; returnData: string;

View File

@ -29,6 +29,7 @@ import * as IUniswapExchangeQuotes from '../test/generated-artifacts/IUniswapExc
import * as IUniswapV2Router01 from '../test/generated-artifacts/IUniswapV2Router01.json'; import * as IUniswapV2Router01 from '../test/generated-artifacts/IUniswapV2Router01.json';
import * as KyberSampler from '../test/generated-artifacts/KyberSampler.json'; import * as KyberSampler from '../test/generated-artifacts/KyberSampler.json';
import * as LiquidityProviderSampler from '../test/generated-artifacts/LiquidityProviderSampler.json'; import * as LiquidityProviderSampler from '../test/generated-artifacts/LiquidityProviderSampler.json';
import * as MakerPSMSampler from '../test/generated-artifacts/MakerPSMSampler.json';
import * as MooniswapSampler from '../test/generated-artifacts/MooniswapSampler.json'; import * as MooniswapSampler from '../test/generated-artifacts/MooniswapSampler.json';
import * as MStableSampler from '../test/generated-artifacts/MStableSampler.json'; import * as MStableSampler from '../test/generated-artifacts/MStableSampler.json';
import * as MultiBridgeSampler from '../test/generated-artifacts/MultiBridgeSampler.json'; import * as MultiBridgeSampler from '../test/generated-artifacts/MultiBridgeSampler.json';
@ -55,6 +56,7 @@ export const artifacts = {
KyberSampler: KyberSampler as ContractArtifact, KyberSampler: KyberSampler as ContractArtifact,
LiquidityProviderSampler: LiquidityProviderSampler as ContractArtifact, LiquidityProviderSampler: LiquidityProviderSampler as ContractArtifact,
MStableSampler: MStableSampler as ContractArtifact, MStableSampler: MStableSampler as ContractArtifact,
MakerPSMSampler: MakerPSMSampler as ContractArtifact,
MooniswapSampler: MooniswapSampler as ContractArtifact, MooniswapSampler: MooniswapSampler as ContractArtifact,
MultiBridgeSampler: MultiBridgeSampler as ContractArtifact, MultiBridgeSampler: MultiBridgeSampler as ContractArtifact,
NativeOrderSampler: NativeOrderSampler as ContractArtifact, NativeOrderSampler: NativeOrderSampler as ContractArtifact,

View File

@ -67,6 +67,7 @@ const DEFAULT_EXCLUDED = [
ERC20BridgeSource.Linkswap, ERC20BridgeSource.Linkswap,
ERC20BridgeSource.PancakeSwap, ERC20BridgeSource.PancakeSwap,
ERC20BridgeSource.BakerySwap, ERC20BridgeSource.BakerySwap,
ERC20BridgeSource.MakerPsm,
]; ];
const BUY_SOURCES = BUY_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources; const BUY_SOURCES = BUY_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources;
const SELL_SOURCES = SELL_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources; const SELL_SOURCES = SELL_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources;
@ -305,6 +306,7 @@ describe('MarketOperationUtils tests', () => {
[ERC20BridgeSource.Linkswap]: _.times(NUM_SAMPLES, () => 0), [ERC20BridgeSource.Linkswap]: _.times(NUM_SAMPLES, () => 0),
[ERC20BridgeSource.PancakeSwap]: _.times(NUM_SAMPLES, () => 0), [ERC20BridgeSource.PancakeSwap]: _.times(NUM_SAMPLES, () => 0),
[ERC20BridgeSource.BakerySwap]: _.times(NUM_SAMPLES, () => 0), [ERC20BridgeSource.BakerySwap]: _.times(NUM_SAMPLES, () => 0),
[ERC20BridgeSource.MakerPsm]: _.times(NUM_SAMPLES, () => 0),
}; };
const DEFAULT_RATES: RatesBySource = { const DEFAULT_RATES: RatesBySource = {
@ -369,6 +371,7 @@ describe('MarketOperationUtils tests', () => {
[ERC20BridgeSource.Linkswap]: { tokenAddressPath: [] }, [ERC20BridgeSource.Linkswap]: { tokenAddressPath: [] },
[ERC20BridgeSource.Uniswap]: { router: randomAddress() }, [ERC20BridgeSource.Uniswap]: { router: randomAddress() },
[ERC20BridgeSource.Eth2Dai]: { router: randomAddress() }, [ERC20BridgeSource.Eth2Dai]: { router: randomAddress() },
[ERC20BridgeSource.MakerPsm]: {},
}; };
const DEFAULT_OPS = { const DEFAULT_OPS = {

View File

@ -28,6 +28,7 @@ export * from '../test/generated-wrappers/i_uniswap_v2_router01';
export * from '../test/generated-wrappers/kyber_sampler'; export * from '../test/generated-wrappers/kyber_sampler';
export * from '../test/generated-wrappers/liquidity_provider_sampler'; export * from '../test/generated-wrappers/liquidity_provider_sampler';
export * from '../test/generated-wrappers/m_stable_sampler'; export * from '../test/generated-wrappers/m_stable_sampler';
export * from '../test/generated-wrappers/maker_p_s_m_sampler';
export * from '../test/generated-wrappers/mooniswap_sampler'; export * from '../test/generated-wrappers/mooniswap_sampler';
export * from '../test/generated-wrappers/multi_bridge_sampler'; export * from '../test/generated-wrappers/multi_bridge_sampler';
export * from '../test/generated-wrappers/native_order_sampler'; export * from '../test/generated-wrappers/native_order_sampler';

View File

@ -31,6 +31,7 @@
"test/generated-artifacts/KyberSampler.json", "test/generated-artifacts/KyberSampler.json",
"test/generated-artifacts/LiquidityProviderSampler.json", "test/generated-artifacts/LiquidityProviderSampler.json",
"test/generated-artifacts/MStableSampler.json", "test/generated-artifacts/MStableSampler.json",
"test/generated-artifacts/MakerPSMSampler.json",
"test/generated-artifacts/MooniswapSampler.json", "test/generated-artifacts/MooniswapSampler.json",
"test/generated-artifacts/MultiBridgeSampler.json", "test/generated-artifacts/MultiBridgeSampler.json",
"test/generated-artifacts/NativeOrderSampler.json", "test/generated-artifacts/NativeOrderSampler.json",

View File

@ -1,6 +1,6 @@
[ [
{ {
"version": "6.0.0-bsc.0", "version": "6.0.0",
"changes": [ "changes": [
{ {
"note": "Add BSC chain addresses", "note": "Add BSC chain addresses",
@ -13,6 +13,10 @@
{ {
"note": "Redeployed FQT on BSC", "note": "Redeployed FQT on BSC",
"pr": 181 "pr": 181
},
{
"note": "Redeployed FQT on mainnet and ropsten",
"pr": 150
} }
] ]
}, },

View File

@ -36,7 +36,7 @@
"wethTransformer": "0xb2bc06a4efb20fc6553a69dbfa49b7be938034a7", "wethTransformer": "0xb2bc06a4efb20fc6553a69dbfa49b7be938034a7",
"payTakerTransformer": "0x4638a7ebe75b911b995d0ec73a81e4f85f41f24e", "payTakerTransformer": "0x4638a7ebe75b911b995d0ec73a81e4f85f41f24e",
"affiliateFeeTransformer": "0xda6d9fc5998f550a094585cf9171f0e8ee3ac59f", "affiliateFeeTransformer": "0xda6d9fc5998f550a094585cf9171f0e8ee3ac59f",
"fillQuoteTransformer": "0x227e767a9b7517681d1cb6b846aa9e541484c7ab", "fillQuoteTransformer": "0xb8e40acea68db2a7a2020a3eba2664ba4c3b3e3d",
"positiveSlippageFeeTransformer": "0xa9416ce1dbde8d331210c07b5c253d94ee4cc3fd" "positiveSlippageFeeTransformer": "0xa9416ce1dbde8d331210c07b5c253d94ee4cc3fd"
} }
}, },
@ -77,7 +77,7 @@
"wethTransformer": "0x05ad19aa3826e0609a19568ffbd1dfe86c6c7184", "wethTransformer": "0x05ad19aa3826e0609a19568ffbd1dfe86c6c7184",
"payTakerTransformer": "0x6d0ebf2bcd9cc93ec553b60ad201943dcca4e291", "payTakerTransformer": "0x6d0ebf2bcd9cc93ec553b60ad201943dcca4e291",
"affiliateFeeTransformer": "0x6588256778ca4432fa43983ac685c45efb2379e2", "affiliateFeeTransformer": "0x6588256778ca4432fa43983ac685c45efb2379e2",
"fillQuoteTransformer": "0x2088a820787ebbe937a0612ef024f1e1d65f9784", "fillQuoteTransformer": "0xc0c6fc6911978a65fe3b17391bb30b630bfc637d",
"positiveSlippageFeeTransformer": "0x8b332f700fd37e71c5c5b26c4d78b5ca63dd33b2" "positiveSlippageFeeTransformer": "0x8b332f700fd37e71c5c5b26c4d78b5ca63dd33b2"
} }
}, },

View File

@ -125,6 +125,7 @@ export enum BridgeProtocol {
Bancor, Bancor,
CoFiX, CoFiX,
Nerve, Nerve,
MakerPsm,
} }
// tslint:enable: enum-naming // tslint:enable: enum-naming

View File

@ -646,7 +646,6 @@
"@0x/abi-gen@^5.4.21": "@0x/abi-gen@^5.4.21":
version "5.4.21" version "5.4.21"
resolved "https://registry.yarnpkg.com/@0x/abi-gen/-/abi-gen-5.4.21.tgz#96705962c75e116bd5050784287012ede4607564" resolved "https://registry.yarnpkg.com/@0x/abi-gen/-/abi-gen-5.4.21.tgz#96705962c75e116bd5050784287012ede4607564"
integrity sha512-rJPzWUjCeygMC71HfyGQAEeYtfkv5Mi+cjIOrmWfTQmM4SN+6wBraEWKLJHkcFTZ3lmFjkS/ZfbGhQere6/Y4w==
dependencies: dependencies:
"@0x/types" "^3.3.1" "@0x/types" "^3.3.1"
"@0x/typescript-typings" "^5.1.6" "@0x/typescript-typings" "^5.1.6"
@ -712,7 +711,6 @@
"@0x/contracts-gen@^2.0.32": "@0x/contracts-gen@^2.0.32":
version "2.0.32" version "2.0.32"
resolved "https://registry.yarnpkg.com/@0x/contracts-gen/-/contracts-gen-2.0.32.tgz#e4817730685acc0047157e55d58a6cab87596799" resolved "https://registry.yarnpkg.com/@0x/contracts-gen/-/contracts-gen-2.0.32.tgz#e4817730685acc0047157e55d58a6cab87596799"
integrity sha512-FkdCn9L48u6M2WyyQOWuDFvmqvYIfv1O47Hlwf8MGVJaxGmhDhqJsCr4HlmE4Jg84dK7I7xIeh0MMs8jPNpRUA==
dependencies: dependencies:
"@0x/sol-compiler" "^4.6.1" "@0x/sol-compiler" "^4.6.1"
"@0x/sol-resolver" "^3.1.6" "@0x/sol-resolver" "^3.1.6"
@ -805,7 +803,6 @@
"@0x/monorepo-scripts@^3.1.1": "@0x/monorepo-scripts@^3.1.1":
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/@0x/monorepo-scripts/-/monorepo-scripts-3.1.1.tgz#2ded9ef1d4885bbf106612794a331e29f391733a" resolved "https://registry.yarnpkg.com/@0x/monorepo-scripts/-/monorepo-scripts-3.1.1.tgz#2ded9ef1d4885bbf106612794a331e29f391733a"
integrity sha512-thovxmZMivSeESlY+FXLxkf4wrmLe40ZjfGOcJaPhe29me03ddgEtVgToi+k7ZGfTeRWm5gmvlisHak2D6TFwA==
dependencies: dependencies:
"@0x/types" "^3.3.1" "@0x/types" "^3.3.1"
"@0x/utils" "^6.2.0" "@0x/utils" "^6.2.0"
@ -847,7 +844,6 @@
"@0x/sol-compiler@^4.6.1": "@0x/sol-compiler@^4.6.1":
version "4.6.1" version "4.6.1"
resolved "https://registry.yarnpkg.com/@0x/sol-compiler/-/sol-compiler-4.6.1.tgz#d1f9c1547605ddbd4ad9cc6ebed60b91f5e1ce3d" resolved "https://registry.yarnpkg.com/@0x/sol-compiler/-/sol-compiler-4.6.1.tgz#d1f9c1547605ddbd4ad9cc6ebed60b91f5e1ce3d"
integrity sha512-iEFcrn+5OSNCD2yr0WjF9h0+0J/0DNNpEuc1yK5OAD6F4X6U/YChYohSx/odWNhYfJODW+dj1SABWxZfybgIwQ==
dependencies: dependencies:
"@0x/assert" "^3.0.21" "@0x/assert" "^3.0.21"
"@0x/json-schemas" "^5.4.1" "@0x/json-schemas" "^5.4.1"
@ -876,7 +872,6 @@
"@0x/sol-coverage@^4.0.31": "@0x/sol-coverage@^4.0.31":
version "4.0.31" version "4.0.31"
resolved "https://registry.yarnpkg.com/@0x/sol-coverage/-/sol-coverage-4.0.31.tgz#ec958d892dce3773059b925e442e21d7c4f9b104" resolved "https://registry.yarnpkg.com/@0x/sol-coverage/-/sol-coverage-4.0.31.tgz#ec958d892dce3773059b925e442e21d7c4f9b104"
integrity sha512-XcD2MntdpjDAV2KWmZyD6T3dI2sgaXwBXVa/cRtlC0cUAJcXp+tblwvtt1VOxc2J6QFCaTG4UTs9oS2nGbxwbA==
dependencies: dependencies:
"@0x/sol-tracing-utils" "^7.1.21" "@0x/sol-tracing-utils" "^7.1.21"
"@0x/subproviders" "^6.4.1" "@0x/subproviders" "^6.4.1"
@ -891,7 +886,6 @@
"@0x/sol-profiler@^4.1.21": "@0x/sol-profiler@^4.1.21":
version "4.1.21" version "4.1.21"
resolved "https://registry.yarnpkg.com/@0x/sol-profiler/-/sol-profiler-4.1.21.tgz#76f4860b3e0c73b8e11ac56ce25e52164cee1476" resolved "https://registry.yarnpkg.com/@0x/sol-profiler/-/sol-profiler-4.1.21.tgz#76f4860b3e0c73b8e11ac56ce25e52164cee1476"
integrity sha512-JFDUhFrWJP1WqVIKK1w/2nU/s8g91xNeZW1l4ZydEGhZPsRNgQdk8rFBwGqxPeqMqUY7T+Xm2Y/IVjYvE+Ck3w==
dependencies: dependencies:
"@0x/sol-tracing-utils" "^7.1.21" "@0x/sol-tracing-utils" "^7.1.21"
"@0x/subproviders" "^6.4.1" "@0x/subproviders" "^6.4.1"
@ -915,7 +909,6 @@
"@0x/sol-trace@^3.0.31": "@0x/sol-trace@^3.0.31":
version "3.0.31" version "3.0.31"
resolved "https://registry.yarnpkg.com/@0x/sol-trace/-/sol-trace-3.0.31.tgz#9ed79139c81ad8953a9947019053ead5a20f9408" resolved "https://registry.yarnpkg.com/@0x/sol-trace/-/sol-trace-3.0.31.tgz#9ed79139c81ad8953a9947019053ead5a20f9408"
integrity sha512-wQjdVc/IOcyzIfDVfurzFQuhkZlnejwNVNWn+9S6uYXteIqgHcJv0WqD5dZNFxcNG4Jn7tXxHJ/AXxXDygM+cw==
dependencies: dependencies:
"@0x/sol-tracing-utils" "^7.1.21" "@0x/sol-tracing-utils" "^7.1.21"
"@0x/subproviders" "^6.4.1" "@0x/subproviders" "^6.4.1"
@ -931,7 +924,6 @@
"@0x/sol-tracing-utils@^7.1.21": "@0x/sol-tracing-utils@^7.1.21":
version "7.1.21" version "7.1.21"
resolved "https://registry.yarnpkg.com/@0x/sol-tracing-utils/-/sol-tracing-utils-7.1.21.tgz#9ffb9f51fdc6bcf0be8f95841563a6ccccbac474" resolved "https://registry.yarnpkg.com/@0x/sol-tracing-utils/-/sol-tracing-utils-7.1.21.tgz#9ffb9f51fdc6bcf0be8f95841563a6ccccbac474"
integrity sha512-Y0aYJD1h+0IBZe7A9FKorhf7qtWawftahV61FjPCOaHfvQNfVeza7wm9hdMYOb+B2hbFCDFo06GfZaINw7VFVA==
dependencies: dependencies:
"@0x/dev-utils" "^4.2.1" "@0x/dev-utils" "^4.2.1"
"@0x/sol-compiler" "^4.6.1" "@0x/sol-compiler" "^4.6.1"
@ -1311,18 +1303,38 @@
"@ethersproject/logger" "^5.0.5" "@ethersproject/logger" "^5.0.5"
bn.js "^4.4.0" bn.js "^4.4.0"
"@ethersproject/bignumber@^5.0.13":
version "5.0.15"
resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.15.tgz#b089b3f1e0381338d764ac1c10512f0c93b184ed"
dependencies:
"@ethersproject/bytes" "^5.0.9"
"@ethersproject/logger" "^5.0.8"
bn.js "^4.4.0"
"@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4": "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4":
version "5.0.5" version "5.0.5"
resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.5.tgz#688b70000e550de0c97a151a21f15b87d7f97d7c" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.5.tgz#688b70000e550de0c97a151a21f15b87d7f97d7c"
dependencies: dependencies:
"@ethersproject/logger" "^5.0.5" "@ethersproject/logger" "^5.0.5"
"@ethersproject/bytes@^5.0.9":
version "5.0.11"
resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.11.tgz#21118e75b1d00db068984c15530e316021101276"
dependencies:
"@ethersproject/logger" "^5.0.8"
"@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4": "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4":
version "5.0.5" version "5.0.5"
resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.5.tgz#0ed19b002e8404bdf6d135234dc86a7d9bcf9b71" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.5.tgz#0ed19b002e8404bdf6d135234dc86a7d9bcf9b71"
dependencies: dependencies:
"@ethersproject/bignumber" "^5.0.7" "@ethersproject/bignumber" "^5.0.7"
"@ethersproject/constants@^5.0.8":
version "5.0.10"
resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.10.tgz#eb0c604fbc44c53ba9641eed31a1d0c9e1ebcadc"
dependencies:
"@ethersproject/bignumber" "^5.0.13"
"@ethersproject/contracts@^5.0.1": "@ethersproject/contracts@^5.0.1":
version "5.0.5" version "5.0.5"
resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.0.5.tgz#64831a341ec8ca225e83ff3e9437c26b970fd5d7" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.0.5.tgz#64831a341ec8ca225e83ff3e9437c26b970fd5d7"
@ -1361,6 +1373,10 @@
version "5.0.6" version "5.0.6"
resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.6.tgz#faa484203e86e08be9e07fef826afeef7183fe88" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.6.tgz#faa484203e86e08be9e07fef826afeef7183fe88"
"@ethersproject/logger@^5.0.8":
version "5.0.10"
resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.10.tgz#fd884688b3143253e0356ef92d5f22d109d2e026"
"@ethersproject/networks@^5.0.3": "@ethersproject/networks@^5.0.3":
version "5.0.4" version "5.0.4"
resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.0.4.tgz#6d320a5e15a0cda804f5da88be0ba846156f6eec" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.0.4.tgz#6d320a5e15a0cda804f5da88be0ba846156f6eec"
@ -1436,6 +1452,14 @@
"@ethersproject/constants" "^5.0.4" "@ethersproject/constants" "^5.0.4"
"@ethersproject/logger" "^5.0.5" "@ethersproject/logger" "^5.0.5"
"@ethersproject/strings@^5.0.10":
version "5.0.10"
resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.0.10.tgz#ddce1e9724f4ac4f3f67e0cac0b48748e964bfdb"
dependencies:
"@ethersproject/bytes" "^5.0.9"
"@ethersproject/constants" "^5.0.8"
"@ethersproject/logger" "^5.0.8"
"@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.0.5": "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.0.5":
version "5.0.6" version "5.0.6"
resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.0.6.tgz#b8b27938be6e9ed671dbdd35fe98af8b14d0df7c" resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.0.6.tgz#b8b27938be6e9ed671dbdd35fe98af8b14d0df7c"
@ -2995,7 +3019,6 @@ aws4@^1.8.0:
axios-mock-adapter@^1.19.0: axios-mock-adapter@^1.19.0:
version "1.19.0" version "1.19.0"
resolved "https://registry.yarnpkg.com/axios-mock-adapter/-/axios-mock-adapter-1.19.0.tgz#9d72e321a6c5418e1eff067aa99761a86c5188a4" resolved "https://registry.yarnpkg.com/axios-mock-adapter/-/axios-mock-adapter-1.19.0.tgz#9d72e321a6c5418e1eff067aa99761a86c5188a4"
integrity sha512-D+0U4LNPr7WroiBDvWilzTMYPYTuZlbo6BI8YHZtj7wYQS8NkARlP9KBt8IWWHTQJ0q/8oZ0ClPBtKCCkx8cQg==
dependencies: dependencies:
fast-deep-equal "^3.1.3" fast-deep-equal "^3.1.3"
is-buffer "^2.0.3" is-buffer "^2.0.3"
@ -3003,7 +3026,6 @@ axios-mock-adapter@^1.19.0:
axios@^0.21.1: axios@^0.21.1:
version "0.21.1" version "0.21.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
dependencies: dependencies:
follow-redirects "^1.10.0" follow-redirects "^1.10.0"
@ -6359,7 +6381,6 @@ flush-write-stream@^1.0.0, flush-write-stream@^1.0.2:
follow-redirects@^1.10.0: follow-redirects@^1.10.0:
version "1.13.3" version "1.13.3"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267"
integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==
for-each@~0.3.3: for-each@~0.3.3:
version "0.3.3" version "0.3.3"
@ -11692,7 +11713,6 @@ strip-bom@^3.0.0:
strip-comments@^2.0.1: strip-comments@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-2.0.1.tgz#4ad11c3fbcac177a67a40ac224ca339ca1c1ba9b" resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-2.0.1.tgz#4ad11c3fbcac177a67a40ac224ca339ca1c1ba9b"
integrity sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==
strip-dirs@^2.0.0: strip-dirs@^2.0.0:
version "2.1.0" version "2.1.0"