Source Code
Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Fee To Sette... | 7077189 | 1435 days ago | IN | 0 ETH | 0.000214091826 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AmmFactory
Compiler Version
v0.8.2+commit.661d1103
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./Amm.sol";
import "./interfaces/IAmmFactory.sol";
import "./interfaces/IPriceOracle.sol";
contract AmmFactory is IAmmFactory {
address public immutable override upperFactory; // PairFactory
address public immutable override config;
address public override feeTo;
address public override feeToSetter;
// baseToken => quoteToken => amm
mapping(address => mapping(address => address)) public override getAmm;
modifier onlyUpper() {
require(msg.sender == upperFactory, "AmmFactory: FORBIDDEN");
_;
}
constructor(
address upperFactory_,
address config_,
address feeToSetter_
) {
require(config_ != address(0) && feeToSetter_ != address(0), "AmmFactory: ZERO_ADDRESS");
upperFactory = upperFactory_;
config = config_;
feeToSetter = feeToSetter_;
}
function createAmm(address baseToken, address quoteToken) external override onlyUpper returns (address amm) {
require(baseToken != quoteToken, "AmmFactory.createAmm: IDENTICAL_ADDRESSES");
require(baseToken != address(0) && quoteToken != address(0), "AmmFactory.createAmm: ZERO_ADDRESS");
require(getAmm[baseToken][quoteToken] == address(0), "AmmFactory.createAmm: AMM_EXIST");
bytes32 salt = keccak256(abi.encodePacked(baseToken, quoteToken));
bytes memory ammBytecode = type(Amm).creationCode;
assembly {
amm := create2(0, add(ammBytecode, 32), mload(ammBytecode), salt)
}
getAmm[baseToken][quoteToken] = amm;
emit AmmCreated(baseToken, quoteToken, amm);
}
function initAmm(
address baseToken,
address quoteToken,
address margin
) external override onlyUpper {
address amm = getAmm[baseToken][quoteToken];
Amm(amm).initialize(baseToken, quoteToken, margin);
IPriceOracle(IConfig(config).priceOracle()).setupTwap(amm);
}
function setFeeTo(address feeTo_) external override {
require(msg.sender == feeToSetter, "AmmFactory.setFeeTo: FORBIDDEN");
feeTo = feeTo_;
}
function setFeeToSetter(address feeToSetter_) external override {
require(msg.sender == feeToSetter, "AmmFactory.setFeeToSetter: FORBIDDEN");
feeToSetter = feeToSetter_;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./LiquidityERC20.sol";
import "./interfaces/IAmmFactory.sol";
import "./interfaces/IConfig.sol";
import "./interfaces/IPriceOracle.sol";
import "./interfaces/IMarginFactory.sol";
import "./interfaces/IAmm.sol";
import "./interfaces/IVault.sol";
import "./interfaces/IMargin.sol";
import "./interfaces/IPairFactory.sol";
import "../utils/Reentrant.sol";
import "../libraries/UQ112x112.sol";
import "../libraries/Math.sol";
import "../libraries/FullMath.sol";
import "../libraries/ChainAdapter.sol";
contract Amm is IAmm, LiquidityERC20, Reentrant {
using UQ112x112 for uint224;
uint256 public constant override MINIMUM_LIQUIDITY = 10**3;
address public immutable override factory;
address public override config;
address public override baseToken;
address public override quoteToken;
address public override margin;
uint256 public override price0CumulativeLast;
uint256 public override price1CumulativeLast;
uint256 public kLast;
uint256 public override lastPrice;
bytes4 private constant SELECTOR = bytes4(keccak256(bytes("transfer(address,uint256)")));
uint112 private baseReserve; // uses single storage slot, accessible via getReserves
uint112 private quoteReserve; // uses single storage slot, accessible via getReserves
uint32 private blockTimestampLast;
uint256 private lastBlockNumber;
uint256 private rebaseTimestampLast;
modifier onlyMargin() {
require(margin == msg.sender, "Amm: ONLY_MARGIN");
_;
}
constructor() {
factory = msg.sender;
}
function initialize(
address baseToken_,
address quoteToken_,
address margin_
) external override {
require(msg.sender == factory, "Amm.initialize: FORBIDDEN"); // sufficient check
baseToken = baseToken_;
quoteToken = quoteToken_;
margin = margin_;
config = IAmmFactory(factory).config();
}
/// @notice add liquidity
/// @dev calculate the liquidity according to the real baseReserve.
function mint(address to)
external
override
nonReentrant
returns (
uint256 baseAmount,
uint256 quoteAmount,
uint256 liquidity
)
{
(uint112 _baseReserve, uint112 _quoteReserve, ) = getReserves(); // gas savings
// get real baseReserve
int256 baseTokenOfNetPosition = IMargin(margin).netPosition();
require(int256(uint256(_baseReserve)) + baseTokenOfNetPosition <= 2**112, "Amm.mint:NetPosition_VALUE_WRONT");
int256 realBaseReserveSigned = int256(uint256(_baseReserve)) + baseTokenOfNetPosition;
uint256 realBaseReserve = uint256(realBaseReserveSigned);
baseAmount = IERC20(baseToken).balanceOf(address(this));
require(baseAmount > 0, "Amm.mint: ZERO_BASE_AMOUNT");
bool feeOn = _mintFee(_baseReserve, _quoteReserve);
uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
if (_totalSupply == 0) {
(quoteAmount, ) = IPriceOracle(IConfig(config).priceOracle()).quote(baseToken, quoteToken, baseAmount);
require(quoteAmount > 0, "Amm.mint: INSUFFICIENT_QUOTE_AMOUNT");
liquidity = Math.sqrt(baseAmount * quoteAmount) - MINIMUM_LIQUIDITY;
_mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
} else {
quoteAmount = (baseAmount * _quoteReserve) / _baseReserve;
// realBaseReserve
liquidity = (baseAmount * _totalSupply) / realBaseReserve;
}
require(liquidity > 0, "Amm.mint: INSUFFICIENT_LIQUIDITY_MINTED");
_mint(to, liquidity);
_update(_baseReserve + baseAmount, _quoteReserve + quoteAmount, _baseReserve, _quoteReserve, false);
if (feeOn) kLast = uint256(baseReserve) * quoteReserve;
_safeTransfer(baseToken, margin, baseAmount);
IVault(margin).deposit(msg.sender, baseAmount);
emit Mint(msg.sender, to, baseAmount, quoteAmount, liquidity);
}
/// @notice add liquidity
/// @dev calculate the liquidity according to the real baseReserve.
function burn(address to)
external
override
nonReentrant
returns (
uint256 baseAmount,
uint256 quoteAmount,
uint256 liquidity
)
{
(uint112 _baseReserve, uint112 _quoteReserve, ) = getReserves(); // gas savings
liquidity = balanceOf[address(this)];
// get real baseReserve
int256 baseTokenOfNetPosition = IMargin(margin).netPosition();
int256 realBaseReserveSigned = int256(uint256(_baseReserve)) + baseTokenOfNetPosition;
uint256 realBaseReserve = uint256(realBaseReserveSigned);
bool feeOn = _mintFee(_baseReserve, _quoteReserve);
uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
baseAmount = (liquidity * realBaseReserve) / _totalSupply; // using balances ensures pro-rata distribution
// quoteAmount = (liquidity * _quoteReserve) / _totalSupply; // using balances ensures pro-rata distribution
quoteAmount = (baseAmount * _quoteReserve) / _baseReserve;
require(baseAmount > 0 && quoteAmount > 0, "Amm.burn: INSUFFICIENT_LIQUIDITY_BURNED");
_burn(address(this), liquidity);
_update(_baseReserve - baseAmount, _quoteReserve - quoteAmount, _baseReserve, _quoteReserve, false);
if (feeOn) kLast = uint256(baseReserve) * quoteReserve;
IVault(margin).withdraw(msg.sender, to, baseAmount);
emit Burn(msg.sender, to, baseAmount, quoteAmount, liquidity);
}
/// @notice
function swap(
address trader,
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 outputAmount
) external override nonReentrant onlyMargin returns (uint256[2] memory amounts) {
uint256[2] memory reserves;
(reserves, amounts) = _estimateSwap(inputToken, outputToken, inputAmount, outputAmount);
//check trade slippage
_checkTradeSlippage(reserves[0], reserves[1], baseReserve, quoteReserve);
_update(reserves[0], reserves[1], baseReserve, quoteReserve, false);
emit Swap(trader, inputToken, outputToken, amounts[0], amounts[1]);
}
/// @notice use in the situation of forcing closing position
function forceSwap(
address trader,
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 outputAmount
) external override nonReentrant onlyMargin {
require(inputToken == baseToken || inputToken == quoteToken, "Amm.forceSwap: WRONG_INPUT_TOKEN");
require(outputToken == baseToken || outputToken == quoteToken, "Amm.forceSwap: WRONG_OUTPUT_TOKEN");
require(inputToken != outputToken, "Amm.forceSwap: SAME_TOKENS");
(uint112 _baseReserve, uint112 _quoteReserve, ) = getReserves();
bool feeOn = _mintFee(_baseReserve, _quoteReserve);
uint256 reserve0;
uint256 reserve1;
if (inputToken == baseToken) {
reserve0 = _baseReserve + inputAmount;
reserve1 = _quoteReserve - outputAmount;
} else {
reserve0 = _baseReserve - outputAmount;
reserve1 = _quoteReserve + inputAmount;
}
_update(reserve0, reserve1, _baseReserve, _quoteReserve, true);
if (feeOn) kLast = uint256(baseReserve) * quoteReserve;
emit ForceSwap(trader, inputToken, outputToken, inputAmount, outputAmount);
}
/// @notice invoke when price gap is larger than "gap" percent;
/// @notice gap is in config contract
function rebase() external override nonReentrant returns (uint256 quoteReserveAfter) {
require(msg.sender == tx.origin, "Amm.rebase: ONLY_EOA");
uint256 interval = IConfig(config).rebaseInterval();
require(block.timestamp - rebaseTimestampLast >= interval, "Amm.rebase: NOT_REACH_NEXT_REBASE_TIME");
(uint112 _baseReserve, uint112 _quoteReserve, ) = getReserves();
bool feeOn = _mintFee(_baseReserve, _quoteReserve);
uint256 quoteReserveFromInternal;
(uint256 quoteReserveFromExternal, uint8 priceSource) = IPriceOracle(IConfig(config).priceOracle()).quote(
baseToken,
quoteToken,
_baseReserve
);
if (priceSource == 0) { // external price use UniswapV3Twap, internal price use ammTwap
quoteReserveFromInternal = IPriceOracle(IConfig(config).priceOracle()).quoteFromAmmTwap(address(this), _baseReserve);
} else { // otherwise, use lastPrice as internal price
quoteReserveFromInternal = lastPrice * _baseReserve / 2**112;
}
uint256 gap = IConfig(config).rebasePriceGap();
require(
quoteReserveFromExternal * 100 >= quoteReserveFromInternal * (100 + gap) ||
quoteReserveFromExternal * 100 <= quoteReserveFromInternal * (100 - gap),
"Amm.rebase: NOT_BEYOND_PRICE_GAP"
);
if (quoteReserveFromExternal * 100 >= quoteReserveFromInternal * (100 + gap)) {
quoteReserveAfter = uint256(_quoteReserve) * (100 + gap) / 100;
} else {
quoteReserveAfter = uint256(_quoteReserve) * (100 - gap) / 100;
}
rebaseTimestampLast = uint32(block.timestamp % 2**32);
_update(_baseReserve, quoteReserveAfter, _baseReserve, _quoteReserve, true);
if (feeOn) kLast = uint256(baseReserve) * quoteReserve;
emit Rebase(_quoteReserve, quoteReserveAfter, _baseReserve, quoteReserveFromInternal, quoteReserveFromExternal);
}
/// notice view method for estimating swap
function estimateSwap(
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 outputAmount
) external view override returns (uint256[2] memory amounts) {
(, amounts) = _estimateSwap(inputToken, outputToken, inputAmount, outputAmount);
}
function getReserves()
public
view
override
returns (
uint112 reserveBase,
uint112 reserveQuote,
uint32 blockTimestamp
)
{
reserveBase = baseReserve;
reserveQuote = quoteReserve;
blockTimestamp = blockTimestampLast;
}
function _checkTradeSlippage(
uint256 baseReserveNew,
uint256 quoteReserveNew,
uint112 baseReserveOld,
uint112 quoteReserveOld
) internal view {
// check trade slippage for every transaction
uint256 numerator = quoteReserveNew * baseReserveOld * 100;
uint256 demominator = baseReserveNew * quoteReserveOld;
uint256 tradingSlippage = IConfig(config).tradingSlippage();
require(
(numerator < (100 + tradingSlippage) * demominator) && (numerator > (100 - tradingSlippage) * demominator),
"AMM._update: TRADINGSLIPPAGE_TOO_LARGE_THAN_LAST_TRANSACTION"
);
require(
(quoteReserveNew * 100 < ((100 + tradingSlippage) * baseReserveNew * lastPrice) / 2**112) &&
(quoteReserveNew * 100 > ((100 - tradingSlippage) * baseReserveNew * lastPrice) / 2**112),
"AMM._update: TRADINGSLIPPAGE_TOO_LARGE_THAN_LAST_BLOCK"
);
}
function _estimateSwap(
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 outputAmount
) internal view returns (uint256[2] memory reserves, uint256[2] memory amounts) {
require(inputToken == baseToken || inputToken == quoteToken, "Amm._estimateSwap: WRONG_INPUT_TOKEN");
require(outputToken == baseToken || outputToken == quoteToken, "Amm._estimateSwap: WRONG_OUTPUT_TOKEN");
require(inputToken != outputToken, "Amm._estimateSwap: SAME_TOKENS");
require(inputAmount > 0 || outputAmount > 0, "Amm._estimateSwap: INSUFFICIENT_AMOUNT");
(uint112 _baseReserve, uint112 _quoteReserve, ) = getReserves();
uint256 reserve0;
uint256 reserve1;
if (inputAmount > 0 && inputToken != address(0)) {
// swapInput
if (inputToken == baseToken) {
outputAmount = _getAmountOut(inputAmount, _baseReserve, _quoteReserve);
reserve0 = _baseReserve + inputAmount;
reserve1 = _quoteReserve - outputAmount;
} else {
outputAmount = _getAmountOut(inputAmount, _quoteReserve, _baseReserve);
reserve0 = _baseReserve - outputAmount;
reserve1 = _quoteReserve + inputAmount;
}
} else {
//swapOutput
if (outputToken == baseToken) {
require(outputAmount < _baseReserve, "AMM._estimateSwap: INSUFFICIENT_LIQUIDITY");
inputAmount = _getAmountIn(outputAmount, _quoteReserve, _baseReserve);
reserve0 = _baseReserve - outputAmount;
reserve1 = _quoteReserve + inputAmount;
} else {
require(outputAmount < _quoteReserve, "AMM._estimateSwap: INSUFFICIENT_LIQUIDITY");
inputAmount = _getAmountIn(outputAmount, _baseReserve, _quoteReserve);
reserve0 = _baseReserve + inputAmount;
reserve1 = _quoteReserve - outputAmount;
}
}
reserves = [reserve0, reserve1];
amounts = [inputAmount, outputAmount];
}
// given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
function _getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) internal pure returns (uint256 amountOut) {
require(amountIn > 0, "Amm._getAmountOut: INSUFFICIENT_INPUT_AMOUNT");
require(reserveIn > 0 && reserveOut > 0, "Amm._getAmountOut: INSUFFICIENT_LIQUIDITY");
uint256 amountInWithFee = amountIn * 999;
uint256 numerator = amountInWithFee * reserveOut;
uint256 denominator = reserveIn * 1000 + amountInWithFee;
amountOut = numerator / denominator;
}
// given an output amount of an asset and pair reserves, returns a required input amount of the other asset
function _getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) internal pure returns (uint256 amountIn) {
require(amountOut > 0, "Amm._getAmountIn: INSUFFICIENT_OUTPUT_AMOUNT");
require(reserveIn > 0 && reserveOut > 0, "Amm._getAmountIn: INSUFFICIENT_LIQUIDITY");
uint256 numerator = reserveIn * amountOut * 1000;
uint256 denominator = (reserveOut - amountOut) * 999;
amountIn = (numerator / denominator) + 1;
}
// if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k)
function _mintFee(uint112 reserve0, uint112 reserve1) private returns (bool feeOn) {
address feeTo = IAmmFactory(factory).feeTo();
feeOn = feeTo != address(0);
uint256 _kLast = kLast; // gas savings
if (feeOn) {
if (_kLast != 0) {
uint256 rootK = Math.sqrt(uint256(reserve0) * reserve1);
uint256 rootKLast = Math.sqrt(_kLast);
if (rootK > rootKLast) {
uint256 numerator = totalSupply * (rootK - rootKLast);
uint256 feeParameter = IConfig(config).feeParameter();
uint256 denominator = (rootK * feeParameter) / 100 + rootKLast;
uint256 liquidity = numerator / denominator;
if (liquidity > 0) _mint(feeTo, liquidity);
}
}
} else if (_kLast != 0) {
kLast = 0;
}
}
function _update(
uint256 baseReserveNew,
uint256 quoteReserveNew,
uint112 baseReserveOld,
uint112 quoteReserveOld,
bool isRebaseOrForceSwap
) private {
require(baseReserveNew <= type(uint112).max && quoteReserveNew <= type(uint112).max, "AMM._update: OVERFLOW");
uint32 blockTimestamp = uint32(block.timestamp % 2**32);
uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
// last price means last block price.
if (timeElapsed > 0 && baseReserveOld != 0 && quoteReserveOld != 0) {
// * never overflows, and + overflow is desired
price0CumulativeLast += uint256(UQ112x112.encode(quoteReserveOld).uqdiv(baseReserveOld)) * timeElapsed;
price1CumulativeLast += uint256(UQ112x112.encode(baseReserveOld).uqdiv(quoteReserveOld)) * timeElapsed;
// update twap
IPriceOracle(IConfig(config).priceOracle()).updateAmmTwap(address(this));
}
uint256 blockNumberDelta = ChainAdapter.blockNumber() - lastBlockNumber;
//every arbi block number calculate
if (blockNumberDelta > 0 && baseReserveOld != 0) {
lastPrice = uint256(UQ112x112.encode(quoteReserveOld).uqdiv(baseReserveOld));
}
//set the last price to current price for rebase may cause price gap oversize the tradeslippage.
if ((lastPrice == 0 && baseReserveNew != 0) || isRebaseOrForceSwap) {
lastPrice = uint256(UQ112x112.encode(uint112(quoteReserveNew)).uqdiv(uint112(baseReserveNew)));
}
baseReserve = uint112(baseReserveNew);
quoteReserve = uint112(quoteReserveNew);
lastBlockNumber = ChainAdapter.blockNumber();
blockTimestampLast = blockTimestamp;
emit Sync(baseReserve, quoteReserve);
}
function _safeTransfer(
address token,
address to,
uint256 value
) private {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), "AMM._safeTransfer: TRANSFER_FAILED");
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IAmmFactory {
event AmmCreated(address indexed baseToken, address indexed quoteToken, address amm);
function createAmm(address baseToken, address quoteToken) external returns (address amm);
function initAmm(
address baseToken,
address quoteToken,
address margin
) external;
function setFeeTo(address) external;
function setFeeToSetter(address) external;
function upperFactory() external view returns (address);
function config() external view returns (address);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getAmm(address baseToken, address quoteToken) external view returns (address amm);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IPriceOracle {
function setupTwap(address amm) external;
function quoteFromAmmTwap(address amm, uint256 baseAmount) external view returns (uint256 quoteAmount);
function updateAmmTwap(address pair) external ;
// index price maybe get from different oracle, like UniswapV3 TWAP,Chainklink, or others
// source represents which oracle used. 0 = UniswapV3 TWAP
function quote(
address baseToken,
address quoteToken,
uint256 baseAmount
) external view returns (uint256 quoteAmount, uint8 source);
function getIndexPrice(address amm) external view returns (uint256);
function getMarkPrice(address amm) external view returns (uint256 price);
function getMarkPriceAcc(
address amm,
uint8 beta,
uint256 quoteAmount,
bool negative
) external view returns (uint256 baseAmount);
function getPremiumFraction(address amm) external view returns (int256);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./interfaces/ILiquidityERC20.sol";
contract LiquidityERC20 is ILiquidityERC20 {
string public constant override name = "APEX LP";
string public constant override symbol = "APEX-LP";
uint8 public constant override decimals = 18;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant override PERMIT_TYPEHASH =
0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
bytes32 public immutable override DOMAIN_SEPARATOR;
uint256 public override totalSupply;
mapping(address => uint256) public override balanceOf;
mapping(address => mapping(address => uint256)) public override allowance;
mapping(address => uint256) public override nonces;
constructor() {
uint256 chainId;
assembly {
chainId := chainid()
}
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256(bytes("1")),
chainId,
address(this)
)
);
}
function approve(address spender, uint256 value) external override returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transfer(address to, uint256 value) external override returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function transferFrom(
address from,
address to,
uint256 value
) external override returns (bool) {
if (allowance[from][msg.sender] != type(uint256).max) {
allowance[from][msg.sender] = allowance[from][msg.sender] - value;
}
_transfer(from, to, value);
return true;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external override {
require(deadline >= block.timestamp, "LiquidityERC20: EXPIRED");
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, "LiquidityERC20: INVALID_SIGNATURE");
_approve(owner, spender, value);
}
function _mint(address to, uint256 value) internal {
totalSupply = totalSupply + value;
balanceOf[to] = balanceOf[to] + value;
emit Transfer(address(0), to, value);
}
function _burn(address from, uint256 value) internal {
balanceOf[from] = balanceOf[from] - value;
totalSupply = totalSupply - value;
emit Transfer(from, address(0), value);
}
function _approve(
address owner,
address spender,
uint256 value
) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _transfer(
address from,
address to,
uint256 value
) private {
balanceOf[from] = balanceOf[from] - value;
balanceOf[to] = balanceOf[to] + value;
emit Transfer(from, to, value);
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IConfig {
event PriceOracleChanged(address indexed oldOracle, address indexed newOracle);
event RebasePriceGapChanged(uint256 oldGap, uint256 newGap);
event RebaseIntervalChanged(uint256 oldInterval, uint256 newInterval);
event TradingSlippageChanged(uint256 oldTradingSlippage, uint256 newTradingSlippage);
event RouterRegistered(address indexed router);
event RouterUnregistered(address indexed router);
event SetLiquidateFeeRatio(uint256 oldLiquidateFeeRatio, uint256 liquidateFeeRatio);
event SetLiquidateThreshold(uint256 oldLiquidateThreshold, uint256 liquidateThreshold);
event SetInitMarginRatio(uint256 oldInitMarginRatio, uint256 initMarginRatio);
event SetBeta(uint256 oldBeta, uint256 beta);
event SetFeeParameter(uint256 oldFeeParameter, uint256 feeParameter);
event SetMaxCPFBoost(uint256 oldMaxCPFBoost, uint256 maxCPFBoost);
/// @notice get price oracle address.
function priceOracle() external view returns (address);
/// @notice get beta of amm.
function beta() external view returns (uint8);
/// @notice get feeParameter of amm.
function feeParameter() external view returns (uint256);
/// @notice get init margin ratio of margin.
function initMarginRatio() external view returns (uint256);
/// @notice get liquidate threshold of margin.
function liquidateThreshold() external view returns (uint256);
/// @notice get liquidate fee ratio of margin.
function liquidateFeeRatio() external view returns (uint256);
/// @notice get trading slippage of amm.
function tradingSlippage() external view returns (uint256);
/// @notice get rebase gap of amm.
function rebasePriceGap() external view returns (uint256);
function rebaseInterval() external view returns (uint256);
function routerMap(address) external view returns (bool);
function maxCPFBoost() external view returns (uint256);
function registerRouter(address router) external;
function unregisterRouter(address router) external;
/// @notice Set a new oracle
/// @param newOracle new oracle address.
function setPriceOracle(address newOracle) external;
/// @notice Set a new beta of amm
/// @param newBeta new beta.
function setBeta(uint8 newBeta) external;
/// @notice Set a new rebase gap of amm
/// @param newGap new gap.
function setRebasePriceGap(uint256 newGap) external;
function setRebaseInterval(uint256 interval) external;
/// @notice Set a new trading slippage of amm
/// @param newTradingSlippage .
function setTradingSlippage(uint256 newTradingSlippage) external;
/// @notice Set a new init margin ratio of margin
/// @param marginRatio new init margin ratio.
function setInitMarginRatio(uint256 marginRatio) external;
/// @notice Set a new liquidate threshold of margin
/// @param threshold new liquidate threshold of margin.
function setLiquidateThreshold(uint256 threshold) external;
/// @notice Set a new liquidate fee of margin
/// @param feeRatio new liquidate fee of margin.
function setLiquidateFeeRatio(uint256 feeRatio) external;
/// @notice Set a new feeParameter.
/// @param newFeeParameter New feeParameter get from AMM swap fee.
/// @dev feeParameter = (1/fee -1 ) *100 where fee set by owner.
function setFeeParameter(uint256 newFeeParameter) external;
function setMaxCPFBoost(uint256 newMaxCPFBoost) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IMarginFactory {
event MarginCreated(address indexed baseToken, address indexed quoteToken, address margin);
function createMargin(address baseToken, address quoteToken) external returns (address margin);
function initMargin(
address baseToken,
address quoteToken,
address amm
) external;
function upperFactory() external view returns (address);
function config() external view returns (address);
function getMargin(address baseToken, address quoteToken) external view returns (address margin);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IAmm {
event Mint(address indexed sender, address indexed to, uint256 baseAmount, uint256 quoteAmount, uint256 liquidity);
event Burn(address indexed sender, address indexed to, uint256 baseAmount, uint256 quoteAmount, uint256 liquidity);
event Swap(address indexed trader, address indexed inputToken, address indexed outputToken, uint256 inputAmount, uint256 outputAmount);
event ForceSwap(address indexed trader, address indexed inputToken, address indexed outputToken, uint256 inputAmount, uint256 outputAmount);
event Rebase(uint256 quoteReserveBefore, uint256 quoteReserveAfter, uint256 _baseReserve , uint256 quoteReserveFromInternal, uint256 quoteReserveFromExternal );
event Sync(uint112 reserveBase, uint112 reserveQuote);
// only factory can call this function
function initialize(
address baseToken_,
address quoteToken_,
address margin_
) external;
function mint(address to)
external
returns (
uint256 baseAmount,
uint256 quoteAmount,
uint256 liquidity
);
function burn(address to)
external
returns (
uint256 baseAmount,
uint256 quoteAmount,
uint256 liquidity
);
// only binding margin can call this function
function swap(
address trader,
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 outputAmount
) external returns (uint256[2] memory amounts);
// only binding margin can call this function
function forceSwap(
address trader,
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 outputAmount
) external;
function rebase() external returns (uint256 quoteReserveAfter);
function factory() external view returns (address);
function config() external view returns (address);
function baseToken() external view returns (address);
function quoteToken() external view returns (address);
function price0CumulativeLast() external view returns (uint256);
function price1CumulativeLast() external view returns (uint256);
function margin() external view returns (address);
function lastPrice() external view returns (uint256);
function getReserves()
external
view
returns (
uint112 reserveBase,
uint112 reserveQuote,
uint32 blockTimestamp
);
function estimateSwap(
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 outputAmount
) external view returns (uint256[2] memory amounts);
function MINIMUM_LIQUIDITY() external pure returns (uint256);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IVault {
event Deposit(address indexed user, uint256 amount);
event Withdraw(address indexed user, address indexed receiver, uint256 amount);
/// @notice deposit baseToken to user
function deposit(address user, uint256 amount) external;
/// @notice withdraw user's baseToken from margin contract to receiver
function withdraw(
address user,
address receiver,
uint256 amount
) external;
/// @notice get baseToken amount in margin
function reserve() external view returns (uint256);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IMargin {
struct Position {
int256 quoteSize; //quote amount of position
int256 baseSize; //margin + fundingFee + unrealizedPnl + deltaBaseWhenClosePosition
uint256 tradeSize; //if quoteSize>0 unrealizedPnl = baseValueOfQuoteSize - tradeSize; if quoteSize<0 unrealizedPnl = tradeSize - baseValueOfQuoteSize;
}
event AddMargin(address indexed trader, uint256 depositAmount, Position position);
event RemoveMargin(
address indexed trader,
address indexed to,
uint256 withdrawAmount,
int256 fundingFee,
uint256 withdrawAmountFromMargin,
Position position
);
event OpenPosition(
address indexed trader,
uint8 side,
uint256 baseAmount,
uint256 quoteAmount,
int256 fundingFee,
Position position
);
event ClosePosition(
address indexed trader,
uint256 quoteAmount,
uint256 baseAmount,
int256 fundingFee,
Position position
);
event Liquidate(
address indexed liquidator,
address indexed trader,
uint256 quoteAmount,
uint256 baseAmount,
uint256 bonus,
int256 fundingFee,
Position position
);
event UpdateCPF(uint256 timeStamp, int256 cpf);
/// @notice only factory can call this function
/// @param baseToken_ margin's baseToken.
/// @param quoteToken_ margin's quoteToken.
/// @param amm_ amm address.
function initialize(
address baseToken_,
address quoteToken_,
address amm_
) external;
/// @notice add margin to trader
/// @param trader .
/// @param depositAmount base amount to add.
function addMargin(address trader, uint256 depositAmount) external;
/// @notice remove margin to msg.sender
/// @param withdrawAmount base amount to withdraw.
function removeMargin(
address trader,
address to,
uint256 withdrawAmount
) external;
/// @notice open position with side and quoteAmount by msg.sender
/// @param side long or short.
/// @param quoteAmount quote amount.
function openPosition(
address trader,
uint8 side,
uint256 quoteAmount
) external returns (uint256 baseAmount);
/// @notice close msg.sender's position with quoteAmount
/// @param quoteAmount quote amount to close.
function closePosition(address trader, uint256 quoteAmount) external returns (uint256 baseAmount);
/// @notice liquidate trader
function liquidate(address trader)
external
returns (
uint256 quoteAmount,
uint256 baseAmount,
uint256 bonus
);
function updateCPF() external returns (int256);
/// @notice get factory address
function factory() external view returns (address);
/// @notice get config address
function config() external view returns (address);
/// @notice get base token address
function baseToken() external view returns (address);
/// @notice get quote token address
function quoteToken() external view returns (address);
/// @notice get amm address of this margin
function amm() external view returns (address);
/// @notice get all users' net position of base
function netPosition() external view returns (int256 netBasePosition);
/// @notice get trader's position
function getPosition(address trader)
external
view
returns (
int256 baseSize,
int256 quoteSize,
uint256 tradeSize
);
/// @notice get withdrawable margin of trader
function getWithdrawable(address trader) external view returns (uint256 amount);
/// @notice check if can liquidate this trader's position
function canLiquidate(address trader) external view returns (bool);
/// @notice calculate the latest funding fee with current position
function calFundingFee(address trader) external view returns (int256 fundingFee);
/// @notice calculate the latest debt ratio with Pnl and funding fee
function calDebtRatio(address trader) external view returns (uint256 debtRatio);
function calUnrealizedPnl(address trader) external view returns (int256);
function getNewLatestCPF() external view returns (int256);
function querySwapBaseWithAmm(bool isLong, uint256 quoteAmount) external view returns (uint256);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IPairFactory {
event NewPair(address indexed baseToken, address indexed quoteToken, address amm, address margin);
function createPair(address baseToken, address quotoToken) external returns (address amm, address margin);
function ammFactory() external view returns (address);
function marginFactory() external view returns (address);
function getAmm(address baseToken, address quoteToken) external view returns (address);
function getMargin(address baseToken, address quoteToken) external view returns (address);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
abstract contract Reentrant {
bool private entered;
modifier nonReentrant() {
require(entered == false, "Reentrant: reentrant call");
entered = true;
_;
entered = false;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
// range: [0, 2**112 - 1]
// resolution: 1 / 2**112
library UQ112x112 {
uint224 constant Q112 = 2**112;
// encode a uint112 as a UQ112x112
function encode(uint112 y) internal pure returns (uint224 z) {
z = uint224(y) * Q112; // never overflows
}
// divide a UQ112x112 by a uint112, returning a UQ112x112
function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
z = x / uint224(y);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library Math {
function min(uint256 x, uint256 y) internal pure returns (uint256) {
if (x > y) {
return y;
}
return x;
}
// babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
function sqrt(uint256 y) internal pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
function mulDiv(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
// 512-bit multiply [prod1 prod0] = a * b
// Compute the product mod 2**256 and mod 2**256 - 1
// then 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
// todo unchecked
unchecked {
assembly {
let mm := mulmod(a, b, not(0))
prod0 := mul(a, b)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division
if (prod1 == 0) {
require(denominator > 0);
assembly {
result := div(prod0, denominator)
}
return result;
}
// Make sure the result is less than 2**256.
// Also prevents denominator == 0
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0]
// Compute remainder using mulmod
uint256 remainder;
assembly {
remainder := mulmod(a, b, denominator)
}
// Subtract 256 bit number from 512 bit number
assembly {
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator
// Compute largest power of two divisor of denominator.
// Always >= 1.
uint256 twos = (~denominator + 1) & denominator;
// Divide denominator by power of two
assembly {
denominator := div(denominator, twos)
}
// Divide [prod1 prod0] by the factors of two
assembly {
prod0 := div(prod0, twos)
}
// Shift in bits from prod1 into prod0. For this we need
// to flip `twos` such that it is 2**256 / twos.
// If twos is zero, then it becomes one
assembly {
twos := add(div(sub(0, twos), twos), 1)
}
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
// correct for four bits. That is, denominator * inv = 1 mod 2**4
uint256 inv = (3 * denominator) ^ 2;
// Now use 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.
inv *= 2 - denominator * inv; // inverse mod 2**8
inv *= 2 - denominator * inv; // inverse mod 2**16
inv *= 2 - denominator * inv; // inverse mod 2**32
inv *= 2 - denominator * inv; // inverse mod 2**64
inv *= 2 - denominator * inv; // inverse mod 2**128
inv *= 2 - denominator * inv; // 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 precoditions 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 * inv;
return result;
}
}
/// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
function mulDivRoundingUp(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) > 0) {
require(result < type(uint256).max);
result++;
}
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
interface IArbSys {
function arbBlockNumber() external view returns (uint256);
}
library ChainAdapter {
address constant arbSys = address(100);
function blockNumber() internal view returns (uint256) {
uint256 chainId;
assembly {
chainId := chainid()
}
if (chainId == 421611 || chainId == 42161) { // Arbitrum Testnet || Arbitrum Mainnet
return IArbSys(arbSys).arbBlockNumber();
} else {
return block.number;
}
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "./IERC20.sol";
interface ILiquidityERC20 is IERC20 {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external pure returns (uint8);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"upperFactory_","type":"address"},{"internalType":"address","name":"config_","type":"address"},{"internalType":"address","name":"feeToSetter_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"baseToken","type":"address"},{"indexed":true,"internalType":"address","name":"quoteToken","type":"address"},{"indexed":false,"internalType":"address","name":"amm","type":"address"}],"name":"AmmCreated","type":"event"},{"inputs":[],"name":"config","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"quoteToken","type":"address"}],"name":"createAmm","outputs":[{"internalType":"address","name":"amm","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeToSetter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getAmm","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"quoteToken","type":"address"},{"internalType":"address","name":"margin","type":"address"}],"name":"initAmm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeTo_","type":"address"}],"name":"setFeeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeToSetter_","type":"address"}],"name":"setFeeToSetter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upperFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60c060405234801561001057600080fd5b506040516140d83803806140d883398101604081905261002f916100fb565b6001600160a01b0382161580159061004f57506001600160a01b03811615155b61009f5760405162461bcd60e51b815260206004820152601860248201527f416d6d466163746f72793a205a45524f5f414444524553530000000000000000604482015260640160405180910390fd5b606092831b6001600160601b03199081166080529190921b1660a052600180546001600160a01b0319166001600160a01b0390921691909117905561013d565b80516001600160a01b03811681146100f657600080fd5b919050565b60008060006060848603121561010f578283fd5b610118846100df565b9250610126602085016100df565b9150610134604085016100df565b90509250925092565b60805160601c60a05160601c613f5b61017d6000396000818161013b01526102ac015260008181610175015281816101b501526103ab0152613f5b6000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c806365cc7a1d1161006657806365cc7a1d1461010257806379502c5514610136578063a2e74af61461015d578063cedc12d814610170578063f46901ed1461019757610093565b8063017e7e5814610098578063094b7415146100c757806335e30d41146100da5780635131c85b146100ef575b600080fd5b6000546100ab906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b6001546100ab906001600160a01b031681565b6100ed6100e83660046107e8565b6101aa565b005b6100ab6100fd3660046107b0565b61039e565b6100ab6101103660046107b0565b60026020908152600092835260408084209091529082529020546001600160a01b031681565b6100ab7f000000000000000000000000000000000000000000000000000000000000000081565b6100ed61016b366004610771565b610660565b6100ab7f000000000000000000000000000000000000000000000000000000000000000081565b6100ed6101a5366004610771565b6106e8565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461021f5760405162461bcd60e51b815260206004820152601560248201527420b6b6a330b1ba37b93c9d102327a92124a22222a760591b60448201526064015b60405180910390fd5b6001600160a01b03838116600081815260026020908152604080832087861680855292529182902054915163c0c53b8b60e01b815260048101939093526024830152838316604483015290911690819063c0c53b8b90606401600060405180830381600087803b15801561029257600080fd5b505af11580156102a6573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632630c12f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561030357600080fd5b505afa158015610317573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033b9190610794565b604051637b2bb85d60e11b81526001600160a01b038381166004830152919091169063f65770ba90602401600060405180830381600087803b15801561038057600080fd5b505af1158015610394573d6000803e3d6000fd5b5050505050505050565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146104105760405162461bcd60e51b815260206004820152601560248201527420b6b6a330b1ba37b93c9d102327a92124a22222a760591b6044820152606401610216565b816001600160a01b0316836001600160a01b031614156104845760405162461bcd60e51b815260206004820152602960248201527f416d6d466163746f72792e637265617465416d6d3a204944454e544943414c5f60448201526841444452455353455360b81b6064820152608401610216565b6001600160a01b038316158015906104a457506001600160a01b03821615155b6104fb5760405162461bcd60e51b815260206004820152602260248201527f416d6d466163746f72792e637265617465416d6d3a205a45524f5f4144445245604482015261535360f01b6064820152608401610216565b6001600160a01b038381166000908152600260209081526040808320868516845290915290205416156105705760405162461bcd60e51b815260206004820152601f60248201527f416d6d466163746f72792e637265617465416d6d3a20414d4d5f4558495354006044820152606401610216565b6040516bffffffffffffffffffffffff19606085811b8216602084015284901b1660348201526000906048016040516020818303038152906040528051906020012090506000604051806020016105c690610764565b6020820181038252601f19601f820116604052509050818151602083016000f56001600160a01b0386811660008181526002602090815260408083208a86168085529083529281902080546001600160a01b0319169587169586179055519384529396509290917f8eef5cf520576c00176a77de7eeee6762c3f44c7231914ce6c5c01e03a703820910160405180910390a3505092915050565b6001546001600160a01b031633146106c65760405162461bcd60e51b8152602060048201526024808201527f416d6d466163746f72792e736574466565546f5365747465723a20464f524249604482015263222222a760e11b6064820152608401610216565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146107425760405162461bcd60e51b815260206004820152601e60248201527f416d6d466163746f72792e736574466565546f3a20464f5242494444454e00006044820152606401610216565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6136db8061084b83390190565b600060208284031215610782578081fd5b813561078d81610832565b9392505050565b6000602082840312156107a5578081fd5b815161078d81610832565b600080604083850312156107c2578081fd5b82356107cd81610832565b915060208301356107dd81610832565b809150509250929050565b6000806000606084860312156107fc578081fd5b833561080781610832565b9250602084013561081781610832565b9150604084013561082781610832565b809150509250925092565b6001600160a01b038116811461084757600080fd5b5056fe60c060405234801561001057600080fd5b506040805180820182526007815266041504558204c560cc1b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f918101919091527f61b9d5b67636ce161ec7cadd1dad2e234b7b19f7846bc9e1c0e66fc72bb44376918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606082015246608082018190523060a08301529060c00160408051601f198184030181529190528051602090910120608052503360601b60a05260805160a05160601c6135a76101346000396000818161049d0152818161183b015281816118f50152611e4d01526000818161031d0152611a0d01526135a76000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806379502c551161010f578063ba9a7a56116100a2578063c55dae6311610071578063c55dae63146104bf578063d505accf146104d2578063dd62ed3e146104e5578063e343fe1214610510576101e5565b8063ba9a7a561461045c578063bc93657614610465578063c0c53b8b14610485578063c45a015514610498576101e5565b806395d89b41116100de57806395d89b4114610406578063988370a31461042c578063a9059cbb14610441578063af14052c14610454576101e5565b806379502c55146103a85780637ecebe00146103c057806389afcb44146103e05780638f76691a146103f3576101e5565b806330adf81f116101875780635a3d5493116101565780635a3d5493146103485780636a6278421461035157806370a082311461037f5780637464fc3d1461039f576101e5565b806330adf81f146102d7578063313ce567146102fe5780633644e515146103185780635909c0d51461033f576101e5565b8063095ea7b3116101c3578063095ea7b31461026d57806318160ddd14610290578063217a4b701461029957806323b872dd146102c4576101e5565b8063053f14da146101ea57806306fdde03146102065780630902f1ac14610239575b600080fd5b6101f3600b5481565b6040519081526020015b60405180910390f35b61022c60405180604001604052806007815260200166041504558204c560cc1b81525081565b6040516101fd91906132ef565b610241610523565b604080516001600160701b03948516815293909216602084015263ffffffff16908201526060016101fd565b61028061027b36600461321b565b61054d565b60405190151581526020016101fd565b6101f360005481565b6006546102ac906001600160a01b031681565b6040516001600160a01b0390911681526020016101fd565b6102806102d2366004613126565b610563565b6101f37f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b610306601281565b60405160ff90911681526020016101fd565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b6101f360085481565b6101f360095481565b61036461035f366004613012565b6105f8565b604080519384526020840192909252908201526060016101fd565b6101f361038d366004613012565b60016020526000908152604090205481565b6101f3600a5481565b6004546102ac9061010090046001600160a01b031681565b6101f36103ce366004613012565b60036020526000908152604090205481565b6103646103ee366004613012565b610bca565b6007546102ac906001600160a01b031681565b61022c604051806040016040528060078152602001660415045582d4c560cc1b81525081565b61043f61043a3660046130cc565b610e8d565b005b61028061044f36600461321b565b6111a1565b6101f36111ae565b6101f36103e881565b610478610473366004613166565b611812565b6040516101fd91906132be565b61043f610493366004613082565b611830565b6102ac7f000000000000000000000000000000000000000000000000000000000000000081565b6005546102ac906001600160a01b031681565b61043f6104e03660046131ab565b6119a1565b6101f36104f336600461304a565b600260209081526000928352604080842090915290825290205481565b61047861051e3660046130cc565b611be5565b600c546001600160701b0380821692600160701b830490911691600160e01b900463ffffffff1690565b600061055a338484611d3e565b50600192915050565b6001600160a01b0383166000908152600260209081526040808320338452909152812054600019146105e3576001600160a01b03841660009081526002602090815260408083203384529091529020546105be908390613483565b6001600160a01b03851660009081526002602090815260408083203384529091529020555b6105ee848484611da0565b5060019392505050565b6004546000908190819060ff161561062b5760405162461bcd60e51b815260040161062290613322565b60405180910390fd5b6004805460ff19166001179055600080610643610523565b50915091506000600760009054906101000a90046001600160a01b03166001600160a01b031663833b0acb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561069857600080fd5b505afa1580156106ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d09190613266565b9050600160701b6106ea826001600160701b0386166133a2565b13156107385760405162461bcd60e51b815260206004820181905260248201527f416d6d2e6d696e743a4e6574506f736974696f6e5f56414c55455f57524f4e546044820152606401610622565b600061074d826001600160701b0386166133a2565b6005546040516370a0823160e01b815230600482015291925082916001600160a01b03909116906370a082319060240160206040518083038186803b15801561079557600080fd5b505afa1580156107a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107cd9190613266565b97506000881161081f5760405162461bcd60e51b815260206004820152601a60248201527f416d6d2e6d696e743a205a45524f5f424153455f414d4f554e540000000000006044820152606401610622565b600061082b8686611e48565b600054909150806109d857600460019054906101000a90046001600160a01b03166001600160a01b0316632630c12f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561088457600080fd5b505afa158015610898573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bc919061302e565b600554600654604051632d9198e160e21b81526001600160a01b0392831660048201529082166024820152604481018d905291169063b646638490606401604080518083038186803b15801561091157600080fd5b505afa158015610925573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610949919061327e565b509850886109a55760405162461bcd60e51b815260206004820152602360248201527f416d6d2e6d696e743a20494e53554646494349454e545f51554f54455f414d4f60448201526215539560ea1b6064820152608401610622565b6103e86109ba6109b58b8d613464565b612037565b6109c49190613483565b97506109d360006103e86120a7565b610a1b565b866001600160701b0316866001600160701b03168b6109f79190613464565b610a019190613421565b985082610a0e828c613464565b610a189190613421565b97505b60008811610a7b5760405162461bcd60e51b815260206004820152602760248201527f416d6d2e6d696e743a20494e53554646494349454e545f4c495155494449545960448201526617d3525395115160ca1b6064820152608401610622565b610a858b896120a7565b610ab7610a9b8b6001600160701b038a166133e3565b610aae8b6001600160701b038a166133e3565b89896000612138565b8115610ae057600c54610adc906001600160701b03600160701b820481169116613464565b600a555b600554600754610afd916001600160a01b0390811691168c6124bd565b6007546040516311f9fbc960e21b8152336004820152602481018c90526001600160a01b03909116906347e7ef2490604401600060405180830381600087803b158015610b4957600080fd5b505af1158015610b5d573d6000803e3d6000fd5b5050604080518d8152602081018d90529081018b90526001600160a01b038e1692503391507f458f5fa412d0f69b08dd84872b0215675cc67bc1d5b6fd93300a1c3878b86196906060015b60405180910390a350506004805460ff19169055509597949650929450505050565b6004546000908190819060ff1615610bf45760405162461bcd60e51b815260040161062290613322565b6004805460ff19166001179055600080610c0c610523565b5030600090815260016020908152604080832054600754825163833b0acb60e01b8152925191995095975093955091936001600160a01b03169263833b0acb926004808201939291829003018186803b158015610c6857600080fd5b505afa158015610c7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca09190613266565b90506000610cb7826001600160701b0386166133a2565b9050806000610cc68686611e48565b60005490915080610cd7848a613464565b610ce19190613421565b9950866001600160701b0316866001600160701b03168b610d029190613464565b610d0c9190613421565b985060008a118015610d1e5750600089115b610d7a5760405162461bcd60e51b815260206004820152602760248201527f416d6d2e6275726e3a20494e53554646494349454e545f4c495155494449545960448201526617d0955493915160ca1b6064820152608401610622565b610d843089612613565b610dad610d9a8b6001600160701b038a16613483565b610aae8b6001600160701b038a16613483565b8115610dd657600c54610dd2906001600160701b03600160701b820481169116613464565b600a555b600754604051636ce5768960e11b81523360048201526001600160a01b038d81166024830152604482018d90529091169063d9caed1290606401600060405180830381600087803b158015610e2a57600080fd5b505af1158015610e3e573d6000803e3d6000fd5b5050604080518d8152602081018d90529081018b90526001600160a01b038e1692503391507f4cf25bc1d991c17529c25213d3cc0cda295eeaad5f13f361969b12ea48015f9090606001610ba8565b60045460ff1615610eb05760405162461bcd60e51b815260040161062290613322565b6004805460ff191660011790556007546001600160a01b03163314610f0a5760405162461bcd60e51b815260206004820152601060248201526f20b6b69d1027a7262cafa6a0a923a4a760811b6044820152606401610622565b6005546001600160a01b0385811691161480610f3357506006546001600160a01b038581169116145b610f7f5760405162461bcd60e51b815260206004820181905260248201527f416d6d2e666f726365537761703a2057524f4e475f494e5055545f544f4b454e6044820152606401610622565b6005546001600160a01b0384811691161480610fa857506006546001600160a01b038481169116145b610ffe5760405162461bcd60e51b815260206004820152602160248201527f416d6d2e666f726365537761703a2057524f4e475f4f55545055545f544f4b456044820152602760f91b6064820152608401610622565b826001600160a01b0316846001600160a01b031614156110605760405162461bcd60e51b815260206004820152601a60248201527f416d6d2e666f726365537761703a2053414d455f544f4b454e530000000000006044820152606401610622565b60008061106b610523565b5091509150600061107c8383611e48565b60055490915060009081906001600160a01b038a8116911614156110c9576110ad876001600160701b0387166133e3565b91506110c2866001600160701b038616613483565b90506110f4565b6110dc866001600160701b038716613483565b91506110f1876001600160701b0386166133e3565b90505b611102828287876001612138565b821561112b57600c54611127906001600160701b03600160701b820481169116613464565b600a555b876001600160a01b0316896001600160a01b03168b6001600160a01b03167fa36e6e2023c9daa81ac16fbc0d2499822bc9617326793b1ec3ab50c90bcfe8728a8a604051611183929190918252602082015260400190565b60405180910390a450506004805460ff191690555050505050505050565b600061055a338484611da0565b60045460009060ff16156111d45760405162461bcd60e51b815260040161062290613322565b6004805460ff191660011790553332146112275760405162461bcd60e51b8152602060048201526014602482015273416d6d2e7265626173653a204f4e4c595f454f4160601b6044820152606401610622565b6000600460019054906101000a90046001600160a01b03166001600160a01b03166389edeb746040518163ffffffff1660e01b815260040160206040518083038186803b15801561127757600080fd5b505afa15801561128b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112af9190613266565b905080600e54426112c09190613483565b101561131d5760405162461bcd60e51b815260206004820152602660248201527f416d6d2e7265626173653a204e4f545f52454143485f4e4558545f5245424153604482015265455f54494d4560d01b6064820152608401610622565b600080611328610523565b509150915060006113398383611e48565b90506000806000600460019054906101000a90046001600160a01b03166001600160a01b0316632630c12f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561138e57600080fd5b505afa1580156113a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c6919061302e565b600554600654604051632d9198e160e21b81526001600160a01b03928316600482015290821660248201526001600160701b038916604482015291169063b646638490606401604080518083038186803b15801561142357600080fd5b505afa158015611437573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145b919061327e565b915091508060ff166000141561158057600460019054906101000a90046001600160a01b03166001600160a01b0316632630c12f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114b957600080fd5b505afa1580156114cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f1919061302e565b6040516335201cc760e21b81523060048201526001600160701b03881660248201526001600160a01b03919091169063d480731c9060440160206040518083038186803b15801561154157600080fd5b505afa158015611555573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115799190613266565b92506115a9565b600160701b866001600160701b0316600b5461159c9190613464565b6115a69190613421565b92505b6000600460019054906101000a90046001600160a01b03166001600160a01b0316638ecb45516040518163ffffffff1660e01b815260040160206040518083038186803b1580156115f957600080fd5b505afa15801561160d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116319190613266565b905061163e8160646133e3565b6116489085613464565b611653846064613464565b10158061167e5750611666816064613483565b6116709085613464565b61167b846064613464565b11155b6116ca5760405162461bcd60e51b815260206004820181905260248201527f416d6d2e7265626173653a204e4f545f4245594f4e445f50524943455f4741506044820152606401610622565b6116d58160646133e3565b6116df9085613464565b6116ea846064613464565b1061171f5760646116fb82826133e3565b61170e906001600160701b038916613464565b6117189190613421565b985061174b565b606461172b8282613483565b61173e906001600160701b038916613464565b6117489190613421565b98505b61175a6401000000004261350a565b63ffffffff16600e5561177a6001600160701b0388168a89896001612138565b84156117a357600c5461179f906001600160701b03600160701b820481169116613464565b600a555b604080516001600160701b038881168252602082018c9052891681830152606081018690526080810185905290517fa904dcf42a3461c90173c0b966672b2cb4350e529ea12d44e562fcec438363249181900360a00190a150506004805460ff19169055509495945050505050565b61181a612ff4565b6118268585858561269f565b9695505050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146118a85760405162461bcd60e51b815260206004820152601960248201527f416d6d2e696e697469616c697a653a20464f5242494444454e000000000000006044820152606401610622565b600580546001600160a01b038086166001600160a01b03199283161790925560068054858416908316179055600780548484169216919091179055604080516379502c5560e01b815290517f0000000000000000000000000000000000000000000000000000000000000000909216916379502c5591600480820192602092909190829003018186803b15801561193e57600080fd5b505afa158015611952573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611976919061302e565b600460016101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b428410156119f15760405162461bcd60e51b815260206004820152601760248201527f4c697175696469747945524332303a20455850495245440000000000000000006044820152606401610622565b6001600160a01b038716600090815260036020526040812080547f0000000000000000000000000000000000000000000000000000000000000000917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9187611a5f836134ef565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ad892919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611b43573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611b795750886001600160a01b0316816001600160a01b0316145b611bcf5760405162461bcd60e51b815260206004820152602160248201527f4c697175696469747945524332303a20494e56414c49445f5349474e415455526044820152604560f81b6064820152608401610622565b611bda898989611d3e565b505050505050505050565b611bed612ff4565b60045460ff1615611c105760405162461bcd60e51b815260040161062290613322565b6004805460ff191660011790556007546001600160a01b03163314611c6a5760405162461bcd60e51b815260206004820152601060248201526f20b6b69d1027a7262cafa6a0a923a4a760811b6044820152606401610622565b611c72612ff4565b611c7e8686868661269f565b81516020830151600c54929550929350611cad9290916001600160701b0380821691600160701b900416612a78565b80516020820151600c54611cd89291906001600160701b0380821691600160701b9004166000612138565b815160208084015160408051938452918301526001600160a01b038781169289821692918b16917fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e46062910160405180910390a4506004805460ff1916905595945050505050565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038316600090815260016020526040902054611dc4908290613483565b6001600160a01b038085166000908152600160205260408082209390935590841681522054611df49082906133e3565b6001600160a01b0380841660008181526001602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611d939085815260200190565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b158015611ea457600080fd5b505afa158015611eb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611edc919061302e565b600a546001600160a01b03821615801594509192509061202357801561201e576000611f176109b56001600160701b03808816908916613464565b90506000611f2483612037565b90508082111561201b576000611f3a8284613483565b600054611f479190613464565b90506000600460019054906101000a90046001600160a01b03166001600160a01b031663b85f9f0b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f9957600080fd5b505afa158015611fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd19190613266565b90506000836064611fe28488613464565b611fec9190613421565b611ff691906133e3565b905060006120048285613421565b905080156120165761201688826120a7565b505050505b50505b61202f565b801561202f576000600a555b505092915050565b600060038211156120985750806000612051600283613421565b61205c9060016133e3565b90505b81811015612092579050806002816120778186613421565b61208191906133e3565b61208b9190613421565b905061205f565b506120a2565b81156120a2575060015b919050565b806000546120b591906133e3565b60009081556001600160a01b0383168152600160205260409020546120db9082906133e3565b6001600160a01b0383166000818152600160205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061212c9085815260200190565b60405180910390a35050565b6001600160701b03851180159061215657506001600160701b038411155b61219a5760405162461bcd60e51b8152602060048201526015602482015274414d4d2e5f7570646174653a204f564552464c4f5760581b6044820152606401610622565b60006121ab6401000000004261350a565b600c549091506000906121cb90600160e01b900463ffffffff168361349a565b905060008163ffffffff161180156121eb57506001600160701b03851615155b80156121ff57506001600160701b03841615155b15612371578063ffffffff166122278661221887612cdf565b6001600160e01b031690612cfe565b6001600160e01b031661223a9190613464565b6008600082825461224b91906133e3565b909155505063ffffffff81166122648561221888612cdf565b6001600160e01b03166122779190613464565b6009600082825461228891906133e3565b92505081905550600460019054906101000a90046001600160a01b03166001600160a01b0316632630c12f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156122dd57600080fd5b505afa1580156122f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612315919061302e565b604051630422bb0160e41b81523060048201526001600160a01b03919091169063422bb01090602401600060405180830381600087803b15801561235857600080fd5b505af115801561236c573d6000803e3d6000fd5b505050505b6000600d5461237e612d1a565b6123889190613483565b90506000811180156123a257506001600160701b03861615155b156123c1576123b48661221887612cdf565b6001600160e01b0316600b555b600b541580156123d057508715155b806123d85750835b156123f7576123ea8861221889612cdf565b6001600160e01b0316600b555b600c80546001600160701b03898116600160701b026dffffffffffffffffffffffffffff60701b19918c166dffffffffffffffffffffffffffff199093169290921716179055612445612d1a565b600d55600c80546001600160e01b0316600160e01b63ffffffff8616021790819055604080516001600160701b038084168252600160701b90930490921660208301527f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a15050505050505050565b604080518082018252601981527f7472616e7366657228616464726573732c75696e74323536290000000000000060209182015281516001600160a01b0385811660248301526044808301869052845180840390910181526064909201845291810180516001600160e01b031663a9059cbb60e01b1790529151600092839287169161254991906132a2565b6000604051808303816000865af19150503d8060008114612586576040519150601f19603f3d011682016040523d82523d6000602084013e61258b565b606091505b50915091508180156125b55750805115806125b55750808060200190518101906125b59190613246565b61260c5760405162461bcd60e51b815260206004820152602260248201527f414d4d2e5f736166655472616e736665723a205452414e534645525f4641494c604482015261115160f21b6064820152608401610622565b5050505050565b6001600160a01b038216600090815260016020526040902054612637908290613483565b6001600160a01b0383166000908152600160205260408120919091555461265f908290613483565b60009081556040518281526001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161212c565b6126a7612ff4565b6126af612ff4565b6005546001600160a01b03878116911614806126d857506006546001600160a01b038781169116145b6127305760405162461bcd60e51b8152602060048201526024808201527f416d6d2e5f657374696d617465537761703a2057524f4e475f494e5055545f5460448201526327a5a2a760e11b6064820152608401610622565b6005546001600160a01b038681169116148061275957506006546001600160a01b038681169116145b6127b35760405162461bcd60e51b815260206004820152602560248201527f416d6d2e5f657374696d617465537761703a2057524f4e475f4f55545055545f6044820152642a27a5a2a760d91b6064820152608401610622565b846001600160a01b0316866001600160a01b031614156128155760405162461bcd60e51b815260206004820152601e60248201527f416d6d2e5f657374696d617465537761703a2053414d455f544f4b454e5300006044820152606401610622565b60008411806128245750600083115b61287f5760405162461bcd60e51b815260206004820152602660248201527f416d6d2e5f657374696d617465537761703a20494e53554646494349454e545f604482015265105353d5539560d21b6064820152608401610622565b60008061288a610523565b50915091506000806000881180156128aa57506001600160a01b038a1615155b15612962576005546001600160a01b038b811691161415612913576128e288856001600160701b0316856001600160701b0316612db6565b96506128f7886001600160701b0386166133e3565b915061290c876001600160701b038516613483565b905061295d565b61293088846001600160701b0316866001600160701b0316612db6565b9650612945876001600160701b038616613483565b915061295a886001600160701b0385166133e3565b90505b612a44565b6005546001600160a01b038a8116911614156129d257836001600160701b031687106129a05760405162461bcd60e51b815260040161062290613359565b6129bd87846001600160701b0316866001600160701b0316612ed8565b9750612945876001600160701b038616613483565b826001600160701b031687106129fa5760405162461bcd60e51b815260040161062290613359565b612a1787856001600160701b0316856001600160701b0316612ed8565b9750612a2c886001600160701b0386166133e3565b9150612a41876001600160701b038516613483565b90505b6040805180820182529283526020808401929092528051808201909152978852870195909552509296939550929350505050565b6000612a8d6001600160701b03841685613464565b612a98906064613464565b90506000612aaf6001600160701b03841687613464565b90506000600460019054906101000a90046001600160a01b03166001600160a01b0316638ff471f76040518163ffffffff1660e01b815260040160206040518083038186803b158015612b0157600080fd5b505afa158015612b15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b399190613266565b905081612b478260646133e3565b612b519190613464565b83108015612b73575081612b66826064613483565b612b709190613464565b83115b612be55760405162461bcd60e51b815260206004820152603c60248201527f414d4d2e5f7570646174653a2054524144494e47534c4950504147455f544f4f60448201527f5f4c415247455f5448414e5f4c4153545f5452414e53414354494f4e000000006064820152608401610622565b600b54600160701b9088612bfa8460646133e3565b612c049190613464565b612c0e9190613464565b612c189190613421565b612c23876064613464565b108015612c6b5750600b54600160701b9088612c40846064613483565b612c4a9190613464565b612c549190613464565b612c5e9190613421565b612c69876064613464565b115b612cd65760405162461bcd60e51b815260206004820152603660248201527f414d4d2e5f7570646174653a2054524144494e47534c4950504147455f544f4f6044820152755f4c415247455f5448414e5f4c4153545f424c4f434b60501b6064820152608401610622565b50505050505050565b6000612cf8600160701b6001600160701b038416613435565b92915050565b6000612d136001600160701b038316846133fb565b9392505050565b60004662066eeb811480612d2f57508061a4b1145b15612dae5760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d6e57600080fd5b505afa158015612d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da69190613266565b915050612db3565b439150505b90565b6000808411612e1c5760405162461bcd60e51b815260206004820152602c60248201527f416d6d2e5f676574416d6f756e744f75743a20494e53554646494349454e545f60448201526b125394155517d05353d5539560a21b6064820152608401610622565b600083118015612e2c5750600082115b612e8a5760405162461bcd60e51b815260206004820152602960248201527f416d6d2e5f676574416d6f756e744f75743a20494e53554646494349454e545f6044820152684c495155494449545960b81b6064820152608401610622565b6000612e98856103e7613464565b90506000612ea68483613464565b9050600082612eb7876103e8613464565b612ec191906133e3565b9050612ecd8183613421565b979650505050505050565b6000808411612f3e5760405162461bcd60e51b815260206004820152602c60248201527f416d6d2e5f676574416d6f756e74496e3a20494e53554646494349454e545f4f60448201526b155514155517d05353d5539560a21b6064820152608401610622565b600083118015612f4e5750600082115b612fab5760405162461bcd60e51b815260206004820152602860248201527f416d6d2e5f676574416d6f756e74496e3a20494e53554646494349454e545f4c604482015267495155494449545960c01b6064820152608401610622565b6000612fb78585613464565b612fc3906103e8613464565b90506000612fd18685613483565b612fdd906103e7613464565b9050612fe98183613421565b6118269060016133e3565b60405180604001604052806002906020820280368337509192915050565b600060208284031215613023578081fd5b8135612d138161354a565b60006020828403121561303f578081fd5b8151612d138161354a565b6000806040838503121561305c578081fd5b82356130678161354a565b915060208301356130778161354a565b809150509250929050565b600080600060608486031215613096578081fd5b83356130a18161354a565b925060208401356130b18161354a565b915060408401356130c18161354a565b809150509250925092565b600080600080600060a086880312156130e3578081fd5b85356130ee8161354a565b945060208601356130fe8161354a565b9350604086013561310e8161354a565b94979396509394606081013594506080013592915050565b60008060006060848603121561313a578283fd5b83356131458161354a565b925060208401356131558161354a565b929592945050506040919091013590565b6000806000806080858703121561317b578384fd5b84356131868161354a565b935060208501356131968161354a565b93969395505050506040820135916060013590565b600080600080600080600060e0888a0312156131c5578182fd5b87356131d08161354a565b965060208801356131e08161354a565b9550604088013594506060880135935060808801356131fe81613562565b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561322d578182fd5b82356132388161354a565b946020939093013593505050565b600060208284031215613257578081fd5b81518015158114612d13578182fd5b600060208284031215613277578081fd5b5051919050565b60008060408385031215613290578182fd5b82519150602083015161307781613562565b600082516132b48184602087016134bf565b9190910192915050565b60408101818360005b60028110156132e65781518352602092830192909101906001016132c7565b50505092915050565b600060208252825180602084015261330e8160408501602087016134bf565b601f01601f19169190910160400192915050565b60208082526019908201527f5265656e7472616e743a207265656e7472616e742063616c6c00000000000000604082015260600190565b60208082526029908201527f414d4d2e5f657374696d617465537761703a20494e53554646494349454e545f6040820152684c495155494449545960b81b606082015260800190565b600080821280156001600160ff1b03849003851316156133c4576133c461351e565b600160ff1b83900384128116156133dd576133dd61351e565b50500190565b600082198211156133f6576133f661351e565b500190565b60006001600160e01b038381168061341557613415613534565b92169190910492915050565b60008261343057613430613534565b500490565b60006001600160e01b038281168482168115158284048211161561345b5761345b61351e565b02949350505050565b600081600019048311821515161561347e5761347e61351e565b500290565b6000828210156134955761349561351e565b500390565b600063ffffffff838116908316818110156134b7576134b761351e565b039392505050565b60005b838110156134da5781810151838201526020016134c2565b838111156134e9576000848401525b50505050565b60006000198214156135035761350361351e565b5060010190565b60008261351957613519613534565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b038116811461355f57600080fd5b50565b60ff8116811461355f57600080fdfea26469706673582212207be797794c2d35f28ba63893e5e99be3584ad6278fde2c29ff3432442375923664736f6c63430008020033a2646970667358221220ccb7e7fe13f59c3ed8c022cfa36dc94737f7ce55a8ea1d20ba277995d60db4d664736f6c63430008020033000000000000000000000000623ff58c87e4128ec628da4670c311103d31af1a0000000000000000000000007faaf13e445771fd3eef01acd1f24e39ca889d11000000000000000000000000845f67df76391f91a2d378d3c13006456592c939
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100935760003560e01c806365cc7a1d1161006657806365cc7a1d1461010257806379502c5514610136578063a2e74af61461015d578063cedc12d814610170578063f46901ed1461019757610093565b8063017e7e5814610098578063094b7415146100c757806335e30d41146100da5780635131c85b146100ef575b600080fd5b6000546100ab906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b6001546100ab906001600160a01b031681565b6100ed6100e83660046107e8565b6101aa565b005b6100ab6100fd3660046107b0565b61039e565b6100ab6101103660046107b0565b60026020908152600092835260408084209091529082529020546001600160a01b031681565b6100ab7f0000000000000000000000007faaf13e445771fd3eef01acd1f24e39ca889d1181565b6100ed61016b366004610771565b610660565b6100ab7f000000000000000000000000623ff58c87e4128ec628da4670c311103d31af1a81565b6100ed6101a5366004610771565b6106e8565b336001600160a01b037f000000000000000000000000623ff58c87e4128ec628da4670c311103d31af1a161461021f5760405162461bcd60e51b815260206004820152601560248201527420b6b6a330b1ba37b93c9d102327a92124a22222a760591b60448201526064015b60405180910390fd5b6001600160a01b03838116600081815260026020908152604080832087861680855292529182902054915163c0c53b8b60e01b815260048101939093526024830152838316604483015290911690819063c0c53b8b90606401600060405180830381600087803b15801561029257600080fd5b505af11580156102a6573d6000803e3d6000fd5b505050507f0000000000000000000000007faaf13e445771fd3eef01acd1f24e39ca889d116001600160a01b0316632630c12f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561030357600080fd5b505afa158015610317573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033b9190610794565b604051637b2bb85d60e11b81526001600160a01b038381166004830152919091169063f65770ba90602401600060405180830381600087803b15801561038057600080fd5b505af1158015610394573d6000803e3d6000fd5b5050505050505050565b6000336001600160a01b037f000000000000000000000000623ff58c87e4128ec628da4670c311103d31af1a16146104105760405162461bcd60e51b815260206004820152601560248201527420b6b6a330b1ba37b93c9d102327a92124a22222a760591b6044820152606401610216565b816001600160a01b0316836001600160a01b031614156104845760405162461bcd60e51b815260206004820152602960248201527f416d6d466163746f72792e637265617465416d6d3a204944454e544943414c5f60448201526841444452455353455360b81b6064820152608401610216565b6001600160a01b038316158015906104a457506001600160a01b03821615155b6104fb5760405162461bcd60e51b815260206004820152602260248201527f416d6d466163746f72792e637265617465416d6d3a205a45524f5f4144445245604482015261535360f01b6064820152608401610216565b6001600160a01b038381166000908152600260209081526040808320868516845290915290205416156105705760405162461bcd60e51b815260206004820152601f60248201527f416d6d466163746f72792e637265617465416d6d3a20414d4d5f4558495354006044820152606401610216565b6040516bffffffffffffffffffffffff19606085811b8216602084015284901b1660348201526000906048016040516020818303038152906040528051906020012090506000604051806020016105c690610764565b6020820181038252601f19601f820116604052509050818151602083016000f56001600160a01b0386811660008181526002602090815260408083208a86168085529083529281902080546001600160a01b0319169587169586179055519384529396509290917f8eef5cf520576c00176a77de7eeee6762c3f44c7231914ce6c5c01e03a703820910160405180910390a3505092915050565b6001546001600160a01b031633146106c65760405162461bcd60e51b8152602060048201526024808201527f416d6d466163746f72792e736574466565546f5365747465723a20464f524249604482015263222222a760e11b6064820152608401610216565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146107425760405162461bcd60e51b815260206004820152601e60248201527f416d6d466163746f72792e736574466565546f3a20464f5242494444454e00006044820152606401610216565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6136db8061084b83390190565b600060208284031215610782578081fd5b813561078d81610832565b9392505050565b6000602082840312156107a5578081fd5b815161078d81610832565b600080604083850312156107c2578081fd5b82356107cd81610832565b915060208301356107dd81610832565b809150509250929050565b6000806000606084860312156107fc578081fd5b833561080781610832565b9250602084013561081781610832565b9150604084013561082781610832565b809150509250925092565b6001600160a01b038116811461084757600080fd5b5056fe60c060405234801561001057600080fd5b506040805180820182526007815266041504558204c560cc1b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f918101919091527f61b9d5b67636ce161ec7cadd1dad2e234b7b19f7846bc9e1c0e66fc72bb44376918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606082015246608082018190523060a08301529060c00160408051601f198184030181529190528051602090910120608052503360601b60a05260805160a05160601c6135a76101346000396000818161049d0152818161183b015281816118f50152611e4d01526000818161031d0152611a0d01526135a76000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806379502c551161010f578063ba9a7a56116100a2578063c55dae6311610071578063c55dae63146104bf578063d505accf146104d2578063dd62ed3e146104e5578063e343fe1214610510576101e5565b8063ba9a7a561461045c578063bc93657614610465578063c0c53b8b14610485578063c45a015514610498576101e5565b806395d89b41116100de57806395d89b4114610406578063988370a31461042c578063a9059cbb14610441578063af14052c14610454576101e5565b806379502c55146103a85780637ecebe00146103c057806389afcb44146103e05780638f76691a146103f3576101e5565b806330adf81f116101875780635a3d5493116101565780635a3d5493146103485780636a6278421461035157806370a082311461037f5780637464fc3d1461039f576101e5565b806330adf81f146102d7578063313ce567146102fe5780633644e515146103185780635909c0d51461033f576101e5565b8063095ea7b3116101c3578063095ea7b31461026d57806318160ddd14610290578063217a4b701461029957806323b872dd146102c4576101e5565b8063053f14da146101ea57806306fdde03146102065780630902f1ac14610239575b600080fd5b6101f3600b5481565b6040519081526020015b60405180910390f35b61022c60405180604001604052806007815260200166041504558204c560cc1b81525081565b6040516101fd91906132ef565b610241610523565b604080516001600160701b03948516815293909216602084015263ffffffff16908201526060016101fd565b61028061027b36600461321b565b61054d565b60405190151581526020016101fd565b6101f360005481565b6006546102ac906001600160a01b031681565b6040516001600160a01b0390911681526020016101fd565b6102806102d2366004613126565b610563565b6101f37f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b610306601281565b60405160ff90911681526020016101fd565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b6101f360085481565b6101f360095481565b61036461035f366004613012565b6105f8565b604080519384526020840192909252908201526060016101fd565b6101f361038d366004613012565b60016020526000908152604090205481565b6101f3600a5481565b6004546102ac9061010090046001600160a01b031681565b6101f36103ce366004613012565b60036020526000908152604090205481565b6103646103ee366004613012565b610bca565b6007546102ac906001600160a01b031681565b61022c604051806040016040528060078152602001660415045582d4c560cc1b81525081565b61043f61043a3660046130cc565b610e8d565b005b61028061044f36600461321b565b6111a1565b6101f36111ae565b6101f36103e881565b610478610473366004613166565b611812565b6040516101fd91906132be565b61043f610493366004613082565b611830565b6102ac7f000000000000000000000000000000000000000000000000000000000000000081565b6005546102ac906001600160a01b031681565b61043f6104e03660046131ab565b6119a1565b6101f36104f336600461304a565b600260209081526000928352604080842090915290825290205481565b61047861051e3660046130cc565b611be5565b600c546001600160701b0380821692600160701b830490911691600160e01b900463ffffffff1690565b600061055a338484611d3e565b50600192915050565b6001600160a01b0383166000908152600260209081526040808320338452909152812054600019146105e3576001600160a01b03841660009081526002602090815260408083203384529091529020546105be908390613483565b6001600160a01b03851660009081526002602090815260408083203384529091529020555b6105ee848484611da0565b5060019392505050565b6004546000908190819060ff161561062b5760405162461bcd60e51b815260040161062290613322565b60405180910390fd5b6004805460ff19166001179055600080610643610523565b50915091506000600760009054906101000a90046001600160a01b03166001600160a01b031663833b0acb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561069857600080fd5b505afa1580156106ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d09190613266565b9050600160701b6106ea826001600160701b0386166133a2565b13156107385760405162461bcd60e51b815260206004820181905260248201527f416d6d2e6d696e743a4e6574506f736974696f6e5f56414c55455f57524f4e546044820152606401610622565b600061074d826001600160701b0386166133a2565b6005546040516370a0823160e01b815230600482015291925082916001600160a01b03909116906370a082319060240160206040518083038186803b15801561079557600080fd5b505afa1580156107a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107cd9190613266565b97506000881161081f5760405162461bcd60e51b815260206004820152601a60248201527f416d6d2e6d696e743a205a45524f5f424153455f414d4f554e540000000000006044820152606401610622565b600061082b8686611e48565b600054909150806109d857600460019054906101000a90046001600160a01b03166001600160a01b0316632630c12f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561088457600080fd5b505afa158015610898573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bc919061302e565b600554600654604051632d9198e160e21b81526001600160a01b0392831660048201529082166024820152604481018d905291169063b646638490606401604080518083038186803b15801561091157600080fd5b505afa158015610925573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610949919061327e565b509850886109a55760405162461bcd60e51b815260206004820152602360248201527f416d6d2e6d696e743a20494e53554646494349454e545f51554f54455f414d4f60448201526215539560ea1b6064820152608401610622565b6103e86109ba6109b58b8d613464565b612037565b6109c49190613483565b97506109d360006103e86120a7565b610a1b565b866001600160701b0316866001600160701b03168b6109f79190613464565b610a019190613421565b985082610a0e828c613464565b610a189190613421565b97505b60008811610a7b5760405162461bcd60e51b815260206004820152602760248201527f416d6d2e6d696e743a20494e53554646494349454e545f4c495155494449545960448201526617d3525395115160ca1b6064820152608401610622565b610a858b896120a7565b610ab7610a9b8b6001600160701b038a166133e3565b610aae8b6001600160701b038a166133e3565b89896000612138565b8115610ae057600c54610adc906001600160701b03600160701b820481169116613464565b600a555b600554600754610afd916001600160a01b0390811691168c6124bd565b6007546040516311f9fbc960e21b8152336004820152602481018c90526001600160a01b03909116906347e7ef2490604401600060405180830381600087803b158015610b4957600080fd5b505af1158015610b5d573d6000803e3d6000fd5b5050604080518d8152602081018d90529081018b90526001600160a01b038e1692503391507f458f5fa412d0f69b08dd84872b0215675cc67bc1d5b6fd93300a1c3878b86196906060015b60405180910390a350506004805460ff19169055509597949650929450505050565b6004546000908190819060ff1615610bf45760405162461bcd60e51b815260040161062290613322565b6004805460ff19166001179055600080610c0c610523565b5030600090815260016020908152604080832054600754825163833b0acb60e01b8152925191995095975093955091936001600160a01b03169263833b0acb926004808201939291829003018186803b158015610c6857600080fd5b505afa158015610c7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca09190613266565b90506000610cb7826001600160701b0386166133a2565b9050806000610cc68686611e48565b60005490915080610cd7848a613464565b610ce19190613421565b9950866001600160701b0316866001600160701b03168b610d029190613464565b610d0c9190613421565b985060008a118015610d1e5750600089115b610d7a5760405162461bcd60e51b815260206004820152602760248201527f416d6d2e6275726e3a20494e53554646494349454e545f4c495155494449545960448201526617d0955493915160ca1b6064820152608401610622565b610d843089612613565b610dad610d9a8b6001600160701b038a16613483565b610aae8b6001600160701b038a16613483565b8115610dd657600c54610dd2906001600160701b03600160701b820481169116613464565b600a555b600754604051636ce5768960e11b81523360048201526001600160a01b038d81166024830152604482018d90529091169063d9caed1290606401600060405180830381600087803b158015610e2a57600080fd5b505af1158015610e3e573d6000803e3d6000fd5b5050604080518d8152602081018d90529081018b90526001600160a01b038e1692503391507f4cf25bc1d991c17529c25213d3cc0cda295eeaad5f13f361969b12ea48015f9090606001610ba8565b60045460ff1615610eb05760405162461bcd60e51b815260040161062290613322565b6004805460ff191660011790556007546001600160a01b03163314610f0a5760405162461bcd60e51b815260206004820152601060248201526f20b6b69d1027a7262cafa6a0a923a4a760811b6044820152606401610622565b6005546001600160a01b0385811691161480610f3357506006546001600160a01b038581169116145b610f7f5760405162461bcd60e51b815260206004820181905260248201527f416d6d2e666f726365537761703a2057524f4e475f494e5055545f544f4b454e6044820152606401610622565b6005546001600160a01b0384811691161480610fa857506006546001600160a01b038481169116145b610ffe5760405162461bcd60e51b815260206004820152602160248201527f416d6d2e666f726365537761703a2057524f4e475f4f55545055545f544f4b456044820152602760f91b6064820152608401610622565b826001600160a01b0316846001600160a01b031614156110605760405162461bcd60e51b815260206004820152601a60248201527f416d6d2e666f726365537761703a2053414d455f544f4b454e530000000000006044820152606401610622565b60008061106b610523565b5091509150600061107c8383611e48565b60055490915060009081906001600160a01b038a8116911614156110c9576110ad876001600160701b0387166133e3565b91506110c2866001600160701b038616613483565b90506110f4565b6110dc866001600160701b038716613483565b91506110f1876001600160701b0386166133e3565b90505b611102828287876001612138565b821561112b57600c54611127906001600160701b03600160701b820481169116613464565b600a555b876001600160a01b0316896001600160a01b03168b6001600160a01b03167fa36e6e2023c9daa81ac16fbc0d2499822bc9617326793b1ec3ab50c90bcfe8728a8a604051611183929190918252602082015260400190565b60405180910390a450506004805460ff191690555050505050505050565b600061055a338484611da0565b60045460009060ff16156111d45760405162461bcd60e51b815260040161062290613322565b6004805460ff191660011790553332146112275760405162461bcd60e51b8152602060048201526014602482015273416d6d2e7265626173653a204f4e4c595f454f4160601b6044820152606401610622565b6000600460019054906101000a90046001600160a01b03166001600160a01b03166389edeb746040518163ffffffff1660e01b815260040160206040518083038186803b15801561127757600080fd5b505afa15801561128b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112af9190613266565b905080600e54426112c09190613483565b101561131d5760405162461bcd60e51b815260206004820152602660248201527f416d6d2e7265626173653a204e4f545f52454143485f4e4558545f5245424153604482015265455f54494d4560d01b6064820152608401610622565b600080611328610523565b509150915060006113398383611e48565b90506000806000600460019054906101000a90046001600160a01b03166001600160a01b0316632630c12f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561138e57600080fd5b505afa1580156113a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c6919061302e565b600554600654604051632d9198e160e21b81526001600160a01b03928316600482015290821660248201526001600160701b038916604482015291169063b646638490606401604080518083038186803b15801561142357600080fd5b505afa158015611437573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145b919061327e565b915091508060ff166000141561158057600460019054906101000a90046001600160a01b03166001600160a01b0316632630c12f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114b957600080fd5b505afa1580156114cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f1919061302e565b6040516335201cc760e21b81523060048201526001600160701b03881660248201526001600160a01b03919091169063d480731c9060440160206040518083038186803b15801561154157600080fd5b505afa158015611555573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115799190613266565b92506115a9565b600160701b866001600160701b0316600b5461159c9190613464565b6115a69190613421565b92505b6000600460019054906101000a90046001600160a01b03166001600160a01b0316638ecb45516040518163ffffffff1660e01b815260040160206040518083038186803b1580156115f957600080fd5b505afa15801561160d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116319190613266565b905061163e8160646133e3565b6116489085613464565b611653846064613464565b10158061167e5750611666816064613483565b6116709085613464565b61167b846064613464565b11155b6116ca5760405162461bcd60e51b815260206004820181905260248201527f416d6d2e7265626173653a204e4f545f4245594f4e445f50524943455f4741506044820152606401610622565b6116d58160646133e3565b6116df9085613464565b6116ea846064613464565b1061171f5760646116fb82826133e3565b61170e906001600160701b038916613464565b6117189190613421565b985061174b565b606461172b8282613483565b61173e906001600160701b038916613464565b6117489190613421565b98505b61175a6401000000004261350a565b63ffffffff16600e5561177a6001600160701b0388168a89896001612138565b84156117a357600c5461179f906001600160701b03600160701b820481169116613464565b600a555b604080516001600160701b038881168252602082018c9052891681830152606081018690526080810185905290517fa904dcf42a3461c90173c0b966672b2cb4350e529ea12d44e562fcec438363249181900360a00190a150506004805460ff19169055509495945050505050565b61181a612ff4565b6118268585858561269f565b9695505050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146118a85760405162461bcd60e51b815260206004820152601960248201527f416d6d2e696e697469616c697a653a20464f5242494444454e000000000000006044820152606401610622565b600580546001600160a01b038086166001600160a01b03199283161790925560068054858416908316179055600780548484169216919091179055604080516379502c5560e01b815290517f0000000000000000000000000000000000000000000000000000000000000000909216916379502c5591600480820192602092909190829003018186803b15801561193e57600080fd5b505afa158015611952573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611976919061302e565b600460016101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b428410156119f15760405162461bcd60e51b815260206004820152601760248201527f4c697175696469747945524332303a20455850495245440000000000000000006044820152606401610622565b6001600160a01b038716600090815260036020526040812080547f0000000000000000000000000000000000000000000000000000000000000000917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9187611a5f836134ef565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001611ad892919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015611b43573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590611b795750886001600160a01b0316816001600160a01b0316145b611bcf5760405162461bcd60e51b815260206004820152602160248201527f4c697175696469747945524332303a20494e56414c49445f5349474e415455526044820152604560f81b6064820152608401610622565b611bda898989611d3e565b505050505050505050565b611bed612ff4565b60045460ff1615611c105760405162461bcd60e51b815260040161062290613322565b6004805460ff191660011790556007546001600160a01b03163314611c6a5760405162461bcd60e51b815260206004820152601060248201526f20b6b69d1027a7262cafa6a0a923a4a760811b6044820152606401610622565b611c72612ff4565b611c7e8686868661269f565b81516020830151600c54929550929350611cad9290916001600160701b0380821691600160701b900416612a78565b80516020820151600c54611cd89291906001600160701b0380821691600160701b9004166000612138565b815160208084015160408051938452918301526001600160a01b038781169289821692918b16917fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e46062910160405180910390a4506004805460ff1916905595945050505050565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038316600090815260016020526040902054611dc4908290613483565b6001600160a01b038085166000908152600160205260408082209390935590841681522054611df49082906133e3565b6001600160a01b0380841660008181526001602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611d939085815260200190565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b158015611ea457600080fd5b505afa158015611eb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611edc919061302e565b600a546001600160a01b03821615801594509192509061202357801561201e576000611f176109b56001600160701b03808816908916613464565b90506000611f2483612037565b90508082111561201b576000611f3a8284613483565b600054611f479190613464565b90506000600460019054906101000a90046001600160a01b03166001600160a01b031663b85f9f0b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f9957600080fd5b505afa158015611fad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd19190613266565b90506000836064611fe28488613464565b611fec9190613421565b611ff691906133e3565b905060006120048285613421565b905080156120165761201688826120a7565b505050505b50505b61202f565b801561202f576000600a555b505092915050565b600060038211156120985750806000612051600283613421565b61205c9060016133e3565b90505b81811015612092579050806002816120778186613421565b61208191906133e3565b61208b9190613421565b905061205f565b506120a2565b81156120a2575060015b919050565b806000546120b591906133e3565b60009081556001600160a01b0383168152600160205260409020546120db9082906133e3565b6001600160a01b0383166000818152600160205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9061212c9085815260200190565b60405180910390a35050565b6001600160701b03851180159061215657506001600160701b038411155b61219a5760405162461bcd60e51b8152602060048201526015602482015274414d4d2e5f7570646174653a204f564552464c4f5760581b6044820152606401610622565b60006121ab6401000000004261350a565b600c549091506000906121cb90600160e01b900463ffffffff168361349a565b905060008163ffffffff161180156121eb57506001600160701b03851615155b80156121ff57506001600160701b03841615155b15612371578063ffffffff166122278661221887612cdf565b6001600160e01b031690612cfe565b6001600160e01b031661223a9190613464565b6008600082825461224b91906133e3565b909155505063ffffffff81166122648561221888612cdf565b6001600160e01b03166122779190613464565b6009600082825461228891906133e3565b92505081905550600460019054906101000a90046001600160a01b03166001600160a01b0316632630c12f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156122dd57600080fd5b505afa1580156122f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612315919061302e565b604051630422bb0160e41b81523060048201526001600160a01b03919091169063422bb01090602401600060405180830381600087803b15801561235857600080fd5b505af115801561236c573d6000803e3d6000fd5b505050505b6000600d5461237e612d1a565b6123889190613483565b90506000811180156123a257506001600160701b03861615155b156123c1576123b48661221887612cdf565b6001600160e01b0316600b555b600b541580156123d057508715155b806123d85750835b156123f7576123ea8861221889612cdf565b6001600160e01b0316600b555b600c80546001600160701b03898116600160701b026dffffffffffffffffffffffffffff60701b19918c166dffffffffffffffffffffffffffff199093169290921716179055612445612d1a565b600d55600c80546001600160e01b0316600160e01b63ffffffff8616021790819055604080516001600160701b038084168252600160701b90930490921660208301527f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a15050505050505050565b604080518082018252601981527f7472616e7366657228616464726573732c75696e74323536290000000000000060209182015281516001600160a01b0385811660248301526044808301869052845180840390910181526064909201845291810180516001600160e01b031663a9059cbb60e01b1790529151600092839287169161254991906132a2565b6000604051808303816000865af19150503d8060008114612586576040519150601f19603f3d011682016040523d82523d6000602084013e61258b565b606091505b50915091508180156125b55750805115806125b55750808060200190518101906125b59190613246565b61260c5760405162461bcd60e51b815260206004820152602260248201527f414d4d2e5f736166655472616e736665723a205452414e534645525f4641494c604482015261115160f21b6064820152608401610622565b5050505050565b6001600160a01b038216600090815260016020526040902054612637908290613483565b6001600160a01b0383166000908152600160205260408120919091555461265f908290613483565b60009081556040518281526001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161212c565b6126a7612ff4565b6126af612ff4565b6005546001600160a01b03878116911614806126d857506006546001600160a01b038781169116145b6127305760405162461bcd60e51b8152602060048201526024808201527f416d6d2e5f657374696d617465537761703a2057524f4e475f494e5055545f5460448201526327a5a2a760e11b6064820152608401610622565b6005546001600160a01b038681169116148061275957506006546001600160a01b038681169116145b6127b35760405162461bcd60e51b815260206004820152602560248201527f416d6d2e5f657374696d617465537761703a2057524f4e475f4f55545055545f6044820152642a27a5a2a760d91b6064820152608401610622565b846001600160a01b0316866001600160a01b031614156128155760405162461bcd60e51b815260206004820152601e60248201527f416d6d2e5f657374696d617465537761703a2053414d455f544f4b454e5300006044820152606401610622565b60008411806128245750600083115b61287f5760405162461bcd60e51b815260206004820152602660248201527f416d6d2e5f657374696d617465537761703a20494e53554646494349454e545f604482015265105353d5539560d21b6064820152608401610622565b60008061288a610523565b50915091506000806000881180156128aa57506001600160a01b038a1615155b15612962576005546001600160a01b038b811691161415612913576128e288856001600160701b0316856001600160701b0316612db6565b96506128f7886001600160701b0386166133e3565b915061290c876001600160701b038516613483565b905061295d565b61293088846001600160701b0316866001600160701b0316612db6565b9650612945876001600160701b038616613483565b915061295a886001600160701b0385166133e3565b90505b612a44565b6005546001600160a01b038a8116911614156129d257836001600160701b031687106129a05760405162461bcd60e51b815260040161062290613359565b6129bd87846001600160701b0316866001600160701b0316612ed8565b9750612945876001600160701b038616613483565b826001600160701b031687106129fa5760405162461bcd60e51b815260040161062290613359565b612a1787856001600160701b0316856001600160701b0316612ed8565b9750612a2c886001600160701b0386166133e3565b9150612a41876001600160701b038516613483565b90505b6040805180820182529283526020808401929092528051808201909152978852870195909552509296939550929350505050565b6000612a8d6001600160701b03841685613464565b612a98906064613464565b90506000612aaf6001600160701b03841687613464565b90506000600460019054906101000a90046001600160a01b03166001600160a01b0316638ff471f76040518163ffffffff1660e01b815260040160206040518083038186803b158015612b0157600080fd5b505afa158015612b15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b399190613266565b905081612b478260646133e3565b612b519190613464565b83108015612b73575081612b66826064613483565b612b709190613464565b83115b612be55760405162461bcd60e51b815260206004820152603c60248201527f414d4d2e5f7570646174653a2054524144494e47534c4950504147455f544f4f60448201527f5f4c415247455f5448414e5f4c4153545f5452414e53414354494f4e000000006064820152608401610622565b600b54600160701b9088612bfa8460646133e3565b612c049190613464565b612c0e9190613464565b612c189190613421565b612c23876064613464565b108015612c6b5750600b54600160701b9088612c40846064613483565b612c4a9190613464565b612c549190613464565b612c5e9190613421565b612c69876064613464565b115b612cd65760405162461bcd60e51b815260206004820152603660248201527f414d4d2e5f7570646174653a2054524144494e47534c4950504147455f544f4f6044820152755f4c415247455f5448414e5f4c4153545f424c4f434b60501b6064820152608401610622565b50505050505050565b6000612cf8600160701b6001600160701b038416613435565b92915050565b6000612d136001600160701b038316846133fb565b9392505050565b60004662066eeb811480612d2f57508061a4b1145b15612dae5760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d6e57600080fd5b505afa158015612d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da69190613266565b915050612db3565b439150505b90565b6000808411612e1c5760405162461bcd60e51b815260206004820152602c60248201527f416d6d2e5f676574416d6f756e744f75743a20494e53554646494349454e545f60448201526b125394155517d05353d5539560a21b6064820152608401610622565b600083118015612e2c5750600082115b612e8a5760405162461bcd60e51b815260206004820152602960248201527f416d6d2e5f676574416d6f756e744f75743a20494e53554646494349454e545f6044820152684c495155494449545960b81b6064820152608401610622565b6000612e98856103e7613464565b90506000612ea68483613464565b9050600082612eb7876103e8613464565b612ec191906133e3565b9050612ecd8183613421565b979650505050505050565b6000808411612f3e5760405162461bcd60e51b815260206004820152602c60248201527f416d6d2e5f676574416d6f756e74496e3a20494e53554646494349454e545f4f60448201526b155514155517d05353d5539560a21b6064820152608401610622565b600083118015612f4e5750600082115b612fab5760405162461bcd60e51b815260206004820152602860248201527f416d6d2e5f676574416d6f756e74496e3a20494e53554646494349454e545f4c604482015267495155494449545960c01b6064820152608401610622565b6000612fb78585613464565b612fc3906103e8613464565b90506000612fd18685613483565b612fdd906103e7613464565b9050612fe98183613421565b6118269060016133e3565b60405180604001604052806002906020820280368337509192915050565b600060208284031215613023578081fd5b8135612d138161354a565b60006020828403121561303f578081fd5b8151612d138161354a565b6000806040838503121561305c578081fd5b82356130678161354a565b915060208301356130778161354a565b809150509250929050565b600080600060608486031215613096578081fd5b83356130a18161354a565b925060208401356130b18161354a565b915060408401356130c18161354a565b809150509250925092565b600080600080600060a086880312156130e3578081fd5b85356130ee8161354a565b945060208601356130fe8161354a565b9350604086013561310e8161354a565b94979396509394606081013594506080013592915050565b60008060006060848603121561313a578283fd5b83356131458161354a565b925060208401356131558161354a565b929592945050506040919091013590565b6000806000806080858703121561317b578384fd5b84356131868161354a565b935060208501356131968161354a565b93969395505050506040820135916060013590565b600080600080600080600060e0888a0312156131c5578182fd5b87356131d08161354a565b965060208801356131e08161354a565b9550604088013594506060880135935060808801356131fe81613562565b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561322d578182fd5b82356132388161354a565b946020939093013593505050565b600060208284031215613257578081fd5b81518015158114612d13578182fd5b600060208284031215613277578081fd5b5051919050565b60008060408385031215613290578182fd5b82519150602083015161307781613562565b600082516132b48184602087016134bf565b9190910192915050565b60408101818360005b60028110156132e65781518352602092830192909101906001016132c7565b50505092915050565b600060208252825180602084015261330e8160408501602087016134bf565b601f01601f19169190910160400192915050565b60208082526019908201527f5265656e7472616e743a207265656e7472616e742063616c6c00000000000000604082015260600190565b60208082526029908201527f414d4d2e5f657374696d617465537761703a20494e53554646494349454e545f6040820152684c495155494449545960b81b606082015260800190565b600080821280156001600160ff1b03849003851316156133c4576133c461351e565b600160ff1b83900384128116156133dd576133dd61351e565b50500190565b600082198211156133f6576133f661351e565b500190565b60006001600160e01b038381168061341557613415613534565b92169190910492915050565b60008261343057613430613534565b500490565b60006001600160e01b038281168482168115158284048211161561345b5761345b61351e565b02949350505050565b600081600019048311821515161561347e5761347e61351e565b500290565b6000828210156134955761349561351e565b500390565b600063ffffffff838116908316818110156134b7576134b761351e565b039392505050565b60005b838110156134da5781810151838201526020016134c2565b838111156134e9576000848401525b50505050565b60006000198214156135035761350361351e565b5060010190565b60008261351957613519613534565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b038116811461355f57600080fd5b50565b60ff8116811461355f57600080fdfea26469706673582212207be797794c2d35f28ba63893e5e99be3584ad6278fde2c29ff3432442375923664736f6c63430008020033a2646970667358221220ccb7e7fe13f59c3ed8c022cfa36dc94737f7ce55a8ea1d20ba277995d60db4d664736f6c63430008020033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000623ff58c87e4128ec628da4670c311103d31af1a0000000000000000000000007faaf13e445771fd3eef01acd1f24e39ca889d11000000000000000000000000845f67df76391f91a2d378d3c13006456592c939
-----Decoded View---------------
Arg [0] : upperFactory_ (address): 0x623Ff58C87E4128EC628da4670C311103D31aF1A
Arg [1] : config_ (address): 0x7FAaF13e445771fd3eEf01AcD1f24E39ca889d11
Arg [2] : feeToSetter_ (address): 0x845f67Df76391f91A2D378d3C13006456592c939
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000623ff58c87e4128ec628da4670c311103d31af1a
Arg [1] : 0000000000000000000000007faaf13e445771fd3eef01acd1f24e39ca889d11
Arg [2] : 000000000000000000000000845f67df76391f91a2d378d3c13006456592c939
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$7,316.41
Net Worth in ETH
3.117972
Token Allocations
APEX
98.89%
BSC-USD
0.61%
BNB
0.21%
Others
0.30%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 90.59% | $0.301475 | 21,984.7503 | $6,627.85 | |
| ETH | 0.17% | $0.024769 | 502 | $12.43 | |
| ARB | 8.30% | $0.301786 | 2,012.4158 | $607.32 | |
| BSC | 0.61% | $0.999159 | 44.3219 | $44.28 | |
| BSC | 0.21% | $775.31 | 0.0194 | $15.03 | |
| BSC | 0.05% | $1.37 | 2.781 | $3.81 | |
| BASE | 0.07% | $0.9997 | 5 | $5 | |
| BASE | <0.01% | $2,346.11 | 0.00023066 | $0.541154 | |
| BASE | <0.01% | $0.001406 | 100 | $0.1406 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.