-
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.
Merge branch 'master' into connectors/implement_wormhole_bridge_conne…
…ctor
- Loading branch information
Showing
24 changed files
with
924 additions
and
0 deletions.
There are no files selected for viewing
49 changes: 49 additions & 0 deletions
49
packages/connectors/contracts/swap/1inch-v5/IOneInchV5AggregationRouter.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,49 @@ | ||
// 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'; | ||
|
||
interface IAggregationExecutor { | ||
/// @notice propagates information about original msg.sender and executes arbitrary data | ||
function execute(address msgSender) external payable; | ||
} | ||
|
||
interface IOneInchV5AggregationRouter { | ||
struct SwapDescription { | ||
IERC20 srcToken; | ||
IERC20 dstToken; | ||
address payable srcReceiver; | ||
address payable dstReceiver; | ||
uint256 amount; | ||
uint256 minReturnAmount; | ||
uint256 flags; | ||
} | ||
|
||
/// @notice Performs a swap, delegating all calls encoded in `data` to `executor`. See tests for usage examples | ||
/// @dev router keeps 1 wei of every token on the contract balance for gas optimisations reasons. This affects first swap of every token by leaving 1 wei on the contract. | ||
/// @param executor Aggregation executor that executes calls described in `data` | ||
/// @param desc Swap description | ||
/// @param permit Should contain valid permit that can be used in `IERC20Permit.permit` calls. | ||
/// @param data Encoded calls that `caller` should execute in between of swaps | ||
/// @return returnAmount Resulting token amount | ||
/// @return spentAmount Source token amount | ||
function swap( | ||
IAggregationExecutor executor, | ||
SwapDescription calldata desc, | ||
bytes calldata permit, | ||
bytes calldata data | ||
) external payable returns (uint256 returnAmount, uint256 spentAmount); | ||
} |
68 changes: 68 additions & 0 deletions
68
packages/connectors/contracts/swap/1inch-v5/OneInchV5Connector.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,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/token/ERC20/extensions/IERC20Metadata.sol'; | ||
import '@openzeppelin/contracts/utils/Address.sol'; | ||
|
||
import '@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol'; | ||
|
||
import './IOneInchV5AggregationRouter.sol'; | ||
|
||
/** | ||
* @title OneInchV5Connector | ||
* @dev Interfaces with 1inch V5 to swap tokens | ||
*/ | ||
contract OneInchV5Connector { | ||
// Reference to 1inch aggregation router v5 | ||
IOneInchV5AggregationRouter public immutable oneInchV5Router; | ||
|
||
/** | ||
* @dev Creates a new OneInchV5Connector contract | ||
* @param _oneInchV5Router 1inch aggregation router v5 reference | ||
*/ | ||
constructor(address _oneInchV5Router) { | ||
oneInchV5Router = IOneInchV5AggregationRouter(_oneInchV5Router); | ||
} | ||
|
||
/** | ||
* @dev Executes a token swap in 1Inch V5 | ||
* @param tokenIn Token to be sent | ||
* @param tokenOut Token to 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 1inch aggregation router | ||
*/ | ||
function execute(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut, bytes memory data) | ||
external | ||
returns (uint256 amountOut) | ||
{ | ||
require(tokenIn != tokenOut, '1INCH_V5_SWAP_SAME_TOKEN'); | ||
|
||
uint256 preBalanceIn = IERC20(tokenIn).balanceOf(address(this)); | ||
uint256 preBalanceOut = IERC20(tokenOut).balanceOf(address(this)); | ||
|
||
ERC20Helpers.approve(tokenIn, address(oneInchV5Router), amountIn); | ||
Address.functionCall(address(oneInchV5Router), data, '1INCH_V5_SWAP_FAILED'); | ||
|
||
uint256 postBalanceIn = IERC20(tokenIn).balanceOf(address(this)); | ||
require(postBalanceIn >= preBalanceIn - amountIn, '1INCH_V5_BAD_TOKEN_IN_BALANCE'); | ||
|
||
uint256 postBalanceOut = IERC20(tokenOut).balanceOf(address(this)); | ||
amountOut = postBalanceOut - preBalanceOut; | ||
require(amountOut >= minAmountOut, '1INCH_V5_MIN_AMOUNT_OUT'); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
packages/connectors/contracts/swap/uniswap-v2/IUniswapV2Factory.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,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.5.0; | ||
|
||
interface IUniswapV2Factory { | ||
function getPair(address tokenA, address tokenB) external view returns (address); | ||
} |
27 changes: 27 additions & 0 deletions
27
packages/connectors/contracts/swap/uniswap-v2/IUniswapV2Router02.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,27 @@ | ||
// 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.6.2; | ||
|
||
interface IUniswapV2Router02 { | ||
function factory() external pure returns (address); | ||
|
||
function swapExactTokensForTokens( | ||
uint256 amountIn, | ||
uint256 amountOutMin, | ||
address[] calldata path, | ||
address to, | ||
uint256 deadline | ||
) external returns (uint256[] memory amounts); | ||
} |
129 changes: 129 additions & 0 deletions
129
packages/connectors/contracts/swap/uniswap-v2/UniswapV2Connector.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,129 @@ | ||
// 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/token/ERC20/extensions/IERC20Metadata.sol'; | ||
|
||
import '@mimic-fi/v3-helpers/contracts/math/UncheckedMath.sol'; | ||
import '@mimic-fi/v3-helpers/contracts/utils/Arrays.sol'; | ||
import '@mimic-fi/v3-helpers/contracts/utils/ERC20Helpers.sol'; | ||
|
||
import './IUniswapV2Factory.sol'; | ||
import './IUniswapV2Router02.sol'; | ||
|
||
/** | ||
* @title UniswapV2Connector | ||
* @dev Interfaces with Uniswap V2 to swap tokens | ||
*/ | ||
contract UniswapV2Connector { | ||
using UncheckedMath for uint256; | ||
|
||
// Reference to UniswapV2 router | ||
IUniswapV2Router02 public immutable uniswapV2Router; | ||
|
||
/** | ||
* @dev Initializes the UniswapV2Connector contract | ||
* @param _uniswapV2Router Uniswap V2 router reference | ||
*/ | ||
constructor(address _uniswapV2Router) { | ||
uniswapV2Router = IUniswapV2Router02(_uniswapV2Router); | ||
} | ||
|
||
/** | ||
* @dev Executes a token swap in Uniswap V2 | ||
* @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 hopTokens Optional list of hop-tokens between tokenIn and tokenOut, only used for multi-hops | ||
*/ | ||
function execute( | ||
address tokenIn, | ||
address tokenOut, | ||
uint256 amountIn, | ||
uint256 minAmountOut, | ||
address[] memory hopTokens | ||
) external returns (uint256 amountOut) { | ||
require(tokenIn != tokenOut, 'UNI_V2_SWAP_SAME_TOKEN'); | ||
|
||
uint256 preBalanceIn = IERC20(tokenIn).balanceOf(address(this)); | ||
uint256 preBalanceOut = IERC20(tokenOut).balanceOf(address(this)); | ||
|
||
ERC20Helpers.approve(tokenIn, address(uniswapV2Router), amountIn); | ||
hopTokens.length == 0 | ||
? _singleSwap(tokenIn, tokenOut, amountIn, minAmountOut) | ||
: _batchSwap(tokenIn, tokenOut, amountIn, minAmountOut, hopTokens); | ||
|
||
uint256 postBalanceIn = IERC20(tokenIn).balanceOf(address(this)); | ||
require(postBalanceIn >= preBalanceIn - amountIn, 'UNI_V2_BAD_TOKEN_IN_BALANCE'); | ||
|
||
uint256 postBalanceOut = IERC20(tokenOut).balanceOf(address(this)); | ||
amountOut = postBalanceOut - preBalanceOut; | ||
require(amountOut >= minAmountOut, 'UNI_V2_MIN_AMOUNT_OUT'); | ||
} | ||
|
||
/** | ||
* @dev Swap two tokens through UniswapV2 using a single hop | ||
* @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 | ||
*/ | ||
function _singleSwap(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut) | ||
internal | ||
returns (uint256[] memory) | ||
{ | ||
address factory = uniswapV2Router.factory(); | ||
address[] memory tokens = Arrays.from(tokenIn, tokenOut); | ||
_validatePool(factory, tokenIn, tokenOut); | ||
return uniswapV2Router.swapExactTokensForTokens(amountIn, minAmountOut, tokens, address(this), block.timestamp); | ||
} | ||
|
||
/** | ||
* @dev Swap two tokens through UniswapV2 using a multi hop | ||
* @param tokenIn Token being sent | ||
* @param tokenOut Token being received | ||
* @param amountIn Amount of the first token in the path to be swapped | ||
* @param minAmountOut Minimum amount of the last token in the path willing to receive | ||
* @param hopTokens List of hop-tokens between tokenIn and tokenOut | ||
*/ | ||
function _batchSwap( | ||
address tokenIn, | ||
address tokenOut, | ||
uint256 amountIn, | ||
uint256 minAmountOut, | ||
address[] memory hopTokens | ||
) internal returns (uint256[] memory) { | ||
address factory = uniswapV2Router.factory(); | ||
address[] memory tokens = Arrays.from(tokenIn, hopTokens, tokenOut); | ||
// No need for checked math since we are using it to compute indexes manually, always within boundaries | ||
for (uint256 i = 0; i < tokens.length.uncheckedSub(1); i = i.uncheckedAdd(1)) { | ||
_validatePool(factory, tokens[i], tokens[i.uncheckedAdd(1)]); | ||
} | ||
return uniswapV2Router.swapExactTokensForTokens(amountIn, minAmountOut, tokens, address(this), block.timestamp); | ||
} | ||
|
||
/** | ||
* @dev Validates that there is a pool created for tokenA and tokenB | ||
* @param factory UniswapV2 factory to check against | ||
* @param tokenA First token of the pair | ||
* @param tokenB Second token of the pair | ||
*/ | ||
function _validatePool(address factory, address tokenA, address tokenB) private view { | ||
address pool = IUniswapV2Factory(factory).getPair(tokenA, tokenB); | ||
require(pool != address(0), 'INVALID_UNISWAP_POOL'); | ||
} | ||
} |
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,47 @@ | ||
import axios, { AxiosError } from 'axios' | ||
import { BigNumber, Contract } from 'ethers' | ||
|
||
const ONE_INCH_URL = 'https://api.1inch.io/v5.0' | ||
|
||
export type SwapResponse = { data: { tx: { data: string } } } | ||
|
||
export async function get1inchSwapData( | ||
chainId: number, | ||
sender: Contract, | ||
tokenIn: Contract, | ||
tokenOut: Contract, | ||
amountIn: BigNumber, | ||
slippage: number | ||
): Promise<string> { | ||
try { | ||
const response = await getSwap(chainId, sender, tokenIn, tokenOut, amountIn, slippage) | ||
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, | ||
slippage: number | ||
): Promise<SwapResponse> { | ||
return axios.get(`${ONE_INCH_URL}/${chainId}/swap`, { | ||
headers: { | ||
'Content-Type': 'application/json', | ||
Accept: 'application/json', | ||
}, | ||
params: { | ||
disableEstimate: true, | ||
fromAddress: sender.address, | ||
fromTokenAddress: tokenIn.address, | ||
toTokenAddress: tokenOut.address, | ||
amount: amountIn.toString(), | ||
slippage: slippage < 1 ? slippage * 100 : slippage, | ||
}, | ||
}) | ||
} |
7 changes: 7 additions & 0 deletions
7
packages/connectors/test/helpers/1inch-v5/fixtures/1/17525323/USDC-WBTC.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,7 @@ | ||
{ | ||
"tokenIn": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", | ||
"tokenOut": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", | ||
"amountIn": "10000000000", | ||
"slippage": 0.015, | ||
"data": "0xe449022e00000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000020a42930000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f56408000000000000000000000004585fe77225b41b697c938b018e2ac67ac5a20c0cfee7c08" | ||
} |
7 changes: 7 additions & 0 deletions
7
packages/connectors/test/helpers/1inch-v5/fixtures/1/17525323/USDC-WETH.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,7 @@ | ||
{ | ||
"tokenIn": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", | ||
"tokenOut": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", | ||
"amountIn": "10000000000", | ||
"slippage": 0.015, | ||
"data": "0xe449022e00000000000000000000000000000000000000000000000000000002540be4000000000000000000000000000000000000000000000000004b88924a476a67cd0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640cfee7c08" | ||
} |
7 changes: 7 additions & 0 deletions
7
packages/connectors/test/helpers/1inch-v5/fixtures/1/17525323/WBTC-USDC.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,7 @@ | ||
{ | ||
"tokenIn": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", | ||
"tokenOut": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", | ||
"amountIn": "100000000", | ||
"slippage": 0.015, | ||
"data": "0xe449022e0000000000000000000000000000000000000000000000000000000005f5e1000000000000000000000000000000000000000000000000000000000695097f210000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000099ac8ca7087fa4a2a1fb6357269965a2014abc35cfee7c08" | ||
} |
7 changes: 7 additions & 0 deletions
7
packages/connectors/test/helpers/1inch-v5/fixtures/1/17525323/WETH-USDC.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,7 @@ | ||
{ | ||
"tokenIn": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", | ||
"tokenOut": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", | ||
"amountIn": "1000000000000000000", | ||
"slippage": 0.015, | ||
"data": "0xe449022e0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000006a1d73080000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000180000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640cfee7c08" | ||
} |
7 changes: 7 additions & 0 deletions
7
packages/connectors/test/helpers/1inch-v5/fixtures/137/44153231/USDC-WBTC.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,7 @@ | ||
{ | ||
"tokenIn": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", | ||
"tokenOut": "0x1bfd67037b42cf73acf2047067bd4f2c47d9bfd6", | ||
"amountIn": "10000000000", | ||
"slippage": 0.01, | ||
"data": "0x12aa3caf000000000000000000000000cfd674f8731e801a4a15c1ae31770960e1afded10000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000001bfd67037b42cf73acf2047067bd4f2c47d9bfd6000000000000000000000000cfd674f8731e801a4a15c1ae31770960e1afded1000000000000000000000000502dcaf7b2a3ce981f1a6c86cc4634b16c7a836f00000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000020dd1670000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034900000000000000000000000000000000000000000000000000032b0002fd00a0c9e75c48000000000000000006040000000000000000000000000000000000000000000000000002cf00016200a007e5c0d200000000000000000000000000000000000000000000000000013e00004e4820cdc878c037625afe3a98e14fcc56e169f0b5b4112791bca1f2de4661ed88a30c99a7a9449aa84174dd93f59a000000000000000000000000cfd674f8731e801a4a15c1ae31770960e1afded15120817eb46d60762442da3d931ff51a30334ca39b74c2132d05d31c914a87c6611c10748aeb04b58e8f00447dc20382000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f0000000000000000000000001bfd67037b42cf73acf2047067bd4f2c47d9bfd600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000d2531e000000000000000000000000cfd674f8731e801a4a15c1ae31770960e1afded1000000000000000000000000910bf2d50fa5e014fd06666f456182d4ab7c8bd200a0c9e75c4800000000000000002e0400000000000000000000000000000000000000000000000000013f00004f02a00000000000000000000000000000000000000000000000000000000000193d96ee63c1e500eef1a9507b3d505f0062f2be9453981255b503c82791bca1f2de4661ed88a30c99a7a9449aa841745120817eb46d60762442da3d931ff51a30334ca39b742791bca1f2de4661ed88a30c99a7a9449aa8417400447dc203820000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000001bfd67037b42cf73acf2047067bd4f2c47d9bfd6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000012240b2000000000000000000000000cfd674f8731e801a4a15c1ae31770960e1afded1000000000000000000000000910bf2d50fa5e014fd06666f456182d4ab7c8bd280a06c4eca271bfd67037b42cf73acf2047067bd4f2c47d9bfd61111111254eeb25477b68fb85ed929f73a9605820000000000000000000000000000000000000000000000cfee7c08" | ||
} |
Oops, something went wrong.