Skip to content

Commit

Permalink
Merge branch 'master' of github.com-facuspagnuolo:mimic-fi/v3-core in…
Browse files Browse the repository at this point in the history
…to connectors/implement_wormhole_bridge_connector
  • Loading branch information
facuspagnuolo committed Jun 26, 2023
2 parents 81f3a28 + 597b23c commit 6def78a
Show file tree
Hide file tree
Showing 25 changed files with 456 additions and 75 deletions.
4 changes: 2 additions & 2 deletions .github/scripts/setup-hardhat-config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ echo "
\"optimism\": { \"url\": \"${OPTIMISM_URL}\" },
\"arbitrum\": { \"url\": \"${ARBITRUM_URL}\" },
\"gnosis\": { \"url\": \"${GNOSIS_URL}\" },
\"avalanche\": { \"url\": \"${AVALANCHE_URL}\" },
\"bsc\": { \"url\": \"${BSC_URL}\" },
\"fantom\": { \"url\": \"${FANTOM_URL}\" },
\"avalanche\": { \"url\": \"${AVALANCHE_URL}\" }
\"fantom\": { \"url\": \"${FANTOM_URL}\" }
}
}
" > $HOME/.hardhat/networks.mimic.json
6 changes: 5 additions & 1 deletion .github/workflows/ci-connectors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ jobs:
- name: Set up environment
uses: ./.github/actions/setup
- name: Set up hardhat config
run: .github/scripts/setup-hardhat-config.sh ${{secrets.GOERLI_RPC}} ${{secrets.MUMBAI_RPC}} ${{secrets.MAINNET_RPC}} ${{secrets.POLYGON_RPC}} ${{secrets.OPTIMISM_RPC}} ${{secrets.ARBITRUM_RPC}} ${{secrets.GNOSIS_RPC}} ${{secrets.AVALANCHE_RPC}} ${{secrets.BSC_RPC}} ${{secrets.FANTOM_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}}
- name: Build
run: yarn build
- name: Test mainnet
run: yarn workspace @mimic-fi/v3-connectors test:mainnet
- name: Test polygon
run: yarn workspace @mimic-fi/v3-connectors test:polygon
- name: Test optimism
run: yarn workspace @mimic-fi/v3-connectors test:optimism
- name: Test arbitrum
run: yarn workspace @mimic-fi/v3-connectors test:arbitrum
- name: Test avalanche
run: yarn workspace @mimic-fi/v3-connectors test:avalanche
2 changes: 1 addition & 1 deletion .github/workflows/ci-price-oracle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.GOERLI_RPC}} ${{secrets.MUMBAI_RPC}} ${{secrets.MAINNET_RPC}} ${{secrets.POLYGON_RPC}} ${{secrets.OPTIMISM_RPC}} ${{secrets.ARBITRUM_RPC}} ${{secrets.GNOSIS_RPC}} ${{secrets.AVALANCHE_RPC}} ${{secrets.BSC_RPC}} ${{secrets.FANTOM_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}}
- name: Build
run: yarn build
- name: Test mainnet
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// 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 <http://www.gnu.org/licenses/>.

pragma solidity ^0.8.0;

interface IParaswapV5Augustus {
function getTokenTransferProxy() external view returns (address);
}
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

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 './IParaswapV5Augustus.sol';

