编译器
0.8.13+commit.abaa5c0e
文件 1 的 10:ERC20.sol
pragma solidity >=0.8.0;
abstract contract ERC20 {
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}
文件 2 的 10:IChad.sol
pragma solidity ^0.8.13;
interface IChad {
function burn(address from, uint256 amount) external;
function uniswapV2Pair() external returns (address);
}
文件 3 的 10:IQuoter.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
interface IQuoter {
function quoteExactInput(bytes memory path, uint256 amountIn) external returns (uint256 amountOut);
function quoteExactInputSingle(
address tokenIn,
address tokenOut,
uint24 fee,
uint256 amountIn,
uint160 sqrtPriceLimitX96
) external returns (uint256 amountOut);
function quoteExactOutput(bytes memory path, uint256 amountOut) external returns (uint256 amountIn);
function quoteExactOutputSingle(
address tokenIn,
address tokenOut,
uint24 fee,
uint256 amountOut,
uint160 sqrtPriceLimitX96
) external returns (uint256 amountIn);
}
文件 4 的 10:ISwapRouter.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}
文件 5 的 10:IUniswapV2Router.sol
pragma solidity ^0.8.13;
interface IUniswapV2Router {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
}
文件 6 的 10:IUniswapV3SwapCallback.sol
pragma solidity >=0.5.0;
interface IUniswapV3SwapCallback {
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}
文件 7 的 10:Index.sol
pragma solidity ^0.8.13;
import {Owned} from "solmate/auth/Owned.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";
import {WETH as IWETH} from "solmate/tokens/WETH.sol";
import {IChad} from "./interfaces/IChad.sol";
import {IUniswapV2Router} from "./interfaces/IUniswapV2Router.sol";
import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import {IQuoter} from "@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol";
contract Index is Owned {
using SafeTransferLib for ERC20;
enum UniswapVersion {
V2,
V3
}
struct IndexComponent {
address token;
uint8 weight;
uint24 fee;
UniswapVersion version;
}
struct TokenAmount {
address token;
uint256 amount;
}
event SetChad(address indexed chad);
event IndexComponentUpdated(address indexed token, uint8 weight);
event TokenPurchased(address indexed token, uint256 amount);
event TokenRedeemed(address indexed token, uint256 amount);
IUniswapV2Router public immutable uniswapV2Router;
ISwapRouter public immutable uniswapV3Router;
uint256 public constant MAX_BPS = 1_000_000_000 * 1e18;
uint24 public immutable LOW_FEE = 3_000;
uint24 public immutable HIGH_FEE = 10_000;
address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address public constant CHAD = 0xB777eb033557490abb7Fb8F3948000826423Ea07;
address public constant MILADY = 0xE59aCBE910dcdb8a0E79F337de4391907Dc8989c;
bool public canUpdateWeights = true;
address public chad;
uint256 public lastPurchase;
mapping(address => IndexComponent) public components;
mapping(address => bool) public hasToken;
address[] public tokens;
address[] public allTokens;
constructor(
address routerAddressV2,
address routerAddressV3
) Owned(msg.sender) {
uniswapV2Router = IUniswapV2Router(routerAddressV2);
uniswapV3Router = ISwapRouter(routerAddressV3);
components[CHAD] = IndexComponent({
token: CHAD,
weight: 50,
fee: 0,
version: UniswapVersion.V2
});
components[MILADY] = IndexComponent({
token: MILADY,
weight: 50,
fee: 0,
version: UniswapVersion.V2
});
tokens = [CHAD, MILADY];
allTokens = [CHAD, MILADY];
hasToken[CHAD] = true;
hasToken[MILADY] = true;
ERC20(WETH).approve(routerAddressV2, type(uint256).max);
ERC20(WETH).approve(routerAddressV3, type(uint256).max);
lastPurchase = block.timestamp;
}
receive() external payable {}
function _requireIsOwner() internal view {
require(msg.sender == owner, "!owner");
}
function setToken(address newChad) external {
_requireIsOwner();
chad = newChad;
ERC20(IChad(chad).uniswapV2Pair()).approve(
address(uniswapV2Router),
type(uint256).max
);
emit SetChad(newChad);
}
function enterNewParadigm() external {
_requireIsOwner();
uint256 wethBalance = ERC20(WETH).balanceOf(address(this));
uint256 etherBalance = address(this).balance;
uint256 totalBalance = wethBalance + etherBalance;
if (totalBalance == 0) {
return;
}
uint256 managementFee = (totalBalance * 2) / 100;
uint256 purchaseAmount = (totalBalance * 98) / 100;
uint256 etherToWithdraw = managementFee - etherBalance;
if (etherToWithdraw > 0) {
IWETH(payable(WETH)).withdraw(etherToWithdraw);
}
(bool success, ) = address(owner).call{value: managementFee}("");
require(success);
address token;
uint256 ethAmount;
IndexComponent memory component;
for (uint8 i = 0; i < tokens.length; ) {
token = tokens[i];
component = components[token];
ethAmount = (component.weight * purchaseAmount) / 100;
if (component.version == UniswapVersion.V2) {
_purchaseFromV2(token, ethAmount);
} else {
_purchaseFromV3(token, ethAmount, component.fee);
}
unchecked {
i++;
}
}
lastPurchase = block.timestamp;
}
function updateWeights(IndexComponent[] calldata newComponents) external {
_requireIsOwner();
uint8 totalWeight;
for (uint8 i = 0; i < newComponents.length; ) {
totalWeight += newComponents[i].weight;
unchecked {
i++;
}
}
require(totalWeight == 100, "!valid");
for (uint i = 0; i < allTokens.length; ) {
address token = allTokens[i];
delete components[token];
emit IndexComponentUpdated(token, 0);
unchecked {
i++;
}
}
delete tokens;
IndexComponent memory currentComponent;
for (uint i = 0; i < newComponents.length; ) {
currentComponent = newComponents[i];
components[currentComponent.token] = currentComponent;
tokens.push(currentComponent.token);
if (!hasToken[currentComponent.token]) {
hasToken[currentComponent.token] = true;
allTokens.push(currentComponent.token);
}
emit IndexComponentUpdated(
currentComponent.token,
currentComponent.weight
);
unchecked {
i++;
}
}
}
function redeem(uint256 amount) external {
require(chad != address(0));
require(amount > 0, "!tokens");
uint256 share = (amount * MAX_BPS) / ERC20(chad).totalSupply();
IChad(chad).burn(msg.sender, amount);
address token;
uint256 allocation;
uint256 contractBalance;
for (uint8 i = 0; i < allTokens.length; ) {
token = allTokens[i];
contractBalance = ERC20(token).balanceOf(address(this));
if (contractBalance > 0) {
allocation = (contractBalance * share) / MAX_BPS;
ERC20(token).safeTransfer(msg.sender, allocation);
emit TokenRedeemed(token, allocation);
}
unchecked {
i++;
}
}
if (lastPurchase != 0 && lastPurchase + 15 days < block.timestamp) {
address liquidityAddress = IChad(chad).uniswapV2Pair();
uint256 liquidityBalance = ERC20(liquidityAddress).balanceOf(
address(this)
);
uint256 liquidityAllocation = (liquidityBalance * share) / MAX_BPS;
if (liquidityAllocation > 0) {
uniswapV2Router.removeLiquidity(
WETH,
chad,
liquidityAllocation,
0,
0,
address(this),
block.timestamp
);
}
uint256 chadRemoved = ERC20(chad).balanceOf(address(this));
IChad(chad).burn(address(this), chadRemoved);
uint256 wethBalance = ERC20(WETH).balanceOf(address(this));
uint256 wethAllocation = (wethBalance * share) / MAX_BPS;
if (wethAllocation > 0) {
ERC20(WETH).safeTransfer(msg.sender, wethAllocation);
}
}
}
function redemptionAmounts() external view returns (TokenAmount[] memory) {
TokenAmount[] memory tokenAmounts = new TokenAmount[](allTokens.length);
for (uint8 i = 0; i < allTokens.length; ) {
address token = allTokens[i];
tokenAmounts[i].token = token;
tokenAmounts[i].amount = ERC20(token).balanceOf(address(this));
unchecked {
i++;
}
}
return tokenAmounts;
}
function currentTokenCount() external view returns (uint256) {
return tokens.length;
}
function totalTokenCount() external view returns (uint256) {
return allTokens.length;
}
function _purchaseFromV2(address token, uint256 amount) internal {
address[] memory path = new address[](2);
path[0] = WETH;
path[1] = token;
uint256 balanceBefore = ERC20(token).balanceOf(address(this));
uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amount,
0,
path,
address(this),
block.timestamp
);
uint256 balanceAfter = ERC20(token).balanceOf(address(this));
emit TokenPurchased(token, balanceAfter - balanceBefore);
}
function _purchaseFromV3(
address token,
uint256 amount,
uint24 fee
) internal {
uint256 balanceBefore = ERC20(token).balanceOf(address(this));
uniswapV3Router.exactInput(
ISwapRouter.ExactInputParams({
path: abi.encodePacked(WETH, fee, token),
recipient: address(this),
deadline: block.timestamp,
amountIn: amount,
amountOutMinimum: 0
})
);
uint256 balanceAfter = ERC20(token).balanceOf(address(this));
emit TokenPurchased(token, balanceAfter - balanceBefore);
}
}
文件 8 的 10:Owned.sol
pragma solidity >=0.8.0;
abstract contract Owned {
event OwnershipTransferred(address indexed user, address indexed newOwner);
address public owner;
modifier onlyOwner() virtual {
require(msg.sender == owner, "UNAUTHORIZED");
_;
}
constructor(address _owner) {
owner = _owner;
emit OwnershipTransferred(address(0), _owner);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
owner = newOwner;
emit OwnershipTransferred(msg.sender, newOwner);
}
}
文件 9 的 10:SafeTransferLib.sol
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
library SafeTransferLib {
function safeTransferETH(address to, uint256 amount) internal {
bool success;
assembly {
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 68), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}
文件 10 的 10:WETH.sol
pragma solidity >=0.8.0;
import {ERC20} from "./ERC20.sol";
import {SafeTransferLib} from "../utils/SafeTransferLib.sol";
contract WETH is ERC20("Wrapped Ether", "WETH", 18) {
using SafeTransferLib for address;
event Deposit(address indexed from, uint256 amount);
event Withdrawal(address indexed to, uint256 amount);
function deposit() public payable virtual {
_mint(msg.sender, msg.value);
emit Deposit(msg.sender, msg.value);
}
function withdraw(uint256 amount) public virtual {
_burn(msg.sender, amount);
emit Withdrawal(msg.sender, amount);
msg.sender.safeTransferETH(amount);
}
receive() external payable virtual {
deposit();
}
}
{
"compilationTarget": {
"src/Index.sol": "Index"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/",
":solmate/=lib/solmate/src/"
]
}
[{"inputs":[{"internalType":"address","name":"routerAddressV2","type":"address"},{"internalType":"address","name":"routerAddressV3","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint8","name":"weight","type":"uint8"}],"name":"IndexComponentUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"chad","type":"address"}],"name":"SetChad","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenRedeemed","type":"event"},{"inputs":[],"name":"CHAD","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HIGH_FEE","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOW_FEE","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MILADY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"canUpdateWeights","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chad","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"components","outputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint8","name":"weight","type":"uint8"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"enum Index.UniswapVersion","name":"version","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTokenCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enterNewParadigm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPurchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redemptionAmounts","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Index.TokenAmount[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newChad","type":"address"}],"name":"setToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokenCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapV2Router","outputs":[{"internalType":"contract IUniswapV2Router","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV3Router","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint8","name":"weight","type":"uint8"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"enum Index.UniswapVersion","name":"version","type":"uint8"}],"internalType":"struct Index.IndexComponent[]","name":"newComponents","type":"tuple[]"}],"name":"updateWeights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]