Source Code
Overview
ETH Balance
ETH Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 25744197 | 12 secs ago | 0 ETH | ||||
| 25744197 | 12 secs ago | 0 ETH | ||||
| 25744197 | 12 secs ago | 0 ETH | ||||
| 25744056 | 5 mins ago | 0 ETH | ||||
| 25744056 | 5 mins ago | 0 ETH | ||||
| 25744056 | 5 mins ago | 0 ETH | ||||
| 25744056 | 5 mins ago | 0 ETH | ||||
| 25744042 | 5 mins ago | 0 ETH | ||||
| 25744042 | 5 mins ago | 0 ETH | ||||
| 25744042 | 5 mins ago | 0 ETH | ||||
| 25744042 | 5 mins ago | 0 ETH | ||||
| 25743743 | 16 mins ago | 0 ETH | ||||
| 25743743 | 16 mins ago | 0 ETH | ||||
| 25743743 | 16 mins ago | 0 ETH | ||||
| 25743738 | 16 mins ago | 0 ETH | ||||
| 25743738 | 16 mins ago | 0 ETH | ||||
| 25743372 | 29 mins ago | 0 ETH | ||||
| 25743372 | 29 mins ago | 0 ETH | ||||
| 25743362 | 29 mins ago | 0 ETH | ||||
| 25743028 | 41 mins ago | 0 ETH | ||||
| 25742822 | 49 mins ago | 0 ETH | ||||
| 25742822 | 49 mins ago | 0 ETH | ||||
| 25742473 | 1 hr ago | 0 ETH | ||||
| 25742473 | 1 hr ago | 0 ETH | ||||
| 25742473 | 1 hr ago | 0 ETH |
Loading...
Loading
Contract Name:
Pair
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 800 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import "./interfaces/IPair.sol";
import "./interfaces/IPairCallee.sol";
import "./interfaces/IPairFactory.sol";
import "./PairFees.sol";
import "./interfaces/IERC20.sol";
import "./interfaces/IVoter.sol";
/// @notice The base pair of pools, either stable or volatile
contract Pair is IPair, Initializable {
string public name;
string public symbol;
uint8 public constant decimals = 18;
uint8 public feeSplit;
/// @notice Used to denote stable (correlated) or volatile pairs.
/// @notice Not immutable since construction happens in the initialize method for CREATE2 deterministic addresses
bool public stable;
bool hasActiveGauge;
mapping(address => mapping(address => uint256)) public allowance;
mapping(address => uint256) public balanceOf;
bytes32 internal DOMAIN_SEPARATOR;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 internal constant PERMIT_TYPEHASH =
0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address => uint256) public nonces;
address public token0;
address public token1;
address public fees;
address factory;
address voter;
/// @notice Structure to capture time period obervations every 30 minutes, used for local oracles
struct Observation {
uint256 timestamp;
uint256 reserve0Cumulative;
uint256 reserve1Cumulative;
}
Observation[] public observations;
/// @notice Capture oracle reading every 30 minutes
uint256 constant periodSize = 1800;
uint256 internal constant MINIMUM_LIQUIDITY = 10 ** 3;
uint256 internal constant MINIMUM_K = 1e9;
uint256 internal decimals0;
uint256 internal decimals1;
uint256 public reserve0;
uint256 public reserve1;
uint256 public blockTimestampLast;
uint256 public reserve0CumulativeLast;
uint256 public reserve1CumulativeLast;
uint256 internal _unlocked;
uint256 public totalSupply;
event Fees(address indexed sender, uint256 amount0, uint256 amount1);
event Mint(address indexed sender, uint256 amount0, uint256 amount1);
event Burn(
address indexed sender,
uint256 amount0,
uint256 amount1,
address indexed to
);
event Swap(
address indexed sender,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out,
address indexed to
);
event Sync(uint256 reserve0, uint256 reserve1);
event Claim(
address indexed sender,
address indexed recipient,
uint256 amount0,
uint256 amount1
);
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(
address indexed owner,
address indexed spender,
uint256 amount
);
event SetFeeSplit(
uint8 toFeesOld,
uint8 toTreasuryOld,
uint8 toFeesNew,
uint8 toTreasuryNew
);
constructor() {
_disableInitializers();
}
function initialize(
address _factory,
address _token0,
address _token1,
bool _stable,
address _voter
) external initializer {
factory = _factory;
token0 = _token0;
token1 = _token1;
stable = _stable;
voter = _voter;
fees = address(new PairFees(token0, token1, _voter));
if (stable) {
name = string(
abi.encodePacked(
"Correlated - ",
IERC20(_token0).symbol(),
"/",
IERC20(_token1).symbol()
)
);
symbol = string(
abi.encodePacked(
"cAMM-",
IERC20(token0).symbol(),
"/",
IERC20(token1).symbol()
)
);
} else {
name = string(
abi.encodePacked(
"Volatile - ",
IERC20(token0).symbol(),
"/",
IERC20(token1).symbol()
)
);
symbol = string(
abi.encodePacked(
"vAMM-",
IERC20(token0).symbol(),
"/",
IERC20(token1).symbol()
)
);
}
decimals0 = 10 ** IERC20(token0).decimals();
decimals1 = 10 ** IERC20(token1).decimals();
observations.push(Observation(block.timestamp, 0, 0));
_unlocked = 1;
}
/// @dev simple re-entrancy check
modifier lock() {
require(_unlocked == 1);
_unlocked = 2;
_;
_unlocked = 1;
}
function observationLength() external view returns (uint256) {
return observations.length;
}
function lastObservation() public view returns (Observation memory) {
return observations[observations.length - 1];
}
function metadata()
external
view
returns (
uint256 dec0,
uint256 dec1,
uint256 r0,
uint256 r1,
bool st,
address t0,
address t1
)
{
return (
decimals0,
decimals1,
reserve0,
reserve1,
stable,
token0,
token1
);
}
function tokens() external view returns (address, address) {
return (token0, token1);
}
/* Since the indexing system was removed, all fees must only go to the proper contracts for fee distribution.
* If a gauge does not exist, fees will keep accruing inside the PairFees contract.
* This function is unguarded and anybody can call it to push fees to the proper contracts.
*/
function claimFees() external returns (uint256 claimed0, uint256 claimed1) {
(claimed0, claimed1) = PairFees(fees).claimFeesFor();
emit Claim(msg.sender, msg.sender, claimed0, claimed1);
return (claimed0, claimed1);
}
/// @dev Accrue fees on token0
function _update0(uint256 amount) internal {
uint8 _feeSplit = feeSplit;
uint256 amountToFees = (amount * (_feeSplit % 16) * 5) / 100;
uint256 amountToTreasury = (amount * (_feeSplit >> 4) * 5) / 100;
if (hasActiveGauge) {
_safeTransfer(token0, fees, amountToFees); // transfer the fees out to PairFees
_safeTransfer(
token0,
IPairFactory(factory).treasury(),
amountToTreasury
);
} else {
_safeTransfer(
token0,
IPairFactory(factory).treasury(),
amountToTreasury
);
}
emit Fees(msg.sender, amount, 0);
}
/// @dev Accrue fees on token1
function _update1(uint256 amount) internal {
uint8 _feeSplit = feeSplit;
uint256 amountToFees = (amount * (_feeSplit % 16) * 5) / 100;
uint256 amountToTreasury = (amount * (_feeSplit >> 4) * 5) / 100;
if (hasActiveGauge) {
_safeTransfer(token1, fees, amountToFees); // transfer the fees out to PairFees
_safeTransfer(
token1,
IPairFactory(factory).treasury(),
amountToTreasury
);
} else {
_safeTransfer(
token1,
IPairFactory(factory).treasury(),
amountToTreasury
);
}
emit Fees(msg.sender, amount, 0);
}
function getReserves()
public
view
returns (
uint256 _reserve0,
uint256 _reserve1,
uint256 _blockTimestampLast
)
{
_reserve0 = reserve0;
_reserve1 = reserve1;
_blockTimestampLast = blockTimestampLast;
}
/// @dev update reserves and, on the first call per block, price accumulators
function _update(
uint256 balance0,
uint256 balance1,
uint256 _reserve0,
uint256 _reserve1
) internal {
uint256 blockTimestamp = block.timestamp;
uint256 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
reserve0CumulativeLast += _reserve0 * timeElapsed;
reserve1CumulativeLast += _reserve1 * timeElapsed;
}
Observation memory _point = lastObservation();
timeElapsed = blockTimestamp - _point.timestamp; /// @dev compare the last observation with current timestamp, if greater than 30 minutes, record a new event
if (timeElapsed > periodSize) {
observations.push(
Observation(
blockTimestamp,
reserve0CumulativeLast,
reserve1CumulativeLast
)
);
}
reserve0 = balance0;
reserve1 = balance1;
blockTimestampLast = blockTimestamp;
emit Sync(reserve0, reserve1);
}
/// @dev produces the cumulative price using counterfactuals to save gas and avoid a call to sync.
function currentCumulativePrices()
public
view
returns (
uint256 reserve0Cumulative,
uint256 reserve1Cumulative,
uint256 blockTimestamp
)
{
blockTimestamp = block.timestamp;
reserve0Cumulative = reserve0CumulativeLast;
reserve1Cumulative = reserve1CumulativeLast;
/// @dev if time has elapsed since the last update on the pair, mock the accumulated price values
(
uint256 _reserve0,
uint256 _reserve1,
uint256 _blockTimestampLast
) = getReserves();
if (_blockTimestampLast != blockTimestamp) {
/// @dev subtraction overflow is desired
uint256 timeElapsed = blockTimestamp - _blockTimestampLast;
reserve0Cumulative += _reserve0 * timeElapsed;
reserve1Cumulative += _reserve1 * timeElapsed;
}
}
/// @dev gives the current twap price measured from amountIn * tokenIn gives amountOut
function current(
address tokenIn,
uint256 amountIn
) external view returns (uint256 amountOut) {
Observation memory _observation = lastObservation();
(
uint256 reserve0Cumulative,
uint256 reserve1Cumulative,
) = currentCumulativePrices();
if (block.timestamp == _observation.timestamp) {
_observation = observations[observations.length - 2];
}
uint256 timeElapsed = block.timestamp - _observation.timestamp;
uint256 _reserve0 = (reserve0Cumulative -
_observation.reserve0Cumulative) / timeElapsed;
uint256 _reserve1 = (reserve1Cumulative -
_observation.reserve1Cumulative) / timeElapsed;
amountOut = _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);
}
/// @dev as per `current`, however allows user configured granularity, up to the full window size
function quote(
address tokenIn,
uint256 amountIn,
uint256 granularity
) external view returns (uint256 amountOut) {
uint256[] memory _prices = sample(tokenIn, amountIn, granularity, 1);
uint256 priceAverageCumulative;
for (uint256 i = 0; i < _prices.length; ++i) {
priceAverageCumulative += _prices[i];
}
return priceAverageCumulative / granularity;
}
/// @dev returns a memory set of twap prices
function prices(
address tokenIn,
uint256 amountIn,
uint256 points
) external view returns (uint256[] memory) {
return sample(tokenIn, amountIn, points, 1);
}
function sample(
address tokenIn,
uint256 amountIn,
uint256 points,
uint256 window
) public view returns (uint256[] memory) {
uint256[] memory _prices = new uint256[](points);
uint256 length = observations.length - 1;
uint256 i = length - (points * window);
uint256 nextIndex = 0;
uint256 index = 0;
for (; i < length; i += window) {
nextIndex = i + window;
uint256 timeElapsed = observations[nextIndex].timestamp -
observations[i].timestamp;
uint256 _reserve0 = (observations[nextIndex].reserve0Cumulative -
observations[i].reserve0Cumulative) / timeElapsed;
uint256 _reserve1 = (observations[nextIndex].reserve1Cumulative -
observations[i].reserve1Cumulative) / timeElapsed;
_prices[index] = _getAmountOut(
amountIn,
tokenIn,
_reserve0,
_reserve1
);
/// @dev index < length; length cannot overflow
unchecked {
index = index + 1;
}
}
return _prices;
}
/// @dev this low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks
/// @dev standard uniswap v2 implementation
function mint(address to) external lock returns (uint256 liquidity) {
(uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);
uint256 _balance0 = IERC20(token0).balanceOf(address(this));
uint256 _balance1 = IERC20(token1).balanceOf(address(this));
uint256 _amount0 = _balance0 - _reserve0;
uint256 _amount1 = _balance1 - _reserve1;
uint256 _totalSupply = totalSupply; /// @dev gas savings, must be defined here since totalSupply can update in _mintFee
if (_totalSupply == 0) {
liquidity =
MathUpgradeable.sqrt(_amount0 * _amount1) -
MINIMUM_LIQUIDITY;
_mint(address(0), MINIMUM_LIQUIDITY); /// @dev permanently lock the first MINIMUM_LIQUIDITY tokens
if (stable) {
require(_k(_amount0, _amount1) > MINIMUM_K, "K"); /// @dev minimum K needs to be acheived for stable pairs
}
} else {
liquidity = MathUpgradeable.min(
(_amount0 * _totalSupply) / _reserve0,
(_amount1 * _totalSupply) / _reserve1
);
}
require(liquidity > 0, "ILM"); /// @dev Pair: INSUFFICIENT_LIQUIDITY_MINTED
_mint(to, liquidity);
_update(_balance0, _balance1, _reserve0, _reserve1);
emit Mint(msg.sender, _amount0, _amount1);
}
/// @dev this low-level function should be called from a contract which performs important safety checks
/// @dev standard uniswap v2 implementation
function burn(
address to
) external lock returns (uint256 amount0, uint256 amount1) {
(uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);
(address _token0, address _token1) = (token0, token1);
uint256 _balance0 = IERC20(_token0).balanceOf(address(this));
uint256 _balance1 = IERC20(_token1).balanceOf(address(this));
uint256 _liquidity = balanceOf[address(this)];
uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
amount0 = (_liquidity * _balance0) / _totalSupply; // using balances ensures pro-rata distribution
amount1 = (_liquidity * _balance1) / _totalSupply; // using balances ensures pro-rata distribution
require(amount0 > 0 && amount1 > 0, "ILB"); // Pair: INSUFFICIENT_LIQUIDITY_BURNED
_burn(address(this), _liquidity);
_safeTransfer(_token0, to, amount0);
_safeTransfer(_token1, to, amount1);
_balance0 = IERC20(_token0).balanceOf(address(this));
_balance1 = IERC20(_token1).balanceOf(address(this));
_update(_balance0, _balance1, _reserve0, _reserve1);
emit Burn(msg.sender, amount0, amount1, to);
}
/// @dev this low-level function should be called from a contract which performs important safety checks
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external lock {
require(!IPairFactory(factory).isPaused());
require(amount0Out > 0 || amount1Out > 0, "IOA"); // Pair: INSUFFICIENT_OUTPUT_AMOUNT
(uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);
require(amount0Out < _reserve0 && amount1Out < _reserve1, "IL"); // Pair: INSUFFICIENT_LIQUIDITY
uint256 _balance0;
uint256 _balance1;
{
/// @dev scope for _token{0,1}, avoids stack too deep errors
(address _token0, address _token1) = (token0, token1);
require(to != _token0 && to != _token1, "IT"); // Pair: INVALID_TO
if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); /// @dev optimistically transfer tokens
if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); /// @dev optimistically transfer tokens
if (data.length > 0)
IPairCallee(to).hook(msg.sender, amount0Out, amount1Out, data); /// @dev callback, used for flash loans
_balance0 = IERC20(_token0).balanceOf(address(this));
_balance1 = IERC20(_token1).balanceOf(address(this));
}
uint256 amount0In = _balance0 > _reserve0 - amount0Out
? _balance0 - (_reserve0 - amount0Out)
: 0;
uint256 amount1In = _balance1 > _reserve1 - amount1Out
? _balance1 - (_reserve1 - amount1Out)
: 0;
require(amount0In > 0 || amount1In > 0, "IIA"); // Pair: INSUFFICIENT_INPUT_AMOUNT
{
/// @dev scope for reserve{0,1}Adjusted, avoids stack too deep errors
(address _token0, address _token1) = (token0, token1);
if (amount0In > 0)
_update0(
(amount0In * IPairFactory(factory).getFee(stable)) / 10000
); /// @dev accrue fees for token0 and move them out of pool
if (amount1In > 0)
_update1(
(amount1In * IPairFactory(factory).getFee(stable)) / 10000
); /// @dev accrue fees for token1 and move them out of pool
_balance0 = IERC20(_token0).balanceOf(address(this)); /// @dev since we removed tokens, we need to reconfirm balances, can also simply use previous balance - amountIn/ 10000, but doing balanceOf again as safety check
_balance1 = IERC20(_token1).balanceOf(address(this));
/// @dev The curve, either x3y+y3x for stable pools, or x*y for volatile pools
require(_k(_balance0, _balance1) >= _k(_reserve0, _reserve1), "K"); // Pair: K
}
_update(_balance0, _balance1, _reserve0, _reserve1);
emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
}
/// @dev force balances to match reserves
function skim(address to) external lock {
(address _token0, address _token1) = (token0, token1);
_safeTransfer(
_token0,
to,
IERC20(_token0).balanceOf(address(this)) - (reserve0)
);
_safeTransfer(
_token1,
to,
IERC20(_token1).balanceOf(address(this)) - (reserve1)
);
}
/// @dev force reserves to match balances
function sync() external lock {
_update(
IERC20(token0).balanceOf(address(this)),
IERC20(token1).balanceOf(address(this)),
reserve0,
reserve1
);
}
function _f(uint256 x0, uint256 y) internal pure returns (uint256) {
uint256 _a = (x0 * y) / 1e18;
uint256 _b = ((x0 * x0) / 1e18 + (y * y) / 1e18);
return (_a * _b) / 1e18;
}
function _d(uint256 x0, uint256 y) internal pure returns (uint256) {
return
(3 * x0 * ((y * y) / 1e18)) /
1e18 +
((((x0 * x0) / 1e18) * x0) / 1e18);
}
function _get_y(
uint256 x0,
uint256 xy,
uint256 y
) internal view returns (uint256 _y) {
for (uint256 i = 0; i < 255; i++) {
uint256 k = _f(x0, y);
if (k < xy) {
uint256 dy = ((xy - k) * 1e18) / _d(x0, y);
if (dy == 0) {
if (k == xy) {
return y;
}
if (_k(x0, y + 1) > xy) {
return y + 1;
}
dy = 1;
}
y = y + dy;
} else {
uint256 dy = ((k - xy) * 1e18) / _d(x0, y);
if (dy == 0) {
if (k == xy || _f(x0, y - 1) < xy) {
return y;
}
dy = 1;
}
y = y - dy;
}
}
}
function getAmountOut(
uint256 amountIn,
address tokenIn
) external view returns (uint256) {
(uint256 _reserve0, uint256 _reserve1) = (reserve0, reserve1);
amountIn -= (amountIn * IPairFactory(factory).getFee(stable)) / 10000; /// @dev remove fee from amount received
return _getAmountOut(amountIn, tokenIn, _reserve0, _reserve1);
}
function _getAmountOut(
uint256 amountIn,
address tokenIn,
uint256 _reserve0,
uint256 _reserve1
) internal view returns (uint256) {
if (stable) {
uint256 xy = _k(_reserve0, _reserve1);
_reserve0 = (_reserve0 * 1e18) / decimals0;
_reserve1 = (_reserve1 * 1e18) / decimals1;
(uint256 reserveA, uint256 reserveB) = tokenIn == token0
? (_reserve0, _reserve1)
: (_reserve1, _reserve0);
amountIn = tokenIn == token0
? (amountIn * 1e18) / decimals0
: (amountIn * 1e18) / decimals1;
uint256 y = reserveB - _get_y(amountIn + reserveA, xy, reserveB);
return (y * (tokenIn == token0 ? decimals1 : decimals0)) / 1e18;
} else {
(uint256 reserveA, uint256 reserveB) = tokenIn == token0
? (_reserve0, _reserve1)
: (_reserve1, _reserve0);
return (amountIn * reserveB) / (reserveA + amountIn);
}
}
function _k(uint256 x, uint256 y) internal view returns (uint256) {
if (stable) {
uint256 _x = (x * 1e18) / decimals0;
uint256 _y = (y * 1e18) / decimals1;
uint256 _a = (_x * _y) / 1e18;
uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);
return (_a * _b) / 1e18; // x3y+y3x >= k
} else {
return x * y; // xy >= k
}
}
function _mint(address dst, uint256 amount) internal {
totalSupply += amount;
balanceOf[dst] += amount;
emit Transfer(address(0), dst, amount);
}
function _burn(address dst, uint256 amount) internal {
totalSupply -= amount;
balanceOf[dst] -= amount;
emit Transfer(dst, address(0), amount);
}
function approve(address spender, uint256 amount) external returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
require(deadline >= block.timestamp, "Pair: EXPIRED");
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(name)),
keccak256(bytes("1")),
block.chainid,
address(this)
)
);
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,
"Pair: INVALID_SIGNATURE"
);
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
function transfer(address dst, uint256 amount) external returns (bool) {
_transferTokens(msg.sender, dst, amount);
return true;
}
function transferFrom(
address src,
address dst,
uint256 amount
) external returns (bool) {
address spender = msg.sender;
uint256 spenderAllowance = allowance[src][spender];
if (spender != src && spenderAllowance != type(uint256).max) {
uint256 newAllowance = spenderAllowance - amount;
allowance[src][spender] = newAllowance;
emit Approval(src, spender, newAllowance);
}
_transferTokens(src, dst, amount);
return true;
}
function _transferTokens(
address src,
address dst,
uint256 amount
) internal {
balanceOf[src] -= amount;
balanceOf[dst] += amount;
emit Transfer(src, dst, amount);
}
function _safeTransfer(address token, address to, uint256 value) internal {
require(token.code.length > 0);
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(IERC20.transfer.selector, to, value)
);
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
function setActiveGauge(bool isActive) external {
require(msg.sender == voter, "!AUTH");
hasActiveGauge = isActive;
}
function setFeeSplit() external {
uint8 oldFeeSplit = feeSplit;
uint8 _feeSplit = IPairFactory(factory).getPoolFeeSplit(address(this));
if (_feeSplit != oldFeeSplit) {
feeSplit = _feeSplit;
emit SetFeeSplit(
oldFeeSplit % 16,
oldFeeSplit >> 4,
_feeSplit % 16,
_feeSplit >> 4
);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathUpgradeable {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/Address.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or 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 {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// 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);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IERC20 {
function totalSupply() external view returns (uint256);
function transfer(
address recipient,
uint256 amount
) external returns (bool);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function balanceOf(address) external view returns (uint256);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
function allowance(
address owner,
address spender
) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
function name() external view returns (string memory);
function burn(uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IFeeDistributor {
function initialize(address _voter, address _pairFees) external;
function _deposit(uint256 amount, uint256 tokenId) external;
function _withdraw(uint256 amount, uint256 tokenId) external;
function getRewardForOwner(
uint256 tokenId,
address[] memory tokens
) external;
function notifyRewardAmount(address token, uint256 amount) external;
function getRewardTokens() external view returns (address[] memory);
function earned(
address token,
uint256 tokenId
) external view returns (uint256 reward);
function incentivize(address token, uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13 || =0.7.6;
interface IPair {
function initialize(
address _factory,
address _token0,
address _token1,
bool _stable,
address _voter
) external;
function metadata()
external
view
returns (
uint256 dec0,
uint256 dec1,
uint256 r0,
uint256 r1,
bool st,
address t0,
address t1
);
function claimFees() external returns (uint256, uint256);
function tokens() external view returns (address, address);
function transferFrom(
address src,
address dst,
uint256 amount
) external returns (bool);
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;
function burn(
address to
) external returns (uint256 amount0, uint256 amount1);
function mint(address to) external returns (uint256 liquidity);
function getReserves()
external
view
returns (
uint256 _reserve0,
uint256 _reserve1,
uint256 _blockTimestampLast
);
function getAmountOut(
uint256 amountIn,
address tokenIn
) external view returns (uint256);
function symbol() external view returns (string memory);
function fees() external view returns (address);
function setActiveGauge(bool isActive) external;
function setFeeSplit() external;
function feeSplit() external view returns (uint8 _feeSplit);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IPairCallee {
function hook(
address sender,
uint256 amount0,
uint256 amount1,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IPairFactory {
function allPairsLength() external view returns (uint256);
function isPair(address pair) external view returns (bool);
function pairCodeHash() external view returns (bytes32);
function getPair(
address tokenA,
address token,
bool stable
) external view returns (address);
function createPair(
address tokenA,
address tokenB,
bool stable
) external returns (address pair);
function voter() external view returns (address);
function allPairs(uint256) external view returns (address);
function pairFee(address) external view returns (uint256);
function getFee(bool) external view returns (uint256);
function isPaused() external view returns (bool);
function setFeeManager(address _feeManager) external;
function setPairFee(address _pair, uint256 _fee) external;
function setFee(bool _stable, uint256 _fee) external;
function treasury() external view returns (address);
function feeSplit() external view returns (uint8);
function getPoolFeeSplit(
address _pool
) external view returns (uint8 _poolFeeSplit);
function setFeeSplit(uint8 _toFees, uint8 _toTreasury) external;
function setPoolFeeSplit(
address _pool,
uint8 _toFees,
uint8 _toTreasury
) external;
}// SPDX-License-Identifier: MIT
pragma solidity =0.7.6 || ^0.8.13;
pragma abicoder v2;
interface IVoter {
function _ve() external view returns (address);
function governor() external view returns (address);
function emergencyCouncil() external view returns (address);
function attachTokenToGauge(uint256 _tokenId, address account) external;
function detachTokenFromGauge(uint256 _tokenId, address account) external;
function emitDeposit(
uint256 _tokenId,
address account,
uint256 amount
) external;
function emitWithdraw(
uint256 _tokenId,
address account,
uint256 amount
) external;
function isWhitelisted(address token) external view returns (bool);
function notifyRewardAmount(uint256 amount) external;
function distribute(address _gauge) external;
function gauges(address pool) external view returns (address);
function feeDistributors(address gauge) external view returns (address);
function gaugefactory() external view returns (address);
function feeDistributorFactory() external view returns (address);
function minter() external view returns (address);
function factory() external view returns (address);
function length() external view returns (uint256);
function pools(uint256) external view returns (address);
function isAlive(address) external view returns (bool);
function setXRatio(uint256 _xRatio) external;
function setPoolXRatio(
address[] calldata _gauges,
uint256[] calldata _xRaRatios
) external;
function resetGaugeXRatio(address[] calldata _gauges) external;
function whitelist(address _token) external;
function forbid(address _token, bool _status) external;
function whitelistOperator() external view returns (address);
function gaugeXRatio(address gauge) external view returns (uint256);
function isGauge(address gauge) external view returns (bool);
function killGauge(address _gauge) external;
function reviveGauge(address _gauge) external;
function stale(uint256 _tokenID) external view returns (bool);
function poolForGauge(address gauge) external view returns (address pool);
function recoverFees(
address[] calldata fees,
address[][] calldata tokens
) external;
function designateStale(uint256 _tokenId, bool _status) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "./interfaces/IERC20.sol";
import "./interfaces/IVoter.sol";
import "./interfaces/IFeeDistributor.sol";
/// @notice Pair Fees contract is used as a 1:1 pair relationship to split out fees, this ensures that the curve does not need to be modified for LP shares
contract PairFees {
address internal immutable pair; // The pair it is bonded to
address internal immutable token0; // token0 of pair, saved localy and statically for gas optimization
address internal immutable token1; // Token1 of pair, saved localy and statically for gas optimization
address voter;
address public feeDistributor;
constructor(address _token0, address _token1, address _voter) {
pair = msg.sender;
token0 = _token0;
token1 = _token1;
voter = _voter;
}
function initialize(address _feeDistributor) external {
require(msg.sender == voter, "!VOTER");
feeDistributor = _feeDistributor;
IERC20(token0).approve(_feeDistributor, type(uint256).max);
IERC20(token1).approve(_feeDistributor, type(uint256).max);
}
function _safeTransfer(address token, address to, uint256 value) internal {
require(token.code.length > 0);
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(IERC20.transfer.selector, to, value)
);
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
/// @notice notifies all fees to feeDistributor
function claimFeesFor() external returns (uint256, uint256) {
if (feeDistributor == address(0)) {
return (0, 0);
}
uint256 amount0 = IERC20(token0).balanceOf(address(this));
uint256 amount1 = IERC20(token1).balanceOf(address(this));
IFeeDistributor(feeDistributor).notifyRewardAmount(token0, amount0);
IFeeDistributor(feeDistributor).notifyRewardAmount(token1, amount1);
return (amount0, amount1);
}
/// @notice takes the entire balance of `token` and sends to `to`
function recoverFees(address token, address to) external {
require(msg.sender == voter, "!VOTER");
address gauge = IVoter(voter).gauges(pair);
bool isAlive = IVoter(voter).isAlive(gauge);
require(feeDistributor == address(0) || !isAlive, "ACTIVE");
IERC20 _token = IERC20(token);
uint256 bal = _token.balanceOf(address(this));
_token.transfer(to, bal);
}
}{
"optimizer": {
"enabled": true,
"runs": 800
},
"evmVersion": "paris",
"viaIR": true,
"metadata": {
"bytecodeHash": "none"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"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":"to","type":"address"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Claim","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"}],"name":"Fees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","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"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"toFeesOld","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"toTreasuryOld","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"toFeesNew","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"toTreasuryNew","type":"uint8"}],"name":"SetFeeSplit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1Out","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"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":[{"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":"blockTimestampLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"burn","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimFees","outputs":[{"internalType":"uint256","name":"claimed0","type":"uint256"},{"internalType":"uint256","name":"claimed1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"current","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentCumulativePrices","outputs":[{"internalType":"uint256","name":"reserve0Cumulative","type":"uint256"},{"internalType":"uint256","name":"reserve1Cumulative","type":"uint256"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeSplit","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fees","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint256","name":"_reserve0","type":"uint256"},{"internalType":"uint256","name":"_reserve1","type":"uint256"},{"internalType":"uint256","name":"_blockTimestampLast","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"},{"internalType":"bool","name":"_stable","type":"bool"},{"internalType":"address","name":"_voter","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastObservation","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"reserve0Cumulative","type":"uint256"},{"internalType":"uint256","name":"reserve1Cumulative","type":"uint256"}],"internalType":"struct Pair.Observation","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadata","outputs":[{"internalType":"uint256","name":"dec0","type":"uint256"},{"internalType":"uint256","name":"dec1","type":"uint256"},{"internalType":"uint256","name":"r0","type":"uint256"},{"internalType":"uint256","name":"r1","type":"uint256"},{"internalType":"bool","name":"st","type":"bool"},{"internalType":"address","name":"t0","type":"address"},{"internalType":"address","name":"t1","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"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":[],"name":"observationLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"observations","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"reserve0Cumulative","type":"uint256"},{"internalType":"uint256","name":"reserve1Cumulative","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":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"points","type":"uint256"}],"name":"prices","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"granularity","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve0CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve1CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"points","type":"uint256"},{"internalType":"uint256","name":"window","type":"uint256"}],"name":"sample","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"isActive","type":"bool"}],"name":"setActiveGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setFeeSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"skim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0Out","type":"uint256"},{"internalType":"uint256","name":"amount1Out","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","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":"tokens","outputs":[{"internalType":"address","name":"","type":"address"},{"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":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60808060405234620000c6576000549060ff8260081c1662000074575060ff8082160362000038575b604051614a109081620000cc8239f35b60ff90811916176000557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160ff8152a13862000028565b62461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b6064820152608490fd5b600080fdfe60808060405260043610156200001457600080fd5b600090813560e01c908163022c0d9f14620029525750806306fdde0314620028ae5780630902f1ac146200287a578063095ea7b314620027fc5780630dfe168114620027d357806313345fe1146200265e5780631688041c146200257a57806318160ddd146200255a5780631df8c717146200251c57806322be3de114620024f457806323b872dd1462002414578063252c09d714620023b9578063313ce567146200239b578063390f75701462001678578063392f37e91462001611578063443cb4bc14620015f1578063517b3f8214620014fe5780635881c47514620014d05780635a76f25e14620014b05780636373ea69146200148d5780636a627842146200115157806370a0823114620011155780637ecebe0014620010d957806389afcb441462000dbd5780638a7b8cf21462000d8257806395d89b411462000c9e5780639af1d35a1462000c755780639d63848a1462000c425780639e8cc04b1462000be3578063a9059cbb1462000bab578063b71a4ece1462000b17578063bc25cf7714620009ca578063bf944dbc14620009aa578063c245febc146200098a578063c5700a02146200096a578063d21220a71462000941578063d294f0931462000866578063d505accf14620004b2578063dd62ed3e146200045c578063ebeb31db146200043c578063f140a35a146200034d5763fff6cae9146200021a57600080fd5b346200034a57806003193601126200034a576001601554036200034a5760026015556001600160a01b0380600854169060405180916370a0823160e01b9384835230600484015282602460209485935afa9283156200033f5785936200030a575b508190600954169360246040518096819382523060048301525afa908115620002ff578491620002c3575b50620002bb9250601054906011549262003b37565b600160155580f35b905082813d8311620002f7575b620002dc8183620034c1565b81010312620002f257620002bb915138620002a6565b600080fd5b503d620002d0565b6040513d86823e3d90fd5b9092508181813d831162000337575b620003258183620034c1565b81010312620002f2575191816200027b565b503d62000319565b6040513d87823e3d90fd5b80fd5b50346200034a5760403660031901126200034a576004356200036e62003433565b60105490601154926001600160a01b03600b5416602060ff60035460081c16602460405180948193632895a2f560e11b8352151560048301525afa958615620004305795620003eb575b6020620003e3868686620003dd87612710620003d58e836200361b565b04906200360d565b62003c42565b604051908152f35b94509291906020853d60201162000427575b816200040c60209383620034c1565b81010312620002f2579351939192909190620003dd620003b8565b3d9150620003fd565b604051903d90823e3d90fd5b50346200034a57806003193601126200034a576020600d54604051908152f35b50346200034a5760403660031901126200034a576200047a6200341c565b60406200048662003433565b926001600160a01b03809316815260046020522091166000526020526020604060002054604051908152f35b50346200034a5760e03660031901126200034a57620004d06200341c565b620004da62003433565b604435606435906084359360ff851680950362000862574283106200081d5760405193869360019586549062000510826200344a565b80825281602098898201948a8c8216918260001462000800575050600114620007b3575b6200054292500382620034c1565b5190206040805167ffffffffffffffff9492918101858111828210176200078957603160f81b9189916040528a81520152604051878101917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f835260408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811086821117620007895760405251902097886006556001600160a01b0380951697888b526007885260408b20998a549a6000198c146200079f57828c01905560405194878a8701957f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c987528c6040890152169b8c606088015289608088015260a087015260c086015260c0855260e0850195858710908711176200078957858c956101226080968c99604052825190209161010081019461190160f01b8652610102820152015260428152620006b481620034a4565b519020916040519283528583015260a435604083015260c43560608301528380525afa156200033f578551168381151591826200077e575b5050156200073957907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591838652600482526040862085600052825280604060002055604051908152a380f35b60405162461bcd60e51b815260048101839052601760248201527f506169723a20494e56414c49445f5349474e41545552450000000000000000006044820152606490fd5b1490508338620006ec565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b8d52601160045260248dfd5b5050888b5281888c8b600080516020620049e48339815191525b858310620007e657505062000542935082010162000534565b80919294505483858801015201910189908b8593620007cd565b60ff191687526200054294151560051b8401019150620005349050565b60405162461bcd60e51b815260206004820152600d60248201527f506169723a2045585049524544000000000000000000000000000000000000006044820152606490fd5b8580fd5b50346200034a57806003193601126200034a578060406001600160a01b03600a54166004825180948193633d9af89b60e11b83525af18015620009365782918391620008ef575b60408383825182815281602082015233907f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645853392a382519182526020820152f35b9150506040813d6040116200092d575b816200090e60409383620034c1565b810103126200092957604091506020815191015138620008ad565b5080fd5b3d9150620008ff565b6040513d84823e3d90fd5b50346200034a57806003193601126200034a5760206001600160a01b0360095416604051908152f35b50346200034a57806003193601126200034a576020601254604051908152f35b50346200034a57806003193601126200034a576020601454604051908152f35b50346200034a57806003193601126200034a576020601354604051908152f35b50346200034a576020806003193601126200092957620009e96200341c565b60016015540362000b135760026015556008546009546040516370a0823160e01b8082523060048301526001600160a01b0392831694939092168582602481845afa91821562000b08578490889362000acd575b5062000a5162000a5893601054906200360d565b91620039a6565b6040519081523060048201528381602481865afa9384156200033f57859462000a91575b505062000a51620002bb93601154906200360d565b90809450813d831162000ac5575b62000aab8183620034c1565b81010312620002f25762000a51620002bb93519362000a7c565b503d62000a9f565b809350878092503d831162000b00575b62000ae98183620034c1565b81010312620002f2579051908362000a5162000a3d565b503d62000add565b6040513d89823e3d90fd5b8280fd5b50346200034a5760203660031901126200034a57600435801515809103620002f2576001600160a01b03600c5416330362000b665762ff00006003549160101b169062ff000019161760035580f35b60405162461bcd60e51b815260206004820152600560248201527f21415554480000000000000000000000000000000000000000000000000000006044820152606490fd5b50346200034a5760403660031901126200034a5762000bd862000bcd6200341c565b602435903362003db0565b602060405160018152f35b50346200034a5762000c0462000bf936620035c7565b9291908391620036bd565b825b815184101562000c345762000c2b60019162000c238685620036a8565b51906200369a565b93019262000c06565b620003e3836020926200362f565b50346200034a57806003193601126200034a5760406001600160a01b038060085416906009541682519182526020820152f35b50346200034a57806003193601126200034a5760206001600160a01b03600a5416604051908152f35b50346200034a57806003193601126200034a57604051600060025462000cc4816200344a565b8084529060209060019081811690811562000d55575060011462000d07575b62000d038562000cf681870382620034c1565b6040519182918262003509565b0390f35b600260009081529350600080516020620049c48339815191525b83851062000d415750505050810160200162000cf68262000d0362000ce3565b805486860184015293820193810162000d21565b86955062000d039693506020925062000cf694915060ff191682840152151560051b820101929362000ce3565b50346200034a57806003193601126200034a57606062000da16200396b565b6040805191805183526020810151602084015201516040820152f35b50346200034a57602090816003193601126200034a5762000ddd6200341c565b6001601554036200092957600260155560105492601154916001600160a01b03806008541693816009541695604051966370a0823160e01b8089523060048a015286896024818b5afa988915620010ce57839962001099575b50604051978189523060048a01528789602481865afa988915620002ff57849962001061575b5062000e8a98993085526005895262000e9860408620549162000e8a62000e90601654809e8194876200361b565b6200362f565b9d846200361b565b998b15158062001057575b156200102c5791858262000ebd8c9460249897966200360d565b601655308252600584526040822062000ed88282546200360d565b90556040519081527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef843092a362000f128c8a83620039a6565b62000f1f8b8a86620039a6565b604051948580928582523060048301525afa928315620002ff57908891859462000ff5575b5060246040518094819382523060048301525afa92831562000430579262000fb9575b509762000f78929160409962003b37565b855191858352848484015216907fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496863392a360016015558351928352820152f35b929150978583813d831162000fed575b62000fd58183620034c1565b81010312620002f25791519197909190604062000f67565b503d62000fc9565b8281939295503d831162001024575b620010108183620034c1565b81010312620002f257879051923862000f44565b503d62001004565b60405162461bcd60e51b8152600481018b9052600360248201526224a62160e91b6044820152606490fd5b508a151562000ea3565b98508789813d831162001091575b6200107b8183620034c1565b81010312620002f25762000e8a98519862000e5c565b503d6200106f565b9098508681813d8311620010c6575b620010b48183620034c1565b81010312620002f25751973862000e36565b503d620010a8565b6040513d85823e3d90fd5b50346200034a5760203660031901126200034a5760406020916001600160a01b03620011046200341c565b168152600783522054604051908152f35b50346200034a5760203660031901126200034a5760406020916001600160a01b03620011406200341c565b168152600583522054604051908152f35b50346200034a576020806003193601126200092957620011706200341c565b916001601554036200034a57600260155560105492601154906001600160a01b0391826008541695604051968787816370a0823160e01b9384825230600483015260249b8c915afa90811562000b085787916200145a575b50878660095416928a6040518095819382523060048301525afa91821562000b0857879262001425575b50620011ff83826200360d565b956200120c85846200360d565b95601654988915600014620013e557620012316200122b898b6200361b565b62003e23565b6103e719810191908211620013d25750986103e890818101809111620013bd576016556000805260058b526040600020908154818101809111620013a8578c600093927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92859455604051908152a360ff60035460081c1662001386575b88156200135c5788999a50620012ce6200131f9798996016546200369a565b601655168060005260058a526040600020620012ec8a82546200369a565b905560007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8b6040518c8152a362003b37565b604051918252838201527f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f60403392a26001601555604051908152f35b60405162461bcd60e51b8152600481018b90526003818d015262494c4d60e81b6044820152606490fd5b620013a2633b9aca006200139b898b62003a8b565b1162003650565b620012af565b8d634e487b7160e01b60005260116004526000fd5b8c634e487b7160e01b60005260116004526000fd5b634e487b7160e01b815260116004528c90fd5b620014098762000e8a620014018962000e8a8f979f8f6200361b565b948b6200361b565b9050808210156200141d57505b97620012af565b905062001416565b9091508781813d831162001452575b620014408183620034c1565b81010312620002f257519038620011f2565b503d62001434565b90508781813d831162001485575b620014748183620034c1565b81010312620002f2575138620011c8565b503d62001468565b50346200034a57806003193601126200034a57602060ff60035416604051908152f35b50346200034a57806003193601126200034a576020601154604051908152f35b50346200034a5762000d03620014f1620014ea36620035c7565b91620036bd565b6040519182918262003537565b50346200034a5760403660031901126200034a576200151c6200341c565b90620015276200396b565b9062001532620037ec565b50918351421462001589575b6020620003e386866200157f62000e8a62000e8a896040620015758b620015678851426200360d565b9586918c8a0151906200360d565b950151906200360d565b9160243562003c42565b600d549193506001198201918211620015dd5750916200157f62000e8a62000e8a60209694604062001575620015ce620015c7620003e39a62003575565b5062003941565b9850505094965050506200153e565b634e487b7160e01b81526011600452602490fd5b50346200034a57806003193601126200034a576020601054604051908152f35b50346200034a57806003193601126200034a5760e0600e54600f5460105460ff601154600354906001600160a01b0393846008541694600954169560405197885260208801526040870152606086015260081c161515608084015260a083015260c0820152f35b50346200034a5760a03660031901126200034a57620016966200341c565b90620016a162003433565b91620016ac62003405565b92606435801515809103620002f2576084356001600160a01b0381168103620002f257845460ff8160081c1615948580966200238d575b801562002374575b15620023095760ff19821660011787556001600160a01b039186620022f7575b50166001600160a01b0319600b541617600b55600854916001600160a01b0384166001600160a01b0319841617600855600954906001600160a01b0388166001600160a01b031983161760095561ff006003549160081b169061ff001916176003556001600160a01b0382166001600160a01b0319600c541617600c55604051928361082b81011067ffffffffffffffff61082b86011117620022e357906001600160a01b03929161082b62004199863987168584161761082b8501908152908716888416176020820152911660408201528190036060019084f08015620010ce576001600160a01b03166001600160a01b0319600a541617600a5560ff60035460081c1660001462001e3b57826001600160a01b03916004604051809481936395d89b4160e01b8352165afa908115620010ce576001600160a01b03948491829362001e1b575b506004604051809781936395d89b4160e01b8352165afa938415620010ce57839462001df3575b50602e620018f5916040519586917f436f7272656c61746564202d20000000000000000000000000000000000000006020840152620018c4815180926020602d87019101620034e4565b8201602f60f81b602d820152620018e58251809360208785019101620034e4565b0103600e810186520184620034c1565b82519267ffffffffffffffff841162001c9957620019156001546200344a565b601f811162001d84575b50602090601f851160011462001d08576004949184918362001cfc575b50508160011b916000199060031b1c1916176001555b816001600160a01b0360085416604051948580926395d89b4160e01b82525afa80156200093657600493839162001cde575b50826001600160a01b0360095416604051958680926395d89b4160e01b82525afa938415620010ce57839462001cad575b50602662001a30916040519586917f63414d4d2d0000000000000000000000000000000000000000000000000000006020840152620019ff815180926020602587019101620034e4565b8201602f60f81b602582015262001a208251809360208785019101620034e4565b01036006810186520184620034c1565b825167ffffffffffffffff811162001c995762001a4f6002546200344a565b601f811162001c26575b506020601f821160011462001bb15783948293949262001ba5575b50508160011b916000199060031b1c1916176002555b6001600160a01b036008541660405160208160048163313ce56760e01b958682525afa8015620002ff5762001ac891859162001b6f575b50620038d0565b600e5560206001600160a01b03600954169160046040518094819382525afa8015620010ce5762001b0191849162001b6f5750620038d0565b600f5562001b2b60405162001b168162003487565b428152836020820152836040820152620038e2565b600160155562001b385780f35b61ff001981541681557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a180f35b62001b96915060203d60201162001b9d575b62001b8d8183620034c1565b810190620037d1565b3862001ac1565b503d62001b81565b01519050388062001a74565b60028452600080516020620049c483398151915290601f198316855b81811062001c0d5750958360019596971062001bf3575b505050811b0160025562001a8a565b015160001960f88460031b161c1916905538808062001be4565b9192602060018192868b01518155019401920162001bcd565b60028452601f820160051c600080516020620049c483398151915201906020831062001c81575b601f0160051c600080516020620049c483398151915201905b81811062001c75575062001a59565b84815560010162001c66565b600080516020620049c4833981519152915062001c4d565b634e487b7160e01b83526041600452602483fd5b62001a3091945062001cd56026913d8087833e62001ccc8183620034c1565b81019062003864565b949150620019b5565b62001cf591503d8085833e62001ccc8183620034c1565b3862001984565b0151905038806200193c565b9060018452600080516020620049e483398151915291845b601f198716811062001d6b5750918591600193600497601f1981161062001d51575b505050811b0160015562001952565b015160001960f88460031b161c1916905538808062001d42565b9192602060018192868501518155019401920162001d20565b60018452601f850160051c600080516020620049e4833981519152016020861062001ddc575b601f820160051c600080516020620049e483398151915201811062001dd057506200191f565b84815560010162001daa565b50600080516020620049e483398151915262001daa565b620018f591945062001e12602e913d8087833e62001ccc8183620034c1565b9491506200187a565b62001e339193503d8084833e62001ccc8183620034c1565b913862001853565b5060049250816001600160a01b0360085416604051948580926395d89b4160e01b82525afa801562000936576004938391620022c5575b50826001600160a01b0360095416604051958680926395d89b4160e01b82525afa938415620010ce5783946200229d575b50602c62001f1e916040519586917f566f6c6174696c65202d20000000000000000000000000000000000000000000602084015262001eed815180926020602b87019101620034e4565b8201602f60f81b602b82015262001f0e8251809360208785019101620034e4565b0103600c810186520184620034c1565b82519267ffffffffffffffff841162001c995762001f3e6001546200344a565b601f81116200222e575b50602090601f8511600114620021b25760049491849183620021a6575b50508160011b916000199060031b1c1916176001555b816001600160a01b0360085416604051948580926395d89b4160e01b82525afa80156200093657600493839162002188575b50826001600160a01b0360095416604051958680926395d89b4160e01b82525afa938415620010ce57839462002160575b50602662002028916040519586917f76414d4d2d0000000000000000000000000000000000000000000000000000006020840152620019ff815180926020602587019101620034e4565b825167ffffffffffffffff811162001c9957620020476002546200344a565b601f8111620020ed575b506020601f8211600114620020935783948293949262002087575b50508160011b916000199060031b1c19161760025562001a8a565b0151905038806200206c565b60028452600080516020620049c483398151915290601f198316855b818110620020d45750958360019596971062001bf357505050811b0160025562001a8a565b9192602060018192868b015181550194019201620020af565b60028452601f820160051c600080516020620049c483398151915201906020831062002148575b601f0160051c600080516020620049c483398151915201905b8181106200213c575062002051565b8481556001016200212d565b600080516020620049c4833981519152915062002114565b620020289194506200217f6026913d8087833e62001ccc8183620034c1565b94915062001fde565b6200219f91503d8085833e62001ccc8183620034c1565b3862001fad565b01519050388062001f65565b9060018452600080516020620049e483398151915291845b601f1987168110620022155750918591600193600497601f19811610620021fb575b505050811b0160015562001f7b565b015160001960f88460031b161c19169055388080620021ec565b91926020600181928685015181550194019201620021ca565b60018452601f850160051c600080516020620049e4833981519152016020861062002286575b601f820160051c600080516020620049e48339815191520181106200227a575062001f48565b84815560010162002254565b50600080516020620049e483398151915262002254565b62001f1e919450620022bc602c913d8087833e62001ccc8183620034c1565b94915062001ea3565b620022dc91503d8085833e62001ccc8183620034c1565b3862001e72565b634e487b7160e01b87526041600452602487fd5b61ffff1916610101178755386200170b565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608490fd5b50303b158015620016eb5750600160ff831614620016eb565b50600160ff831610620016e3565b50346200034a57806003193601126200034a57602060405160128152f35b50346200034a5760203660031901126200034a57600435600d548110156200092957620023e69062003575565b50805462000d0360026001840154930154604051938493846040919493926060820195825260208201520152565b50346200034a5760603660031901126200034a5762002485620024366200341c565b6200244062003433565b604435916001600160a01b038116948581526020956004875260408220336000528752846040600020548233141580620024e7575b6200248e575b5050505062003db0565b60405160018152f35b6040916200249c916200360d565b928281526004895220336000528752816040600020556040519182527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925873393a3388084816200247b565b5060001981141562002475565b50346200034a57806003193601126200034a57602060ff60035460081c166040519015158152f35b50346200034a57806003193601126200034a5762000d036200253d620037ec565b604080519384526020840192909252908201529081906060820190565b50346200034a57806003193601126200034a576020601654604051908152f35b50346200034a57806003193601126200034a57600354602460206001600160a01b03600b54166040519283809263e829263f60e01b82523060048301525afa908115620010ce5783916200263a575b5060ff81169160ff81168303620025de578380f35b600f6080927f9d570c3cf62eac0107df282c148bdcecbbad2390ba6bfc8224e596d28c17bd989460ff198416176003558160405193818116855260041c166020840152818116604084015260041c166060820152a13880808380f35b62002657915060203d60201162001b9d5762001b8d8183620034c1565b38620025c9565b50346200034a5760803660031901126200034a576200267c6200341c565b602435906044359060643590620026938362003681565b92620026a36040519485620034c1565b808452601f19620026b48262003681565b01366020860137600d54600019810191908211620027bd57620026df84620026e6929793976200361b565b866200360d565b9060005b86831062002702576040518062000d03888262003537565b8462002774620027b692620027a16200271c84886200369a565b6200279862000e8a62000e8a620027856200277e8c62002756620027408862003575565b50546200274d8362003575565b5054906200360d565b948591620027648962003575565b5060019c8d809201549262003575565b500154906200360d565b9462003575565b5060028091015490620027748d62003575565b90898862003c42565b620027ad828b620036a8565b5201936200369a565b91620026ea565b634e487b7160e01b600052601160045260246000fd5b50346200034a57806003193601126200034a5760206001600160a01b0360085416604051908152f35b50346200034a5760403660031901126200034a576200281a6200341c565b906001600160a01b0360406024359233815260046020522092169182600052602052806040600020556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b50346200034a57806003193601126200034a5760105460115460125460408051938452602084019290925290820152606090f35b50346200034a57806003193601126200034a57604051600060018054620028d5816200344a565b808552916020916001811690811562000d555750600114620029045762000d038562000cf681870382620034c1565b600160009081529350600080516020620049e48339815191525b8385106200293e5750505050810160200162000cf68262000d0362000ce3565b80548686018401529382019381016200291e565b9050346200092957608036600319011262000929576200297162003405565b9067ffffffffffffffff6064351162000b135736602360643501121562000b135767ffffffffffffffff606435600401351162000b13573660246064356004013560643501011162000b135760016015540362000b135760026015556020816004816001600160a01b03600b54166358c3de9360e11b82525afa908115620010ce578391620033cf575b506200092957600435159081158092620033c3575b156200339857601054906011548260043510806200338c575b1562003362576001600160a01b0360085416936001600160a01b036009541690856001600160a01b0385161415806200334e575b1562003324576200330f575b602435620032fa575b606435600401356200323f575b6020602495604051968780926370a0823160e01b82523060048301525afa948515620031f957869562003204575b50936020602495604051968780926370a0823160e01b82523060048301525afa948515620031f9578695620031bf575b5062002aec600435856200360d565b811115620031b65762002b0e9062002b07600435866200360d565b906200360d565b935b62002b1e602435836200360d565b811115620031ad5762002b399062002b07602435846200360d565b905b841580158091620031a3575b1562003178576001600160a01b03600854166001600160a01b03600954169162002f32575b8362002ce5575b906020602492604051938480926370a0823160e01b82523060048301525afa91821562002c9f57889262002caa575b50906020602492604051938480926370a0823160e01b82523060048301525afa91821562002c9f57889262002c58575b5094818662002c0762002bf362002c0d96956001600160a01b039a62003a8b565b62002bff868662003a8b565b111562003650565b62003b37565b60405193845260208401526004356040840152602435606084015216907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d82260803392a3600160155580f35b929150946020833d60201162002c96575b8162002c7860209383620034c1565b81010312620002f257915191949091906001600160a01b0362002bd2565b3d915062002c69565b6040513d8a823e3d90fd5b91506020823d60201162002cdc575b8162002cc860209383620034c1565b81010312620002f257905190602062002ba2565b3d915062002cb9565b6001600160a01b03600b54169160035491604051632895a2f560e11b815260ff8460081c1615156004820152602081602481885afa90811562002f27578b9162002eec575b5062002d3a61271091886200361b565b0462002d4a600f8516826200361b565b948560058102046005148615171562002ed85762002d6f600f8660041c16836200361b565b806005810204600514811517156200079f5760ff606460058f9302049660101c1660001462002e8a57505062002dca6004939495606460056001600160a01b0360095416920204906001600160a01b03600a541690620039a6565b8a6001600160a01b03600954169560206001600160a01b03600b5416604051968780926361d027b360e01b82525afa8015620009365760249760209662002e19949262002e54575b50620039a6565b6040519081528a838201527f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860260403392a29192505062002b73565b62002e7a919250873d891162002e82575b62002e718183620034c1565b81019062003a6a565b903862002e12565b503d62002e65565b9095506004939460206001600160a01b036009541697604051968780926361d027b360e01b82525afa8015620009365760249760209662002ed2949262002e545750620039a6565b62002e19565b634e487b7160e01b8c52601160045260248cfd5b90506020813d60201162002f1e575b8162002f0a60209383620034c1565b81010312620002f2575162002d3a62002d2a565b3d915062002efb565b6040513d8d823e3d90fd5b6001600160a01b03600b5416600354604051632895a2f560e11b815260ff8260081c1615156004820152602081602481865afa90811562002f27578b916200313d575b5062002f85612710918b6200361b565b049162002f96600f8316846200361b565b908160058102046005148215171562002ed85762002fbb600f8460041c16856200361b565b92836005810204600514841517156200079f5760049392919060101c60ff1615620030ce57506200300d90606460056001600160a01b0360085416920204906001600160a01b03600a541690620039a6565b6001600160a01b03600854169060206001600160a01b03600b5416604051948580926361d027b360e01b82525afa908115620030c3576200305f938d9262003097575b506005606491020491620039a6565b6040519081528860208201527f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860260403392a262002b6c565b6064919250620030ba60059160203d60201162002e825762002e718183620034c1565b92915062003050565b6040513d8e823e3d90fd5b6040516361d027b360e01b81529360209250849182905afa90811562002f27576200310b928c9262003111575b50600560649102049084620039a6565b6200305f565b60649192506200313460059160203d60201162002e825762002e718183620034c1565b929150620030fb565b90506020813d6020116200316f575b816200315b60209383620034c1565b81010312620002f2575162002f8562002f75565b3d91506200314c565b60405162461bcd60e51b815260206004820152600360248201526249494160e81b6044820152606490fd5b5082151562002b47565b50849062002b3b565b50849362002b10565b9094506020813d602011620031f0575b81620031de60209383620034c1565b81010312620002f25751933862002add565b3d9150620031cf565b6040513d88823e3d90fd5b94506020853d60201162003236575b816200322260209383620034c1565b81010312620002f257935193602062002aad565b3d915062003213565b6001600160a01b0383163b156200086257604051639a7bff7960e01b815233600482015260043560248201526024356044820152608060648201526064356004013560848201526064356004013560246064350160a48301378660a46064356004013583010152868160a481601f19601f6064356004013501168101030181836001600160a01b0389165af1801562000b0857620032df575b5062002a7f565b67ffffffffffffffff8111620022e3576040526020620032d8565b620033096024358483620039a6565b62002a72565b6200331e6004358487620039a6565b62002a69565b60405162461bcd60e51b8152602060048201526002602482015261125560f21b6044820152606490fd5b50816001600160a01b038516141562002a5d565b60405162461bcd60e51b8152602060048201526002602482015261125360f21b6044820152606490fd5b50806024351062002a29565b60405162461bcd60e51b8152602060048201526003602482015262494f4160e81b6044820152606490fd5b50602435151562002a10565b620033f6915060203d602011620033fd575b620033ed8183620034c1565b810190620035f3565b38620029fb565b503d620033e1565b604435906001600160a01b0382168203620002f257565b600435906001600160a01b0382168203620002f257565b602435906001600160a01b0382168203620002f257565b90600182811c921680156200347c575b60208310146200346657565b634e487b7160e01b600052602260045260246000fd5b91607f16916200345a565b6060810190811067ffffffffffffffff8211176200078957604052565b6080810190811067ffffffffffffffff8211176200078957604052565b90601f8019910116810190811067ffffffffffffffff8211176200078957604052565b60005b838110620034f85750506000910152565b8181015183820152602001620034e7565b604091602082526200352b8151809281602086015260208686019101620034e4565b601f01601f1916010190565b602090602060408183019282815285518094520193019160005b82811062003560575050505090565b83518552938101939281019260010162003551565b600d54811015620035b157600390600d600052027fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50190600090565b634e487b7160e01b600052603260045260246000fd5b6060906003190112620002f2576004356001600160a01b0381168103620002f257906024359060443590565b90816020910312620002f257518015158103620002f25790565b91908203918211620027bd57565b81810292918115918404141715620027bd57565b81156200363a570490565b634e487b7160e01b600052601260045260246000fd5b156200365857565b60405162461bcd60e51b81526020600482015260016024820152604b60f81b6044820152606490fd5b67ffffffffffffffff8111620007895760051b60200190565b91908201809211620027bd57565b8051821015620035b15760209160051b010190565b91620036c98162003681565b92620036d96040519485620034c1565b818452601f19620036ea8362003681565b01366020860137600d546000198101908111620027bd57600192808004841481151715620027bd5762003720908295926200360d565b9060005b858310620037355750505050505090565b84830190818411620027bd57620037b082620037a7620037676200375a8a9662003575565b50546200274d8962003575565b62000e8a620037946200277e8362000e8a8c8b62002774816200378a8c62003575565b5001549262003575565b5060028091015490620027748b62003575565b90878662003c42565b620037bc828a620036a8565b520191848101809111620027bd579162003724565b90816020910312620002f2575160ff81168103620002f25790565b42906013549160145491601054601154906012544281036200380d57505050565b906200383d6200384494969397620038366200382e6200383695426200360d565b80946200361b565b906200369a565b966200361b565b91565b67ffffffffffffffff81116200078957601f01601f191660200190565b602081830312620002f25780519067ffffffffffffffff8211620002f2570181601f82011215620002f25780516200389c8162003847565b92620038ac6040519485620034c1565b81845260208284010111620002f257620038cd9160208085019101620034e4565b90565b60ff16604d8111620027bd57600a0a90565b600d54680100000000000000008110156200078957806001620039099201600d5562003575565b9190916200392b57604081600292518455602081015160018501550151910155565b634e487b7160e01b600052600060045260246000fd5b90604051620039508162003487565b60406002829480548452600181015460208501520154910152565b6000604080516200397c8162003487565b8281528260208201520152600d546000198101908111620027bd57620015c7620038cd9162003575565b91823b15620002f257604051906001600160a01b03602083019363a9059cbb60e01b8552166024830152604482015260448152620039e481620034a4565b600092839283809351925af13d1562003a62573d62003a038162003847565b9062003a136040519283620034c1565b81523d83602083013e5b8162003a2e575b50156200034a5750565b805180159250821562003a45575b50503862003a24565b62003a5a9250602080918301019101620035f3565b388062003a3c565b606062003a1d565b90816020910312620002f257516001600160a01b0381168103620002f25790565b9060ff60035460081c1660001462003b2c57670de0b6b3a76400009182810290808204841490151715620027bd57600e5462003ac7916200362f565b82820291808304841490151715620027bd5762003b2162003af062003b2893600f54906200362f565b8462003b198162003b108162003b0786896200361b565b0496806200361b565b0492806200361b565b04906200369a565b906200361b565b0490565b620038cd916200361b565b907fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a9360409362003b6b601254426200360d565b8015158062003c38575b8062003c2e575b62003bee575b50505061070862003b9e62003b966200396b565b51426200360d565b1162003bbe575b81601055806011554260125582519182526020820152a1565b62003be860135460145485519162003bd68362003487565b428352602083015285820152620038e2565b62003ba5565b62003c229262003c1062003c078362003c19956200361b565b6013546200369a565b6013556200361b565b6014546200369a565b60145538808062003b82565b5082151562003b7c565b5081151562003b75565b90919260ff60035460081c1660001462003d625762003c62818562003a8b565b93670de0b6b3a76400009485820291808304871490151715620027bd5762003c8e600e5480936200362f565b9386840293808504881490151715620027bd5762003cb0600f5480956200362f565b956001600160a01b038060085416911614948560001462003d5b5795905b851562003d2a5787810290808204891490151715620027bd578162003d129362003d0c62003b289962003d068862002b07966200362f565b6200369a565b62003f88565b921562003d215750906200361b565b9050906200361b565b87810290808204891490151715620027bd578162003d129362003d0c62003b289962003d068962002b07966200362f565b9062003cce565b90620038cd93926001600160a01b03806008541691161460001462003da05762003d9262003d99925b826200361b565b926200369a565b906200362f565b62003d9262003d99929362003d8b565b60207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef916001600160a01b03809116938460005260058352604060002062003dfa8782546200360d565b905516938460005260058252604060002062003e188282546200369a565b9055604051908152a3565b801562003f825762003f07816000908360801c8062003f75575b508060401c8062003f67575b508060201c8062003f59575b508060101c8062003f4b575b508060081c8062003f3d575b508060041c8062003f2f575b508060021c8062003f21575b50600191828092811c62003f19575b1c1b62003ea281856200362f565b01811c62003eb181856200362f565b01811c62003ec081856200362f565b01811c62003ecf81856200362f565b01811c62003ede81856200362f565b01811c62003eed81856200362f565b01811c62003efc81856200362f565b01901c80926200362f565b8082101562003f14575090565b905090565b018162003e94565b600291509101903862003e85565b600491509101903862003e79565b600891509101903862003e6d565b601091509101903862003e61565b602091509101903862003e55565b604091509101903862003e49565b9150506080903862003e3d565b50600090565b600093928492839290915b60ff851062003fa3575050505050565b62003faf81836200411a565b838110156200406e5762003fc481856200360d565b670de0b6b3a764000090818102918183041490151715620040525762003ff1859162003d99858762004144565b91821562004014575b50506200400a906001926200369a565b945b019362003f93565b1490506200406657600180820180831162004052578462004036828662003a8b565b11620040485750836200400a62003ffa565b9750505050505050565b634e487b7160e01b86526011600452602486fd5b955050505050565b6200407a84826200360d565b670de0b6b3a7640000908181029181830414901517156200405257620040a7859162003d99858762004144565b918215620040c7575b5050620040c0906001926200360d565b946200400c565b1490508015620040e4575b6200406657600183620040c0620040b0565b5060001981018181116200410657620040ff8491846200411a565b10620040d2565b634e487b7160e01b85526011600452602485fd5b62003b289062003b21670de0b6b3a7640000938462003b198162003b108162003b0786896200361b565b8060030291600383048203620027bd5762003b196200417a9162004182620038cd95670de0b6b3a764000080958482956200361b565b04906200361b565b0492826200419182806200361b565b046200361b56fe60e0346100c357601f61082b38819003918201601f19168301916001600160401b038311848410176100c8578084926060946040528339810103126100c357610047816100de565b906100606040610059602084016100de565b92016100de565b3360805260a09290925260c052600080546001600160a01b0319166001600160a01b0390921691909117905560405161073890816100f3823960805181610232015260a05181818160d7015261057a015260c05181818161012201526105b50152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036100c35756fe6080604081815260048036101561001557600080fd5b600092833560e01c9081630d43e8ad146104565750806359f168f6146101e35780637b35f136146101b95763c4d66de81461004f57600080fd5b346101b557602091826003193601126101b15761006a61047b565b916001600160a01b038093610083828854163314610496565b1692837fffffffffffffffffffffffff000000000000000000000000000000000000000060015416176001558583519163095ea7b360e01b92838152868582015260001990816024820152888160448187877f0000000000000000000000000000000000000000000000000000000000000000165af180156101a7579189969593916044959361018a575b5087519889968795865285015260248401527f0000000000000000000000000000000000000000000000000000000000000000165af19081156101815750610154578280f35b8161017392903d1061017a575b61016b818361050c565b81019061052e565b5038808280f35b503d610161565b513d85823e3d90fd5b6101a090883d8a1161017a5761016b818361050c565b503861010e565b87513d86823e3d90fd5b8380fd5b8280fd5b8284346101e057806003193601126101e057506101d4610546565b82519182526020820152f35b80fd5b508290346104525782600319360112610452576101fe61047b565b926001600160a01b0391602435838116810361044e578385541693610224853314610496565b835163b9a09fd560e01b81527f0000000000000000000000000000000000000000000000000000000000000000821684820152602095908681602481855afa90811561044457879184918a91610403575b508751631703e5f960e01b815291168682015291829060249082905afa9081156103f95787916103dc575b508160015416159081156103d3575b501561039057859695949516908351926370a0823160e01b845230818501528684602481865afa93841561038657908794939291879461034d575b50855163a9059cbb60e01b81526001600160a01b03909216908201908152602081019390935294859283919082906040015b03925af19081156101815750610330578280f35b8161034692903d1061017a5761016b818361050c565b5081808280f35b8581969295503d831161037f575b610365818361050c565b8101031261037b5792518693909261031c6102ea565b8580fd5b503d61035b565b85513d88823e3d90fd5b835162461bcd60e51b8152808401869052600660248201527f41435449564500000000000000000000000000000000000000000000000000006044820152606490fd5b905015886102af565b6103f39150863d881161017a5761016b818361050c565b886102a0565b85513d89823e3d90fd5b928092508391503d831161043d575b61041c818361050c565b810103126104395751828116810361043957826024889290610275565b8780fd5b503d610412565b86513d8a823e3d90fd5b8480fd5b5080fd5b8490346104525781600319360112610452576020906001600160a01b03600154168152f35b600435906001600160a01b038216820361049157565b600080fd5b1561049d57565b60405162461bcd60e51b815260206004820152600660248201527f21564f54455200000000000000000000000000000000000000000000000000006044820152606490fd5b67ffffffffffffffff81116104f657604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176104f657604052565b90816020910312610491575180151581036104915790565b6001546001600160a01b0390811691906000831561072457604080516370a0823160e01b80825230600483015260209691947f00000000000000000000000000000000000000000000000000000000000000009288876024818588165afa9687156103865786976106f5575b507f000000000000000000000000000000000000000000000000000000000000000092855190815230600482015289816024818688165afa998a156106eb57879a6106bb575b5050803b1561037b57845163b66503cf60e01b8082526001600160a01b03959095166004820152602481018890529086908290604490829084905af18015610386576106a8575b506001541691823b1561044e5783519081526001600160a01b0391909116600482015260248101879052919083908390604490829084905af190811561069f575061068b575b50509190565b61069582916104e2565b6101e05780610685565b513d84823e3d90fd5b6106b4909591956104e2565b933861063f565b9080929a50813d83116106e4575b6106d3818361050c565b8101031261037b57519738806105f8565b503d6106c9565b86513d89823e3d90fd5b9096508881813d831161071d575b61070d818361050c565b8101031261037b575195386105b2565b503d610703565b925050819056fea164736f6c6343000816000a405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5aceb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a164736f6c6343000816000a
Deployed Bytecode
0x60808060405260043610156200001457600080fd5b600090813560e01c908163022c0d9f14620029525750806306fdde0314620028ae5780630902f1ac146200287a578063095ea7b314620027fc5780630dfe168114620027d357806313345fe1146200265e5780631688041c146200257a57806318160ddd146200255a5780631df8c717146200251c57806322be3de114620024f457806323b872dd1462002414578063252c09d714620023b9578063313ce567146200239b578063390f75701462001678578063392f37e91462001611578063443cb4bc14620015f1578063517b3f8214620014fe5780635881c47514620014d05780635a76f25e14620014b05780636373ea69146200148d5780636a627842146200115157806370a0823114620011155780637ecebe0014620010d957806389afcb441462000dbd5780638a7b8cf21462000d8257806395d89b411462000c9e5780639af1d35a1462000c755780639d63848a1462000c425780639e8cc04b1462000be3578063a9059cbb1462000bab578063b71a4ece1462000b17578063bc25cf7714620009ca578063bf944dbc14620009aa578063c245febc146200098a578063c5700a02146200096a578063d21220a71462000941578063d294f0931462000866578063d505accf14620004b2578063dd62ed3e146200045c578063ebeb31db146200043c578063f140a35a146200034d5763fff6cae9146200021a57600080fd5b346200034a57806003193601126200034a576001601554036200034a5760026015556001600160a01b0380600854169060405180916370a0823160e01b9384835230600484015282602460209485935afa9283156200033f5785936200030a575b508190600954169360246040518096819382523060048301525afa908115620002ff578491620002c3575b50620002bb9250601054906011549262003b37565b600160155580f35b905082813d8311620002f7575b620002dc8183620034c1565b81010312620002f257620002bb915138620002a6565b600080fd5b503d620002d0565b6040513d86823e3d90fd5b9092508181813d831162000337575b620003258183620034c1565b81010312620002f2575191816200027b565b503d62000319565b6040513d87823e3d90fd5b80fd5b50346200034a5760403660031901126200034a576004356200036e62003433565b60105490601154926001600160a01b03600b5416602060ff60035460081c16602460405180948193632895a2f560e11b8352151560048301525afa958615620004305795620003eb575b6020620003e3868686620003dd87612710620003d58e836200361b565b04906200360d565b62003c42565b604051908152f35b94509291906020853d60201162000427575b816200040c60209383620034c1565b81010312620002f2579351939192909190620003dd620003b8565b3d9150620003fd565b604051903d90823e3d90fd5b50346200034a57806003193601126200034a576020600d54604051908152f35b50346200034a5760403660031901126200034a576200047a6200341c565b60406200048662003433565b926001600160a01b03809316815260046020522091166000526020526020604060002054604051908152f35b50346200034a5760e03660031901126200034a57620004d06200341c565b620004da62003433565b604435606435906084359360ff851680950362000862574283106200081d5760405193869360019586549062000510826200344a565b80825281602098898201948a8c8216918260001462000800575050600114620007b3575b6200054292500382620034c1565b5190206040805167ffffffffffffffff9492918101858111828210176200078957603160f81b9189916040528a81520152604051878101917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f835260408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811086821117620007895760405251902097886006556001600160a01b0380951697888b526007885260408b20998a549a6000198c146200079f57828c01905560405194878a8701957f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c987528c6040890152169b8c606088015289608088015260a087015260c086015260c0855260e0850195858710908711176200078957858c956101226080968c99604052825190209161010081019461190160f01b8652610102820152015260428152620006b481620034a4565b519020916040519283528583015260a435604083015260c43560608301528380525afa156200033f578551168381151591826200077e575b5050156200073957907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591838652600482526040862085600052825280604060002055604051908152a380f35b60405162461bcd60e51b815260048101839052601760248201527f506169723a20494e56414c49445f5349474e41545552450000000000000000006044820152606490fd5b1490508338620006ec565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b8d52601160045260248dfd5b5050888b5281888c8b600080516020620049e48339815191525b858310620007e657505062000542935082010162000534565b80919294505483858801015201910189908b8593620007cd565b60ff191687526200054294151560051b8401019150620005349050565b60405162461bcd60e51b815260206004820152600d60248201527f506169723a2045585049524544000000000000000000000000000000000000006044820152606490fd5b8580fd5b50346200034a57806003193601126200034a578060406001600160a01b03600a54166004825180948193633d9af89b60e11b83525af18015620009365782918391620008ef575b60408383825182815281602082015233907f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645853392a382519182526020820152f35b9150506040813d6040116200092d575b816200090e60409383620034c1565b810103126200092957604091506020815191015138620008ad565b5080fd5b3d9150620008ff565b6040513d84823e3d90fd5b50346200034a57806003193601126200034a5760206001600160a01b0360095416604051908152f35b50346200034a57806003193601126200034a576020601254604051908152f35b50346200034a57806003193601126200034a576020601454604051908152f35b50346200034a57806003193601126200034a576020601354604051908152f35b50346200034a576020806003193601126200092957620009e96200341c565b60016015540362000b135760026015556008546009546040516370a0823160e01b8082523060048301526001600160a01b0392831694939092168582602481845afa91821562000b08578490889362000acd575b5062000a5162000a5893601054906200360d565b91620039a6565b6040519081523060048201528381602481865afa9384156200033f57859462000a91575b505062000a51620002bb93601154906200360d565b90809450813d831162000ac5575b62000aab8183620034c1565b81010312620002f25762000a51620002bb93519362000a7c565b503d62000a9f565b809350878092503d831162000b00575b62000ae98183620034c1565b81010312620002f2579051908362000a5162000a3d565b503d62000add565b6040513d89823e3d90fd5b8280fd5b50346200034a5760203660031901126200034a57600435801515809103620002f2576001600160a01b03600c5416330362000b665762ff00006003549160101b169062ff000019161760035580f35b60405162461bcd60e51b815260206004820152600560248201527f21415554480000000000000000000000000000000000000000000000000000006044820152606490fd5b50346200034a5760403660031901126200034a5762000bd862000bcd6200341c565b602435903362003db0565b602060405160018152f35b50346200034a5762000c0462000bf936620035c7565b9291908391620036bd565b825b815184101562000c345762000c2b60019162000c238685620036a8565b51906200369a565b93019262000c06565b620003e3836020926200362f565b50346200034a57806003193601126200034a5760406001600160a01b038060085416906009541682519182526020820152f35b50346200034a57806003193601126200034a5760206001600160a01b03600a5416604051908152f35b50346200034a57806003193601126200034a57604051600060025462000cc4816200344a565b8084529060209060019081811690811562000d55575060011462000d07575b62000d038562000cf681870382620034c1565b6040519182918262003509565b0390f35b600260009081529350600080516020620049c48339815191525b83851062000d415750505050810160200162000cf68262000d0362000ce3565b805486860184015293820193810162000d21565b86955062000d039693506020925062000cf694915060ff191682840152151560051b820101929362000ce3565b50346200034a57806003193601126200034a57606062000da16200396b565b6040805191805183526020810151602084015201516040820152f35b50346200034a57602090816003193601126200034a5762000ddd6200341c565b6001601554036200092957600260155560105492601154916001600160a01b03806008541693816009541695604051966370a0823160e01b8089523060048a015286896024818b5afa988915620010ce57839962001099575b50604051978189523060048a01528789602481865afa988915620002ff57849962001061575b5062000e8a98993085526005895262000e9860408620549162000e8a62000e90601654809e8194876200361b565b6200362f565b9d846200361b565b998b15158062001057575b156200102c5791858262000ebd8c9460249897966200360d565b601655308252600584526040822062000ed88282546200360d565b90556040519081527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef843092a362000f128c8a83620039a6565b62000f1f8b8a86620039a6565b604051948580928582523060048301525afa928315620002ff57908891859462000ff5575b5060246040518094819382523060048301525afa92831562000430579262000fb9575b509762000f78929160409962003b37565b855191858352848484015216907fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496863392a360016015558351928352820152f35b929150978583813d831162000fed575b62000fd58183620034c1565b81010312620002f25791519197909190604062000f67565b503d62000fc9565b8281939295503d831162001024575b620010108183620034c1565b81010312620002f257879051923862000f44565b503d62001004565b60405162461bcd60e51b8152600481018b9052600360248201526224a62160e91b6044820152606490fd5b508a151562000ea3565b98508789813d831162001091575b6200107b8183620034c1565b81010312620002f25762000e8a98519862000e5c565b503d6200106f565b9098508681813d8311620010c6575b620010b48183620034c1565b81010312620002f25751973862000e36565b503d620010a8565b6040513d85823e3d90fd5b50346200034a5760203660031901126200034a5760406020916001600160a01b03620011046200341c565b168152600783522054604051908152f35b50346200034a5760203660031901126200034a5760406020916001600160a01b03620011406200341c565b168152600583522054604051908152f35b50346200034a576020806003193601126200092957620011706200341c565b916001601554036200034a57600260155560105492601154906001600160a01b0391826008541695604051968787816370a0823160e01b9384825230600483015260249b8c915afa90811562000b085787916200145a575b50878660095416928a6040518095819382523060048301525afa91821562000b0857879262001425575b50620011ff83826200360d565b956200120c85846200360d565b95601654988915600014620013e557620012316200122b898b6200361b565b62003e23565b6103e719810191908211620013d25750986103e890818101809111620013bd576016556000805260058b526040600020908154818101809111620013a8578c600093927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92859455604051908152a360ff60035460081c1662001386575b88156200135c5788999a50620012ce6200131f9798996016546200369a565b601655168060005260058a526040600020620012ec8a82546200369a565b905560007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8b6040518c8152a362003b37565b604051918252838201527f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f60403392a26001601555604051908152f35b60405162461bcd60e51b8152600481018b90526003818d015262494c4d60e81b6044820152606490fd5b620013a2633b9aca006200139b898b62003a8b565b1162003650565b620012af565b8d634e487b7160e01b60005260116004526000fd5b8c634e487b7160e01b60005260116004526000fd5b634e487b7160e01b815260116004528c90fd5b620014098762000e8a620014018962000e8a8f979f8f6200361b565b948b6200361b565b9050808210156200141d57505b97620012af565b905062001416565b9091508781813d831162001452575b620014408183620034c1565b81010312620002f257519038620011f2565b503d62001434565b90508781813d831162001485575b620014748183620034c1565b81010312620002f2575138620011c8565b503d62001468565b50346200034a57806003193601126200034a57602060ff60035416604051908152f35b50346200034a57806003193601126200034a576020601154604051908152f35b50346200034a5762000d03620014f1620014ea36620035c7565b91620036bd565b6040519182918262003537565b50346200034a5760403660031901126200034a576200151c6200341c565b90620015276200396b565b9062001532620037ec565b50918351421462001589575b6020620003e386866200157f62000e8a62000e8a896040620015758b620015678851426200360d565b9586918c8a0151906200360d565b950151906200360d565b9160243562003c42565b600d549193506001198201918211620015dd5750916200157f62000e8a62000e8a60209694604062001575620015ce620015c7620003e39a62003575565b5062003941565b9850505094965050506200153e565b634e487b7160e01b81526011600452602490fd5b50346200034a57806003193601126200034a576020601054604051908152f35b50346200034a57806003193601126200034a5760e0600e54600f5460105460ff601154600354906001600160a01b0393846008541694600954169560405197885260208801526040870152606086015260081c161515608084015260a083015260c0820152f35b50346200034a5760a03660031901126200034a57620016966200341c565b90620016a162003433565b91620016ac62003405565b92606435801515809103620002f2576084356001600160a01b0381168103620002f257845460ff8160081c1615948580966200238d575b801562002374575b15620023095760ff19821660011787556001600160a01b039186620022f7575b50166001600160a01b0319600b541617600b55600854916001600160a01b0384166001600160a01b0319841617600855600954906001600160a01b0388166001600160a01b031983161760095561ff006003549160081b169061ff001916176003556001600160a01b0382166001600160a01b0319600c541617600c55604051928361082b81011067ffffffffffffffff61082b86011117620022e357906001600160a01b03929161082b62004199863987168584161761082b8501908152908716888416176020820152911660408201528190036060019084f08015620010ce576001600160a01b03166001600160a01b0319600a541617600a5560ff60035460081c1660001462001e3b57826001600160a01b03916004604051809481936395d89b4160e01b8352165afa908115620010ce576001600160a01b03948491829362001e1b575b506004604051809781936395d89b4160e01b8352165afa938415620010ce57839462001df3575b50602e620018f5916040519586917f436f7272656c61746564202d20000000000000000000000000000000000000006020840152620018c4815180926020602d87019101620034e4565b8201602f60f81b602d820152620018e58251809360208785019101620034e4565b0103600e810186520184620034c1565b82519267ffffffffffffffff841162001c9957620019156001546200344a565b601f811162001d84575b50602090601f851160011462001d08576004949184918362001cfc575b50508160011b916000199060031b1c1916176001555b816001600160a01b0360085416604051948580926395d89b4160e01b82525afa80156200093657600493839162001cde575b50826001600160a01b0360095416604051958680926395d89b4160e01b82525afa938415620010ce57839462001cad575b50602662001a30916040519586917f63414d4d2d0000000000000000000000000000000000000000000000000000006020840152620019ff815180926020602587019101620034e4565b8201602f60f81b602582015262001a208251809360208785019101620034e4565b01036006810186520184620034c1565b825167ffffffffffffffff811162001c995762001a4f6002546200344a565b601f811162001c26575b506020601f821160011462001bb15783948293949262001ba5575b50508160011b916000199060031b1c1916176002555b6001600160a01b036008541660405160208160048163313ce56760e01b958682525afa8015620002ff5762001ac891859162001b6f575b50620038d0565b600e5560206001600160a01b03600954169160046040518094819382525afa8015620010ce5762001b0191849162001b6f5750620038d0565b600f5562001b2b60405162001b168162003487565b428152836020820152836040820152620038e2565b600160155562001b385780f35b61ff001981541681557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160018152a180f35b62001b96915060203d60201162001b9d575b62001b8d8183620034c1565b810190620037d1565b3862001ac1565b503d62001b81565b01519050388062001a74565b60028452600080516020620049c483398151915290601f198316855b81811062001c0d5750958360019596971062001bf3575b505050811b0160025562001a8a565b015160001960f88460031b161c1916905538808062001be4565b9192602060018192868b01518155019401920162001bcd565b60028452601f820160051c600080516020620049c483398151915201906020831062001c81575b601f0160051c600080516020620049c483398151915201905b81811062001c75575062001a59565b84815560010162001c66565b600080516020620049c4833981519152915062001c4d565b634e487b7160e01b83526041600452602483fd5b62001a3091945062001cd56026913d8087833e62001ccc8183620034c1565b81019062003864565b949150620019b5565b62001cf591503d8085833e62001ccc8183620034c1565b3862001984565b0151905038806200193c565b9060018452600080516020620049e483398151915291845b601f198716811062001d6b5750918591600193600497601f1981161062001d51575b505050811b0160015562001952565b015160001960f88460031b161c1916905538808062001d42565b9192602060018192868501518155019401920162001d20565b60018452601f850160051c600080516020620049e4833981519152016020861062001ddc575b601f820160051c600080516020620049e483398151915201811062001dd057506200191f565b84815560010162001daa565b50600080516020620049e483398151915262001daa565b620018f591945062001e12602e913d8087833e62001ccc8183620034c1565b9491506200187a565b62001e339193503d8084833e62001ccc8183620034c1565b913862001853565b5060049250816001600160a01b0360085416604051948580926395d89b4160e01b82525afa801562000936576004938391620022c5575b50826001600160a01b0360095416604051958680926395d89b4160e01b82525afa938415620010ce5783946200229d575b50602c62001f1e916040519586917f566f6c6174696c65202d20000000000000000000000000000000000000000000602084015262001eed815180926020602b87019101620034e4565b8201602f60f81b602b82015262001f0e8251809360208785019101620034e4565b0103600c810186520184620034c1565b82519267ffffffffffffffff841162001c995762001f3e6001546200344a565b601f81116200222e575b50602090601f8511600114620021b25760049491849183620021a6575b50508160011b916000199060031b1c1916176001555b816001600160a01b0360085416604051948580926395d89b4160e01b82525afa80156200093657600493839162002188575b50826001600160a01b0360095416604051958680926395d89b4160e01b82525afa938415620010ce57839462002160575b50602662002028916040519586917f76414d4d2d0000000000000000000000000000000000000000000000000000006020840152620019ff815180926020602587019101620034e4565b825167ffffffffffffffff811162001c9957620020476002546200344a565b601f8111620020ed575b506020601f8211600114620020935783948293949262002087575b50508160011b916000199060031b1c19161760025562001a8a565b0151905038806200206c565b60028452600080516020620049c483398151915290601f198316855b818110620020d45750958360019596971062001bf357505050811b0160025562001a8a565b9192602060018192868b015181550194019201620020af565b60028452601f820160051c600080516020620049c483398151915201906020831062002148575b601f0160051c600080516020620049c483398151915201905b8181106200213c575062002051565b8481556001016200212d565b600080516020620049c4833981519152915062002114565b620020289194506200217f6026913d8087833e62001ccc8183620034c1565b94915062001fde565b6200219f91503d8085833e62001ccc8183620034c1565b3862001fad565b01519050388062001f65565b9060018452600080516020620049e483398151915291845b601f1987168110620022155750918591600193600497601f19811610620021fb575b505050811b0160015562001f7b565b015160001960f88460031b161c19169055388080620021ec565b91926020600181928685015181550194019201620021ca565b60018452601f850160051c600080516020620049e4833981519152016020861062002286575b601f820160051c600080516020620049e48339815191520181106200227a575062001f48565b84815560010162002254565b50600080516020620049e483398151915262002254565b62001f1e919450620022bc602c913d8087833e62001ccc8183620034c1565b94915062001ea3565b620022dc91503d8085833e62001ccc8183620034c1565b3862001e72565b634e487b7160e01b87526041600452602487fd5b61ffff1916610101178755386200170b565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608490fd5b50303b158015620016eb5750600160ff831614620016eb565b50600160ff831610620016e3565b50346200034a57806003193601126200034a57602060405160128152f35b50346200034a5760203660031901126200034a57600435600d548110156200092957620023e69062003575565b50805462000d0360026001840154930154604051938493846040919493926060820195825260208201520152565b50346200034a5760603660031901126200034a5762002485620024366200341c565b6200244062003433565b604435916001600160a01b038116948581526020956004875260408220336000528752846040600020548233141580620024e7575b6200248e575b5050505062003db0565b60405160018152f35b6040916200249c916200360d565b928281526004895220336000528752816040600020556040519182527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925873393a3388084816200247b565b5060001981141562002475565b50346200034a57806003193601126200034a57602060ff60035460081c166040519015158152f35b50346200034a57806003193601126200034a5762000d036200253d620037ec565b604080519384526020840192909252908201529081906060820190565b50346200034a57806003193601126200034a576020601654604051908152f35b50346200034a57806003193601126200034a57600354602460206001600160a01b03600b54166040519283809263e829263f60e01b82523060048301525afa908115620010ce5783916200263a575b5060ff81169160ff81168303620025de578380f35b600f6080927f9d570c3cf62eac0107df282c148bdcecbbad2390ba6bfc8224e596d28c17bd989460ff198416176003558160405193818116855260041c166020840152818116604084015260041c166060820152a13880808380f35b62002657915060203d60201162001b9d5762001b8d8183620034c1565b38620025c9565b50346200034a5760803660031901126200034a576200267c6200341c565b602435906044359060643590620026938362003681565b92620026a36040519485620034c1565b808452601f19620026b48262003681565b01366020860137600d54600019810191908211620027bd57620026df84620026e6929793976200361b565b866200360d565b9060005b86831062002702576040518062000d03888262003537565b8462002774620027b692620027a16200271c84886200369a565b6200279862000e8a62000e8a620027856200277e8c62002756620027408862003575565b50546200274d8362003575565b5054906200360d565b948591620027648962003575565b5060019c8d809201549262003575565b500154906200360d565b9462003575565b5060028091015490620027748d62003575565b90898862003c42565b620027ad828b620036a8565b5201936200369a565b91620026ea565b634e487b7160e01b600052601160045260246000fd5b50346200034a57806003193601126200034a5760206001600160a01b0360085416604051908152f35b50346200034a5760403660031901126200034a576200281a6200341c565b906001600160a01b0360406024359233815260046020522092169182600052602052806040600020556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b50346200034a57806003193601126200034a5760105460115460125460408051938452602084019290925290820152606090f35b50346200034a57806003193601126200034a57604051600060018054620028d5816200344a565b808552916020916001811690811562000d555750600114620029045762000d038562000cf681870382620034c1565b600160009081529350600080516020620049e48339815191525b8385106200293e5750505050810160200162000cf68262000d0362000ce3565b80548686018401529382019381016200291e565b9050346200092957608036600319011262000929576200297162003405565b9067ffffffffffffffff6064351162000b135736602360643501121562000b135767ffffffffffffffff606435600401351162000b13573660246064356004013560643501011162000b135760016015540362000b135760026015556020816004816001600160a01b03600b54166358c3de9360e11b82525afa908115620010ce578391620033cf575b506200092957600435159081158092620033c3575b156200339857601054906011548260043510806200338c575b1562003362576001600160a01b0360085416936001600160a01b036009541690856001600160a01b0385161415806200334e575b1562003324576200330f575b602435620032fa575b606435600401356200323f575b6020602495604051968780926370a0823160e01b82523060048301525afa948515620031f957869562003204575b50936020602495604051968780926370a0823160e01b82523060048301525afa948515620031f9578695620031bf575b5062002aec600435856200360d565b811115620031b65762002b0e9062002b07600435866200360d565b906200360d565b935b62002b1e602435836200360d565b811115620031ad5762002b399062002b07602435846200360d565b905b841580158091620031a3575b1562003178576001600160a01b03600854166001600160a01b03600954169162002f32575b8362002ce5575b906020602492604051938480926370a0823160e01b82523060048301525afa91821562002c9f57889262002caa575b50906020602492604051938480926370a0823160e01b82523060048301525afa91821562002c9f57889262002c58575b5094818662002c0762002bf362002c0d96956001600160a01b039a62003a8b565b62002bff868662003a8b565b111562003650565b62003b37565b60405193845260208401526004356040840152602435606084015216907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d82260803392a3600160155580f35b929150946020833d60201162002c96575b8162002c7860209383620034c1565b81010312620002f257915191949091906001600160a01b0362002bd2565b3d915062002c69565b6040513d8a823e3d90fd5b91506020823d60201162002cdc575b8162002cc860209383620034c1565b81010312620002f257905190602062002ba2565b3d915062002cb9565b6001600160a01b03600b54169160035491604051632895a2f560e11b815260ff8460081c1615156004820152602081602481885afa90811562002f27578b9162002eec575b5062002d3a61271091886200361b565b0462002d4a600f8516826200361b565b948560058102046005148615171562002ed85762002d6f600f8660041c16836200361b565b806005810204600514811517156200079f5760ff606460058f9302049660101c1660001462002e8a57505062002dca6004939495606460056001600160a01b0360095416920204906001600160a01b03600a541690620039a6565b8a6001600160a01b03600954169560206001600160a01b03600b5416604051968780926361d027b360e01b82525afa8015620009365760249760209662002e19949262002e54575b50620039a6565b6040519081528a838201527f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860260403392a29192505062002b73565b62002e7a919250873d891162002e82575b62002e718183620034c1565b81019062003a6a565b903862002e12565b503d62002e65565b9095506004939460206001600160a01b036009541697604051968780926361d027b360e01b82525afa8015620009365760249760209662002ed2949262002e545750620039a6565b62002e19565b634e487b7160e01b8c52601160045260248cfd5b90506020813d60201162002f1e575b8162002f0a60209383620034c1565b81010312620002f2575162002d3a62002d2a565b3d915062002efb565b6040513d8d823e3d90fd5b6001600160a01b03600b5416600354604051632895a2f560e11b815260ff8260081c1615156004820152602081602481865afa90811562002f27578b916200313d575b5062002f85612710918b6200361b565b049162002f96600f8316846200361b565b908160058102046005148215171562002ed85762002fbb600f8460041c16856200361b565b92836005810204600514841517156200079f5760049392919060101c60ff1615620030ce57506200300d90606460056001600160a01b0360085416920204906001600160a01b03600a541690620039a6565b6001600160a01b03600854169060206001600160a01b03600b5416604051948580926361d027b360e01b82525afa908115620030c3576200305f938d9262003097575b506005606491020491620039a6565b6040519081528860208201527f112c256902bf554b6ed882d2936687aaeb4225e8cd5b51303c90ca6cf43a860260403392a262002b6c565b6064919250620030ba60059160203d60201162002e825762002e718183620034c1565b92915062003050565b6040513d8e823e3d90fd5b6040516361d027b360e01b81529360209250849182905afa90811562002f27576200310b928c9262003111575b50600560649102049084620039a6565b6200305f565b60649192506200313460059160203d60201162002e825762002e718183620034c1565b929150620030fb565b90506020813d6020116200316f575b816200315b60209383620034c1565b81010312620002f2575162002f8562002f75565b3d91506200314c565b60405162461bcd60e51b815260206004820152600360248201526249494160e81b6044820152606490fd5b5082151562002b47565b50849062002b3b565b50849362002b10565b9094506020813d602011620031f0575b81620031de60209383620034c1565b81010312620002f25751933862002add565b3d9150620031cf565b6040513d88823e3d90fd5b94506020853d60201162003236575b816200322260209383620034c1565b81010312620002f257935193602062002aad565b3d915062003213565b6001600160a01b0383163b156200086257604051639a7bff7960e01b815233600482015260043560248201526024356044820152608060648201526064356004013560848201526064356004013560246064350160a48301378660a46064356004013583010152868160a481601f19601f6064356004013501168101030181836001600160a01b0389165af1801562000b0857620032df575b5062002a7f565b67ffffffffffffffff8111620022e3576040526020620032d8565b620033096024358483620039a6565b62002a72565b6200331e6004358487620039a6565b62002a69565b60405162461bcd60e51b8152602060048201526002602482015261125560f21b6044820152606490fd5b50816001600160a01b038516141562002a5d565b60405162461bcd60e51b8152602060048201526002602482015261125360f21b6044820152606490fd5b50806024351062002a29565b60405162461bcd60e51b8152602060048201526003602482015262494f4160e81b6044820152606490fd5b50602435151562002a10565b620033f6915060203d602011620033fd575b620033ed8183620034c1565b810190620035f3565b38620029fb565b503d620033e1565b604435906001600160a01b0382168203620002f257565b600435906001600160a01b0382168203620002f257565b602435906001600160a01b0382168203620002f257565b90600182811c921680156200347c575b60208310146200346657565b634e487b7160e01b600052602260045260246000fd5b91607f16916200345a565b6060810190811067ffffffffffffffff8211176200078957604052565b6080810190811067ffffffffffffffff8211176200078957604052565b90601f8019910116810190811067ffffffffffffffff8211176200078957604052565b60005b838110620034f85750506000910152565b8181015183820152602001620034e7565b604091602082526200352b8151809281602086015260208686019101620034e4565b601f01601f1916010190565b602090602060408183019282815285518094520193019160005b82811062003560575050505090565b83518552938101939281019260010162003551565b600d54811015620035b157600390600d600052027fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50190600090565b634e487b7160e01b600052603260045260246000fd5b6060906003190112620002f2576004356001600160a01b0381168103620002f257906024359060443590565b90816020910312620002f257518015158103620002f25790565b91908203918211620027bd57565b81810292918115918404141715620027bd57565b81156200363a570490565b634e487b7160e01b600052601260045260246000fd5b156200365857565b60405162461bcd60e51b81526020600482015260016024820152604b60f81b6044820152606490fd5b67ffffffffffffffff8111620007895760051b60200190565b91908201809211620027bd57565b8051821015620035b15760209160051b010190565b91620036c98162003681565b92620036d96040519485620034c1565b818452601f19620036ea8362003681565b01366020860137600d546000198101908111620027bd57600192808004841481151715620027bd5762003720908295926200360d565b9060005b858310620037355750505050505090565b84830190818411620027bd57620037b082620037a7620037676200375a8a9662003575565b50546200274d8962003575565b62000e8a620037946200277e8362000e8a8c8b62002774816200378a8c62003575565b5001549262003575565b5060028091015490620027748b62003575565b90878662003c42565b620037bc828a620036a8565b520191848101809111620027bd579162003724565b90816020910312620002f2575160ff81168103620002f25790565b42906013549160145491601054601154906012544281036200380d57505050565b906200383d6200384494969397620038366200382e6200383695426200360d565b80946200361b565b906200369a565b966200361b565b91565b67ffffffffffffffff81116200078957601f01601f191660200190565b602081830312620002f25780519067ffffffffffffffff8211620002f2570181601f82011215620002f25780516200389c8162003847565b92620038ac6040519485620034c1565b81845260208284010111620002f257620038cd9160208085019101620034e4565b90565b60ff16604d8111620027bd57600a0a90565b600d54680100000000000000008110156200078957806001620039099201600d5562003575565b9190916200392b57604081600292518455602081015160018501550151910155565b634e487b7160e01b600052600060045260246000fd5b90604051620039508162003487565b60406002829480548452600181015460208501520154910152565b6000604080516200397c8162003487565b8281528260208201520152600d546000198101908111620027bd57620015c7620038cd9162003575565b91823b15620002f257604051906001600160a01b03602083019363a9059cbb60e01b8552166024830152604482015260448152620039e481620034a4565b600092839283809351925af13d1562003a62573d62003a038162003847565b9062003a136040519283620034c1565b81523d83602083013e5b8162003a2e575b50156200034a5750565b805180159250821562003a45575b50503862003a24565b62003a5a9250602080918301019101620035f3565b388062003a3c565b606062003a1d565b90816020910312620002f257516001600160a01b0381168103620002f25790565b9060ff60035460081c1660001462003b2c57670de0b6b3a76400009182810290808204841490151715620027bd57600e5462003ac7916200362f565b82820291808304841490151715620027bd5762003b2162003af062003b2893600f54906200362f565b8462003b198162003b108162003b0786896200361b565b0496806200361b565b0492806200361b565b04906200369a565b906200361b565b0490565b620038cd916200361b565b907fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a9360409362003b6b601254426200360d565b8015158062003c38575b8062003c2e575b62003bee575b50505061070862003b9e62003b966200396b565b51426200360d565b1162003bbe575b81601055806011554260125582519182526020820152a1565b62003be860135460145485519162003bd68362003487565b428352602083015285820152620038e2565b62003ba5565b62003c229262003c1062003c078362003c19956200361b565b6013546200369a565b6013556200361b565b6014546200369a565b60145538808062003b82565b5082151562003b7c565b5081151562003b75565b90919260ff60035460081c1660001462003d625762003c62818562003a8b565b93670de0b6b3a76400009485820291808304871490151715620027bd5762003c8e600e5480936200362f565b9386840293808504881490151715620027bd5762003cb0600f5480956200362f565b956001600160a01b038060085416911614948560001462003d5b5795905b851562003d2a5787810290808204891490151715620027bd578162003d129362003d0c62003b289962003d068862002b07966200362f565b6200369a565b62003f88565b921562003d215750906200361b565b9050906200361b565b87810290808204891490151715620027bd578162003d129362003d0c62003b289962003d068962002b07966200362f565b9062003cce565b90620038cd93926001600160a01b03806008541691161460001462003da05762003d9262003d99925b826200361b565b926200369a565b906200362f565b62003d9262003d99929362003d8b565b60207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef916001600160a01b03809116938460005260058352604060002062003dfa8782546200360d565b905516938460005260058252604060002062003e188282546200369a565b9055604051908152a3565b801562003f825762003f07816000908360801c8062003f75575b508060401c8062003f67575b508060201c8062003f59575b508060101c8062003f4b575b508060081c8062003f3d575b508060041c8062003f2f575b508060021c8062003f21575b50600191828092811c62003f19575b1c1b62003ea281856200362f565b01811c62003eb181856200362f565b01811c62003ec081856200362f565b01811c62003ecf81856200362f565b01811c62003ede81856200362f565b01811c62003eed81856200362f565b01811c62003efc81856200362f565b01901c80926200362f565b8082101562003f14575090565b905090565b018162003e94565b600291509101903862003e85565b600491509101903862003e79565b600891509101903862003e6d565b601091509101903862003e61565b602091509101903862003e55565b604091509101903862003e49565b9150506080903862003e3d565b50600090565b600093928492839290915b60ff851062003fa3575050505050565b62003faf81836200411a565b838110156200406e5762003fc481856200360d565b670de0b6b3a764000090818102918183041490151715620040525762003ff1859162003d99858762004144565b91821562004014575b50506200400a906001926200369a565b945b019362003f93565b1490506200406657600180820180831162004052578462004036828662003a8b565b11620040485750836200400a62003ffa565b9750505050505050565b634e487b7160e01b86526011600452602486fd5b955050505050565b6200407a84826200360d565b670de0b6b3a7640000908181029181830414901517156200405257620040a7859162003d99858762004144565b918215620040c7575b5050620040c0906001926200360d565b946200400c565b1490508015620040e4575b6200406657600183620040c0620040b0565b5060001981018181116200410657620040ff8491846200411a565b10620040d2565b634e487b7160e01b85526011600452602485fd5b62003b289062003b21670de0b6b3a7640000938462003b198162003b108162003b0786896200361b565b8060030291600383048203620027bd5762003b196200417a9162004182620038cd95670de0b6b3a764000080958482956200361b565b04906200361b565b0492826200419182806200361b565b046200361b56fe60e0346100c357601f61082b38819003918201601f19168301916001600160401b038311848410176100c8578084926060946040528339810103126100c357610047816100de565b906100606040610059602084016100de565b92016100de565b3360805260a09290925260c052600080546001600160a01b0319166001600160a01b0390921691909117905560405161073890816100f3823960805181610232015260a05181818160d7015261057a015260c05181818161012201526105b50152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036100c35756fe6080604081815260048036101561001557600080fd5b600092833560e01c9081630d43e8ad146104565750806359f168f6146101e35780637b35f136146101b95763c4d66de81461004f57600080fd5b346101b557602091826003193601126101b15761006a61047b565b916001600160a01b038093610083828854163314610496565b1692837fffffffffffffffffffffffff000000000000000000000000000000000000000060015416176001558583519163095ea7b360e01b92838152868582015260001990816024820152888160448187877f0000000000000000000000000000000000000000000000000000000000000000165af180156101a7579189969593916044959361018a575b5087519889968795865285015260248401527f0000000000000000000000000000000000000000000000000000000000000000165af19081156101815750610154578280f35b8161017392903d1061017a575b61016b818361050c565b81019061052e565b5038808280f35b503d610161565b513d85823e3d90fd5b6101a090883d8a1161017a5761016b818361050c565b503861010e565b87513d86823e3d90fd5b8380fd5b8280fd5b8284346101e057806003193601126101e057506101d4610546565b82519182526020820152f35b80fd5b508290346104525782600319360112610452576101fe61047b565b926001600160a01b0391602435838116810361044e578385541693610224853314610496565b835163b9a09fd560e01b81527f0000000000000000000000000000000000000000000000000000000000000000821684820152602095908681602481855afa90811561044457879184918a91610403575b508751631703e5f960e01b815291168682015291829060249082905afa9081156103f95787916103dc575b508160015416159081156103d3575b501561039057859695949516908351926370a0823160e01b845230818501528684602481865afa93841561038657908794939291879461034d575b50855163a9059cbb60e01b81526001600160a01b03909216908201908152602081019390935294859283919082906040015b03925af19081156101815750610330578280f35b8161034692903d1061017a5761016b818361050c565b5081808280f35b8581969295503d831161037f575b610365818361050c565b8101031261037b5792518693909261031c6102ea565b8580fd5b503d61035b565b85513d88823e3d90fd5b835162461bcd60e51b8152808401869052600660248201527f41435449564500000000000000000000000000000000000000000000000000006044820152606490fd5b905015886102af565b6103f39150863d881161017a5761016b818361050c565b886102a0565b85513d89823e3d90fd5b928092508391503d831161043d575b61041c818361050c565b810103126104395751828116810361043957826024889290610275565b8780fd5b503d610412565b86513d8a823e3d90fd5b8480fd5b5080fd5b8490346104525781600319360112610452576020906001600160a01b03600154168152f35b600435906001600160a01b038216820361049157565b600080fd5b1561049d57565b60405162461bcd60e51b815260206004820152600660248201527f21564f54455200000000000000000000000000000000000000000000000000006044820152606490fd5b67ffffffffffffffff81116104f657604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176104f657604052565b90816020910312610491575180151581036104915790565b6001546001600160a01b0390811691906000831561072457604080516370a0823160e01b80825230600483015260209691947f00000000000000000000000000000000000000000000000000000000000000009288876024818588165afa9687156103865786976106f5575b507f000000000000000000000000000000000000000000000000000000000000000092855190815230600482015289816024818688165afa998a156106eb57879a6106bb575b5050803b1561037b57845163b66503cf60e01b8082526001600160a01b03959095166004820152602481018890529086908290604490829084905af18015610386576106a8575b506001541691823b1561044e5783519081526001600160a01b0391909116600482015260248101879052919083908390604490829084905af190811561069f575061068b575b50509190565b61069582916104e2565b6101e05780610685565b513d84823e3d90fd5b6106b4909591956104e2565b933861063f565b9080929a50813d83116106e4575b6106d3818361050c565b8101031261037b57519738806105f8565b503d6106c9565b86513d89823e3d90fd5b9096508881813d831161071d575b61070d818361050c565b8101031261037b575195386105b2565b503d610703565b925050819056fea164736f6c6343000816000a405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5aceb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a164736f6c6343000816000a
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.