Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 107558218 | 924 days ago | 0 ETH | ||||
| 107558218 | 924 days ago | 0 ETH | ||||
| 107558218 | 924 days ago | 0 ETH | ||||
| 107558218 | 924 days ago | 0 ETH | ||||
| 107558218 | 924 days ago | 0 ETH | ||||
| 107558218 | 924 days ago | 0 ETH | ||||
| 107558218 | 924 days ago | 0 ETH | ||||
| 107558218 | 924 days ago | 0 ETH | ||||
| 107558218 | 924 days ago | 0 ETH | ||||
| 107558218 | 924 days ago | 0 ETH | ||||
| 107557978 | 924 days ago | 0 ETH | ||||
| 107557978 | 924 days ago | 0 ETH | ||||
| 107557978 | 924 days ago | 0 ETH | ||||
| 107557978 | 924 days ago | 0 ETH | ||||
| 107557978 | 924 days ago | 0 ETH | ||||
| 107557978 | 924 days ago | 0 ETH | ||||
| 107557978 | 924 days ago | 0 ETH | ||||
| 107557978 | 924 days ago | 0 ETH | ||||
| 107557978 | 924 days ago | 0 ETH | ||||
| 107557978 | 924 days ago | 0 ETH | ||||
| 107557843 | 924 days ago | 0 ETH | ||||
| 107557843 | 924 days ago | 0 ETH | ||||
| 107557843 | 924 days ago | 0 ETH | ||||
| 107557843 | 924 days ago | 0 ETH | ||||
| 107557843 | 924 days ago | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
StablePool
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 999999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.0;
import {ERC20} from "@rari-capital/solmate/src/tokens/ERC20.sol";
import {ReentrancyGuard} from "@rari-capital/solmate/src/utils/ReentrancyGuard.sol";
import {IBentoBoxMinimal} from "../../interfaces/IBentoBoxMinimal.sol";
import {IMasterDeployerV2} from "../../interfaces/IMasterDeployerV2.sol";
import {IPool} from "../../interfaces/IPool.sol";
import {IStablePoolFactory} from "../../interfaces/IStablePoolFactory.sol";
import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {TridentMath} from "../../libraries/TridentMath.sol";
import "../../libraries/RebaseLibrary.sol";
/// @dev Custom Errors
error ZeroAddress();
error IdenticalAddress();
error InvalidSwapFee();
error InsufficientLiquidityMinted();
error InvalidAmounts();
error InvalidInputToken();
error PoolUninitialized();
error InvalidOutputToken();
/// @notice Trident exchange pool template with stable swap (solidly exchange) for swapping between tightly correlated assets
contract StablePool is IPool, ERC20, ReentrancyGuard {
using RebaseLibrary for Rebase;
using SafeERC20 for IERC20;
event Mint(address indexed sender, uint256 amount0, uint256 amount1, address indexed recipient);
event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed recipient);
event Sync(uint256 reserve0, uint256 reserve1);
uint256 internal constant MINIMUM_LIQUIDITY = 1000;
uint256 internal constant MAX_FEE = 10000; // @dev 100%.
uint256 public immutable swapFee;
uint256 internal immutable MAX_FEE_MINUS_SWAP_FEE;
IBentoBoxMinimal public immutable bento;
IMasterDeployerV2 public immutable masterDeployer;
address public immutable token0;
address public immutable token1;
uint256 public barFee;
address public barFeeTo;
uint256 public kLast;
uint256 internal reserve0;
uint256 internal reserve1;
uint256 public immutable decimals0;
uint256 public immutable decimals1;
bytes32 public constant poolIdentifier = "Trident:StablePool";
constructor() ERC20("Sushi Stable LP Token", "SSLP", 18) {
(bytes memory _deployData, IMasterDeployerV2 _masterDeployer) = IStablePoolFactory(msg.sender).getDeployData();
(address _token0, address _token1, uint256 _swapFee) = abi.decode(_deployData, (address, address, uint256));
// Factory ensures that the tokens are sorted.
if (_token0 == address(0)) revert ZeroAddress();
if (_token0 == _token1) revert IdenticalAddress();
if (_swapFee > MAX_FEE) revert InvalidSwapFee();
token0 = _token0;
token1 = _token1;
swapFee = _swapFee;
// This is safe from underflow - `swapFee` cannot exceed `MAX_FEE` per previous check.
unchecked {
MAX_FEE_MINUS_SWAP_FEE = MAX_FEE - _swapFee;
}
decimals0 = uint256(10)**(ERC20(_token0).decimals());
decimals1 = uint256(10)**(ERC20(_token1).decimals());
barFee = _masterDeployer.barFee();
barFeeTo = _masterDeployer.barFeeTo();
bento = IBentoBoxMinimal(_masterDeployer.bento());
masterDeployer = _masterDeployer;
}
/// @dev Mints LP tokens - should be called via the router after transferring `bento` tokens.
/// The router must ensure that sufficient LP tokens are minted by using the return value.
function mint(bytes calldata data) public override nonReentrant returns (uint256 liquidity) {
address recipient = abi.decode(data, (address));
(uint256 _reserve0, uint256 _reserve1) = _getReserves();
(uint256 balance0, uint256 balance1) = _balance();
uint256 newLiq = _computeLiquidity(balance0, balance1);
uint256 amount0 = balance0 - _reserve0;
uint256 amount1 = balance1 - _reserve1;
(uint256 fee0, uint256 fee1) = _nonOptimalMintFee(amount0, amount1, _reserve0, _reserve1);
_reserve0 += uint112(fee0);
_reserve1 += uint112(fee1);
(uint256 _totalSupply, uint256 oldLiq) = _mintFee(_reserve0, _reserve1);
if (_totalSupply == 0) {
if (amount0 == 0 || amount1 == 0) revert InvalidAmounts();
liquidity = newLiq - MINIMUM_LIQUIDITY;
_mint(address(0), MINIMUM_LIQUIDITY);
} else {
liquidity = ((newLiq - oldLiq) * _totalSupply) / oldLiq;
}
if (liquidity == 0) revert InsufficientLiquidityMinted();
_mint(recipient, liquidity);
_updateReserves();
kLast = newLiq;
emit Mint(msg.sender, amount0, amount1, recipient);
}
/// @dev Burns LP tokens sent to this contract. The router must ensure that the user gets sufficient output tokens.
function burn(bytes calldata data) public override nonReentrant returns (IPool.TokenAmount[] memory withdrawnAmounts) {
(address recipient, bool unwrapBento) = abi.decode(data, (address, bool));
(uint256 balance0, uint256 balance1) = _balance();
uint256 liquidity = balanceOf[address(this)];
(uint256 _totalSupply, ) = _mintFee(balance0, balance1);
uint256 amount0 = (liquidity * balance0) / _totalSupply;
uint256 amount1 = (liquidity * balance1) / _totalSupply;
_burn(address(this), liquidity);
_transfer(token0, amount0, recipient, unwrapBento);
_transfer(token1, amount1, recipient, unwrapBento);
_updateReserves();
withdrawnAmounts = new TokenAmount[](2);
withdrawnAmounts[0] = TokenAmount({token: token0, amount: amount0});
withdrawnAmounts[1] = TokenAmount({token: token1, amount: amount1});
kLast = _computeLiquidity(balance0 - amount0, balance1 - amount1);
emit Burn(msg.sender, amount0, amount1, recipient);
}
function burnSingle(bytes calldata data) public override nonReentrant returns (uint256 amountOut) {
(address tokenOut, address recipient, bool unwrapBento) = abi.decode(data, (address, address, bool));
(uint256 _reserve0, uint256 _reserve1) = _getReserves();
(uint256 balance0, uint256 balance1) = _balance();
uint256 liquidity = balanceOf[address(this)];
(uint256 _totalSupply, ) = _mintFee(balance0, balance1);
uint256 amount0 = (liquidity * balance0) / _totalSupply;
uint256 amount1 = (liquidity * balance1) / _totalSupply;
kLast = _computeLiquidity(balance0 - amount0, balance1 - amount1);
_burn(address(this), liquidity);
unchecked {
if (tokenOut == token1) {
amount1 += _getAmountOut(amount0, _reserve0 - amount0, _reserve1 - amount1, true);
_transfer(token1, amount1, recipient, unwrapBento);
amountOut = amount1;
amount0 = 0;
} else {
if (tokenOut != token0) revert InvalidOutputToken();
amount0 += _getAmountOut(amount1, _reserve0 - amount0, _reserve1 - amount1, false);
_transfer(token0, amount0, recipient, unwrapBento);
amountOut = amount0;
amount1 = 0;
}
}
_updateReserves();
emit Burn(msg.sender, amount0, amount1, recipient);
}
/// @dev Swaps one token for another. The router must prefund this contract and ensure there isn't too much slippage.
function swap(bytes calldata data) public override nonReentrant returns (uint256 amountOut) {
(address tokenIn, address recipient, bool unwrapBento) = abi.decode(data, (address, address, bool));
(uint256 _reserve0, uint256 _reserve1, uint256 balance0, uint256 balance1) = _getReservesAndBalances();
uint256 amountIn;
address tokenOut;
if (tokenIn == token0) {
tokenOut = token1;
unchecked {
amountIn = balance0 - _reserve0;
}
amountOut = _getAmountOut(amountIn, _reserve0, _reserve1, true);
} else {
if (tokenIn != token1) revert InvalidInputToken();
tokenOut = token0;
unchecked {
amountIn = balance1 - _reserve1;
}
amountOut = _getAmountOut(amountIn, _reserve0, _reserve1, false);
}
_transfer(tokenOut, amountOut, recipient, unwrapBento);
_updateReserves();
emit Swap(recipient, tokenIn, tokenOut, amountIn, amountOut);
}
/// @dev Updates `barFee` and `barFeeTo` for Trident protocol.
function updateBarParameters() public {
barFee = masterDeployer.barFee();
barFeeTo = masterDeployer.barFeeTo();
}
function _balance() internal view returns (uint256 balance0, uint256 balance1) {
balance0 = bento.toAmount(token0, bento.balanceOf(token0, address(this)), false);
balance1 = bento.toAmount(token1, bento.balanceOf(token1, address(this)), false);
}
function _getReservesAndBalances()
internal
view
returns (
uint256 _reserve0,
uint256 _reserve1,
uint256 balance0,
uint256 balance1
)
{
(_reserve0, _reserve1) = (reserve0, reserve1);
balance0 = bento.balanceOf(token0, address(this));
balance1 = bento.balanceOf(token1, address(this));
Rebase memory total0 = bento.totals(token0);
Rebase memory total1 = bento.totals(token1);
balance0 = total0.toElastic(balance0);
balance1 = total1.toElastic(balance1);
}
function _updateReserves() internal {
(uint256 _reserve0, uint256 _reserve1) = _balance();
reserve0 = _reserve0;
reserve1 = _reserve1;
emit Sync(_reserve0, _reserve1);
}
function _computeLiquidity(uint256 _reserve0, uint256 _reserve1) internal view returns (uint256 liquidity) {
unchecked {
uint256 adjustedReserve0 = (_reserve0 * 1e12) / decimals0;
uint256 adjustedReserve1 = (_reserve1 * 1e12) / decimals1;
liquidity = _computeLiquidityFromAdjustedBalances(adjustedReserve0, adjustedReserve1);
}
}
function _computeLiquidityFromAdjustedBalances(uint256 x, uint256 y) internal pure returns (uint256 computed) {
return TridentMath.sqrt(TridentMath.sqrt(_k(x, y)));
}
function _mintFee(uint256 _reserve0, uint256 _reserve1) internal returns (uint256 _totalSupply, uint256 computed) {
_totalSupply = totalSupply;
uint256 _kLast = kLast;
if (_kLast != 0) {
computed = _computeLiquidity(_reserve0, _reserve1);
if (computed > _kLast) {
// `barFee` % of increase in liquidity.
uint256 _barFee = barFee;
uint256 numerator = _totalSupply * (computed - _kLast) * _barFee;
uint256 denominator = (MAX_FEE - _barFee) * computed + _barFee * _kLast;
uint256 liquidity = numerator / denominator;
if (liquidity != 0) {
_mint(barFeeTo, liquidity);
_totalSupply += liquidity;
}
}
}
}
/// @dev This fee is charged to cover for `swapFee` when users add unbalanced liquidity.
function _nonOptimalMintFee(
uint256 _amount0,
uint256 _amount1,
uint256 _reserve0,
uint256 _reserve1
) internal view returns (uint256 token0Fee, uint256 token1Fee) {
if (_reserve0 == 0 || _reserve1 == 0) return (0, 0);
uint256 amount1Optimal = (_amount0 * _reserve1) / _reserve0;
if (amount1Optimal <= _amount1) {
token1Fee = (swapFee * (_amount1 - amount1Optimal)) / (2 * MAX_FEE);
} else {
uint256 amount0Optimal = (_amount1 * _reserve0) / _reserve1;
token0Fee = (swapFee * (_amount0 - amount0Optimal)) / (2 * MAX_FEE);
}
}
function _k(uint256 x, uint256 y) internal pure returns (uint256) {
uint256 _a = (x * y) / 1e12;
uint256 _b = ((x * x) / 1e12 + (y * y) / 1e12);
return ((_a * _b) / 1e12); // x3y+y3x >= k
}
function _f(uint256 x0, uint256 y) internal pure returns (uint256) {
return (x0 * ((((y * y) / 1e12) * y) / 1e12)) / 1e12 + (((((x0 * x0) / 1e12) * x0) / 1e12) * y) / 1e12;
}
function _d(uint256 x0, uint256 y) internal pure returns (uint256) {
return (3 * x0 * ((y * y) / 1e12)) / 1e12 + ((((x0 * x0) / 1e12) * x0) / 1e12);
}
function _get_y(
uint256 x0,
uint256 xy,
uint256 y
) internal pure returns (uint256) {
for (uint256 i = 0; i < 255; i++) {
uint256 y_prev = y;
uint256 k = _f(x0, y);
if (k < xy) {
uint256 dy = ((xy - k) * 1e12) / _d(x0, y);
y = y + dy;
} else {
uint256 dy = ((k - xy) * 1e12) / _d(x0, y);
y = y - dy;
}
if (y > y_prev) {
if (y - y_prev <= 1) {
return y;
}
} else {
if (y_prev - y <= 1) {
return y;
}
}
}
return y;
}
function _getAmountOut(
uint256 amountIn,
uint256 _reserve0,
uint256 _reserve1,
bool token0In
) internal view returns (uint256 dy) {
unchecked {
uint256 adjustedReserve0 = (_reserve0 * 1e12) / decimals0;
uint256 adjustedReserve1 = (_reserve1 * 1e12) / decimals1;
uint256 feeDeductedAmountIn = amountIn - (amountIn * swapFee) / MAX_FEE;
uint256 xy = _k(adjustedReserve0, adjustedReserve1);
if (token0In) {
uint256 x0 = adjustedReserve0 + ((feeDeductedAmountIn * 1e12) / decimals0);
uint256 y = _get_y(x0, xy, adjustedReserve1);
dy = adjustedReserve1 - y;
dy = (dy * decimals1) / 1e12;
} else {
uint256 x0 = adjustedReserve1 + ((feeDeductedAmountIn * 1e12) / decimals1);
uint256 y = _get_y(x0, xy, adjustedReserve0);
dy = adjustedReserve0 - y;
dy = (dy * decimals0) / 1e12;
}
}
}
function getAmountOut(bytes calldata data) public view override returns (uint256 finalAmountOut) {
(address tokenIn, uint256 amountIn) = abi.decode(data, (address, uint256));
(uint256 _reserve0, uint256 _reserve1) = _getReserves();
amountIn = bento.toAmount(tokenIn, amountIn, false);
if (tokenIn == token0) {
finalAmountOut = bento.toShare(token1, _getAmountOut(amountIn, _reserve0, _reserve1, true), false);
} else {
if (tokenIn != token1) revert InvalidInputToken();
finalAmountOut = bento.toShare(token0, _getAmountOut(amountIn, _reserve0, _reserve1, false), false);
}
}
function _transfer(
address token,
uint256 amount,
address to,
bool unwrapBento
) internal {
if (unwrapBento) {
bento.withdraw(token, address(this), to, amount, 0);
} else {
uint256 shares = bento.toShare(token, amount, false);
bento.transfer(token, address(this), to, shares);
}
}
function getAssets() public view returns (address[] memory assets) {
assets = new address[](2);
assets[0] = token0;
assets[1] = token1;
}
function skim() public nonReentrant {
address _token0 = token0;
address _token1 = token1;
address receiver = masterDeployer.owner();
IERC20(_token0).safeTransfer(receiver, IERC20(_token0).balanceOf(address(this)));
IERC20(_token1).safeTransfer(receiver, IERC20(_token1).balanceOf(address(this)));
}
function _getReserves() internal view returns (uint256 _reserve0, uint256 _reserve1) {
(_reserve0, _reserve1) = (reserve0, reserve1);
}
function getReserves() public view returns (uint256 _reserve0, uint256 _reserve1) {
return _getReserves();
}
function getNativeReserves() public view returns (uint256 _nativeReserve0, uint256 _nativeReserve1) {
return _getReserves();
}
function flashSwap(bytes calldata) external pure override returns (uint256) {
revert();
}
function getAmountIn(bytes calldata) external pure override returns (uint256) {
revert();
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*///////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*///////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*///////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*///////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
bytes32 public constant PERMIT_TYPEHASH =
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*///////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*///////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
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;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
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]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*///////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
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 because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
)
);
address recoveredAddress = ecrecover(digest, 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)
)
);
}
/*///////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
uint256 private reentrancyStatus = 1;
modifier nonReentrant() {
require(reentrancyStatus == 1, "REENTRANCY");
reentrancyStatus = 2;
_;
reentrancyStatus = 1;
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.0;
import "../libraries/RebaseLibrary.sol";
/// @notice Minimal BentoBox vault interface.
/// @dev `token` is aliased as `address` from `IERC20` for simplicity.
interface IBentoBoxMinimal {
/// @notice Balance per ERC-20 token per account in shares.
function balanceOf(address, address) external view returns (uint256);
/// @dev Helper function to represent an `amount` of `token` in shares.
/// @param token The ERC-20 token.
/// @param amount The `token` amount.
/// @param roundUp If the result `share` should be rounded up.
/// @return share The token amount represented in shares.
function toShare(
address token,
uint256 amount,
bool roundUp
) external view returns (uint256 share);
/// @dev Helper function to represent shares back into the `token` amount.
/// @param token The ERC-20 token.
/// @param share The amount of shares.
/// @param roundUp If the result should be rounded up.
/// @return amount The share amount back into native representation.
function toAmount(
address token,
uint256 share,
bool roundUp
) external view returns (uint256 amount);
/// @notice Registers this contract so that users can approve it for BentoBox.
function registerProtocol() external;
/// @notice Deposit an amount of `token` represented in either `amount` or `share`.
/// @param token The ERC-20 token to deposit.
/// @param from which account to pull the tokens.
/// @param to which account to push the tokens.
/// @param amount Token amount in native representation to deposit.
/// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.
/// @return amountOut The amount deposited.
/// @return shareOut The deposited amount represented in shares.
function deposit(
address token,
address from,
address to,
uint256 amount,
uint256 share
) external payable returns (uint256 amountOut, uint256 shareOut);
/// @notice Withdraws an amount of `token` from a user account.
/// @param token_ The ERC-20 token to withdraw.
/// @param from which user to pull the tokens.
/// @param to which user to push the tokens.
/// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.
/// @param share Like above, but `share` takes precedence over `amount`.
function withdraw(
address token_,
address from,
address to,
uint256 amount,
uint256 share
) external returns (uint256 amountOut, uint256 shareOut);
/// @notice Transfer shares from a user account to another one.
/// @param token The ERC-20 token to transfer.
/// @param from which user to pull the tokens.
/// @param to which user to push the tokens.
/// @param share The amount of `token` in shares.
function transfer(
address token,
address from,
address to,
uint256 share
) external;
/// @dev Reads the Rebase `totals`from storage for a given token
function totals(address token) external view returns (Rebase memory total);
/// @dev Approves users' BentoBox assets to a "master" contract.
function setMasterContractApproval(
address user,
address masterContract,
bool approved,
uint8 v,
bytes32 r,
bytes32 s
) external;
function harvest(
address token,
bool balance,
uint256 maxChangeAmount
) external;
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.0;
import "./IMasterDeployer.sol";
/// @notice Trident pool deployer interface.
interface IMasterDeployerV2 is IMasterDeployer {
function barFee() external view returns (uint256);
function barFeeTo() external view returns (address);
function bento() external view returns (address);
function migrator() external view returns (address);
function pools(address pool) external view returns (bool);
function deployPool(address factory, bytes calldata deployData) external returns (address);
function owner() external returns (address);
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.5.0;
pragma experimental ABIEncoderV2;
/// @notice Trident pool interface.
interface IPool {
/// @notice Executes a swap from one token to another.
/// @dev The input tokens must've already been sent to the pool.
/// @param data ABI-encoded params that the pool requires.
/// @return finalAmountOut The amount of output tokens that were sent to the user.
function swap(bytes calldata data) external returns (uint256 finalAmountOut);
/// @notice Executes a swap from one token to another with a callback.
/// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.
/// @param data ABI-encoded params that the pool requires.
/// @return finalAmountOut The amount of output tokens that were sent to the user.
function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);
/// @notice Mints liquidity tokens.
/// @param data ABI-encoded params that the pool requires.
/// @return liquidity The amount of liquidity tokens that were minted for the user.
function mint(bytes calldata data) external returns (uint256 liquidity);
/// @notice Burns liquidity tokens.
/// @dev The input LP tokens must've already been sent to the pool.
/// @param data ABI-encoded params that the pool requires.
/// @return withdrawnAmounts The amount of various output tokens that were sent to the user.
function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);
/// @notice Burns liquidity tokens for a single output token.
/// @dev The input LP tokens must've already been sent to the pool.
/// @param data ABI-encoded params that the pool requires.
/// @return amountOut The amount of output tokens that were sent to the user.
function burnSingle(bytes calldata data) external returns (uint256 amountOut);
/// @return A unique identifier for the pool type.
function poolIdentifier() external pure returns (bytes32);
/// @return An array of tokens supported by the pool.
function getAssets() external view returns (address[] memory);
/// @notice Simulates a trade and returns the expected output.
/// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.
/// @param data ABI-encoded params that the pool requires.
/// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.
function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);
/// @notice Simulates a trade and returns the expected output.
/// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.
/// @param data ABI-encoded params that the pool requires.
/// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.
function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);
/// @dev This event must be emitted on all swaps.
event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);
/// @dev This struct frames output tokens for burns.
struct TokenAmount {
address token;
uint256 amount;
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.0;
import "./IMasterDeployerV2.sol";
interface IStablePoolFactory {
function getDeployData() external view returns (bytes memory, IMasterDeployerV2);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.0;
/// @notice Trident sqrt helper library.
library TridentMath {
/// @dev Modified from Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)
function sqrt(uint256 x) internal pure returns (uint256 z) {
assembly {
// This segment is to get a reasonable initial estimate for the Babylonian method.
// If the initial estimate is bad, the number of correct bits increases ~linearly
// each iteration instead of ~quadratically.
// The idea is to get z*z*y within a small factor of x.
// More iterations here gets y in a tighter range. Currently, we will have
// y in [256, 256*2^16). We ensure y>= 256 so that the relative difference
// between y and y+1 is small. If x < 256 this is not possible, but those cases
// are easy enough to verify exhaustively.
z := 181 // The 'correct' value is 1, but this saves a multiply later
let y := x
// Note that we check y>= 2^(k + 8) but shift right by k bits each branch,
// this is to ensure that if x >= 256, then y >= 256.
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
y := shr(128, y)
z := shl(64, z)
}
if iszero(lt(y, 0x1000000000000000000)) {
y := shr(64, y)
z := shl(32, z)
}
if iszero(lt(y, 0x10000000000)) {
y := shr(32, y)
z := shl(16, z)
}
if iszero(lt(y, 0x1000000)) {
y := shr(16, y)
z := shl(8, z)
}
// Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8),
// and either y >= 256, or x < 256.
// Correctness can be checked exhaustively for x < 256, so we assume y >= 256.
// Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.
// For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1)
// is in the range (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s=1
// and when s = 256 or 1/256. Since y is in [256, 256*2^16), let a = y/65536, so
// that a is in [1/256, 256). Then we can estimate sqrt(y) as
// sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18
// There is no overflow risk here since y < 2^136 after the first branch above.
z := shr(18, mul(z, add(y, 65536))) // A multiply is saved from the initial z := 181
// Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
// Possibly with a quadratic/cubic polynomial above we could get 4-6.
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
// See https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division.
// If x+1 is a perfect square, the Babylonian method cycles between
// floor(sqrt(x)) and ceil(sqrt(x)). This check ensures we return floor.
// Since this case is rare, we choose to save gas on the assignment and
// repeat division in the rare case.
// If you don't care whether floor or ceil is returned, you can skip this.
if lt(div(x, z), z) {
z := div(x, z)
}
}
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8;
struct Rebase {
uint128 elastic;
uint128 base;
}
/// @notice A rebasing library
library RebaseLibrary {
/// @notice Calculates the base value in relationship to `elastic` and `total`.
function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {
if (total.elastic == 0) {
base = elastic;
} else {
base = (elastic * total.base) / total.elastic;
}
}
/// @notice Calculates the elastic value in relationship to `base` and `total`.
function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {
if (total.base == 0) {
elastic = base;
} else {
elastic = (base * total.elastic) / total.base;
}
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.0;
/// @notice Trident pool deployer interface.
interface IMasterDeployer {
function barFee() external view returns (uint256);
function barFeeTo() external view returns (address);
function bento() external view returns (address);
function migrator() external view returns (address);
function pools(address pool) external view returns (bool);
function deployPool(address factory, bytes calldata deployData) external returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}{
"optimizer": {
"enabled": true,
"runs": 999999
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"IdenticalAddress","type":"error"},{"inputs":[],"name":"InsufficientLiquidityMinted","type":"error"},{"inputs":[],"name":"InvalidAmounts","type":"error"},{"inputs":[],"name":"InvalidInputToken","type":"error"},{"inputs":[],"name":"InvalidOutputToken","type":"error"},{"inputs":[],"name":"InvalidSwapFee","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reserve0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reserve1","type":"uint256"}],"name":"Sync","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"barFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"barFeeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bento","outputs":[{"internalType":"contract IBentoBoxMinimal","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"burn","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IPool.TokenAmount[]","name":"withdrawnAmounts","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"burnSingle","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"flashSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"finalAmountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAssets","outputs":[{"internalType":"address[]","name":"assets","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeReserves","outputs":[{"internalType":"uint256","name":"_nativeReserve0","type":"uint256"},{"internalType":"uint256","name":"_nativeReserve1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint256","name":"_reserve0","type":"uint256"},{"internalType":"uint256","name":"_reserve1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"masterDeployer","outputs":[{"internalType":"contract IMasterDeployerV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mint","outputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"poolIdentifier","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"skim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swap","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateBarParameters","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101e060405260016006553480156200001757600080fd5b50604080518082018252601581527f537573686920537461626c65204c5020546f6b656e0000000000000000000000602080830191825283518085019094526004845263053534c560e41b9084015281519192916012916200007d9160009190620004f6565b50815162000093906001906020850190620004f6565b5060ff81166080524660a052620000a96200045a565b60c08181525050505050600080336001600160a01b031663d039f6226040518163ffffffff1660e01b8152600401600060405180830381865afa158015620000f5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200011f9190810190620005dd565b915091506000806000848060200190518101906200013e9190620006ce565b919450925090506001600160a01b0383166200016d5760405163d92e233d60e01b815260040160405180910390fd5b816001600160a01b0316836001600160a01b03161415620001a15760405163065af08d60e01b815260040160405180910390fd5b612710811115620001c55760405163da7459b760e01b815260040160405180910390fd5b6001600160a01b038084166101608190529083166101805260e0829052612710829003610100526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa15801562000228573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200024e919062000716565b6200025b90600a62000857565b6101a08181525050816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002a2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002c8919062000716565b620002d590600a62000857565b6101c08181525050836001600160a01b031663c14ad8026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200031c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000342919062000868565b600781905550836001600160a01b0316630c0a0cd26040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000387573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003ad919062000882565b600860006101000a8154816001600160a01b0302191690836001600160a01b03160217905550836001600160a01b0316634da318276040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000412573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000438919062000882565b6001600160a01b03908116610120529390931661014052506200098392505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60006040516200048e9190620008df565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b8280546200050490620008a2565b90600052602060002090601f01602090048101928262000528576000855562000573565b82601f106200054357805160ff191683800117855562000573565b8280016001018555821562000573579182015b828111156200057357825182559160200191906001019062000556565b506200058192915062000585565b5090565b5b8082111562000581576000815560010162000586565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114620005c857600080fd5b50565b8051620005d881620005b2565b919050565b60008060408385031215620005f157600080fd5b82516001600160401b03808211156200060957600080fd5b818501915085601f8301126200061e57600080fd5b8151818111156200063357620006336200059c565b604051601f8201601f19908116603f011681019083821181831017156200065e576200065e6200059c565b816040528281526020935088848487010111156200067b57600080fd5b600091505b828210156200069f578482018401518183018501529083019062000680565b82821115620006b15760008484830101525b9550620006c3915050858201620005cb565b925050509250929050565b600080600060608486031215620006e457600080fd5b8351620006f181620005b2565b60208501519093506200070481620005b2565b80925050604084015190509250925092565b6000602082840312156200072957600080fd5b815160ff811681146200073b57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600181815b80851115620007995781600019048211156200077d576200077d62000742565b808516156200078b57918102915b93841c93908002906200075d565b509250929050565b600082620007b25750600162000851565b81620007c15750600062000851565b8160018114620007da5760028114620007e55762000805565b600191505062000851565b60ff841115620007f957620007f962000742565b50506001821b62000851565b5060208310610133831016604e8410600b84101617156200082a575081810a62000851565b62000836838362000758565b80600019048211156200084d576200084d62000742565b0290505b92915050565b60006200073b60ff841683620007a1565b6000602082840312156200087b57600080fd5b5051919050565b6000602082840312156200089557600080fd5b81516200073b81620005b2565b600181811c90821680620008b757607f821691505b60208210811415620008d957634e487b7160e01b600052602260045260246000fd5b50919050565b600080835481600182811c915080831680620008fc57607f831692505b60208084108214156200091d57634e487b7160e01b86526022600452602486fd5b818015620009345760018114620009465762000975565b60ff1986168952848901965062000975565b60008a81526020902060005b868110156200096d5781548b82015290850190830162000952565b505084890196505b509498975050505050505050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051613e6262000b73600039600081816104fc0152818161288201528181612d2e01528181612df70152612e260152600081816104ad0152818161284701528181612cf301528181612da60152612e770152600081816105b3015281816107e401528181610c7001528181610d5401528181610f8e01528181610fc3015281816111bc0152818161162a015281816116f801528181611a2901528181611a92015281816122e701528181612a840152612c34015260008181610326015281816107bf01528181610c4401528181610ceb01528181610f350152818161104d0152818161114e0152818161159a015281816117b901528181611ac701528181611b640152818161216a015281816129a90152612b5f01526000818161058c0152818161080901528181611f320152611fc70152600081816103fb01528181611529015281816115ee0152818161177d0152818161219e01528181612319015281816125f1015281816126ba01528181612784015281816129dc01528181612ab501528181612b8d0152612c620152600050506000818161042201528181612d6a01528181612f040152612f6f01526000610e6f01526000610e3a015260006103ba0152613e626000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c806367e4ac2c11610145578063a8f1f52e116100bd578063cf58879a1161008c578063d505accf11610071578063d505accf146105d5578063dd62ed3e146105e8578063f1c49a391461061357600080fd5b8063cf58879a14610587578063d21220a7146105ae57600080fd5b8063a8f1f52e14610545578063a9059cbb14610558578063af8c09bf1461056b578063c14ad8021461057e57600080fd5b80637bdd6b441161011457806395d89b41116100f957806395d89b41146104ef578063a28af8a4146104f7578063a69840a81461051e57600080fd5b80637bdd6b44146104a85780637ecebe00146104cf57600080fd5b806367e4ac2c1461045757806370a082311461046c5780637464fc3d1461048c5780637ba0e2e71461049557600080fd5b80632a07b6c7116101d8578063499a3c50116101a757806354cf2aeb1161018c57806354cf2aeb1461041d578063627dd56a1461044457806365dfc7671461029c57600080fd5b8063499a3c50146102615780634da31827146103f657600080fd5b80632a07b6c71461036e57806330adf81f1461038e578063313ce567146103b55780633644e515146103ee57600080fd5b80630c0a0cd21161022f57806318160ddd1161021457806318160ddd146103485780631dd19cb41461035157806323b872dd1461035b57600080fd5b80630c0a0cd2146102dc5780630dfe16811461032157600080fd5b8063053da1c81461026157806306fdde03146102875780630902f1ac1461029c578063095ea7b3146102b9575b600080fd5b61027461026f3660046136cf565b61061b565b6040519081526020015b60405180910390f35b61028f610622565b60405161027e919061376d565b6102a46106b0565b6040805192835260208301919091520161027e565b6102cc6102c73660046137e3565b6106c8565b604051901515815260200161027e565b6008546102fc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161027e565b6102fc7f000000000000000000000000000000000000000000000000000000000000000081565b61027460025481565b610359610742565b005b6102cc61036936600461380f565b610a09565b61038161037c3660046136cf565b610b4f565b60405161027e9190613850565b6102747f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b6103dc7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff909116815260200161027e565b610274610e36565b6102fc7f000000000000000000000000000000000000000000000000000000000000000081565b6102747f000000000000000000000000000000000000000000000000000000000000000081565b6102746104523660046136cf565b610e91565b61045f61112c565b60405161027e91906138b5565b61027461047a36600461390f565b60036020526000908152604090205481565b61027460095481565b6102746104a33660046136cf565b61122b565b6102747f000000000000000000000000000000000000000000000000000000000000000081565b6102746104dd36600461390f565b60056020526000908152604090205481565b61028f61149f565b6102747f000000000000000000000000000000000000000000000000000000000000000081565b6102747f54726964656e743a537461626c65506f6f6c000000000000000000000000000081565b6102746105533660046136cf565b6114ac565b6102cc6105663660046137e3565b61188b565b6102746105793660046136cf565b611910565b61027460075481565b6102fc7f000000000000000000000000000000000000000000000000000000000000000081565b6102fc7f000000000000000000000000000000000000000000000000000000000000000081565b6103596105e336600461392c565b611c04565b6102746105f63660046139a3565b600460209081526000928352604080842090915290825290205481565b610359611f30565b6000806000fd5b6000805461062f906139dc565b80601f016020809104026020016040519081016040528092919081815260200182805461065b906139dc565b80156106a85780601f1061067d576101008083540402835291602001916106a8565b820191906000526020600020905b81548152906001019060200180831161068b57829003601f168201915b505050505081565b6000806106c0600a54600b549091565b915091509091565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906107309086815260200190565b60405180910390a35060015b92915050565b6006546001146107b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600260068190555060007f0000000000000000000000000000000000000000000000000000000000000000905060007f0000000000000000000000000000000000000000000000000000000000000000905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610874573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108989190613a30565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915061094d90829073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa15801561090b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092f9190613a4d565b73ffffffffffffffffffffffffffffffffffffffff8616919061209b565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526109ff90829073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156109bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e19190613a4d565b73ffffffffffffffffffffffffffffffffffffffff8516919061209b565b5050600160065550565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610a9d57610a6b8382613a95565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff851660009081526003602052604081208054859290610ad2908490613a95565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610b3a9087815260200190565b60405180910390a360019150505b9392505050565b6060600654600114610bbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016107aa565b6002600655600080610bd184860186613aba565b91509150600080610be061212d565b30600090815260036020526040812054929450909250610c00848461242b565b509050600081610c108685613ae8565b610c1a9190613b54565b9050600082610c298686613ae8565b610c339190613b54565b9050610c3f30856124f4565b610c6b7f0000000000000000000000000000000000000000000000000000000000000000838a8a61258a565b610c977f0000000000000000000000000000000000000000000000000000000000000000828a8a61258a565b610c9f6127ea565b6040805160028082526060820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081610cb557905050985060405180604001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020018381525089600081518110610d3c57610d3c613b8f565b602002602001018190525060405180604001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020018281525089600181518110610da557610da5613b8f565b6020908102919091010152610dcc610dbd8388613a95565b610dc78388613a95565b612842565b600955604080518381526020810183905273ffffffffffffffffffffffffffffffffffffffff8a169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a3505060016006555094979650505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610e6c57610e676128cc565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b6000600654600114610eff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016107aa565b600260065560008080610f1485870187613bbe565b925092509250600080600080610f28612966565b93509350935093506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415610fc15750508382037f0000000000000000000000000000000000000000000000000000000000000000610fba8287876001612cee565b995061107c565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614611046576040517f2df9739b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50508281037f00000000000000000000000000000000000000000000000000000000000000006110798287876000612cee565b99505b611088818b8a8a61258a565b6110906127ea565b8073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e46062858e60405161110f929190918252602082015260400190565b60405180910390a450506001600655509598975050505050505050565b60408051600280825260608083018452926020830190803683370190505090507f00000000000000000000000000000000000000000000000000000000000000008160008151811061118057611180613b8f565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f0000000000000000000000000000000000000000000000000000000000000000816001815181106111ee576111ee613b8f565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505090565b6000600654600114611299576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016107aa565b600260065560006112ac8385018561390f565b90506000806112be600a54600b549091565b915091506000806112cd61212d565b9150915060006112dd8383612842565b905060006112eb8685613a95565b905060006112f98685613a95565b905060008061130a84848b8b612ea9565b90925090506113296dffffffffffffffffffffffffffff83168a613c09565b98506113456dffffffffffffffffffffffffffff821689613c09565b97506000806113548b8b61242b565b9150915081600014156113c35785158061136c575084155b156113a3576040517fd856fc5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113af6103e888613a95565b9c506113be60006103e8612fac565b6113e6565b80826113cf828a613a95565b6113d99190613ae8565b6113e39190613b54565b9c505b8c61141d576040517fd226f9d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114278c8e612fac565b61142f6127ea565b6009879055604080518781526020810187905273ffffffffffffffffffffffffffffffffffffffff8e169133917fdbba30eb0402b389513e87f51f4db2db80bed454384ec6925a24097c3548a02a910160405180910390a35050600160065550989b9a5050505050505050505050565b6001805461062f906139dc565b600080806114bc848601866137e3565b915091506000806114d0600a54600b549091565b6040517f5662311800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260248201879052600060448301529294509092507f000000000000000000000000000000000000000000000000000000000000000090911690635662311890606401602060405180830381865afa158015611572573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115969190613a4d565b92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156116f6577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663da5139ca7f00000000000000000000000000000000000000000000000000000000000000006116568686866001612cee565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260006044820152606401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a4d565b9450611881565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461177b576040517f2df9739b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663da5139ca7f00000000000000000000000000000000000000000000000000000000000000006117e58686866000612cee565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260006044820152606401602060405180830381865afa15801561185a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061187e9190613a4d565b94505b5050505092915050565b336000908152600360205260408120805483919083906118ac908490613a95565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107309086815260200190565b600060065460011461197e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016107aa565b60026006556000808061199385870187613bbe565b9250925092506000806119a9600a54600b549091565b915091506000806119b861212d565b306000908152600360205260408120549294509092506119d8848461242b565b5090506000816119e88685613ae8565b6119f29190613b54565b9050600082611a018686613ae8565b611a0b9190613b54565b9050611a1a610dbd8388613a95565b600955611a2730856124f4565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff161415611ac557611a8c82838a03838a036001612cee565b01611ab97f0000000000000000000000000000000000000000000000000000000000000000828c8c61258a565b809b5060009150611b92565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff1614611b4a576040517f0620202000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b5b81838a03838a036000612cee565b82019150611b8b7f0000000000000000000000000000000000000000000000000000000000000000838c8c61258a565b5099508960005b611b9a6127ea565b604080518381526020810183905273ffffffffffffffffffffffffffffffffffffffff8c169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050600160065550979a9950505050505050505050565b42841015611c6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f4558504952454400000000000000000060448201526064016107aa565b6000611c78610e36565b73ffffffffffffffffffffffffffffffffffffffff89811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938c166060840152608083018b905260a083019390935260c08083018a90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611dd7573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590611e5257508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611eb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e455200000000000000000000000000000000000060448201526064016107aa565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208b8516808552908352928190208a905551898152919350918a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663c14ad8026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fbf9190613a4d565b6007819055507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630c0a0cd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015612030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120549190613a30565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261212890849061301d565b505050565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000818116600484015230602484015260009283927f00000000000000000000000000000000000000000000000000000000000000001691635662311891839063f7888aec90604401602060405180830381865afa1580156121ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122119190613a4d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260006044820152606401602060405180830381865afa158015612286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122aa9190613a4d565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081811660048401523060248401529294507f00000000000000000000000000000000000000000000000000000000000000001691635662311891839063f7888aec90604401602060405180830381865afa158015612368573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238c9190613a4d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260006044820152606401602060405180830381865afa158015612401573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124259190613a4d565b90509091565b60025460095460009080156124ec576124448585612842565b9150808211156124ec5760075460008161245e8486613a95565b6124689087613ae8565b6124729190613ae8565b905060006124808484613ae8565b8561248d85612710613a95565b6124979190613ae8565b6124a19190613c09565b905060006124af8284613b54565b905080156124e7576008546124da9073ffffffffffffffffffffffffffffffffffffffff1682612fac565b6124e48188613c09565b96505b505050505b509250929050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054839290612529908490613a95565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b8015612664576040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152838116604483015260648201859052600060848301527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612639573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265d9190613c21565b50506127e4565b6040517fda5139ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260248201859052600060448301819052917f00000000000000000000000000000000000000000000000000000000000000009091169063da5139ca90606401602060405180830381865afa158015612703573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127279190613a4d565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301523060248301528581166044830152606482018390529192507f00000000000000000000000000000000000000000000000000000000000000009091169063f18d03cc90608401600060405180830381600087803b1580156127ca57600080fd5b505af11580156127de573d6000803e3d6000fd5b50505050505b50505050565b6000806127f561212d565b600a829055600b81905560408051838152602081018390529294509092507fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a15050565b6000807f00000000000000000000000000000000000000000000000000000000000000008464e8d4a51000028161287b5761287b613b25565b04905060007f00000000000000000000000000000000000000000000000000000000000000008464e8d4a5100002816128b6576128b6613b25565b0490506128c38282613129565b95945050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60006040516128fe9190613c45565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b600a54600b546040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015230602483015260009182917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612a23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a479190613a4d565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301529193507f00000000000000000000000000000000000000000000000000000000000000009091169063f7888aec90604401602060405180830381865afa158015612afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b229190613a4d565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301529192506000917f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa158015612bd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf79190613d38565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301529192506000917f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa158015612ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ccc9190613d38565b9050612cd88285613140565b9350612ce48184613140565b9250505090919293565b6000807f00000000000000000000000000000000000000000000000000000000000000008564e8d4a510000281612d2757612d27613b25565b04905060007f00000000000000000000000000000000000000000000000000000000000000008564e8d4a510000281612d6257612d62613b25565b0490506127107f000000000000000000000000000000000000000000000000000000000000000088020487036000612d9a8484613199565b90508515612e225760007f00000000000000000000000000000000000000000000000000000000000000008364e8d4a510000281612dda57612dda613b25565b04850190506000612dec828487613214565b64e8d4a510009086037f000000000000000000000000000000000000000000000000000000000000000002049650612e9d915050565b60007f00000000000000000000000000000000000000000000000000000000000000008364e8d4a510000281612e5a57612e5a613b25565b04840190506000612e6c828488613214565b64e8d4a510009087037f00000000000000000000000000000000000000000000000000000000000000000204965050505b50505050949350505050565b600080831580612eb7575082155b15612ec757506000905080612fa3565b600084612ed48589613ae8565b612ede9190613b54565b9050858111612f3957612ef46127106002613ae8565b612efe8288613a95565b612f28907f0000000000000000000000000000000000000000000000000000000000000000613ae8565b612f329190613b54565b9150612fa1565b600084612f468789613ae8565b612f509190613b54565b9050612f5f6127106002613ae8565b612f69828a613a95565b612f93907f0000000000000000000000000000000000000000000000000000000000000000613ae8565b612f9d9190613b54565b9350505b505b94509492505050565b8060026000828254612fbe9190613c09565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161257e565b600061307f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661331d9092919063ffffffff16565b805190915015612128578080602001905181019061309d9190613dba565b612128576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016107aa565b6000610b4861313b61313b8585613199565b613334565b600082602001516fffffffffffffffffffffffffffffffff166000141561316857508061073c565b602083015183516fffffffffffffffffffffffffffffffff9182169161318f911684613ae8565b610b489190613b54565b60008064e8d4a510006131ac8486613ae8565b6131b69190613b54565b9050600064e8d4a510006131ca8580613ae8565b6131d49190613b54565b64e8d4a510006131e48780613ae8565b6131ee9190613b54565b6131f89190613c09565b905064e8d4a5100061320a8284613ae8565b6128c39190613b54565b6000805b60ff8110156133145782600061322e87836133ed565b90508581101561327b5760006132448887613484565b61324e8389613a95565b61325d9064e8d4a51000613ae8565b6132679190613b54565b90506132738187613c09565b9550506132ba565b60006132878887613484565b6132918884613a95565b6132a09064e8d4a51000613ae8565b6132aa9190613b54565b90506132b68187613a95565b9550505b818511156132e35760016132ce8387613a95565b116132de57849350505050610b48565b6132ff565b60016132ef8684613a95565b116132ff57849350505050610b48565b5050808061330c90613dd7565b915050613218565b50909392505050565b606061332c84846000856134e6565b949350505050565b60b58171010000000000000000000000000000000000811061335b5760409190911b9060801c5b690100000000000000000081106133775760209190911b9060401c5b65010000000000811061338f5760109190911b9060201c5b630100000081106133a55760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c8082048111156133e85781045b919050565b600064e8d4a51000828185816134038280613ae8565b61340d9190613b54565b6134179190613ae8565b6134219190613b54565b61342b9190613ae8565b6134359190613b54565b64e8d4a510008084816134488280613ae8565b6134529190613b54565b61345c9190613ae8565b6134669190613b54565b6134709086613ae8565b61347a9190613b54565b610b489190613c09565b600064e8d4a5100083816134988280613ae8565b6134a29190613b54565b6134ac9190613ae8565b6134b69190613b54565b64e8d4a51000806134c78580613ae8565b6134d19190613b54565b6134dc866003613ae8565b6134709190613ae8565b606082471015613578576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016107aa565b73ffffffffffffffffffffffffffffffffffffffff85163b6135f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107aa565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161361f9190613e10565b60006040518083038185875af1925050503d806000811461365c576040519150601f19603f3d011682016040523d82523d6000602084013e613661565b606091505b509150915061367182828661367c565b979650505050505050565b6060831561368b575081610b48565b82511561369b5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107aa919061376d565b600080602083850312156136e257600080fd5b823567ffffffffffffffff808211156136fa57600080fd5b818501915085601f83011261370e57600080fd5b81358181111561371d57600080fd5b86602082850101111561372f57600080fd5b60209290920196919550909350505050565b60005b8381101561375c578181015183820152602001613744565b838111156127e45750506000910152565b602081526000825180602084015261378c816040850160208701613741565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff811681146137e057600080fd5b50565b600080604083850312156137f657600080fd5b8235613801816137be565b946020939093013593505050565b60008060006060848603121561382457600080fd5b833561382f816137be565b9250602084013561383f816137be565b929592945050506040919091013590565b602080825282518282018190526000919060409081850190868401855b828110156138a8578151805173ffffffffffffffffffffffffffffffffffffffff16855286015186850152928401929085019060010161386d565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561390357835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016138d1565b50909695505050505050565b60006020828403121561392157600080fd5b8135610b48816137be565b600080600080600080600060e0888a03121561394757600080fd5b8735613952816137be565b96506020880135613962816137be565b95506040880135945060608801359350608088013560ff8116811461398657600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156139b657600080fd5b82356139c1816137be565b915060208301356139d1816137be565b809150509250929050565b600181811c908216806139f057607f821691505b60208210811415613a2a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600060208284031215613a4257600080fd5b8151610b48816137be565b600060208284031215613a5f57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613aa757613aa7613a66565b500390565b80151581146137e057600080fd5b60008060408385031215613acd57600080fd5b8235613ad8816137be565b915060208301356139d181613aac565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613b2057613b20613a66565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613b8a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080600060608486031215613bd357600080fd5b8335613bde816137be565b92506020840135613bee816137be565b91506040840135613bfe81613aac565b809150509250925092565b60008219821115613c1c57613c1c613a66565b500190565b60008060408385031215613c3457600080fd5b505080516020909101519092909150565b600080835481600182811c915080831680613c6157607f831692505b6020808410821415613c9a577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b818015613cae5760018114613cdd57613d0a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00861689528489019650613d0a565b60008a81526020902060005b86811015613d025781548b820152908501908301613ce9565b505084890196505b509498975050505050505050565b80516fffffffffffffffffffffffffffffffff811681146133e857600080fd5b600060408284031215613d4a57600080fd5b6040516040810181811067ffffffffffffffff82111715613d94577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052613da083613d18565b8152613dae60208401613d18565b60208201529392505050565b600060208284031215613dcc57600080fd5b8151610b4881613aac565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613e0957613e09613a66565b5060010190565b60008251613e22818460208701613741565b919091019291505056fea26469706673582212205896af001c312e838d0681c524a1611a530550596c1663962913eec2cd7f22e664736f6c634300080a0033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061025c5760003560e01c806367e4ac2c11610145578063a8f1f52e116100bd578063cf58879a1161008c578063d505accf11610071578063d505accf146105d5578063dd62ed3e146105e8578063f1c49a391461061357600080fd5b8063cf58879a14610587578063d21220a7146105ae57600080fd5b8063a8f1f52e14610545578063a9059cbb14610558578063af8c09bf1461056b578063c14ad8021461057e57600080fd5b80637bdd6b441161011457806395d89b41116100f957806395d89b41146104ef578063a28af8a4146104f7578063a69840a81461051e57600080fd5b80637bdd6b44146104a85780637ecebe00146104cf57600080fd5b806367e4ac2c1461045757806370a082311461046c5780637464fc3d1461048c5780637ba0e2e71461049557600080fd5b80632a07b6c7116101d8578063499a3c50116101a757806354cf2aeb1161018c57806354cf2aeb1461041d578063627dd56a1461044457806365dfc7671461029c57600080fd5b8063499a3c50146102615780634da31827146103f657600080fd5b80632a07b6c71461036e57806330adf81f1461038e578063313ce567146103b55780633644e515146103ee57600080fd5b80630c0a0cd21161022f57806318160ddd1161021457806318160ddd146103485780631dd19cb41461035157806323b872dd1461035b57600080fd5b80630c0a0cd2146102dc5780630dfe16811461032157600080fd5b8063053da1c81461026157806306fdde03146102875780630902f1ac1461029c578063095ea7b3146102b9575b600080fd5b61027461026f3660046136cf565b61061b565b6040519081526020015b60405180910390f35b61028f610622565b60405161027e919061376d565b6102a46106b0565b6040805192835260208301919091520161027e565b6102cc6102c73660046137e3565b6106c8565b604051901515815260200161027e565b6008546102fc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161027e565b6102fc7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160781565b61027460025481565b610359610742565b005b6102cc61036936600461380f565b610a09565b61038161037c3660046136cf565b610b4f565b60405161027e9190613850565b6102747f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b6103dc7f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff909116815260200161027e565b610274610e36565b6102fc7f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c481565b6102747f000000000000000000000000000000000000000000000000000000000000000181565b6102746104523660046136cf565b610e91565b61045f61112c565b60405161027e91906138b5565b61027461047a36600461390f565b60036020526000908152604090205481565b61027460095481565b6102746104a33660046136cf565b61122b565b6102747f00000000000000000000000000000000000000000000000000000000000f424081565b6102746104dd36600461390f565b60056020526000908152604090205481565b61028f61149f565b6102747f00000000000000000000000000000000000000000000000000000000000f424081565b6102747f54726964656e743a537461626c65506f6f6c000000000000000000000000000081565b6102746105533660046136cf565b6114ac565b6102cc6105663660046137e3565b61188b565b6102746105793660046136cf565b611910565b61027460075481565b6102fc7f000000000000000000000000caabdd9cf4b61813d4a52f980d6bc1b713fe66f581565b6102fc7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5881565b6103596105e336600461392c565b611c04565b6102746105f63660046139a3565b600460209081526000928352604080842090915290825290205481565b610359611f30565b6000806000fd5b6000805461062f906139dc565b80601f016020809104026020016040519081016040528092919081815260200182805461065b906139dc565b80156106a85780601f1061067d576101008083540402835291602001916106a8565b820191906000526020600020905b81548152906001019060200180831161068b57829003601f168201915b505050505081565b6000806106c0600a54600b549091565b915091509091565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906107309086815260200190565b60405180910390a35060015b92915050565b6006546001146107b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600260068190555060007f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607905060007f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58905060007f000000000000000000000000caabdd9cf4b61813d4a52f980d6bc1b713fe66f573ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b81526004016020604051808303816000875af1158015610874573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108989190613a30565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915061094d90829073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa15801561090b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092f9190613a4d565b73ffffffffffffffffffffffffffffffffffffffff8616919061209b565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526109ff90829073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156109bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e19190613a4d565b73ffffffffffffffffffffffffffffffffffffffff8516919061209b565b5050600160065550565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610a9d57610a6b8382613a95565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff851660009081526003602052604081208054859290610ad2908490613a95565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610b3a9087815260200190565b60405180910390a360019150505b9392505050565b6060600654600114610bbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016107aa565b6002600655600080610bd184860186613aba565b91509150600080610be061212d565b30600090815260036020526040812054929450909250610c00848461242b565b509050600081610c108685613ae8565b610c1a9190613b54565b9050600082610c298686613ae8565b610c339190613b54565b9050610c3f30856124f4565b610c6b7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607838a8a61258a565b610c977f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58828a8a61258a565b610c9f6127ea565b6040805160028082526060820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081610cb557905050985060405180604001604052807f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160773ffffffffffffffffffffffffffffffffffffffff1681526020018381525089600081518110610d3c57610d3c613b8f565b602002602001018190525060405180604001604052807f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5873ffffffffffffffffffffffffffffffffffffffff1681526020018281525089600181518110610da557610da5613b8f565b6020908102919091010152610dcc610dbd8388613a95565b610dc78388613a95565b612842565b600955604080518381526020810183905273ffffffffffffffffffffffffffffffffffffffff8a169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a3505060016006555094979650505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000a4614610e6c57610e676128cc565b905090565b507fbbe9b25e3de3142d7f9b2c43c0dceb86da06d81d16f136d35151b39f1f3aae2690565b6000600654600114610eff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016107aa565b600260065560008080610f1485870187613bbe565b925092509250600080600080610f28612966565b93509350935093506000807f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160773ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415610fc15750508382037f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58610fba8287876001612cee565b995061107c565b7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5873ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614611046576040517f2df9739b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50508281037f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316076110798287876000612cee565b99505b611088818b8a8a61258a565b6110906127ea565b8073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff167fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e46062858e60405161110f929190918252602082015260400190565b60405180910390a450506001600655509598975050505050505050565b60408051600280825260608083018452926020830190803683370190505090507f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316078160008151811061118057611180613b8f565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250507f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58816001815181106111ee576111ee613b8f565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505090565b6000600654600114611299576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016107aa565b600260065560006112ac8385018561390f565b90506000806112be600a54600b549091565b915091506000806112cd61212d565b9150915060006112dd8383612842565b905060006112eb8685613a95565b905060006112f98685613a95565b905060008061130a84848b8b612ea9565b90925090506113296dffffffffffffffffffffffffffff83168a613c09565b98506113456dffffffffffffffffffffffffffff821689613c09565b97506000806113548b8b61242b565b9150915081600014156113c35785158061136c575084155b156113a3576040517fd856fc5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113af6103e888613a95565b9c506113be60006103e8612fac565b6113e6565b80826113cf828a613a95565b6113d99190613ae8565b6113e39190613b54565b9c505b8c61141d576040517fd226f9d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114278c8e612fac565b61142f6127ea565b6009879055604080518781526020810187905273ffffffffffffffffffffffffffffffffffffffff8e169133917fdbba30eb0402b389513e87f51f4db2db80bed454384ec6925a24097c3548a02a910160405180910390a35050600160065550989b9a5050505050505050505050565b6001805461062f906139dc565b600080806114bc848601866137e3565b915091506000806114d0600a54600b549091565b6040517f5662311800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260248201879052600060448301529294509092507f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c490911690635662311890606401602060405180830381865afa158015611572573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115969190613a4d565b92507f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156116f6577f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c473ffffffffffffffffffffffffffffffffffffffff1663da5139ca7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e586116568686866001612cee565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260006044820152606401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a4d565b9450611881565b7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5873ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461177b576040517f2df9739b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c473ffffffffffffffffffffffffffffffffffffffff1663da5139ca7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316076117e58686866000612cee565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260006044820152606401602060405180830381865afa15801561185a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061187e9190613a4d565b94505b5050505092915050565b336000908152600360205260408120805483919083906118ac908490613a95565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107309086815260200190565b600060065460011461197e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064016107aa565b60026006556000808061199385870187613bbe565b9250925092506000806119a9600a54600b549091565b915091506000806119b861212d565b306000908152600360205260408120549294509092506119d8848461242b565b5090506000816119e88685613ae8565b6119f29190613b54565b9050600082611a018686613ae8565b611a0b9190613b54565b9050611a1a610dbd8388613a95565b600955611a2730856124f4565b7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5873ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff161415611ac557611a8c82838a03838a036001612cee565b01611ab97f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58828c8c61258a565b809b5060009150611b92565b7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c3160773ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff1614611b4a576040517f0620202000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b5b81838a03838a036000612cee565b82019150611b8b7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607838c8c61258a565b5099508960005b611b9a6127ea565b604080518381526020810183905273ffffffffffffffffffffffffffffffffffffffff8c169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050600160065550979a9950505050505050505050565b42841015611c6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f4558504952454400000000000000000060448201526064016107aa565b6000611c78610e36565b73ffffffffffffffffffffffffffffffffffffffff89811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938c166060840152608083018b905260a083019390935260c08083018a90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611dd7573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590611e5257508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611eb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e455200000000000000000000000000000000000060448201526064016107aa565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208b8516808552908352928190208a905551898152919350918a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b7f000000000000000000000000caabdd9cf4b61813d4a52f980d6bc1b713fe66f573ffffffffffffffffffffffffffffffffffffffff1663c14ad8026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fbf9190613a4d565b6007819055507f000000000000000000000000caabdd9cf4b61813d4a52f980d6bc1b713fe66f573ffffffffffffffffffffffffffffffffffffffff16630c0a0cd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015612030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120549190613a30565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261212890849061301d565b505050565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607818116600484015230602484015260009283927f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c41691635662311891839063f7888aec90604401602060405180830381865afa1580156121ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122119190613a4d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260006044820152606401602060405180830381865afa158015612286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122aa9190613a4d565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e5881811660048401523060248401529294507f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c41691635662311891839063f7888aec90604401602060405180830381865afa158015612368573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238c9190613a4d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260006044820152606401602060405180830381865afa158015612401573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124259190613a4d565b90509091565b60025460095460009080156124ec576124448585612842565b9150808211156124ec5760075460008161245e8486613a95565b6124689087613ae8565b6124729190613ae8565b905060006124808484613ae8565b8561248d85612710613a95565b6124979190613ae8565b6124a19190613c09565b905060006124af8284613b54565b905080156124e7576008546124da9073ffffffffffffffffffffffffffffffffffffffff1682612fac565b6124e48188613c09565b96505b505050505b509250929050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054839290612529908490613a95565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b8015612664576040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152838116604483015260648201859052600060848301527f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c416906397da6d309060a40160408051808303816000875af1158015612639573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265d9190613c21565b50506127e4565b6040517fda5139ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260248201859052600060448301819052917f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c49091169063da5139ca90606401602060405180830381865afa158015612703573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127279190613a4d565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301523060248301528581166044830152606482018390529192507f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c49091169063f18d03cc90608401600060405180830381600087803b1580156127ca57600080fd5b505af11580156127de573d6000803e3d6000fd5b50505050505b50505050565b6000806127f561212d565b600a829055600b81905560408051838152602081018390529294509092507fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a910160405180910390a15050565b6000807f00000000000000000000000000000000000000000000000000000000000f42408464e8d4a51000028161287b5761287b613b25565b04905060007f00000000000000000000000000000000000000000000000000000000000f42408464e8d4a5100002816128b6576128b6613b25565b0490506128c38282613129565b95945050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60006040516128fe9190613c45565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b600a54600b546040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316078116600483015230602483015260009182917f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4169063f7888aec90604401602060405180830381865afa158015612a23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a479190613a4d565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58811660048301523060248301529193507f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c49091169063f7888aec90604401602060405180830381865afa158015612afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b229190613a4d565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c31607811660048301529192506000917f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c41690634ffe34db906024016040805180830381865afa158015612bd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf79190613d38565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000094b008aa00579c1307b0ef2c499ad98a8ce58e58811660048301529192506000917f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c41690634ffe34db906024016040805180830381865afa158015612ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ccc9190613d38565b9050612cd88285613140565b9350612ce48184613140565b9250505090919293565b6000807f00000000000000000000000000000000000000000000000000000000000f42408564e8d4a510000281612d2757612d27613b25565b04905060007f00000000000000000000000000000000000000000000000000000000000f42408564e8d4a510000281612d6257612d62613b25565b0490506127107f000000000000000000000000000000000000000000000000000000000000000188020487036000612d9a8484613199565b90508515612e225760007f00000000000000000000000000000000000000000000000000000000000f42408364e8d4a510000281612dda57612dda613b25565b04850190506000612dec828487613214565b64e8d4a510009086037f00000000000000000000000000000000000000000000000000000000000f424002049650612e9d915050565b60007f00000000000000000000000000000000000000000000000000000000000f42408364e8d4a510000281612e5a57612e5a613b25565b04840190506000612e6c828488613214565b64e8d4a510009087037f00000000000000000000000000000000000000000000000000000000000f42400204965050505b50505050949350505050565b600080831580612eb7575082155b15612ec757506000905080612fa3565b600084612ed48589613ae8565b612ede9190613b54565b9050858111612f3957612ef46127106002613ae8565b612efe8288613a95565b612f28907f0000000000000000000000000000000000000000000000000000000000000001613ae8565b612f329190613b54565b9150612fa1565b600084612f468789613ae8565b612f509190613b54565b9050612f5f6127106002613ae8565b612f69828a613a95565b612f93907f0000000000000000000000000000000000000000000000000000000000000001613ae8565b612f9d9190613b54565b9350505b505b94509492505050565b8060026000828254612fbe9190613c09565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910161257e565b600061307f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661331d9092919063ffffffff16565b805190915015612128578080602001905181019061309d9190613dba565b612128576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016107aa565b6000610b4861313b61313b8585613199565b613334565b600082602001516fffffffffffffffffffffffffffffffff166000141561316857508061073c565b602083015183516fffffffffffffffffffffffffffffffff9182169161318f911684613ae8565b610b489190613b54565b60008064e8d4a510006131ac8486613ae8565b6131b69190613b54565b9050600064e8d4a510006131ca8580613ae8565b6131d49190613b54565b64e8d4a510006131e48780613ae8565b6131ee9190613b54565b6131f89190613c09565b905064e8d4a5100061320a8284613ae8565b6128c39190613b54565b6000805b60ff8110156133145782600061322e87836133ed565b90508581101561327b5760006132448887613484565b61324e8389613a95565b61325d9064e8d4a51000613ae8565b6132679190613b54565b90506132738187613c09565b9550506132ba565b60006132878887613484565b6132918884613a95565b6132a09064e8d4a51000613ae8565b6132aa9190613b54565b90506132b68187613a95565b9550505b818511156132e35760016132ce8387613a95565b116132de57849350505050610b48565b6132ff565b60016132ef8684613a95565b116132ff57849350505050610b48565b5050808061330c90613dd7565b915050613218565b50909392505050565b606061332c84846000856134e6565b949350505050565b60b58171010000000000000000000000000000000000811061335b5760409190911b9060801c5b690100000000000000000081106133775760209190911b9060401c5b65010000000000811061338f5760109190911b9060201c5b630100000081106133a55760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c8082048111156133e85781045b919050565b600064e8d4a51000828185816134038280613ae8565b61340d9190613b54565b6134179190613ae8565b6134219190613b54565b61342b9190613ae8565b6134359190613b54565b64e8d4a510008084816134488280613ae8565b6134529190613b54565b61345c9190613ae8565b6134669190613b54565b6134709086613ae8565b61347a9190613b54565b610b489190613c09565b600064e8d4a5100083816134988280613ae8565b6134a29190613b54565b6134ac9190613ae8565b6134b69190613b54565b64e8d4a51000806134c78580613ae8565b6134d19190613b54565b6134dc866003613ae8565b6134709190613ae8565b606082471015613578576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016107aa565b73ffffffffffffffffffffffffffffffffffffffff85163b6135f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107aa565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161361f9190613e10565b60006040518083038185875af1925050503d806000811461365c576040519150601f19603f3d011682016040523d82523d6000602084013e613661565b606091505b509150915061367182828661367c565b979650505050505050565b6060831561368b575081610b48565b82511561369b5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107aa919061376d565b600080602083850312156136e257600080fd5b823567ffffffffffffffff808211156136fa57600080fd5b818501915085601f83011261370e57600080fd5b81358181111561371d57600080fd5b86602082850101111561372f57600080fd5b60209290920196919550909350505050565b60005b8381101561375c578181015183820152602001613744565b838111156127e45750506000910152565b602081526000825180602084015261378c816040850160208701613741565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff811681146137e057600080fd5b50565b600080604083850312156137f657600080fd5b8235613801816137be565b946020939093013593505050565b60008060006060848603121561382457600080fd5b833561382f816137be565b9250602084013561383f816137be565b929592945050506040919091013590565b602080825282518282018190526000919060409081850190868401855b828110156138a8578151805173ffffffffffffffffffffffffffffffffffffffff16855286015186850152928401929085019060010161386d565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561390357835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016138d1565b50909695505050505050565b60006020828403121561392157600080fd5b8135610b48816137be565b600080600080600080600060e0888a03121561394757600080fd5b8735613952816137be565b96506020880135613962816137be565b95506040880135945060608801359350608088013560ff8116811461398657600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156139b657600080fd5b82356139c1816137be565b915060208301356139d1816137be565b809150509250929050565b600181811c908216806139f057607f821691505b60208210811415613a2a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600060208284031215613a4257600080fd5b8151610b48816137be565b600060208284031215613a5f57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613aa757613aa7613a66565b500390565b80151581146137e057600080fd5b60008060408385031215613acd57600080fd5b8235613ad8816137be565b915060208301356139d181613aac565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613b2057613b20613a66565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613b8a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080600060608486031215613bd357600080fd5b8335613bde816137be565b92506020840135613bee816137be565b91506040840135613bfe81613aac565b809150509250925092565b60008219821115613c1c57613c1c613a66565b500190565b60008060408385031215613c3457600080fd5b505080516020909101519092909150565b600080835481600182811c915080831680613c6157607f831692505b6020808410821415613c9a577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b818015613cae5760018114613cdd57613d0a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00861689528489019650613d0a565b60008a81526020902060005b86811015613d025781548b820152908501908301613ce9565b505084890196505b509498975050505050505050565b80516fffffffffffffffffffffffffffffffff811681146133e857600080fd5b600060408284031215613d4a57600080fd5b6040516040810181811067ffffffffffffffff82111715613d94577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052613da083613d18565b8152613dae60208401613d18565b60208201529392505050565b600060208284031215613dcc57600080fd5b8151610b4881613aac565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613e0957613e09613a66565b5060010190565b60008251613e22818460208701613741565b919091019291505056fea26469706673582212205896af001c312e838d0681c524a1611a530550596c1663962913eec2cd7f22e664736f6c634300080a0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.