/**
* @title ParaswapV5Connector
* @dev Interfaces with Paraswap V5 to swap tokens
*/
contract ParaswapV5Connector {
// Reference to Paraswap V5 Augustus swapper
IParaswapV5Augustus public immutable paraswapV5Augustus;

/**
* @dev Creates a new ParaswapV5Connector contract
* @param _paraswapV5Augustus Paraswap V5 augusts reference
*/
constructor(address _paraswapV5Augustus) {
paraswapV5Augustus = IParaswapV5Augustus(_paraswapV5Augustus);
}

/**
* @dev Executes a token swap in Paraswap V5
* @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 Augusuts swapper
*/
function execute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes memory data)
external
returns (uint256 amountOut)
{
require(tokenIn != tokenOut, 'PARASWAP_V5_SWAP_SAME_TOKEN');

uint256 preBalanceIn = IERC20(tokenIn).balanceOf(address(this));
uint256 preBalanceOut = IERC20(tokenOut).balanceOf(address(this));

address tokenTransferProxy = paraswapV5Augustus.getTokenTransferProxy();
ERC20Helpers.approve(tokenIn, tokenTransferProxy, amountIn);
Address.functionCall(address(paraswapV5Augustus), data, 'PARASWAP_V5_SWAP_FAILED');

uint256 postBalanceIn = IERC20(tokenIn).balanceOf(address(this));
require(postBalanceIn >= preBalanceIn - amountIn, 'PARASWAP_V5_BAD_TOKEN_IN_BALANCE');

uint256 postBalanceOut = IERC20(tokenOut).balanceOf(address(this));
amountOut = postBalanceOut - preBalanceOut;
require(amountOut >= minAmountOut, 'PARASWAP_V5_MIN_AMOUNT_OUT');
}
}
2 changes: 2 additions & 0 deletions packages/connectors/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"test": "hardhat test",
"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:avalanche": "yarn test --fork avalanche --block-number 31333905 --chain-id 43114",
"prepare": "yarn build"
},
Expand Down
103 changes: 103 additions & 0 deletions packages/connectors/src/paraswap-v5.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { bn, currentTimestamp, MINUTE, pct } from '@mimic-fi/v3-helpers'
import axios, { AxiosError } from 'axios'
import { BigNumber, Contract } from 'ethers'

const PARASWAP_URL = 'https://apiv5.paraswap.io'

export type PricesResponse = { data: { priceRoute: { [key: string]: string } } }

export type TransactionsResponse = { data: { data: string; sig: string; signer: string } }

export type SwapData = {
data: string
sig: string
signer: string
minAmountOut: BigNumber
expectedAmountOut: BigNumber
}

export async function getParaswapSwapData(
chainId: number,
sender: Contract,
tokenIn: Contract,
tokenOut: Contract,
amountIn: BigNumber,
slippage: number
): Promise<SwapData> {
const prices = await getPrices(chainId, sender, tokenIn, tokenOut, amountIn)
const priceRoute = prices.data.priceRoute

try {
const { destAmount } = priceRoute
const minAmountOut = bn(destAmount).sub(pct(bn(destAmount), slippage))
const transactions = await postTransactions(chainId, sender, tokenIn, tokenOut, amountIn, minAmountOut, priceRoute)
const { data, sig, signer } = transactions.data
return { data, sig, signer, minAmountOut, expectedAmountOut: bn(destAmount) }
} catch (error) {
if (error instanceof AxiosError) throw Error(error.toString() + ' - ' + error.response?.data?.error)
else throw error
}
}

export async function getPrices(
chainId: number,
sender: Contract,
tokenIn: Contract,
tokenOut: Contract,
amountIn: BigNumber
): Promise<PricesResponse> {
return axios.get(`${PARASWAP_URL}/prices`, {
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
params: {
srcToken: tokenIn.address,
srcDecimals: await tokenIn.decimals(),
destToken: tokenOut.address,
destDecimals: await tokenOut.decimals(),
amount: amountIn.toString(),
side: 'SELL',
network: chainId,
userAddress: sender.address,
},
})
}

export async function postTransactions(
chainId: number,
sender: Contract,
tokenIn: Contract,
tokenOut: Contract,
amountIn: BigNumber,
minAmountOut: BigNumber,
priceRoute: { [key: string]: string }
): Promise<TransactionsResponse> {
const { ethers } = await import('hardhat')
return axios.post(
`${PARASWAP_URL}/transactions/${chainId}`,
{
srcToken: tokenIn.address,
destToken: tokenOut.address,
srcAmount: amountIn.toString(),
srcDecimals: await tokenIn.decimals(),
destAmount: minAmountOut.toString(),
destDecimals: await tokenOut.decimals(),
userAddress: sender.address,
receiver: sender.address,
deadline: (await currentTimestamp()).add(MINUTE).toString(),
priceRoute,
},
{
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
params: {
gasPrice: (await ethers.provider.getGasPrice()).toString(),
signCalldata: true,
ignoreChecks: true,
},
}
)
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit 6def78a

Please sign in to comment.