-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Connectors: Implement socket bridge connector (#161)
- Loading branch information
1 parent
42946b3
commit daf4423
Showing
14 changed files
with
373 additions
and
14 deletions.
There are no files selected for viewing
38 changes: 38 additions & 0 deletions
38
packages/connectors/contracts/interfaces/socket/ISocketConnector.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// 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; | ||
|
||
/** | ||
* @title Socket connector interface | ||
*/ | ||
interface ISocketConnector { | ||
/** | ||
* @dev The post token balance is lower than the previous token balance minus the amount bridged | ||
*/ | ||
error SocketBridgeBadPostTokenBalance(uint256 postBalance, uint256 preBalance, uint256 amount); | ||
|
||
/** | ||
* @dev Tells the reference to the Socket gateway of the source chain | ||
*/ | ||
function socketGateway() external view returns (address); | ||
|
||
/** | ||
* @dev Executes a bridge of assets using Socket | ||
* @param token Address of the token to be bridged | ||
* @param amount Amount of tokens to be bridged | ||
* @param data Data to be sent to the socket gateway | ||
*/ | ||
function execute(address token, uint256 amount, bytes memory data) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// 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/utils/Address.sol'; | ||
|
||
import '@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol'; | ||
|
||
import '../interfaces/socket/ISocketConnector.sol'; | ||
|
||
/** | ||
* @title SocketConnector | ||
* @dev Interfaces with Socket to bridge tokens | ||
*/ | ||
contract SocketConnector is ISocketConnector { | ||
// Reference to the Socket gateway of the source chain | ||
address public immutable override socketGateway; | ||
|
||
/** | ||
* @dev Creates a new Socket connector | ||
* @param _socketGateway Address of the Socket gateway for the source chain | ||
*/ | ||
constructor(address _socketGateway) { | ||
socketGateway = _socketGateway; | ||
} | ||
|
||
/** | ||
* @dev Executes a bridge of assets using Socket | ||
* @param token Address of the token to be bridged | ||
* @param amount Amount of tokens to be bridged | ||
* @param data Data to be sent to the Socket gateway | ||
*/ | ||
function execute(address token, uint256 amount, bytes memory data) external override { | ||
uint256 preBalance = IERC20(token).balanceOf(address(this)); | ||
ERC20Helpers.approve(token, socketGateway, amount); | ||
Address.functionCall(socketGateway, data, 'SOCKET_BRIDGE_FAILED'); | ||
|
||
uint256 postBalance = IERC20(token).balanceOf(address(this)); | ||
bool isPostBalanceUnexpected = postBalance < preBalance - amount; | ||
if (isPostBalanceUnexpected) revert SocketBridgeBadPostTokenBalance(postBalance, preBalance, amount); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import axios, { AxiosError } from 'axios' | ||
import { BigNumber, Contract } from 'ethers' | ||
|
||
const SOCKET_URL = 'https://api.socket.tech/v2' | ||
const SOCKET_API_KEY = '72a5b4b0-e727-48be-8aa1-5da9d62fe635' | ||
|
||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
|
||
export type QuoteResponse = { data: { result: { routes: any[] } } } | ||
export type TransactionDataResponse = { data: { result: { txData: string } } } | ||
|
||
export async function getSocketBridgeData( | ||
sender: Contract, | ||
fromChainId: number, | ||
fromToken: Contract, | ||
fromAmount: BigNumber, | ||
toChainId: number, | ||
toToken: Contract, | ||
slippage: number | ||
): Promise<string> { | ||
try { | ||
const quote = await getQuote(sender, fromChainId, fromToken, fromAmount, toChainId, toToken, slippage) | ||
const transaction = await getTransactionData(quote.data.result.routes[0]) | ||
return transaction.data.result.txData | ||
} catch (error) { | ||
if (error instanceof AxiosError) throw Error(error.toString() + ' - ' + error.response?.data?.description) | ||
else throw error | ||
} | ||
} | ||
|
||
async function getQuote( | ||
sender: Contract, | ||
fromChainId: number, | ||
fromToken: Contract, | ||
fromAmount: BigNumber, | ||
toChainId: number, | ||
toToken: Contract, | ||
slippage: number | ||
): Promise<QuoteResponse> { | ||
return axios.get(`${SOCKET_URL}/quote`, { | ||
headers: { | ||
'API-KEY': SOCKET_API_KEY, | ||
Accept: 'application/json', | ||
}, | ||
params: { | ||
userAddress: sender.address, | ||
fromChainId: fromChainId, | ||
fromTokenAddress: fromToken.address, | ||
fromAmount: fromAmount.toString(), | ||
toChainId: toChainId, | ||
toTokenAddress: toToken.address, | ||
defaultBridgeSlippage: slippage < 1 ? slippage * 100 : slippage, | ||
singleTxOnly: true, | ||
uniqueRoutesPerBridge: true, | ||
sort: 'output', | ||
includeDexes: ['oneinch', 'rainbow'], | ||
includeBridges: ['cctp', 'celer', 'connext', 'hop', 'stargate'], | ||
}, | ||
}) | ||
} | ||
|
||
async function getTransactionData(route: any): Promise<TransactionDataResponse> { | ||
return axios.post( | ||
`${SOCKET_URL}/build-tx`, | ||
{ route }, | ||
{ | ||
headers: { | ||
'API-KEY': SOCKET_API_KEY, | ||
Accept: 'application/json', | ||
}, | ||
} | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
packages/connectors/test/helpers/socket/fixtures/56/42144988/USDC-1.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"fromChainId": 56, | ||
"fromToken": "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", | ||
"fromAmount": "50000000000000000000000", | ||
"toChainId": 1, | ||
"toToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", | ||
"slippage": 0.02, | ||
"data": "0x0000000d52106ce9345fa8d86eeffdd25c389441ff96e05cf90592de8ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000a968163f0a57b4000000000000100b8d397000068dc" | ||
} |
9 changes: 9 additions & 0 deletions
9
packages/connectors/test/helpers/socket/fixtures/56/42144988/USDC-10.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"fromChainId": 56, | ||
"fromToken": "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", | ||
"fromAmount": "50000000000000000000000", | ||
"toChainId": 10, | ||
"toToken": "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", | ||
"slippage": 0.02, | ||
"data": "0x0000000d52106ce9345fa8d86eeffdd25c389441ff96e05cf90592de8ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000a968163f0a57b4000000000000a00b8e5120000620c" | ||
} |
9 changes: 9 additions & 0 deletions
9
packages/connectors/test/helpers/socket/fixtures/56/42145576/USDC-1.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"fromChainId": 56, | ||
"fromToken": "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", | ||
"fromAmount": "50000000000000000000000", | ||
"toChainId": 1, | ||
"toToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", | ||
"slippage": 0.02, | ||
"data": "0x0000000d52106ce94a1bf945c2995b53a00df694fab85f453e5e1f5e8ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000a968163f0a57b4000000000000100d2437d000068dd" | ||
} |
9 changes: 9 additions & 0 deletions
9
packages/connectors/test/helpers/socket/fixtures/56/42145576/USDC-10.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"fromChainId": 56, | ||
"fromToken": "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", | ||
"fromAmount": "50000000000000000000000", | ||
"toChainId": 10, | ||
"toToken": "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", | ||
"slippage": 0.02, | ||
"data": "0x0000000d52106ce94a1bf945c2995b53a00df694fab85f453e5e1f5e8ac76a51cc950d9822d68b83fe1ad97b32cd580d0000000000000a968163f0a57b4000000000000a00d256670000620c" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
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 { getSocketBridgeData } from '../../../src/socket' | ||
|
||
type Fixture = { | ||
fromChainId: number | ||
fromToken: string | ||
fromAmount: string | ||
toChainId: number | ||
toToken: string | ||
slippage: number | ||
data: string | ||
} | ||
|
||
export async function loadOrGetSocketData( | ||
sender: Contract, | ||
fromChainId: number, | ||
fromToken: Contract, | ||
fromAmount: BigNumber, | ||
toChainId: number, | ||
toToken: Contract, | ||
slippage: number | ||
): Promise<string> { | ||
const config = hre.network.config as HardhatNetworkConfig | ||
const blockNumber = config?.forking?.blockNumber?.toString() || (await currentBlockNumber()).toString() | ||
|
||
const fixture = await readFixture(fromChainId, fromToken, toChainId, toToken, blockNumber) | ||
if (fixture) return fixture.data | ||
|
||
const data = await getSocketBridgeData(sender, fromChainId, fromToken, fromAmount, toChainId, toToken, slippage) | ||
await saveFixture(fromChainId, fromToken, fromAmount, toChainId, toToken, slippage, data, blockNumber) | ||
return data | ||
} | ||
|
||
async function readFixture( | ||
fromChainId: number, | ||
fromToken: Contract, | ||
toChainId: number, | ||
toToken: Contract, | ||
blockNumber: string | ||
): Promise<Fixture | undefined> { | ||
const bridgePath = `${await fromToken.symbol()}-${toChainId}.json` | ||
const fixturePath = path.join(__dirname, 'fixtures', fromChainId.toString(), blockNumber, bridgePath) | ||
if (!fs.existsSync(fixturePath)) return undefined | ||
return JSON.parse(fs.readFileSync(fixturePath).toString()) | ||
} | ||
|
||
async function saveFixture( | ||
fromChainId: number, | ||
fromToken: Contract, | ||
fromAmount: BigNumber, | ||
toChainId: number, | ||
toToken: Contract, | ||
slippage: number, | ||
data: string, | ||
blockNumber: string | ||
): Promise<void> { | ||
const output = { | ||
fromChainId: fromChainId, | ||
fromToken: fromToken.address, | ||
fromAmount: fromAmount.toString(), | ||
toChainId: toChainId, | ||
toToken: toToken.address, | ||
slippage, | ||
data, | ||
} | ||
|
||
const fixturesPath = path.join(__dirname, 'fixtures') | ||
if (!fs.existsSync(fixturesPath)) fs.mkdirSync(fixturesPath) | ||
|
||
const networkPath = path.join(fixturesPath, fromChainId.toString()) | ||
if (!fs.existsSync(networkPath)) fs.mkdirSync(networkPath) | ||
|
||
const blockNumberPath = path.join(networkPath, blockNumber) | ||
if (!fs.existsSync(blockNumberPath)) fs.mkdirSync(blockNumberPath) | ||
|
||
const bridgePath = path.join(blockNumberPath, `${await fromToken.symbol()}-${toChainId}.json`) | ||
fs.writeFileSync(bridgePath, JSON.stringify(output, null, 2)) | ||
} |
Oops, something went wrong.