@0x/asset-swapper: Return Mooniswap pool in sampler and encode it in bridge data
				
					
				
			This commit is contained in:
		@@ -97,6 +97,10 @@
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Set `rfqtTakerAddress` to null in EP consumer",
 | 
			
		||||
                "pr": 2692
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Return Mooniswap pool in sampler and encode it in bridge data",
 | 
			
		||||
                "pr": 2692
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -46,44 +46,31 @@ contract MooniswapSampler is
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256[] memory makerTokenAmounts)
 | 
			
		||||
        returns (IMooniswap pool, uint256[] memory makerTokenAmounts)
 | 
			
		||||
    {
 | 
			
		||||
        _assertValidPair(makerToken, takerToken);
 | 
			
		||||
        uint256 numSamples = takerTokenAmounts.length;
 | 
			
		||||
        makerTokenAmounts = new uint256[](numSamples);
 | 
			
		||||
 | 
			
		||||
        address _takerToken = takerToken == _getWethAddress() ? address(0) : takerToken;
 | 
			
		||||
        address _makerToken = makerToken == _getWethAddress() ? address(0) : makerToken;
 | 
			
		||||
        address mooniswapTakerToken = takerToken == _getWethAddress() ? address(0) : takerToken;
 | 
			
		||||
        address mooniswapMakerToken = makerToken == _getWethAddress() ? address(0) : makerToken;
 | 
			
		||||
        // Find the pool for the pair, ETH is represented
 | 
			
		||||
        // as address(0)
 | 
			
		||||
        IMooniswap pool = IMooniswap(
 | 
			
		||||
            IMooniswapRegistry(_getMooniswapAddress()).pools(_takerToken, _makerToken)
 | 
			
		||||
        pool = IMooniswap(
 | 
			
		||||
            IMooniswapRegistry(_getMooniswapAddress()).pools(mooniswapTakerToken, mooniswapMakerToken)
 | 
			
		||||
        );
 | 
			
		||||
        // If there is no pool then return early
 | 
			
		||||
        if (address(pool) == address(0)) {
 | 
			
		||||
            return makerTokenAmounts;
 | 
			
		||||
            return (pool, makerTokenAmounts);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        uint256 poolBalance = _takerToken == address(0) ? address(pool).balance : IERC20Token(_takerToken).balanceOf(address(pool));
 | 
			
		||||
 | 
			
		||||
        for (uint256 i = 0; i < numSamples; i++) {
 | 
			
		||||
            // If the pool balance is smaller than the sell amount
 | 
			
		||||
            // don't sample to avoid multiplication overflow in buys
 | 
			
		||||
            if (poolBalance < takerTokenAmounts[i]) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            (bool didSucceed, bytes memory resultData) =
 | 
			
		||||
                address(pool).staticcall.gas(MOONISWAP_CALL_GAS)(
 | 
			
		||||
                    abi.encodeWithSelector(
 | 
			
		||||
                        IMooniswap(0).getReturn.selector,
 | 
			
		||||
                        _takerToken,
 | 
			
		||||
                        _makerToken,
 | 
			
		||||
            uint256 buyAmount = sampleSingleSellFromMooniswapPool(
 | 
			
		||||
                pool,
 | 
			
		||||
                mooniswapTakerToken,
 | 
			
		||||
                mooniswapMakerToken,
 | 
			
		||||
                takerTokenAmounts[i]
 | 
			
		||||
                    ));
 | 
			
		||||
            uint256 buyAmount = 0;
 | 
			
		||||
            if (didSucceed) {
 | 
			
		||||
                buyAmount = abi.decode(resultData, (uint256));
 | 
			
		||||
            }
 | 
			
		||||
            );
 | 
			
		||||
            // Exit early if the amount is too high for the source to serve
 | 
			
		||||
            if (buyAmount == 0) {
 | 
			
		||||
                break;
 | 
			
		||||
@@ -92,6 +79,38 @@ contract MooniswapSampler is
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function sampleSingleSellFromMooniswapPool(
 | 
			
		||||
        IMooniswap pool,
 | 
			
		||||
        address mooniswapTakerToken,
 | 
			
		||||
        address mooniswapMakerToken,
 | 
			
		||||
        uint256 takerTokenAmount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 makerTokenAmount)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 poolBalance = mooniswapTakerToken == address(0)
 | 
			
		||||
            ? address(pool).balance
 | 
			
		||||
            : IERC20Token(mooniswapTakerToken).balanceOf(address(pool));
 | 
			
		||||
 | 
			
		||||
        // If the pool balance is smaller than the sell amount
 | 
			
		||||
        // don't sample to avoid multiplication overflow in buys
 | 
			
		||||
        if (poolBalance < takerTokenAmount) {
 | 
			
		||||
            return makerTokenAmount;
 | 
			
		||||
        }
 | 
			
		||||
        (bool didSucceed, bytes memory resultData) =
 | 
			
		||||
            address(pool).staticcall.gas(MOONISWAP_CALL_GAS)(
 | 
			
		||||
                abi.encodeWithSelector(
 | 
			
		||||
                    IMooniswap(0).getReturn.selector,
 | 
			
		||||
                    mooniswapTakerToken,
 | 
			
		||||
                    mooniswapMakerToken,
 | 
			
		||||
                    takerTokenAmount
 | 
			
		||||
                ));
 | 
			
		||||
        if (didSucceed) {
 | 
			
		||||
            makerTokenAmount = abi.decode(resultData, (uint256));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Sample buy quotes from Mooniswap.
 | 
			
		||||
    /// @param takerToken Address of the taker token (what to sell).
 | 
			
		||||
    /// @param makerToken Address of the maker token (what to buy).
 | 
			
		||||
@@ -105,12 +124,28 @@ contract MooniswapSampler is
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256[] memory takerTokenAmounts)
 | 
			
		||||
        returns (IMooniswap pool, uint256[] memory takerTokenAmounts)
 | 
			
		||||
    {
 | 
			
		||||
        return _sampleApproximateBuys(
 | 
			
		||||
        _assertValidPair(makerToken, takerToken);
 | 
			
		||||
        uint256 numSamples = takerTokenAmounts.length;
 | 
			
		||||
        makerTokenAmounts = new uint256[](numSamples);
 | 
			
		||||
 | 
			
		||||
        address mooniswapTakerToken = takerToken == _getWethAddress() ? address(0) : takerToken;
 | 
			
		||||
        address mooniswapMakerToken = makerToken == _getWethAddress() ? address(0) : makerToken;
 | 
			
		||||
        // Find the pool for the pair, ETH is represented
 | 
			
		||||
        // as address(0)
 | 
			
		||||
        pool = IMooniswap(
 | 
			
		||||
            IMooniswapRegistry(_getMooniswapAddress()).pools(mooniswapTakerToken, mooniswapMakerToken)
 | 
			
		||||
        );
 | 
			
		||||
        // If there is no pool then return early
 | 
			
		||||
        if (address(pool) == address(0)) {
 | 
			
		||||
            return (pool, takerTokenAmounts);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        takerTokenAmounts = _sampleApproximateBuys(
 | 
			
		||||
            ApproximateBuyQuoteOpts({
 | 
			
		||||
                makerTokenData: abi.encode(makerToken),
 | 
			
		||||
                takerTokenData: abi.encode(takerToken),
 | 
			
		||||
                makerTokenData: abi.encode(mooniswapMakerToken, pool),
 | 
			
		||||
                takerTokenData: abi.encode(mooniswapTakerToken, pool),
 | 
			
		||||
                getSellQuoteCallback: _sampleSellForApproximateBuyFromMooniswap
 | 
			
		||||
            }),
 | 
			
		||||
            makerTokenAmounts
 | 
			
		||||
@@ -126,15 +161,16 @@ contract MooniswapSampler is
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 buyAmount)
 | 
			
		||||
    {
 | 
			
		||||
        (address takerToken) =
 | 
			
		||||
            abi.decode(takerTokenData, (address));
 | 
			
		||||
        (address makerToken) =
 | 
			
		||||
        (address mooniswapTakerToken, IMooniswap pool) =
 | 
			
		||||
            abi.decode(takerTokenData, (address, IMooniswap));
 | 
			
		||||
        (address mooniswapMakerToken) =
 | 
			
		||||
            abi.decode(makerTokenData, (address));
 | 
			
		||||
        (bool success, bytes memory resultData) =
 | 
			
		||||
            address(this).staticcall(abi.encodeWithSelector(
 | 
			
		||||
                this.sampleSellsFromMooniswap.selector,
 | 
			
		||||
                takerToken,
 | 
			
		||||
                makerToken,
 | 
			
		||||
                this.sampleSingleSellFromMooniswapPool.selector,
 | 
			
		||||
                pool,
 | 
			
		||||
                mooniswapTakerToken,
 | 
			
		||||
                mooniswapMakerToken,
 | 
			
		||||
                _toSingleValueArray(sellAmount)
 | 
			
		||||
            ));
 | 
			
		||||
        if (!success) {
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@ import {
 | 
			
		||||
    Fill,
 | 
			
		||||
    KyberFillData,
 | 
			
		||||
    LiquidityProviderFillData,
 | 
			
		||||
    MooniswapFillData,
 | 
			
		||||
    MultiBridgeFillData,
 | 
			
		||||
    MultiHopFillData,
 | 
			
		||||
    NativeCollapsedFill,
 | 
			
		||||
@@ -304,6 +305,14 @@ function createBridgeOrder(
 | 
			
		||||
                createKyberBridgeData(takerToken, kyberFillData.hint),
 | 
			
		||||
            );
 | 
			
		||||
            break;
 | 
			
		||||
        case ERC20BridgeSource.Mooniswap:
 | 
			
		||||
            const mooniswapFillData = (fill as CollapsedFill<MooniswapFillData>).fillData!; // tslint:disable-line:no-non-null-assertion
 | 
			
		||||
            makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
 | 
			
		||||
                makerToken,
 | 
			
		||||
                bridgeAddress,
 | 
			
		||||
                createMooniswapBridgeData(takerToken, mooniswapFillData.poolAddress),
 | 
			
		||||
            );
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
 | 
			
		||||
                makerToken,
 | 
			
		||||
@@ -407,6 +416,11 @@ function createKyberBridgeData(fromTokenAddress: string, hint: string): string {
 | 
			
		||||
    return encoder.encode({ fromTokenAddress, hint });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createMooniswapBridgeData(takerToken: string, poolAddress: string): string {
 | 
			
		||||
    const encoder = AbiEncoder.create([{ name: 'takerToken', type: 'address' }, { name: 'pool', type: 'address' }]);
 | 
			
		||||
    return encoder.encode({ takerToken, poolAddress });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createCurveBridgeData(
 | 
			
		||||
    curveAddress: string,
 | 
			
		||||
    exchangeFunctionSelector: string,
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ import {
 | 
			
		||||
    HopInfo,
 | 
			
		||||
    KyberFillData,
 | 
			
		||||
    LiquidityProviderFillData,
 | 
			
		||||
    MooniswapFillData,
 | 
			
		||||
    MultiBridgeFillData,
 | 
			
		||||
    MultiHopFillData,
 | 
			
		||||
    SourceQuoteOperation,
 | 
			
		||||
@@ -446,6 +447,14 @@ export class SamplerOperations {
 | 
			
		||||
            contract: this._samplerContract,
 | 
			
		||||
            function: this._samplerContract.sampleSellsFromMooniswap,
 | 
			
		||||
            params: [takerToken, makerToken, takerFillAmounts],
 | 
			
		||||
            callback: (callResults: string, fillData: MooniswapFillData): BigNumber[] => {
 | 
			
		||||
                const [poolAddress, samples] = this._samplerContract.getABIDecodedReturnData<[string, BigNumber[]]>(
 | 
			
		||||
                    'sampleSellsFromMooniswap',
 | 
			
		||||
                    callResults,
 | 
			
		||||
                );
 | 
			
		||||
                fillData.poolAddress = poolAddress;
 | 
			
		||||
                return samples;
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -459,6 +468,14 @@ export class SamplerOperations {
 | 
			
		||||
            contract: this._samplerContract,
 | 
			
		||||
            function: this._samplerContract.sampleBuysFromMooniswap,
 | 
			
		||||
            params: [takerToken, makerToken, makerFillAmounts],
 | 
			
		||||
            callback: (callResults: string, fillData: MooniswapFillData): BigNumber[] => {
 | 
			
		||||
                const [poolAddress, samples] = this._samplerContract.getABIDecodedReturnData<[string, BigNumber[]]>(
 | 
			
		||||
                    'sampleBuysFromMooniswap',
 | 
			
		||||
                    callResults,
 | 
			
		||||
                );
 | 
			
		||||
                fillData.poolAddress = poolAddress;
 | 
			
		||||
                return samples;
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,10 @@ export interface KyberFillData extends FillData {
 | 
			
		||||
    reserveId: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface MooniswapFillData extends FillData {
 | 
			
		||||
    poolAddress: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Quote<TFillData = FillData> {
 | 
			
		||||
    amount: BigNumber;
 | 
			
		||||
    fillData?: TFillData;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user