Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Code
Read Contract
Write Contract
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- PoolMgmt
- Optimization enabled
- true
- Compiler version
- v0.8.17+commit.8df45f5f
- Optimization runs
- 999999
- EVM Version
- default
- Verified at
- 2023-05-25T14:43:13.954872Z
poolMgmt.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
interface IERC20 {
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
}
import "./safeMath.sol";
import "./pool.sol";
interface IToken {
function registerPool(address poolAddress, bool isPool) external;
function mintSupply(address account, uint256 amount) external;
function transfer(address account, uint256 amount) external;
function balanceOf(address account) external view returns(uint256);
function approve(address spender, uint256 amount) external returns (bool);
function DEAD_ADDRESS() external view returns (address);
}
enum DepthChangeEnum {
Maintain,
Increase,
NoAction
}
interface IMath {
function calcOutputAmountSwapTokensToTokens(uint256 amountX, uint256 poolX, uint256 poolY, uint256 taxNum, uint256 taxDen) external pure returns (uint256 amountY);
function checkIfDepthShouldBeAdjusted(uint256 poolErc20Mean, uint256 poolTokenMean, uint256 erc20Reserves) external returns (DepthChangeEnum action, uint256 erc20Load, uint256 tokenLoad, uint256 liquidity);
function TargetPoolDepth() external view returns (uint256);
function sqrt(uint256 y) external pure returns (uint256);
function calcOptimalErc20Load(uint256 targetPoolDepth, uint256 avgPoolDepth) external returns (uint256 optimalErc20Load);
}
interface IErc20FeesReceiver {
function claimErc20() external;
}
/**
* @dev Abstract contract to manage owner access to contract
*/
abstract contract Owner {
address public CONTRACT_DEFINER;
address public POOL_MNGR;
modifier mod_onlyContractDefiner() {
require(msg.sender == CONTRACT_DEFINER, "Wrong sender.");
_;
}
modifier mod_onlyPoolMngr() {
require(msg.sender == POOL_MNGR, "Wrong sender.");
_;
}
function renounceOwnership() external mod_onlyContractDefiner {
CONTRACT_DEFINER = address(0x0);
}
function changeOwnershipPoolMngr(address newOwner) external mod_onlyPoolMngr {
POOL_MNGR = newOwner;
}
}
/**
* @dev Abstract contract with base variables
*/
abstract contract Base is Owner {
IERC20 public ERC20_CONTRACT;
address public UNISWAP_ROUTER;
IMath public MATH_CONTRACT;
IToken public TOKEN_CONTRACT;
IErc20FeesReceiver public ERC20_FEES_RECEIVER;
address public UNISWAP_PAIR;
uint256 public DEFAULT_TOKEN_ERC20_RATIO = 100;
uint256 public TRADE_TAX = 3;
function updateTradeTax(uint256 tradeTax) mod_onlyPoolMngr external {
TRADE_TAX = tradeTax;
}
}
/**
* @dev Abstract contract to manage pool creation
*/
abstract contract PoolCreation is Base {
using SafeMath for uint256;
/**
* @dev Checks if the pool has already been created
*/
function hasPoolBeenCreated() public view returns (bool) {
return pool.hasPoolBeenCreated(UNISWAP_ROUTER, address(TOKEN_CONTRACT), address(ERC20_CONTRACT));
}
/**
* @dev Creates the pool
*/
function createPool() internal {
if (!hasPoolBeenCreated()) {
UNISWAP_PAIR = pool.createPool(UNISWAP_ROUTER, address(ERC20_CONTRACT), address(TOKEN_CONTRACT));
TOKEN_CONTRACT.registerPool(UNISWAP_PAIR, true);
}
}
/**
* @dev This function is called only once to start the pool
*/
function startPool(uint256 erc20Amount) external {
require(msg.sender == address(TOKEN_CONTRACT), "Not authorized");
require(!hasPoolBeenCreated(), "Pool already created");
require(ERC20_CONTRACT.balanceOf(msg.sender) >= erc20Amount, "Account does not have enough ERC20");
require(ERC20_CONTRACT.transferFrom(msg.sender, address(this), erc20Amount), "Unable to transfer required ERC20");
createPool();
uint256 tokensToMint = erc20Amount.mul(DEFAULT_TOKEN_ERC20_RATIO);
TOKEN_CONTRACT.mintSupply(address(this), tokensToMint);
pool.addLiquidity(
address(TOKEN_CONTRACT),
address(ERC20_CONTRACT),
address(TOKEN_CONTRACT.DEAD_ADDRESS()),
address(UNISWAP_ROUTER),
tokensToMint,
erc20Amount,
block.timestamp + 10000
);
}
}
/**
* @dev Abstract contract that provides stats about the pool
*/
abstract contract PoolStatsMgmt is PoolCreation {
using SafeMath for uint256;
struct PricePair {
uint256 token;
uint256 erc20;
}
uint256 public poolTokenMean = 0;
uint256 public poolErc20Mean = 0;
PricePair[] public prices;
uint256 public pricePos = 0;
uint256 public maxSize = 5;
uint256 public lastPriceAvgTimestamp = 0;
/**
* @dev Returns the difference in minutes between the two timestamps
*/
function diffMinutes(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _minutes) {
require(fromTimestamp <= toTimestamp, "From must be before to");
_minutes = (toTimestamp - fromTimestamp) / 60;
}
function erc20WethReserves() public view returns (uint256 erc20Amount, uint256 wethAmount) {
address pair = pool.getPairWithWETH(UNISWAP_ROUTER, address(ERC20_CONTRACT));
(uint256 erc20, uint256 weth) = pool.getPoolReserves(address(ERC20_CONTRACT), pair);
return (erc20, weth);
}
/**
* @dev Returns the exact pool reserves of TOKEN and ERC20 from the pool. It is called by multiple contracts, including TOKEN and Auctions
*/
function poolReserves() public view returns (uint256 tokenAmount, uint256 erc20Amount) {
(uint256 token, uint256 erc20) = pool.getPoolReserves(address(TOKEN_CONTRACT), UNISWAP_PAIR);
if (token == 0 || erc20 == 0) return (0, 1);
return (token, erc20);
}
//consider dropping this implementation. Since it does an average, the average values can easily fall outside of the actual market maker curve
function updatePoolPriceAvgs() public {
(uint256 tokenAmount, uint256 erc20Amount) = poolReserves();
if (tokenAmount == 0 || erc20Amount == 0) return;
//if prices have been collected
//and either the recorded timestamp is later than the block.timestamp or less than 3 minutes have elapsed, don't allow the registation
if(prices.length > 0 && (lastPriceAvgTimestamp >= block.timestamp || diffMinutes(lastPriceAvgTimestamp, block.timestamp) <= 3)) {
return;
}
//update the timestamp to the current time
lastPriceAvgTimestamp = block.timestamp;
//if the length of the array of prices is smaller than the allowed maximum, push a new value into the array
if (prices.length < maxSize) {
PricePair memory newPricePair = PricePair(tokenAmount, erc20Amount);
prices.push(newPricePair);
}
//otherwise, write over the current pricePos in prices, and increase pricePos. If pricePos overflows the maxSize, move it back to zero
//this basically cycles the array of prices
else {
PricePair memory newPricePair = PricePair(tokenAmount, erc20Amount);
prices[pricePos++] = newPricePair;
if (pricePos >= maxSize) pricePos = 0;
}
uint256 poolTokenSum = 0;
uint256 poolErc20Sum = 0;
//sum all values in the array to calculate the average
for (uint256 i = 0; i < prices.length; i++) {
poolTokenSum = poolTokenSum.add(prices[i].token);
poolErc20Sum = poolErc20Sum.add(prices[i].erc20);
}
poolTokenMean = poolTokenSum.div(prices.length);
poolErc20Mean = poolErc20Sum.div(prices.length);
}
function currentPoolDepth() public view returns (uint256) {
(uint256 tokenAmount, uint256 erc20Amount) = poolReserves();
return tokenAmount.mul(erc20Amount);
}
function avgPoolDepth() public view returns (uint256) {
return poolErc20Mean.mul(poolTokenMean);
}
function calcOutputAmountSwapErc20ToToken(uint256 amountErc20, uint256 taxNum) public view returns (uint256 amountToken) {
(uint256 tokenReserves, uint256 erc20Reserves) = poolReserves();
return MATH_CONTRACT.calcOutputAmountSwapTokensToTokens(amountErc20, erc20Reserves, tokenReserves, taxNum, 100);
}
function calcOutputAmountSwapTokenToErc20(uint256 amountToken, uint256 taxNum) public view returns (uint256 amountErc20) {
(uint256 tokenReserves, uint256 erc20Reserves) = poolReserves();
return MATH_CONTRACT.calcOutputAmountSwapTokensToTokens(amountToken, tokenReserves, erc20Reserves, taxNum, 100);
}
function calcOutputAmountSwapWETHtoErc20(uint256 amountWeth, uint256 taxNum) public view returns (uint256 amountErc20) {
(uint256 erc20Reserves, uint256 wethReserves) = erc20WethReserves();
return MATH_CONTRACT.calcOutputAmountSwapTokensToTokens(amountWeth, wethReserves, erc20Reserves, taxNum, 100);
}
}
interface IContractsManager {
function find(string memory contractName) external view returns (address, bool);
}
/**
* @dev Pool management contract.
*/
contract PoolMgmt is PoolStatsMgmt {
using SafeMath for uint256;
uint256 public totalErc20TaxedOnBuys;
uint256 public totalErc20UsedForTokenLiquidity;
uint256 public totalErc20UsedForBuybacks;
uint256 public totalTokenBurnedFromBuybacks;
uint256 public tokensForPoolAccounting;
uint256 public erc20ForPoolAccounting;
/**
* @dev Increases the liquidity of the pool according to the amounts provided by the mathematical function
*/
function tryIncreasePoolDepth() external {
uint256 erc20Reserves = erc20ForPoolAccounting;
//if you've got values to work with, otherwise do nothing
if (poolErc20Mean > 0 && poolTokenMean > 0) {
(DepthChangeEnum depthChange, uint256 erc20Load, uint256 tokenLoad, ) =
MATH_CONTRACT.checkIfDepthShouldBeAdjusted(poolErc20Mean, poolTokenMean, erc20Reserves);
if (depthChange == DepthChangeEnum.NoAction) return;
if (depthChange == DepthChangeEnum.Increase) {
//check how much tokens the contract has
uint256 tokenAmountBeforeAdd = TOKEN_CONTRACT.balanceOf(address(this));
//determine how much needs to be minted
uint256 tokenAmountToMint = tokenLoad > tokenAmountBeforeAdd ? tokenLoad - tokenAmountBeforeAdd : 0;
if(tokenAmountToMint > 0)
TOKEN_CONTRACT.mintSupply(address(this), tokenAmountToMint);
//check how much the contract holds in erc20 before the liquidity transfer
uint256 erc20AmountBeforeAdd = ERC20_CONTRACT.balanceOf(address(this));
//transfer liquidity
pool.addLiquidity(
address(TOKEN_CONTRACT),
address(ERC20_CONTRACT),
address(TOKEN_CONTRACT.DEAD_ADDRESS()),
address(UNISWAP_ROUTER),
tokenLoad,
erc20Load,
block.timestamp + 10000
);
//check how much the contract holds in erc20 after the liquidity transfer
uint256 erc20AmountAfterAdd = ERC20_CONTRACT.balanceOf(address(this));
//what is the net difference
uint256 erc20Diff = erc20AmountBeforeAdd.sub(erc20AmountAfterAdd);
//update the amount available
erc20ForPoolAccounting = erc20ForPoolAccounting.sub(erc20Diff);
//increase the total erc20 used for liquidity
totalErc20UsedForTokenLiquidity = totalErc20UsedForTokenLiquidity.add(erc20Diff);
}
}
}
/**
* @dev This function is used to add to the accounting value the amount of tokens that the TOKEN contract transferred to this contract
*/
function addTokensForPoolAccounting(uint256 numTokens) external {
require(msg.sender == address(TOKEN_CONTRACT), "Not authorized");
tokensForPoolAccounting = tokensForPoolAccounting.add(numTokens);
}
/**
* @dev This function sells the total amount of TOKEN tokens it has acquired to convert them fully into ERC20
* These token funds are obtained from buy fees
*/
function trySwapTokenFeesForErc20() external {
if(tokensForPoolAccounting < 20e18) return;
//check values before swap
uint256 tokenBalance = TOKEN_CONTRACT.balanceOf(address(this));
uint256 erc20Balance = ERC20_CONTRACT.balanceOf(address(this));
TOKEN_CONTRACT.approve(UNISWAP_ROUTER, tokensForPoolAccounting);
//swap tokens for ERC20
//calculates the output that should come from the trade with an extra tax deduction for pool taxes
uint256 minOutputErc20Amount = calcOutputAmountSwapTokenToErc20(tokensForPoolAccounting, TRADE_TAX);
pool.swapTokens(
address(ERC20_FEES_RECEIVER), //receiver needs to be another contract to avoid uniswapPairV2 invalid_to
tokensForPoolAccounting,
minOutputErc20Amount,
address(TOKEN_CONTRACT),
address(ERC20_CONTRACT),
UNISWAP_ROUTER,
block.timestamp + 10000
);
//claim the erc20 sent to the receiver
ERC20_FEES_RECEIVER.claimErc20();
//check values after swap
uint256 erc20BalanceAfterSwap = ERC20_CONTRACT.balanceOf(address(this));
uint256 tokenBalanceAfterSwap = TOKEN_CONTRACT.balanceOf(address(this));
//determine how much was actually swapped
uint256 tokensSent = tokenBalance.sub(tokenBalanceAfterSwap);
uint256 erc20Received = erc20BalanceAfterSwap.sub(erc20Balance);
//update the erc20 available for the pool
erc20ForPoolAccounting = erc20ForPoolAccounting.add(erc20Received);
//update the tokens available for future sells
tokensForPoolAccounting = tokensForPoolAccounting.sub(tokensSent);
//update the total erc20 received from token sales
totalErc20TaxedOnBuys = totalErc20TaxedOnBuys.add(erc20Received);
}
/**
* @dev This function uses pool funds to execute a buyback and burn. Can only be triggered by the poolMngr
*/
function executeBuyBackAndBurn(uint256 amountErc20) mod_onlyPoolMngr external {
require(amountErc20 <= erc20ForPoolAccounting, "Amount erc20 is higher than available");
uint256 amountErc20BeforeTrade = ERC20_CONTRACT.balanceOf(address(this));
uint256 amountTokensBeforeTrade = TOKEN_CONTRACT.balanceOf(address(this));
//doesn't need to support fees because pool mgmt contract is excluded
ERC20_CONTRACT.approve(UNISWAP_ROUTER, amountErc20);
//calculates the output that should come from the trade with an extra tax deduction for pool taxes
uint256 minOutputTokenAmount = calcOutputAmountSwapErc20ToToken(amountErc20, TRADE_TAX);
pool.swapTokens(
address(this),
amountErc20,
minOutputTokenAmount,
address(ERC20_CONTRACT),
address(TOKEN_CONTRACT),
UNISWAP_ROUTER,
block.timestamp + 10000
);
//check the erc20 balance after the trade
uint256 amountErc20AfterTrade = ERC20_CONTRACT.balanceOf(address(this));
//check the net difference
uint256 erc20Diff = amountErc20BeforeTrade.sub(amountErc20AfterTrade);
//deduct the difference from the accounting
erc20ForPoolAccounting = erc20ForPoolAccounting.sub(erc20Diff);
//increase the total erc20 used for buybacks
totalErc20UsedForBuybacks = totalErc20UsedForBuybacks.add(erc20Diff);
//check the token balance after the trade
uint256 amountTokensAfterTrade = TOKEN_CONTRACT.balanceOf(address(this));
//check the net difference
uint256 tokenDiff = amountTokensAfterTrade.sub(amountTokensBeforeTrade);
//burn the difference
TOKEN_CONTRACT.transfer(TOKEN_CONTRACT.DEAD_ADDRESS(), tokenDiff);
//increase the total token burned from buybacks
totalTokenBurnedFromBuybacks = totalTokenBurnedFromBuybacks.add(tokenDiff);
}
function setContracts(address contractsManager) external mod_onlyContractDefiner {
//Token contract
(address ctr, bool found) = IContractsManager(contractsManager).find("TOKEN_CONTRACT");
require(found, "Contract not found");
TOKEN_CONTRACT = IToken(ctr);
//Math contract
(ctr, found) = IContractsManager(contractsManager).find("MATH_CONTRACT");
require(found, "Contract not found");
MATH_CONTRACT = IMath(ctr);
//Erc20 Fees Receiver contract
(ctr, found) = IContractsManager(contractsManager).find("ERC20_FEES_RECEIVER");
require(found, "Contract not found");
ERC20_FEES_RECEIVER = IErc20FeesReceiver(ctr);
//Uniswap Router
(ctr, found) = IContractsManager(contractsManager).find("UNISWAP_ROUTER");
require(found, "Contract not found");
UNISWAP_ROUTER = ctr;
//Erc20 contract
(ctr, found) = IContractsManager(contractsManager).find("ERC20_CONTRACT");
require(found, "Contract not found");
ERC20_CONTRACT = IERC20(ctr);
}
constructor() {
CONTRACT_DEFINER = msg.sender;
POOL_MNGR = msg.sender;
}
}
pool.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
interface IPoolToken {
function approve(address spender, uint256 amount) external returns (bool);
}
interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB) external returns (address pair);
function getPair(address tokenA, address tokenB) external view returns (address pair);
}
interface IUniswapV2Pair {
function token0() external view returns (address);
function approve(address spender, uint256 amount) external returns (bool);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
}
interface IUniswapV2Router02 {
function factory() external pure returns (address);
function WPLS() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
);
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
}
library pool {
function getPairWithWETH(address router, address tokenAddress) internal view returns (address pair) {
IUniswapV2Factory factory = IUniswapV2Factory((IUniswapV2Router02(router)).factory());
return factory.getPair(IUniswapV2Router02(router).WPLS(), tokenAddress);
}
function getPair(address router, address tokenAddress, address otherTokenAddress) internal view returns (address pair) {
return
IUniswapV2Factory((IUniswapV2Router02(router)).factory()).getPair(
tokenAddress,
otherTokenAddress
);
}
function hasPoolBeenCreated(
address router,
address tokenAddress,
address otherTokenAddress
) internal view returns (bool) {
return
IUniswapV2Factory((IUniswapV2Router02(router)).factory()).getPair(
tokenAddress,
otherTokenAddress
) != address(0x0);
}
function createPool(
address router,
address tokenAddress,
address otherTokenAddress
) internal returns (address) {
return
IUniswapV2Factory((IUniswapV2Router02(router)).factory())
.createPair(tokenAddress, otherTokenAddress);
}
function addLiquidity(
address tokenAddress,
address otherTokenAddress,
address lpTokensReceiver,
address router,
uint256 tokenAmount,
uint256 otherTokenAmount,
uint256 deadline
) internal {
IPoolToken(tokenAddress).approve(router, tokenAmount);
IPoolToken(otherTokenAddress).approve(router, otherTokenAmount);
IUniswapV2Router02(router).addLiquidity(
tokenAddress,
otherTokenAddress,
tokenAmount,
otherTokenAmount,
0,
0,
lpTokensReceiver,
deadline
);
}
function removeLiquidity(
address tokenAddress,
address otherTokenAddress,
address liquidityReceiver,
address router,
address pair,
uint256 lpTokens,
uint256 deadline
) internal {
IUniswapV2Pair(pair).approve(router, lpTokens);
IUniswapV2Router02(router).removeLiquidity(
tokenAddress,
otherTokenAddress,
lpTokens,
0,
0,
liquidityReceiver,
deadline
);
}
function swapTokens(
address receiver,
uint256 tokenAmount,
uint256 outputMinAmount,
address originTokenAddress,
address destinationTokenAddress,
address router,
uint256 deadline
) internal {
address[] memory path = new address[](2);
path[0] = originTokenAddress;
path[1] = destinationTokenAddress;
IUniswapV2Router02(router).swapExactTokensForTokens(
tokenAmount,
outputMinAmount,
path,
receiver,
deadline
);
}
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
address receiver,
uint256 tokenAmount,
address originTokenAddress,
address destinationTokenAddress,
address router,
uint256 deadline
) internal {
address[] memory path = new address[](2);
path[0] = originTokenAddress;
path[1] = destinationTokenAddress;
IUniswapV2Router02(router).swapExactTokensForTokensSupportingFeeOnTransferTokens(
tokenAmount,
0,
path,
receiver,
deadline
);
}
function swapEthForTokens(
uint256 MESSAGE_VALUE,
uint256 outputMinAmount,
address receiver,
address originAddress,
address destinationAddress,
address router,
uint256 deadline
) internal {
address[] memory path = new address[](2);
path[0] = originAddress;
path[1] = destinationAddress;
IUniswapV2Router02(router).swapExactETHForTokens{value: MESSAGE_VALUE}(
outputMinAmount,
path,
receiver,
deadline
);
}
function getPoolReserves(address tokenAddress, address pair)
internal
view
returns (uint256 tokenAmount, uint256 otherTokenAmount)
{
IUniswapV2Pair uniswapPair = IUniswapV2Pair(pair);
(uint256 reserveIn, uint256 reserveOut, ) = uniswapPair.getReserves(); // reserveIn SHOULD be TOKEN, may be ERC20
if (uniswapPair.token0() == tokenAddress) {
tokenAmount = reserveIn;
otherTokenAmount = reserveOut;
} else {
tokenAmount = reserveOut;
otherTokenAmount = reserveIn;
}
return (tokenAmount, otherTokenAmount);
}
}
safeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
}
Contract ABI
[{"type":"constructor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"CONTRACT_DEFINER","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"DEFAULT_TOKEN_ERC20_RATIO","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"ERC20_CONTRACT","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IErc20FeesReceiver"}],"name":"ERC20_FEES_RECEIVER","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IMath"}],"name":"MATH_CONTRACT","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"POOL_MNGR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IToken"}],"name":"TOKEN_CONTRACT","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"TRADE_TAX","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"UNISWAP_PAIR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"UNISWAP_ROUTER","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addTokensForPoolAccounting","inputs":[{"type":"uint256","name":"numTokens","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"avgPoolDepth","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountToken","internalType":"uint256"}],"name":"calcOutputAmountSwapErc20ToToken","inputs":[{"type":"uint256","name":"amountErc20","internalType":"uint256"},{"type":"uint256","name":"taxNum","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountErc20","internalType":"uint256"}],"name":"calcOutputAmountSwapTokenToErc20","inputs":[{"type":"uint256","name":"amountToken","internalType":"uint256"},{"type":"uint256","name":"taxNum","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountErc20","internalType":"uint256"}],"name":"calcOutputAmountSwapWETHtoErc20","inputs":[{"type":"uint256","name":"amountWeth","internalType":"uint256"},{"type":"uint256","name":"taxNum","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeOwnershipPoolMngr","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentPoolDepth","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"erc20ForPoolAccounting","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"erc20Amount","internalType":"uint256"},{"type":"uint256","name":"wethAmount","internalType":"uint256"}],"name":"erc20WethReserves","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeBuyBackAndBurn","inputs":[{"type":"uint256","name":"amountErc20","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasPoolBeenCreated","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastPriceAvgTimestamp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxSize","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"poolErc20Mean","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"tokenAmount","internalType":"uint256"},{"type":"uint256","name":"erc20Amount","internalType":"uint256"}],"name":"poolReserves","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"poolTokenMean","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pricePos","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"token","internalType":"uint256"},{"type":"uint256","name":"erc20","internalType":"uint256"}],"name":"prices","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setContracts","inputs":[{"type":"address","name":"contractsManager","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"startPool","inputs":[{"type":"uint256","name":"erc20Amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokensForPoolAccounting","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalErc20TaxedOnBuys","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalErc20UsedForBuybacks","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalErc20UsedForTokenLiquidity","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalTokenBurnedFromBuybacks","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"tryIncreasePoolDepth","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"trySwapTokenFeesForErc20","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updatePoolPriceAvgs","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateTradeTax","inputs":[{"type":"uint256","name":"tradeTax","internalType":"uint256"}]}]
Contract Creation Code
0x6080604052606460085560036009556000600a556000600b556000600d556005600e556000600f5534801561003357600080fd5b5060008054336001600160a01b0319918216811783556001805490921617905561395f90819061006390396000f3fe608060405234801561001057600080fd5b50600436106102c85760003560e01c8063715018a61161017b578063b651ae17116100d8578063cdac6fda1161008c578063d826492011610071578063d82649201461055e578063e72e4caf1461057e578063e7c0b2281461059e57600080fd5b8063cdac6fda14610543578063cea050151461055657600080fd5b8063bc31c1c1116100bd578063bc31c1c114610514578063bf9a6bda14610527578063c9b71e3b1461053a57600080fd5b8063b651ae17146104f9578063b95924111461050157600080fd5b80639d5d8b851161012f578063a539d66311610114578063a539d663146104be578063a80230de146104c6578063a901d15c146104e657600080fd5b80639d5d8b85146104a25780639ff01cee146104b557600080fd5b8063840a1c2a11610160578063840a1c2a146104715780638ad7f9db14610479578063923d4b151461048257600080fd5b8063715018a6146104615780637334cccd1461046957600080fd5b806335e07c21116102295780634fb886e3116101dd57806369dc5814116101c257806369dc58141461040e5780636b9f69b4146104215780636ba631cf1461044157600080fd5b80634fb886e3146103e35780635a2e2f47146103fb57600080fd5b80633baae36d1161020e5780633baae36d146103be578063444809f9146103c757806344ff54f7146103da57600080fd5b806335e07c2114610395578063363393881461039e57600080fd5b80632565b1591161028057806329265da71161026557806329265da71461032a578063292b7fd214610347578063325e2fd11461035057600080fd5b80632565b1591461031957806325782dcc1461032257600080fd5b80631375f83c116102b15780631375f83c146102f25780631edeeb00146102fb57806320ff46c11461030457600080fd5b80630152551e146102cd57806307a94a2d146102e9575b600080fd5b6102d6600a5481565b6040519081526020015b60405180910390f35b6102d6600f5481565b6102d660125481565b6102d660085481565b610317610312366004613418565b6105a7565b005b6102d6600e5481565b6102d6610674565b610332610697565b604080519283526020830191909152016102e0565b6102d660155481565b6001546103709073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102e0565b6102d660115481565b6005546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6102d660105481565b6103176103d5366004613435565b6106f5565b6102d660145481565b6103eb610789565b60405190151581526020016102e0565b610317610409366004613418565b6107c1565b6102d661041c36600461344e565b610f16565b6002546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6007546103709073ffffffffffffffffffffffffffffffffffffffff1681565b610317610fe3565b61031761108e565b6102d6611293565b6102d6600d5481565b6004546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6102d66104b036600461344e565b6112ac565b6102d660135481565b610332611331565b6000546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6103176104f4366004613435565b611398565b610317611850565b6102d661050f36600461344e565b611cca565b610332610522366004613435565b611cd7565b610317610535366004613435565b611d05565b6102d6600b5481565b610317610551366004613435565b6122dc565b610317612362565b6003546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6006546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6102d660095481565b60015473ffffffffffffffffffffffffffffffffffffffff16331461062d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f57726f6e672073656e6465722e0000000000000000000000000000000000000060448201526064015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000806000610681610697565b909250905061069082826127a3565b9250505090565b6005546007546000918291829182916106c99173ffffffffffffffffffffffffffffffffffffffff9081169116612862565b9150915081600014806106da575080155b156106ec575060009360019350915050565b90939092509050565b60055473ffffffffffffffffffffffffffffffffffffffff163314610776576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e6f7420617574686f72697a65640000000000000000000000000000000000006044820152606401610624565b60145461078390826129be565b60145550565b6003546005546002546000926107bc9273ffffffffffffffffffffffffffffffffffffffff918216929082169116612a37565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610842576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f57726f6e672073656e6465722e000000000000000000000000000000000000006044820152606401610624565b6040517f82b7b50000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f544f4b454e5f434f4e54524143540000000000000000000000000000000000006044820152600090819073ffffffffffffffffffffffffffffffffffffffff8416906382b7b500906064016040805180830381865afa1580156108de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109029190613485565b915091508061096d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152606401610624565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116919091179091556040517f82b7b50000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4d4154485f434f4e5452414354000000000000000000000000000000000000006044820152908416906382b7b500906064016040805180830381865afa158015610a35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a599190613485565b909250905080610ac5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152606401610624565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8481169190911782556040517f82b7b500000000000000000000000000000000000000000000000000000000008152602092810192909252601360248301527f45524332305f464545535f52454345495645520000000000000000000000000060448301528416906382b7b500906064016040805180830381865afa158015610b8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb19190613485565b909250905080610c1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152606401610624565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116919091179091556040517f82b7b50000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f554e49535741505f524f555445520000000000000000000000000000000000006044820152908416906382b7b500906064016040805180830381865afa158015610ce5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d099190613485565b909250905080610d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152606401610624565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116919091179091556040517f82b7b50000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f45524332305f434f4e54524143540000000000000000000000000000000000006044820152908416906382b7b500906064016040805180830381865afa158015610e3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e619190613485565b909250905080610ecd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152606401610624565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b6000806000610f23610697565b600480546040517f4f84245100000000000000000000000000000000000000000000000000000000815291820189905260248201839052604482018490526064808301899052608483015292945090925073ffffffffffffffffffffffffffffffffffffffff90911690634f8424519060a4015b602060405180830381865afa158015610fb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd891906134ba565b925050505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611064576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f57726f6e672073656e6465722e000000000000000000000000000000000000006044820152606401610624565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b600080611099610697565b9150915081600014806110aa575080155b156110b3575050565b600c54158015906110dc575042600f541015806110dc575060036110d9600f5442612b79565b11155b156110e5575050565b42600f55600e54600c541015611170576040805180820190915282815260208101828152600c805460018101825560009190915291517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7600290930292830155517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8909101556111df565b6040805180820190915282815260208101829052600d80548291600c9190600061119983613502565b91905055815481106111ad576111ad61353a565b60009182526020918290208351600290920201908155910151600190910155600e54600d54106111dd576000600d555b505b60008060005b600c5481101561126a5761121d600c82815481106112055761120561353a565b600091825260209091206002909102015484906129be565b9250611256600c82815481106112355761123561353a565b906000526020600020906002020160010154836129be90919063ffffffff16565b91508061126281613502565b9150506111e5565b50600c54611279908390612bfb565b600a55600c5461128a908290612bfb565b600b5550505050565b60006107bc600a54600b546127a390919063ffffffff16565b60008060006112b9610697565b600480546040517f4f84245100000000000000000000000000000000000000000000000000000000815291820189905260248201849052604482018390526064808301899052608483015292945090925073ffffffffffffffffffffffffffffffffffffffff90911690634f8424519060a401610f97565b600354600254600091829182916113619173ffffffffffffffffffffffffffffffffffffffff9182169116612c3d565b600254909150600090819061138c9073ffffffffffffffffffffffffffffffffffffffff1684612862565b90969095509350505050565b60055473ffffffffffffffffffffffffffffffffffffffff163314611419576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e6f7420617574686f72697a65640000000000000000000000000000000000006044820152606401610624565b611421610789565b15611488576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f506f6f6c20616c726561647920637265617465640000000000000000000000006044820152606401610624565b6002546040517f70a08231000000000000000000000000000000000000000000000000000000008152336004820152829173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156114f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151a91906134ba565b10156115a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4163636f756e7420646f6573206e6f74206861766520656e6f7567682045524360448201527f32300000000000000000000000000000000000000000000000000000000000006064820152608401610624565b6002546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526044810183905273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd906064016020604051808303816000875af1158015611625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116499190613569565b6116d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f556e61626c6520746f207472616e73666572207265717569726564204552433260448201527f30000000000000000000000000000000000000000000000000000000000000006064820152608401610624565b6116dd612dd9565b60006116f4600854836127a390919063ffffffff16565b6005546040517fe742806a0000000000000000000000000000000000000000000000000000000081523060048201526024810183905291925073ffffffffffffffffffffffffffffffffffffffff169063e742806a90604401600060405180830381600087803b15801561176757600080fd5b505af115801561177b573d6000803e3d6000fd5b5050600554600254604080517f4e6fd6c4000000000000000000000000000000000000000000000000000000008152905161184c955073ffffffffffffffffffffffffffffffffffffffff938416945092909116918391634e6fd6c49160048083019260209291908290030181865afa1580156117fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118209190613584565b60035473ffffffffffffffffffffffffffffffffffffffff168587611847426127106135a1565b612ecd565b5050565b601554600b541580159061186657506000600a54115b15611cc75760048054600b54600a546040517fc718eeb7000000000000000000000000000000000000000000000000000000008152938401919091526024830152604482018390526000918291829173ffffffffffffffffffffffffffffffffffffffff9091169063c718eeb7906064016080604051808303816000875af11580156118f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191a91906135b4565b50919450925090506002836002811115611936576119366135f7565b036119415750505050565b6001836002811115611955576119556135f7565b03611cc3576005546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156119c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ed91906134ba565b905060008183116119ff576000611a09565b611a098284613626565b90508015611a9c576005546040517fe742806a0000000000000000000000000000000000000000000000000000000081523060048201526024810183905273ffffffffffffffffffffffffffffffffffffffff9091169063e742806a90604401600060405180830381600087803b158015611a8357600080fd5b505af1158015611a97573d6000803e3d6000fd5b505050505b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611b0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2f91906134ba565b600554600254604080517f4e6fd6c40000000000000000000000000000000000000000000000000000000081529051939450611bf99373ffffffffffffffffffffffffffffffffffffffff93841693909216918391634e6fd6c49160048083019260209291908290030181865afa158015611bae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd29190613584565b60035473ffffffffffffffffffffffffffffffffffffffff16888a611847426127106135a1565b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611c68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8c91906134ba565b90506000611c9a83836130d3565b601554909150611caa90826130d3565b601555601154611cba90826129be565b60115550505050505b5050505b50565b6000806000610f23611331565b600c8181548110611ce757600080fd5b60009182526020909120600290910201805460019091015490915082565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f57726f6e672073656e6465722e000000000000000000000000000000000000006044820152606401610624565b601554811115611e18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f416d6f756e7420657263323020697320686967686572207468616e206176616960448201527f6c61626c650000000000000000000000000000000000000000000000000000006064820152608401610624565b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611e87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eab91906134ba565b6005546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015291925060009173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015611f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4391906134ba565b6002546003546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015260248101879052929350169063095ea7b3906044016020604051808303816000875af1158015611fc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe49190613569565b506000611ff384600954610f16565b6002546005546003549293506120389230928892869273ffffffffffffffffffffffffffffffffffffffff928316929182169116612033426127106135a1565b613115565b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156120a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cb91906134ba565b905060006120d985836130d3565b6015549091506120e990826130d3565b6015556012546120f990826129be565b6012556005546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561216b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218f91906134ba565b9050600061219d82876130d3565b600554604080517f4e6fd6c4000000000000000000000000000000000000000000000000000000008152905192935073ffffffffffffffffffffffffffffffffffffffff9091169163a9059cbb918391634e6fd6c4916004808201926020929091908290030181865afa158015612218573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223c9190613584565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156122a957600080fd5b505af11580156122bd573d6000803e3d6000fd5b50506013546122cf92509050826129be565b6013555050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461235d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f57726f6e672073656e6465722e000000000000000000000000000000000000006044820152606401610624565b600955565b6801158e460913d00000601454101561237757565b6005546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156123e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240a91906134ba565b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015291925060009173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561247e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a291906134ba565b6005546003546014546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201526024810191909152929350169063095ea7b3906044016020604051808303816000875af1158015612523573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125479190613569565b5060006125586014546009546112ac565b60065460145460055460025460035494955061259c9473ffffffffffffffffffffffffffffffffffffffff94851694879381169281169116612033426127106135a1565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638e4fa5a26040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561260657600080fd5b505af115801561261a573d6000803e3d6000fd5b50506002546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000935073ffffffffffffffffffffffffffffffffffffffff90911691506370a0823190602401602060405180830381865afa15801561268f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b391906134ba565b6005546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015291925060009173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015612727573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274b91906134ba565b9050600061275986836130d3565b9050600061276784876130d3565b60155490915061277790826129be565b60155560145461278790836130d3565b60145560105461279790826129be565b60105550505050505050565b6000826000036127b557506000610fdd565b60006127c18385613639565b9050826127ce8583613650565b1461285b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60448201527f77000000000000000000000000000000000000000000000000000000000000006064820152608401610624565b9392505050565b60008060008390506000808273ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156128b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128dc91906136a9565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691508673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612963573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129879190613584565b73ffffffffffffffffffffffffffffffffffffffff16036129ad578194508093506129b4565b8094508193505b5050509250929050565b6000806129cb83856135a1565b90508381101561285b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610624565b60008073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abf9190613584565b6040517fe6a4390500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301528581166024830152919091169063e6a4390590604401602060405180830381865afa158015612b35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b599190613584565b73ffffffffffffffffffffffffffffffffffffffff161415949350505050565b600081831115612be5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f46726f6d206d757374206265206265666f726520746f000000000000000000006044820152606401610624565b603c612bf18484613626565b61285b9190613650565b600061285b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613271565b6000808373ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612caf9190613584565b90508073ffffffffffffffffffffffffffffffffffffffff1663e6a439058573ffffffffffffffffffffffffffffffffffffffff1663ef8ef56f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3c9190613584565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff91821660048201529086166024820152604401602060405180830381865afa158015612dad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd19190613584565b949350505050565b612de1610789565b612ecb57600354600254600554612e149273ffffffffffffffffffffffffffffffffffffffff90811692811691166132c2565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9283169081179091556005546040517f3526c0bd00000000000000000000000000000000000000000000000000000000815260048101929092526001602483015290911690633526c0bd90604401600060405180830381600087803b158015612eb757600080fd5b505af1158015611cc3573d6000803e3d6000fd5b565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820185905288169063095ea7b3906044016020604051808303816000875af1158015612f42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f669190613569565b506040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820184905287169063095ea7b3906044016020604051808303816000875af1158015612fdc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130009190613569565b506040517fe8e3370000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff88811660048301528781166024830152604482018590526064820184905260006084830181905260a483015286811660c483015260e4820183905285169063e8e3370090610104016060604051808303816000875af11580156130a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130c791906136f9565b50505050505050505050565b600061285b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506133ab565b604080516002808252606082018352600092602083019080368337019050509050848160008151811061314a5761314a61353a565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505083816001815181106131985761319861353a565b73ffffffffffffffffffffffffffffffffffffffff92831660209182029290920101526040517f38ed1739000000000000000000000000000000000000000000000000000000008152908416906338ed173990613201908a908a9086908e908990600401613756565b6000604051808303816000875af1158015613220573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261326691908101906137e1565b505050505050505050565b600081836132ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062491906138bd565b5060006132b98486613650565b95945050505050565b60008373ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561330f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133339190613584565b6040517fc9c6539600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528481166024830152919091169063c9c65396906044016020604051808303816000875af1158015612dad573d6000803e3d6000fd5b600081848411156133e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062491906138bd565b5060006132b98486613626565b73ffffffffffffffffffffffffffffffffffffffff81168114611cc757600080fd5b60006020828403121561342a57600080fd5b813561285b816133f6565b60006020828403121561344757600080fd5b5035919050565b6000806040838503121561346157600080fd5b50508035926020909101359150565b8051801515811461348057600080fd5b919050565b6000806040838503121561349857600080fd5b82516134a3816133f6565b91506134b160208401613470565b90509250929050565b6000602082840312156134cc57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613533576135336134d3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561357b57600080fd5b61285b82613470565b60006020828403121561359657600080fd5b815161285b816133f6565b80820180821115610fdd57610fdd6134d3565b600080600080608085870312156135ca57600080fd5b8451600381106135d957600080fd5b60208601516040870151606090970151919890975090945092505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81810381811115610fdd57610fdd6134d3565b8082028115828204841417610fdd57610fdd6134d3565b600082613686577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80516dffffffffffffffffffffffffffff8116811461348057600080fd5b6000806000606084860312156136be57600080fd5b6136c78461368b565b92506136d56020850161368b565b9150604084015163ffffffff811681146136ee57600080fd5b809150509250925092565b60008060006060848603121561370e57600080fd5b8351925060208401519150604084015190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156137b357845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101613781565b505073ffffffffffffffffffffffffffffffffffffffff969096166060850152505050608001529392505050565b600060208083850312156137f457600080fd5b825167ffffffffffffffff8082111561380c57600080fd5b818501915085601f83011261382057600080fd5b81518181111561383257613832613727565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561387557613875613727565b60405291825284820192508381018501918883111561389357600080fd5b938501935b828510156138b157845184529385019392850192613898565b98975050505050505050565b600060208083528351808285015260005b818110156138ea578581018301518582016040015282016138ce565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509291505056fea264697066735822122022109c587634049b96e310baa780c707f0e6daedfe3eb9b02d03ee77f05c586764736f6c63430008110033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106102c85760003560e01c8063715018a61161017b578063b651ae17116100d8578063cdac6fda1161008c578063d826492011610071578063d82649201461055e578063e72e4caf1461057e578063e7c0b2281461059e57600080fd5b8063cdac6fda14610543578063cea050151461055657600080fd5b8063bc31c1c1116100bd578063bc31c1c114610514578063bf9a6bda14610527578063c9b71e3b1461053a57600080fd5b8063b651ae17146104f9578063b95924111461050157600080fd5b80639d5d8b851161012f578063a539d66311610114578063a539d663146104be578063a80230de146104c6578063a901d15c146104e657600080fd5b80639d5d8b85146104a25780639ff01cee146104b557600080fd5b8063840a1c2a11610160578063840a1c2a146104715780638ad7f9db14610479578063923d4b151461048257600080fd5b8063715018a6146104615780637334cccd1461046957600080fd5b806335e07c21116102295780634fb886e3116101dd57806369dc5814116101c257806369dc58141461040e5780636b9f69b4146104215780636ba631cf1461044157600080fd5b80634fb886e3146103e35780635a2e2f47146103fb57600080fd5b80633baae36d1161020e5780633baae36d146103be578063444809f9146103c757806344ff54f7146103da57600080fd5b806335e07c2114610395578063363393881461039e57600080fd5b80632565b1591161028057806329265da71161026557806329265da71461032a578063292b7fd214610347578063325e2fd11461035057600080fd5b80632565b1591461031957806325782dcc1461032257600080fd5b80631375f83c116102b15780631375f83c146102f25780631edeeb00146102fb57806320ff46c11461030457600080fd5b80630152551e146102cd57806307a94a2d146102e9575b600080fd5b6102d6600a5481565b6040519081526020015b60405180910390f35b6102d6600f5481565b6102d660125481565b6102d660085481565b610317610312366004613418565b6105a7565b005b6102d6600e5481565b6102d6610674565b610332610697565b604080519283526020830191909152016102e0565b6102d660155481565b6001546103709073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102e0565b6102d660115481565b6005546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6102d660105481565b6103176103d5366004613435565b6106f5565b6102d660145481565b6103eb610789565b60405190151581526020016102e0565b610317610409366004613418565b6107c1565b6102d661041c36600461344e565b610f16565b6002546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6007546103709073ffffffffffffffffffffffffffffffffffffffff1681565b610317610fe3565b61031761108e565b6102d6611293565b6102d6600d5481565b6004546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6102d66104b036600461344e565b6112ac565b6102d660135481565b610332611331565b6000546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6103176104f4366004613435565b611398565b610317611850565b6102d661050f36600461344e565b611cca565b610332610522366004613435565b611cd7565b610317610535366004613435565b611d05565b6102d6600b5481565b610317610551366004613435565b6122dc565b610317612362565b6003546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6006546103709073ffffffffffffffffffffffffffffffffffffffff1681565b6102d660095481565b60015473ffffffffffffffffffffffffffffffffffffffff16331461062d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f57726f6e672073656e6465722e0000000000000000000000000000000000000060448201526064015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000806000610681610697565b909250905061069082826127a3565b9250505090565b6005546007546000918291829182916106c99173ffffffffffffffffffffffffffffffffffffffff9081169116612862565b9150915081600014806106da575080155b156106ec575060009360019350915050565b90939092509050565b60055473ffffffffffffffffffffffffffffffffffffffff163314610776576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e6f7420617574686f72697a65640000000000000000000000000000000000006044820152606401610624565b60145461078390826129be565b60145550565b6003546005546002546000926107bc9273ffffffffffffffffffffffffffffffffffffffff918216929082169116612a37565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610842576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f57726f6e672073656e6465722e000000000000000000000000000000000000006044820152606401610624565b6040517f82b7b50000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f544f4b454e5f434f4e54524143540000000000000000000000000000000000006044820152600090819073ffffffffffffffffffffffffffffffffffffffff8416906382b7b500906064016040805180830381865afa1580156108de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109029190613485565b915091508061096d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152606401610624565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116919091179091556040517f82b7b50000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4d4154485f434f4e5452414354000000000000000000000000000000000000006044820152908416906382b7b500906064016040805180830381865afa158015610a35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a599190613485565b909250905080610ac5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152606401610624565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8481169190911782556040517f82b7b500000000000000000000000000000000000000000000000000000000008152602092810192909252601360248301527f45524332305f464545535f52454345495645520000000000000000000000000060448301528416906382b7b500906064016040805180830381865afa158015610b8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb19190613485565b909250905080610c1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152606401610624565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116919091179091556040517f82b7b50000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f554e49535741505f524f555445520000000000000000000000000000000000006044820152908416906382b7b500906064016040805180830381865afa158015610ce5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d099190613485565b909250905080610d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152606401610624565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff848116919091179091556040517f82b7b50000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f45524332305f434f4e54524143540000000000000000000000000000000000006044820152908416906382b7b500906064016040805180830381865afa158015610e3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e619190613485565b909250905080610ecd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152606401610624565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b6000806000610f23610697565b600480546040517f4f84245100000000000000000000000000000000000000000000000000000000815291820189905260248201839052604482018490526064808301899052608483015292945090925073ffffffffffffffffffffffffffffffffffffffff90911690634f8424519060a4015b602060405180830381865afa158015610fb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd891906134ba565b925050505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611064576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f57726f6e672073656e6465722e000000000000000000000000000000000000006044820152606401610624565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b600080611099610697565b9150915081600014806110aa575080155b156110b3575050565b600c54158015906110dc575042600f541015806110dc575060036110d9600f5442612b79565b11155b156110e5575050565b42600f55600e54600c541015611170576040805180820190915282815260208101828152600c805460018101825560009190915291517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7600290930292830155517fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c8909101556111df565b6040805180820190915282815260208101829052600d80548291600c9190600061119983613502565b91905055815481106111ad576111ad61353a565b60009182526020918290208351600290920201908155910151600190910155600e54600d54106111dd576000600d555b505b60008060005b600c5481101561126a5761121d600c82815481106112055761120561353a565b600091825260209091206002909102015484906129be565b9250611256600c82815481106112355761123561353a565b906000526020600020906002020160010154836129be90919063ffffffff16565b91508061126281613502565b9150506111e5565b50600c54611279908390612bfb565b600a55600c5461128a908290612bfb565b600b5550505050565b60006107bc600a54600b546127a390919063ffffffff16565b60008060006112b9610697565b600480546040517f4f84245100000000000000000000000000000000000000000000000000000000815291820189905260248201849052604482018390526064808301899052608483015292945090925073ffffffffffffffffffffffffffffffffffffffff90911690634f8424519060a401610f97565b600354600254600091829182916113619173ffffffffffffffffffffffffffffffffffffffff9182169116612c3d565b600254909150600090819061138c9073ffffffffffffffffffffffffffffffffffffffff1684612862565b90969095509350505050565b60055473ffffffffffffffffffffffffffffffffffffffff163314611419576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e6f7420617574686f72697a65640000000000000000000000000000000000006044820152606401610624565b611421610789565b15611488576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f506f6f6c20616c726561647920637265617465640000000000000000000000006044820152606401610624565b6002546040517f70a08231000000000000000000000000000000000000000000000000000000008152336004820152829173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156114f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151a91906134ba565b10156115a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4163636f756e7420646f6573206e6f74206861766520656e6f7567682045524360448201527f32300000000000000000000000000000000000000000000000000000000000006064820152608401610624565b6002546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526044810183905273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd906064016020604051808303816000875af1158015611625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116499190613569565b6116d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f556e61626c6520746f207472616e73666572207265717569726564204552433260448201527f30000000000000000000000000000000000000000000000000000000000000006064820152608401610624565b6116dd612dd9565b60006116f4600854836127a390919063ffffffff16565b6005546040517fe742806a0000000000000000000000000000000000000000000000000000000081523060048201526024810183905291925073ffffffffffffffffffffffffffffffffffffffff169063e742806a90604401600060405180830381600087803b15801561176757600080fd5b505af115801561177b573d6000803e3d6000fd5b5050600554600254604080517f4e6fd6c4000000000000000000000000000000000000000000000000000000008152905161184c955073ffffffffffffffffffffffffffffffffffffffff938416945092909116918391634e6fd6c49160048083019260209291908290030181865afa1580156117fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118209190613584565b60035473ffffffffffffffffffffffffffffffffffffffff168587611847426127106135a1565b612ecd565b5050565b601554600b541580159061186657506000600a54115b15611cc75760048054600b54600a546040517fc718eeb7000000000000000000000000000000000000000000000000000000008152938401919091526024830152604482018390526000918291829173ffffffffffffffffffffffffffffffffffffffff9091169063c718eeb7906064016080604051808303816000875af11580156118f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191a91906135b4565b50919450925090506002836002811115611936576119366135f7565b036119415750505050565b6001836002811115611955576119556135f7565b03611cc3576005546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156119c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ed91906134ba565b905060008183116119ff576000611a09565b611a098284613626565b90508015611a9c576005546040517fe742806a0000000000000000000000000000000000000000000000000000000081523060048201526024810183905273ffffffffffffffffffffffffffffffffffffffff9091169063e742806a90604401600060405180830381600087803b158015611a8357600080fd5b505af1158015611a97573d6000803e3d6000fd5b505050505b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611b0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2f91906134ba565b600554600254604080517f4e6fd6c40000000000000000000000000000000000000000000000000000000081529051939450611bf99373ffffffffffffffffffffffffffffffffffffffff93841693909216918391634e6fd6c49160048083019260209291908290030181865afa158015611bae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd29190613584565b60035473ffffffffffffffffffffffffffffffffffffffff16888a611847426127106135a1565b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611c68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8c91906134ba565b90506000611c9a83836130d3565b601554909150611caa90826130d3565b601555601154611cba90826129be565b60115550505050505b5050505b50565b6000806000610f23611331565b600c8181548110611ce757600080fd5b60009182526020909120600290910201805460019091015490915082565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f57726f6e672073656e6465722e000000000000000000000000000000000000006044820152606401610624565b601554811115611e18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f416d6f756e7420657263323020697320686967686572207468616e206176616960448201527f6c61626c650000000000000000000000000000000000000000000000000000006064820152608401610624565b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611e87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eab91906134ba565b6005546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015291925060009173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015611f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4391906134ba565b6002546003546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015260248101879052929350169063095ea7b3906044016020604051808303816000875af1158015611fc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe49190613569565b506000611ff384600954610f16565b6002546005546003549293506120389230928892869273ffffffffffffffffffffffffffffffffffffffff928316929182169116612033426127106135a1565b613115565b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156120a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cb91906134ba565b905060006120d985836130d3565b6015549091506120e990826130d3565b6015556012546120f990826129be565b6012556005546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561216b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218f91906134ba565b9050600061219d82876130d3565b600554604080517f4e6fd6c4000000000000000000000000000000000000000000000000000000008152905192935073ffffffffffffffffffffffffffffffffffffffff9091169163a9059cbb918391634e6fd6c4916004808201926020929091908290030181865afa158015612218573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223c9190613584565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156122a957600080fd5b505af11580156122bd573d6000803e3d6000fd5b50506013546122cf92509050826129be565b6013555050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461235d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f57726f6e672073656e6465722e000000000000000000000000000000000000006044820152606401610624565b600955565b6801158e460913d00000601454101561237757565b6005546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156123e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240a91906134ba565b6002546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015291925060009173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561247e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a291906134ba565b6005546003546014546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201526024810191909152929350169063095ea7b3906044016020604051808303816000875af1158015612523573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125479190613569565b5060006125586014546009546112ac565b60065460145460055460025460035494955061259c9473ffffffffffffffffffffffffffffffffffffffff94851694879381169281169116612033426127106135a1565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638e4fa5a26040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561260657600080fd5b505af115801561261a573d6000803e3d6000fd5b50506002546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000935073ffffffffffffffffffffffffffffffffffffffff90911691506370a0823190602401602060405180830381865afa15801561268f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b391906134ba565b6005546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015291925060009173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015612727573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274b91906134ba565b9050600061275986836130d3565b9050600061276784876130d3565b60155490915061277790826129be565b60155560145461278790836130d3565b60145560105461279790826129be565b60105550505050505050565b6000826000036127b557506000610fdd565b60006127c18385613639565b9050826127ce8583613650565b1461285b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60448201527f77000000000000000000000000000000000000000000000000000000000000006064820152608401610624565b9392505050565b60008060008390506000808273ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa1580156128b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128dc91906136a9565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691508673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612963573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129879190613584565b73ffffffffffffffffffffffffffffffffffffffff16036129ad578194508093506129b4565b8094508193505b5050509250929050565b6000806129cb83856135a1565b90508381101561285b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610624565b60008073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abf9190613584565b6040517fe6a4390500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301528581166024830152919091169063e6a4390590604401602060405180830381865afa158015612b35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b599190613584565b73ffffffffffffffffffffffffffffffffffffffff161415949350505050565b600081831115612be5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f46726f6d206d757374206265206265666f726520746f000000000000000000006044820152606401610624565b603c612bf18484613626565b61285b9190613650565b600061285b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613271565b6000808373ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612caf9190613584565b90508073ffffffffffffffffffffffffffffffffffffffff1663e6a439058573ffffffffffffffffffffffffffffffffffffffff1663ef8ef56f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3c9190613584565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff91821660048201529086166024820152604401602060405180830381865afa158015612dad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd19190613584565b949350505050565b612de1610789565b612ecb57600354600254600554612e149273ffffffffffffffffffffffffffffffffffffffff90811692811691166132c2565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9283169081179091556005546040517f3526c0bd00000000000000000000000000000000000000000000000000000000815260048101929092526001602483015290911690633526c0bd90604401600060405180830381600087803b158015612eb757600080fd5b505af1158015611cc3573d6000803e3d6000fd5b565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820185905288169063095ea7b3906044016020604051808303816000875af1158015612f42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f669190613569565b506040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820184905287169063095ea7b3906044016020604051808303816000875af1158015612fdc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130009190613569565b506040517fe8e3370000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff88811660048301528781166024830152604482018590526064820184905260006084830181905260a483015286811660c483015260e4820183905285169063e8e3370090610104016060604051808303816000875af11580156130a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130c791906136f9565b50505050505050505050565b600061285b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506133ab565b604080516002808252606082018352600092602083019080368337019050509050848160008151811061314a5761314a61353a565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505083816001815181106131985761319861353a565b73ffffffffffffffffffffffffffffffffffffffff92831660209182029290920101526040517f38ed1739000000000000000000000000000000000000000000000000000000008152908416906338ed173990613201908a908a9086908e908990600401613756565b6000604051808303816000875af1158015613220573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261326691908101906137e1565b505050505050505050565b600081836132ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062491906138bd565b5060006132b98486613650565b95945050505050565b60008373ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561330f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133339190613584565b6040517fc9c6539600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528481166024830152919091169063c9c65396906044016020604051808303816000875af1158015612dad573d6000803e3d6000fd5b600081848411156133e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062491906138bd565b5060006132b98486613626565b73ffffffffffffffffffffffffffffffffffffffff81168114611cc757600080fd5b60006020828403121561342a57600080fd5b813561285b816133f6565b60006020828403121561344757600080fd5b5035919050565b6000806040838503121561346157600080fd5b50508035926020909101359150565b8051801515811461348057600080fd5b919050565b6000806040838503121561349857600080fd5b82516134a3816133f6565b91506134b160208401613470565b90509250929050565b6000602082840312156134cc57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613533576135336134d3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561357b57600080fd5b61285b82613470565b60006020828403121561359657600080fd5b815161285b816133f6565b80820180821115610fdd57610fdd6134d3565b600080600080608085870312156135ca57600080fd5b8451600381106135d957600080fd5b60208601516040870151606090970151919890975090945092505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81810381811115610fdd57610fdd6134d3565b8082028115828204841417610fdd57610fdd6134d3565b600082613686577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80516dffffffffffffffffffffffffffff8116811461348057600080fd5b6000806000606084860312156136be57600080fd5b6136c78461368b565b92506136d56020850161368b565b9150604084015163ffffffff811681146136ee57600080fd5b809150509250925092565b60008060006060848603121561370e57600080fd5b8351925060208401519150604084015190509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156137b357845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101613781565b505073ffffffffffffffffffffffffffffffffffffffff969096166060850152505050608001529392505050565b600060208083850312156137f457600080fd5b825167ffffffffffffffff8082111561380c57600080fd5b818501915085601f83011261382057600080fd5b81518181111561383257613832613727565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561387557613875613727565b60405291825284820192508381018501918883111561389357600080fd5b938501935b828510156138b157845184529385019392850192613898565b98975050505050505050565b600060208083528351808285015260005b818110156138ea578581018301518582016040015282016138ce565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509291505056fea264697066735822122022109c587634049b96e310baa780c707f0e6daedfe3eb9b02d03ee77f05c586764736f6c63430008110033