diff --git a/.github/scripts/setup-hardhat-config.sh b/.github/scripts/setup-hardhat-config.sh
index 393f6d3a..792c0483 100755
--- a/.github/scripts/setup-hardhat-config.sh
+++ b/.github/scripts/setup-hardhat-config.sh
@@ -8,6 +8,7 @@ AVALANCHE_URL="$6"
BSC_URL="$7"
FANTOM_URL="$8"
ZKEVM_URL="$9"
+BASE_URL="${10}"
set -o errexit
@@ -24,7 +25,8 @@ echo "
\"avalanche\": { \"url\": \"${AVALANCHE_URL}\" },
\"bsc\": { \"url\": \"${BSC_URL}\" },
\"fantom\": { \"url\": \"${FANTOM_URL}\" },
- \"zkevm\": { \"url\": \"${ZKEVM_URL}\" }
+ \"zkevm\": { \"url\": \"${ZKEVM_URL}\" },
+ \"base\": { \"url\": \"${BASE_URL}\" }
}
}
" > $HOME/.hardhat/networks.mimic.json
diff --git a/.github/workflows/ci-connectors.yml b/.github/workflows/ci-connectors.yml
index b49593d7..32735cbd 100644
--- a/.github/workflows/ci-connectors.yml
+++ b/.github/workflows/ci-connectors.yml
@@ -44,7 +44,7 @@ jobs:
- name: Set up environment
uses: ./.github/actions/setup
- name: Set up hardhat config
- run: .github/scripts/setup-hardhat-config.sh ${{secrets.MAINNET_RPC}} ${{secrets.POLYGON_RPC}} ${{secrets.OPTIMISM_RPC}} ${{secrets.ARBITRUM_RPC}} ${{secrets.GNOSIS_RPC}} ${{secrets.AVALANCHE_RPC}} ${{secrets.BSC_RPC}} ${{secrets.FANTOM_RPC}} ${{secrets.ZKEVM_RPC}}
+ run: .github/scripts/setup-hardhat-config.sh ${{secrets.MAINNET_RPC}} ${{secrets.POLYGON_RPC}} ${{secrets.OPTIMISM_RPC}} ${{secrets.ARBITRUM_RPC}} ${{secrets.GNOSIS_RPC}} ${{secrets.AVALANCHE_RPC}} ${{secrets.BSC_RPC}} ${{secrets.FANTOM_RPC}} ${{secrets.ZKEVM_RPC}} ${{secrets.BASE_RPC}}
- name: Build
run: yarn build
- name: Test mainnet
@@ -64,4 +64,6 @@ jobs:
- name: Test fantom
run: yarn workspace @mimic-fi/v3-connectors test:fantom
- name: Test zkevm
- run: yarn workspace @mimic-fi/v3-connectors test:zkevm
\ No newline at end of file
+ run: yarn workspace @mimic-fi/v3-connectors test:zkevm
+ - name: Test base
+ run: yarn workspace @mimic-fi/v3-connectors test:base
\ No newline at end of file
diff --git a/packages/connectors/contracts/bebop/BebopConnector.sol b/packages/connectors/contracts/bebop/BebopConnector.sol
new file mode 100644
index 00000000..310f74ae
--- /dev/null
+++ b/packages/connectors/contracts/bebop/BebopConnector.sol
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity ^0.8.0;
+
+import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
+import '@openzeppelin/contracts/utils/Address.sol';
+
+import '@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol';
+
+import '../interfaces/bebop/IBebopConnector.sol';
+
+/**
+ * @title BebopConnector
+ * @dev Interfaces with Bebop to swap tokens
+ */
+contract BebopConnector is IBebopConnector {
+ // Reference to Bebop Settlement contract
+ address public immutable override bebopSettlement;
+
+ /**
+ * @dev Creates a new BebopConnector contract
+ * @param _bebopSettlement Address of Bebop Settlement contract
+ */
+ constructor(address _bebopSettlement) {
+ bebopSettlement = _bebopSettlement;
+ }
+
+ /**
+ * @dev Executes a token swap using Bebop
+ * @param tokenIn Token being sent
+ * @param tokenOut Token being received
+ * @param amountIn Amount of tokenIn being swapped
+ * @param minAmountOut Minimum amount of tokenOut willing to receive
+ * @param data Calldata to be sent to the Bebop Settlement contract
+ */
+ function execute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes memory data)
+ external
+ returns (uint256 amountOut)
+ {
+ if (tokenIn == tokenOut) revert BebopSwapSameToken(tokenIn);
+
+ uint256 preBalanceIn = IERC20(tokenIn).balanceOf(address(this));
+ uint256 preBalanceOut = IERC20(tokenOut).balanceOf(address(this));
+
+ ERC20Helpers.approve(tokenIn, bebopSettlement, amountIn);
+ Address.functionCall(bebopSettlement, data, 'BEBOP_SWAP_FAILED');
+
+ uint256 postBalanceIn = IERC20(tokenIn).balanceOf(address(this));
+ bool isPostBalanceInUnexpected = postBalanceIn < preBalanceIn - amountIn;
+ if (isPostBalanceInUnexpected) revert BebopBadPostTokenInBalance(postBalanceIn, preBalanceIn, amountIn);
+
+ uint256 postBalanceOut = IERC20(tokenOut).balanceOf(address(this));
+ amountOut = postBalanceOut - preBalanceOut;
+ if (amountOut < minAmountOut) revert BebopBadAmountOut(amountOut, minAmountOut);
+ }
+}
diff --git a/packages/connectors/contracts/interfaces/bebop/IBebopConnector.sol b/packages/connectors/contracts/interfaces/bebop/IBebopConnector.sol
new file mode 100644
index 00000000..fca643f7
--- /dev/null
+++ b/packages/connectors/contracts/interfaces/bebop/IBebopConnector.sol
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.8.0;
+
+/**
+ * @title Bebop connector interface
+ */
+interface IBebopConnector {
+ /**
+ * @dev The token in is the same as the token out
+ */
+ error BebopSwapSameToken(address token);
+
+ /**
+ * @dev The amount out is lower than the minimum amount out
+ */
+ error BebopBadAmountOut(uint256 amountOut, uint256 minAmountOut);
+
+ /**
+ * @dev The post token in balance is lower than the previous token in balance minus the amount in
+ */
+ error BebopBadPostTokenInBalance(uint256 postBalanceIn, uint256 preBalanceIn, uint256 amountIn);
+
+ /**
+ * @dev Tells the reference to Bebop Settlement contract
+ */
+ function bebopSettlement() external view returns (address);
+
+ /**
+ * @dev Executes a token swap using Bebop
+ * @param tokenIn Token to be sent
+ * @param tokenOut Token to be received
+ * @param amountIn Amount of token in to be swapped
+ * @param minAmountOut Minimum amount of token out willing to receive
+ * @param data Calldata to be sent to the Bebop Settlement contract
+ */
+ function execute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes memory data)
+ external
+ returns (uint256 amountOut);
+}
diff --git a/packages/connectors/package.json b/packages/connectors/package.json
index fed6f5b5..cd38cbd8 100644
--- a/packages/connectors/package.json
+++ b/packages/connectors/package.json
@@ -18,12 +18,13 @@
"test:mainnet": "yarn test --fork mainnet --block-number 17525323 --chain-id 1",
"test:polygon": "yarn test --fork polygon --block-number 44153231 --chain-id 137",
"test:optimism": "yarn test --fork optimism --block-number 105914596 --chain-id 10",
- "test:arbitrum": "yarn test --fork arbitrum --block-number 105116582 --chain-id 42161",
+ "test:arbitrum": "yarn test --fork arbitrum --block-number 212259071 --chain-id 42161",
"test:gnosis": "yarn test --fork gnosis --block-number 28580764 --chain-id 100",
"test:avalanche": "yarn test --fork avalanche --block-number 31333905 --chain-id 43114",
"test:bsc": "yarn test --fork bsc --block-number 27925272 --chain-id 56",
"test:fantom": "yarn test --fork fantom --block-number 61485606 --chain-id 250",
"test:zkevm": "yarn test --fork zkevm --block-number 9014946 --chain-id 1101",
+ "test:base": "yarn test --fork base --block-number 14589312 --chain-id 8453",
"prepare": "yarn build"
},
"dependencies": {
diff --git a/packages/connectors/src/bebop.ts b/packages/connectors/src/bebop.ts
new file mode 100644
index 00000000..0d9100bf
--- /dev/null
+++ b/packages/connectors/src/bebop.ts
@@ -0,0 +1,53 @@
+import axios, { AxiosError } from 'axios'
+import { BigNumber, Contract } from 'ethers'
+
+const BEBOP_URL = 'https://api.bebop.xyz/pmm'
+
+const CHAIN_NAMES = {
+ 42161: 'arbitrum',
+ 8453: 'base',
+}
+
+export type SwapResponse = { data: { tx: { data: string } } }
+
+export async function getBebopSwapData(
+ chainId: number,
+ sender: Contract,
+ tokenIn: Contract,
+ tokenOut: Contract,
+ amountIn: BigNumber
+): Promise {
+ try {
+ const response = await getSwap(chainId, sender, tokenIn, tokenOut, amountIn)
+ return response.data.tx.data
+ } catch (error) {
+ if (error instanceof AxiosError) throw Error(error.toString() + ' - ' + error.response?.data?.description)
+ else throw error
+ }
+}
+
+async function getSwap(
+ chainId: number,
+ sender: Contract,
+ tokenIn: Contract,
+ tokenOut: Contract,
+ amountIn: BigNumber
+): Promise {
+ const chainName = CHAIN_NAMES[chainId]
+ if (!chainName) throw Error('Unsupported chain id')
+
+ return axios.get(`${BEBOP_URL}/${chainName}/v3/quote`, {
+ headers: {
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ },
+ params: {
+ taker_address: sender.address,
+ sell_tokens: tokenIn.address,
+ buy_tokens: tokenOut.address,
+ sell_amounts: amountIn.toString(),
+ gasless: false,
+ skip_validation: true,
+ },
+ })
+}
diff --git a/packages/connectors/src/hop.ts b/packages/connectors/src/hop.ts
index 01b04567..4441e136 100644
--- a/packages/connectors/src/hop.ts
+++ b/packages/connectors/src/hop.ts
@@ -7,7 +7,7 @@ const HOP_URL = 'https://api.hop.exchange/v1'
export type QuoteResponse = { data: { bonderFee: string; error: string } }
const CHAINS: { [key: number]: string } = {
- 1: 'mainnet',
+ 1: 'ethereum',
137: 'polygon',
100: 'gnosis',
10: 'optimism',
diff --git a/packages/connectors/test/balancer/BalancerV2SwapConnector.behavior.ts b/packages/connectors/test/balancer/BalancerV2SwapConnector.behavior.ts
index 90d76a31..fea3d614 100644
--- a/packages/connectors/test/balancer/BalancerV2SwapConnector.behavior.ts
+++ b/packages/connectors/test/balancer/BalancerV2SwapConnector.behavior.ts
@@ -38,7 +38,7 @@ export function itBehavesLikeBalancerV2SwapConnector(
const hopTokens = []
context('USDC-WETH', () => {
- const amountIn = toUSDC(10e3)
+ const amountIn = toUSDC(100)
it('swaps correctly', async function () {
const previousBalance = await weth.balanceOf(this.connector.address)
@@ -94,7 +94,7 @@ export function itBehavesLikeBalancerV2SwapConnector(
})
context('WBTC-USDC', () => {
- const amountIn = toWBTC(1)
+ const amountIn = toWBTC(0.1)
const hopPoolIds = [WETH_USDC_POOL_ID]
it('swaps correctly', async function () {
diff --git a/packages/connectors/test/bebop/BebopConnector.arbitrum.ts b/packages/connectors/test/bebop/BebopConnector.arbitrum.ts
new file mode 100644
index 00000000..6d23ff33
--- /dev/null
+++ b/packages/connectors/test/bebop/BebopConnector.arbitrum.ts
@@ -0,0 +1,25 @@
+import { deploy } from '@mimic-fi/v3-helpers'
+
+import { itBehavesLikeBebopConnector } from './BebopConnector.behavior'
+
+/* eslint-disable no-secrets/no-secrets */
+
+const CHAIN = 42161
+
+const USDC = '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8'
+const WETH = '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1'
+const WHALE = '0xEeBe760354F5dcBa195EDe0a3B93901441D0968F'
+
+const BEBOP_SETTLEMENT = '0xbbbbbBB520d69a9775E85b458C58c648259FAD5F'
+
+const CHAINLINK_ETH_USD = '0x639fe6ab55c921f74e7fac1ee960c0b6293ba612'
+
+describe('BebopConnector', () => {
+ const SLIPPAGE = 0.015
+
+ before('create bebop connector', async function () {
+ this.connector = await deploy('BebopConnector', [BEBOP_SETTLEMENT])
+ })
+
+ itBehavesLikeBebopConnector(CHAIN, USDC, WETH, WHALE, SLIPPAGE, CHAINLINK_ETH_USD)
+})
diff --git a/packages/connectors/test/bebop/BebopConnector.base.ts b/packages/connectors/test/bebop/BebopConnector.base.ts
new file mode 100644
index 00000000..31be5a62
--- /dev/null
+++ b/packages/connectors/test/bebop/BebopConnector.base.ts
@@ -0,0 +1,25 @@
+import { deploy } from '@mimic-fi/v3-helpers'
+
+import { itBehavesLikeBebopConnector } from './BebopConnector.behavior'
+
+/* eslint-disable no-secrets/no-secrets */
+
+const CHAIN = 8453
+
+const USDC = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
+const WETH = '0x4200000000000000000000000000000000000006'
+const WHALE = '0xec8d8D4b215727f3476FF0ab41c406FA99b4272C'
+
+const BEBOP_SETTLEMENT = '0xbbbbbBB520d69a9775E85b458C58c648259FAD5F'
+
+const CHAINLINK_ETH_USD = '0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70'
+
+describe('BebopConnector', () => {
+ const SLIPPAGE = 0.015
+
+ before('create bebop connector', async function () {
+ this.connector = await deploy('BebopConnector', [BEBOP_SETTLEMENT])
+ })
+
+ itBehavesLikeBebopConnector(CHAIN, USDC, WETH, WHALE, SLIPPAGE, CHAINLINK_ETH_USD)
+})
diff --git a/packages/connectors/test/bebop/BebopConnector.behavior.ts b/packages/connectors/test/bebop/BebopConnector.behavior.ts
new file mode 100644
index 00000000..c21d6fcd
--- /dev/null
+++ b/packages/connectors/test/bebop/BebopConnector.behavior.ts
@@ -0,0 +1,76 @@
+import { deployProxy, fp, impersonate, instanceAt, pct, toUSDC, ZERO_ADDRESS } from '@mimic-fi/v3-helpers'
+import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
+import { expect } from 'chai'
+import { BigNumber, Contract } from 'ethers'
+
+import { loadOrGetBebopSwapData } from '../helpers/bebop'
+
+export function itBehavesLikeBebopConnector(
+ CHAIN: number,
+ USDC: string,
+ WETH: string,
+ WHALE: string,
+ SLIPPAGE: number,
+ CHAINLINK_ETH_USD: string
+): void {
+ let weth: Contract, usdc: Contract, whale: SignerWithAddress, priceOracle: Contract
+
+ before('load tokens and accounts', async function () {
+ weth = await instanceAt('IERC20Metadata', WETH)
+ usdc = await instanceAt('IERC20Metadata', USDC)
+ whale = await impersonate(WHALE, fp(100))
+ })
+
+ before('create price oracle', async function () {
+ priceOracle = await deployProxy(
+ '@mimic-fi/v3-price-oracle/artifacts/contracts/PriceOracle.sol/PriceOracle',
+ [],
+ [ZERO_ADDRESS, ZERO_ADDRESS, USDC, [{ base: WETH, quote: USDC, feed: CHAINLINK_ETH_USD }]]
+ )
+ })
+
+ const getExpectedMinAmountOut = async (
+ tokenIn: string,
+ tokenOut: string,
+ amountIn: BigNumber,
+ slippage: number
+ ): Promise => {
+ const price = await priceOracle['getPrice(address,address)'](tokenIn, tokenOut)
+ const expectedAmountOut = price.mul(amountIn).div(fp(1))
+ return expectedAmountOut.sub(pct(expectedAmountOut, slippage))
+ }
+
+ context('USDC-WETH', () => {
+ const amountIn = toUSDC(10e3)
+
+ it('swaps correctly USDC-WETH', async function () {
+ const previousBalance = await weth.balanceOf(this.connector.address)
+ await usdc.connect(whale).transfer(this.connector.address, amountIn)
+
+ const minAmountOut = 0
+ const data = await loadOrGetBebopSwapData(CHAIN, this.connector, usdc, weth, amountIn)
+ await this.connector.connect(whale).execute(USDC, WETH, amountIn, minAmountOut, data)
+
+ const currentBalance = await weth.balanceOf(this.connector.address)
+ const expectedMinAmountOut = await getExpectedMinAmountOut(USDC, WETH, amountIn, SLIPPAGE)
+ expect(currentBalance.sub(previousBalance)).to.be.at.least(expectedMinAmountOut)
+ })
+ })
+
+ context('WETH-USDC', () => {
+ const amountIn = fp(1)
+
+ it('swaps correctly WETH-USDC', async function () {
+ const previousBalance = await usdc.balanceOf(this.connector.address)
+ await weth.connect(whale).transfer(this.connector.address, amountIn)
+
+ const minAmountOut = 0
+ const data = await loadOrGetBebopSwapData(CHAIN, this.connector, weth, usdc, amountIn)
+ await this.connector.connect(whale).execute(WETH, USDC, amountIn, minAmountOut, data)
+
+ const currentBalance = await usdc.balanceOf(this.connector.address)
+ const expectedMinAmountOut = await getExpectedMinAmountOut(WETH, USDC, amountIn, SLIPPAGE)
+ expect(currentBalance.sub(previousBalance)).to.be.at.least(expectedMinAmountOut)
+ })
+ })
+}
diff --git a/packages/connectors/test/helpers/bebop/fixtures/42161/212259071/USDC-WETH.json b/packages/connectors/test/helpers/bebop/fixtures/42161/212259071/USDC-WETH.json
new file mode 100644
index 00000000..9affdf68
--- /dev/null
+++ b/packages/connectors/test/helpers/bebop/fixtures/42161/212259071/USDC-WETH.json
@@ -0,0 +1,6 @@
+{
+ "tokenIn": "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8",
+ "tokenOut": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
+ "amountIn": "10000000000",
+ "data": "0x4dcebcba000000000000000000000000000000000000000000000000000000006647a4370000000000000000000000004f0a4ce902616f0e16a7c31075aa5601779ad40500000000000000000000000051c72848c68a965f66fa7a88855f9f7784502a7f0000000000000000000000000000000000000000000000000000031ef93f4f3b000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc800000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab100000000000000000000000000000000000000000000000000000002540be4000000000000000000000000000000000000000000000000002d0f5f4319e062100000000000000000000000004f0a4ce902616f0e16a7c31075aa5601779ad40500000000000000000000000000000000000000000000000000000000000000007409e45e4bca4e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000041791c1ef4b257ba835057f84321c9e9804a94a1352b8a3961ed1d656fdab3d77f0f8ba4428da58c1c91fcd28472f6e8fce0ba10f9068f1d727e62ce1dbb405cc11b00000000000000000000000000000000000000000000000000000000000000"
+}
\ No newline at end of file
diff --git a/packages/connectors/test/helpers/bebop/fixtures/42161/212259071/WETH-USDC.json b/packages/connectors/test/helpers/bebop/fixtures/42161/212259071/WETH-USDC.json
new file mode 100644
index 00000000..84ff1896
--- /dev/null
+++ b/packages/connectors/test/helpers/bebop/fixtures/42161/212259071/WETH-USDC.json
@@ -0,0 +1,6 @@
+{
+ "tokenIn": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
+ "tokenOut": "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8",
+ "amountIn": "1000000000000000000",
+ "data": "0x4dcebcba000000000000000000000000000000000000000000000000000000006647a4390000000000000000000000004f0a4ce902616f0e16a7c31075aa5601779ad40500000000000000000000000051c72848c68a965f66fa7a88855f9f7784502a7f0000000000000000000000000000000000000000000000000000031ef93f4f3c00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000b7761b950000000000000000000000004f0a4ce902616f0e16a7c31075aa5601779ad40500000000000000000000000000000000000000000000000000000000000000004087748dff5aa5e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000418ad1282832998747d3a68672463c5855f61e09a2485d7505c42d2fddaa998a39077cdf67c41cc05c97b49602b9c2412f0cfd8d94c3ff2869b9d146ea9843d9691b00000000000000000000000000000000000000000000000000000000000000"
+}
\ No newline at end of file
diff --git a/packages/connectors/test/helpers/bebop/fixtures/8453/14589312/USDC-WETH.json b/packages/connectors/test/helpers/bebop/fixtures/8453/14589312/USDC-WETH.json
new file mode 100644
index 00000000..df5ae968
--- /dev/null
+++ b/packages/connectors/test/helpers/bebop/fixtures/8453/14589312/USDC-WETH.json
@@ -0,0 +1,6 @@
+{
+ "tokenIn": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
+ "tokenOut": "0x4200000000000000000000000000000000000006",
+ "amountIn": "10000000000",
+ "data": "0x4dcebcba000000000000000000000000000000000000000000000000000000006647a7a600000000000000000000000034b40ba116d5dec75548a9e9a8f15411461e8c7000000000000000000000000051c72848c68a965f66fa7a88855f9f7784502a7f0000000000000000000000000000000000000000000000000000031ef93f5bf7000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913000000000000000000000000420000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000002540be4000000000000000000000000000000000000000000000000002ce1a31db374011a00000000000000000000000034b40ba116d5dec75548a9e9a8f15411461e8c70000000000000000000000000000000000000000000000000000000000000000085543df12d753b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000410503ae0427d1300d5d9092c65def74ef08b144804dd062976cde63a2813ece05729017fa0ccc9ac2b9587a5a347d189aac529cf55b65185a9585e2f4f50b640d1c00000000000000000000000000000000000000000000000000000000000000"
+}
\ No newline at end of file
diff --git a/packages/connectors/test/helpers/bebop/fixtures/8453/14589312/WETH-USDC.json b/packages/connectors/test/helpers/bebop/fixtures/8453/14589312/WETH-USDC.json
new file mode 100644
index 00000000..f458a55f
--- /dev/null
+++ b/packages/connectors/test/helpers/bebop/fixtures/8453/14589312/WETH-USDC.json
@@ -0,0 +1,6 @@
+{
+ "tokenIn": "0x4200000000000000000000000000000000000006",
+ "tokenOut": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
+ "amountIn": "1000000000000000000",
+ "data": "0x4dcebcba000000000000000000000000000000000000000000000000000000006647a7a700000000000000000000000034b40ba116d5dec75548a9e9a8f15411461e8c7000000000000000000000000051c72848c68a965f66fa7a88855f9f7784502a7f0000000000000000000000000000000000000000000000000000031ef93f5bf90000000000000000000000004200000000000000000000000000000000000006000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029130000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000b7b369c400000000000000000000000034b40ba116d5dec75548a9e9a8f15411461e8c70000000000000000000000000000000000000000000000000000000000000000006a0f9771de8210c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000041252d2f60f204dfa8c3d4ed6950905708d4c6f98d514adaa64fb8fc45f009e0c473ea6273fc4ab2f42c3a1bdb3236978ddca8d36ec1494878f9067f2f995493291b00000000000000000000000000000000000000000000000000000000000000"
+}
\ No newline at end of file
diff --git a/packages/connectors/test/helpers/bebop/index.ts b/packages/connectors/test/helpers/bebop/index.ts
new file mode 100644
index 00000000..e92321c5
--- /dev/null
+++ b/packages/connectors/test/helpers/bebop/index.ts
@@ -0,0 +1,74 @@
+import { currentBlockNumber } from '@mimic-fi/v3-helpers'
+import { BigNumber, Contract } from 'ethers'
+import fs from 'fs'
+import hre from 'hardhat'
+import { HardhatNetworkConfig } from 'hardhat/types'
+import path from 'path'
+
+import { getBebopSwapData } from '../../../src/bebop'
+
+type Fixture = {
+ tokenIn: string
+ tokenOut: string
+ amountIn: string
+ slippage: number
+ data: string
+}
+
+export async function loadOrGetBebopSwapData(
+ chainId: number,
+ sender: Contract,
+ tokenIn: Contract,
+ tokenOut: Contract,
+ amountIn: BigNumber
+): Promise {
+ const config = hre.network.config as HardhatNetworkConfig
+ const blockNumber = config?.forking?.blockNumber?.toString() || (await currentBlockNumber()).toString()
+
+ const fixture = await readFixture(chainId, tokenIn, tokenOut, blockNumber)
+ if (fixture) return fixture.data
+
+ const data = await getBebopSwapData(chainId, sender, tokenIn, tokenOut, amountIn)
+ await saveFixture(chainId, tokenIn, tokenOut, amountIn, data, blockNumber)
+ return data
+}
+
+async function readFixture(
+ chainId: number,
+ tokenIn: Contract,
+ tokenOut: Contract,
+ blockNumber: string
+): Promise {
+ const swapPath = `${await tokenIn.symbol()}-${await tokenOut.symbol()}.json`
+ const fixturePath = path.join(__dirname, 'fixtures', chainId.toString(), blockNumber, swapPath)
+ if (!fs.existsSync(fixturePath)) return undefined
+ return JSON.parse(fs.readFileSync(fixturePath).toString())
+}
+
+async function saveFixture(
+ chainId: number,
+ tokenIn: Contract,
+ tokenOut: Contract,
+ amountIn: BigNumber,
+ data: string,
+ blockNumber: string
+): Promise {
+ const output = {
+ tokenIn: tokenIn.address,
+ tokenOut: tokenOut.address,
+ amountIn: amountIn.toString(),
+ data,
+ }
+
+ const fixturesPath = path.join(__dirname, 'fixtures')
+ if (!fs.existsSync(fixturesPath)) fs.mkdirSync(fixturesPath)
+
+ const networkPath = path.join(fixturesPath, chainId.toString())
+ if (!fs.existsSync(networkPath)) fs.mkdirSync(networkPath)
+
+ const blockNumberPath = path.join(networkPath, blockNumber)
+ if (!fs.existsSync(blockNumberPath)) fs.mkdirSync(blockNumberPath)
+
+ const swapPath = path.join(blockNumberPath, `${await tokenIn.symbol()}-${await tokenOut.symbol()}.json`)
+ fs.writeFileSync(swapPath, JSON.stringify(output, null, 2))
+}
diff --git a/packages/connectors/test/hop/HopBridgeConnector.gnosis.ts b/packages/connectors/test/hop/HopBridgeConnector.gnosis.ts
index d77b7f61..b7e6c913 100644
--- a/packages/connectors/test/hop/HopBridgeConnector.gnosis.ts
+++ b/packages/connectors/test/hop/HopBridgeConnector.gnosis.ts
@@ -5,7 +5,7 @@ import { itBehavesLikeHopNativeConnector } from './HopL2NativeConnector.behavior
/* eslint-disable no-secrets/no-secrets */
-const USDC = '0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83'
+const USDT = '0x4ECaBa5870353805a9F068101A40E0f32ed605C6'
const WXDAI = '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d'
describe('HopBridgeConnector', () => {
@@ -15,11 +15,11 @@ describe('HopBridgeConnector', () => {
this.connector = await deploy('HopBridgeConnector', [WXDAI])
})
- context('USDC', () => {
- const WHALE = '0xc66825c5c04b3c2ccd536d626934e16248a63f68'
- const HOP_USDC_AMM = '0x76b22b8C1079A44F1211D867D68b1eda76a635A7'
+ context('USDT', () => {
+ const WHALE = '0xba12222222228d8ba445958a75a0704d566bf2c8'
+ const HOP_USDT_AMM = '0x49094a1B3463c4e2E82ca41b8e6A023bdd6E222f'
- itBehavesLikeHopERC20Connector(SOURCE_CHAIN_ID, USDC, HOP_USDC_AMM, WHALE)
+ itBehavesLikeHopERC20Connector(SOURCE_CHAIN_ID, USDT, HOP_USDT_AMM, WHALE)
})
context('xDAI', () => {
diff --git a/packages/connectors/test/hop/HopSwapConnector.arbitrum.ts b/packages/connectors/test/hop/HopSwapConnector.arbitrum.ts
index f4545ab2..6d61f473 100644
--- a/packages/connectors/test/hop/HopSwapConnector.arbitrum.ts
+++ b/packages/connectors/test/hop/HopSwapConnector.arbitrum.ts
@@ -12,7 +12,7 @@ const WHALE = '0x5bdf85216ec1e38d6458c870992a69e38e03f7ef'
const HOP_USDC_DEX = '0x10541b07d8ad2647dc6cd67abd4c03575dade261'
describe('HopSwapConnector', () => {
- const SLIPPAGE = 0.01
+ const SLIPPAGE = 0.015
before('create hop swap connector', async function () {
this.connector = await deploy('HopSwapConnector')