Feature Tip: Add private address tag to any address under My Name Tag !
Latest 25 from a total of 836 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Approve | 24293542 | 14 days ago | IN | 0 ETH | 0.00009398 | ||||
| Approve | 24264162 | 18 days ago | IN | 0 ETH | 0.00000172 | ||||
| Transfer | 24264093 | 18 days ago | IN | 0 ETH | 0.00000513 | ||||
| Approve | 24163412 | 32 days ago | IN | 0 ETH | 0.00002858 | ||||
| Approve | 24163399 | 32 days ago | IN | 0 ETH | 0.0000225 | ||||
| Approve | 23999123 | 55 days ago | IN | 0 ETH | 0.00000338 | ||||
| Approve | 23819062 | 80 days ago | IN | 0 ETH | 0.00009859 | ||||
| Approve | 23763891 | 88 days ago | IN | 0 ETH | 0.00000903 | ||||
| Approve | 23763890 | 88 days ago | IN | 0 ETH | 0.00000903 | ||||
| Approve | 23730982 | 92 days ago | IN | 0 ETH | 0.00006052 | ||||
| Approve | 23719072 | 94 days ago | IN | 0 ETH | 0.00007985 | ||||
| Approve | 23677452 | 100 days ago | IN | 0 ETH | 0.00005171 | ||||
| Approve | 23677412 | 100 days ago | IN | 0 ETH | 0.00004877 | ||||
| Approve | 23677405 | 100 days ago | IN | 0 ETH | 0.00005078 | ||||
| Approve | 23677392 | 100 days ago | IN | 0 ETH | 0.00005557 | ||||
| Approve | 23677382 | 100 days ago | IN | 0 ETH | 0.00005418 | ||||
| Approve | 23677374 | 100 days ago | IN | 0 ETH | 0.00006115 | ||||
| Approve | 23664819 | 102 days ago | IN | 0 ETH | 0.00003504 | ||||
| Approve | 23664804 | 102 days ago | IN | 0 ETH | 0.00005507 | ||||
| Approve | 23664790 | 102 days ago | IN | 0 ETH | 0.0000367 | ||||
| Approve | 23664778 | 102 days ago | IN | 0 ETH | 0.00002866 | ||||
| Approve | 23664766 | 102 days ago | IN | 0 ETH | 0.00002121 | ||||
| Approve | 23664752 | 102 days ago | IN | 0 ETH | 0.00003029 | ||||
| Approve | 23664735 | 102 days ago | IN | 0 ETH | 0.00003035 | ||||
| Approve | 23664721 | 102 days ago | IN | 0 ETH | 0.00004458 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 24293542 | 14 days ago | 0.00015162 ETH | ||||
| Transfer | 24293542 | 14 days ago | 0.00015162 ETH | ||||
| Transfer | 24264163 | 18 days ago | 0.00011471 ETH | ||||
| Transfer | 24264163 | 18 days ago | 0.00011471 ETH | ||||
| Transfer | 24163710 | 32 days ago | 0.00046585 ETH | ||||
| Transfer | 24163710 | 32 days ago | 0.00046585 ETH | ||||
| Transfer | 24163701 | 32 days ago | 0.00053595 ETH | ||||
| Transfer | 24163701 | 32 days ago | 0.00053595 ETH | ||||
| Transfer | 24163695 | 32 days ago | 0.00053052 ETH | ||||
| Transfer | 24163695 | 32 days ago | 0.00053052 ETH | ||||
| Transfer | 24163691 | 32 days ago | 0.00049395 ETH | ||||
| Transfer | 24163691 | 32 days ago | 0.00049395 ETH | ||||
| Transfer | 24163685 | 32 days ago | 0.00054175 ETH | ||||
| Transfer | 24163685 | 32 days ago | 0.00054175 ETH | ||||
| Transfer | 24163680 | 32 days ago | 0.00049105 ETH | ||||
| Transfer | 24163680 | 32 days ago | 0.00049105 ETH | ||||
| Transfer | 24163675 | 32 days ago | 0.0005532 ETH | ||||
| Transfer | 24163675 | 32 days ago | 0.0005532 ETH | ||||
| Transfer | 24163669 | 32 days ago | 0.00067426 ETH | ||||
| Transfer | 24163669 | 32 days ago | 0.00067426 ETH | ||||
| Transfer | 24163663 | 32 days ago | 0.00060808 ETH | ||||
| Transfer | 24163663 | 32 days ago | 0.00060808 ETH | ||||
| Transfer | 24163653 | 32 days ago | 0.00052854 ETH | ||||
| Transfer | 24163653 | 32 days ago | 0.00052854 ETH | ||||
| Transfer | 24163648 | 32 days ago | 0.00056039 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Quantlink
Compiler Version
v0.8.20+commit.a1b79de6
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IWETH.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "./IMultisend.sol";
contract Quantlink is Context, IERC20, Ownable, IMultisend, IERC20Permit {
event Bought(address indexed buyer, uint256 amount);
event Sold(address indexed seller, uint256 amount);
using SafeMath for uint256;
// Constants
string private constant _name = "Quantlink";
string private constant _symbol = "QLK";
// Standard decimals
uint8 private constant _decimals = 18;
uint256 private constant totalTokens = 100000000000000000000000000;
// Mappings
mapping(address => uint256) private balances;
mapping(address => mapping(address => uint256)) private _allowances;
/** START OF EIP2612/EIP712 VARS */
using Counters for Counters.Counter;
mapping(address => Counters.Counter) private _nonces;
/* solhint-disable var-name-mixedcase */
// Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
// invalidate the cached domain separator if the chain id changes.
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
/** END OF EIP2612/EIP712 VARS */
struct mappingStructs {
bool _isExcludedFromFee;
uint32 _lastTxBlock;
uint32 botBlock;
bool isLPPair;
}
struct InitialData {
uint32 buyTax;
uint32 sellTax;
uint32 maxWalletDiv;
uint32 maxTxDiv;
uint32 maxSwapDivisor;
}
struct TaxWallet {
address wallet;
uint32 ratio;
}
mapping(address => mappingStructs) mappedAddresses;
// Arrays
TaxWallet[] private taxWallets;
// Global variables
// Block of 256 bits
address public dividendTracker;
uint32 private openBlock;
uint32 private sellTax;
uint32 private buyTax;
// Storage block closed
// Block of 256 bits
address private _controller;
uint32 private maxTxRatio;
uint32 private maxWalletRatio;
bool private tradingOpen;
bool private inSwap = false;
bool private swapEnabled = false;
bool disableAddToBlocklist = false;
// Storage block closed
// Block of 256 bits
address private devWallet;
uint32 ethSendThresholdDivisor = 1000;
uint32 private totalRatio;
uint32 private taxSwapDivisor;
// Block of 256 bits
uint64 lastTxBlockNumber;
IUniswapV2Router02 private uniswapV2Router;
modifier onlyERC20Controller() {
require(
_msgSender() == _controller,
"Caller is not the ERC20 controller."
);
_;
}
modifier onlyDev() {
require(_msgSender() == devWallet, "Only developer can set this.");
_;
}
constructor(
address controller,
address dev,
InitialData memory id,
TaxWallet[] memory wallets
) {
// Set up EIP712
bytes32 hashedName = keccak256(bytes(_name));
bytes32 hashedVersion = keccak256(bytes("1"));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(
typeHash,
hashedName,
hashedVersion
);
_CACHED_THIS = address(this);
_TYPE_HASH = typeHash;
// ERC20 controller
_controller = payable(controller);
devWallet = dev;
buyTax = id.buyTax;
sellTax = id.sellTax;
taxSwapDivisor = id.maxSwapDivisor;
maxTxRatio = id.maxTxDiv;
maxWalletRatio = id.maxWalletDiv;
mappedAddresses[_msgSender()] = mappingStructs({
_isExcludedFromFee: true,
_lastTxBlock: 0,
botBlock: 0,
isLPPair: false
});
mappedAddresses[address(this)] = mappingStructs({
_isExcludedFromFee: true,
_lastTxBlock: 0,
botBlock: 0,
isLPPair: false
});
// For instrumentation, we have to make this copy ourselves
uint32 initialRatio = 0;
for (uint256 i = 0; i < wallets.length; i++) {
mappedAddresses[wallets[i].wallet] = mappingStructs({
_isExcludedFromFee: true,
_lastTxBlock: 0,
botBlock: 0,
isLPPair: false
});
initialRatio += wallets[i].ratio;
// Copy across now as the "classic" non-IR compiler can't do this copy
taxWallets.push(TaxWallet(wallets[i].wallet, wallets[i].ratio));
}
totalRatio = initialRatio;
addTokens(_msgSender(), totalTokens);
emit Transfer(address(0), _msgSender(), totalTokens);
}
function name() public pure returns (string memory) {
return _name;
}
function symbol() public pure returns (string memory) {
return _symbol;
}
function decimals() public pure returns (uint8) {
return _decimals;
}
function totalSupply() public pure override returns (uint256) {
return totalTokens;
}
function balanceOf(address account) public view override returns (uint256) {
return balances[account];
}
function transfer(
address recipient,
uint256 amount
) public override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(
address owner,
address spender
) public view override returns (uint256) {
return _allowances[owner][spender];
}
function approve(
address spender,
uint256 amount
) public override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public override returns (bool) {
_transfer(sender, recipient, amount);
_approve(
sender,
_msgSender(),
_allowances[sender][_msgSender()].sub(
amount,
"ERC20: transfer amount exceeds allowance"
)
);
return true;
}
/// @notice Starts trading. Only callable by owner.
function openTrading() public onlyOwner {
require(!tradingOpen, "Can't open trading that's already open.");
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(
0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
);
uniswapV2Router = _uniswapV2Router;
_approve(address(this), address(uniswapV2Router), totalTokens);
address uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
.createPair(address(this), _uniswapV2Router.WETH());
uniswapV2Router.addLiquidityETH{value: address(this).balance}(
address(this),
balanceOf(address(this)),
0,
0,
owner(),
block.timestamp
);
swapEnabled = true;
tradingOpen = true;
// Add the pairs to the list
mappedAddresses[uniswapV2Pair] = mappingStructs({
_isExcludedFromFee: false,
_lastTxBlock: 0,
botBlock: 0,
isLPPair: true
});
}
function _approve(address owner, address spender, uint256 amount) private {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _transfer(address from, address to, uint256 amount) private {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
uint32 _taxAmt;
bool isSell = false;
if (
from != owner() &&
to != owner() &&
from != address(this) &&
!mappedAddresses[to]._isExcludedFromFee &&
!mappedAddresses[from]._isExcludedFromFee
) {
// Max tx check
require(amount <= totalTokens / maxTxRatio, "Max tx exceeded.");
// Buys
if (
(mappedAddresses[from].isLPPair) &&
to != address(uniswapV2Router)
) {
_taxAmt = buyTax;
// Max wallet check
require(
balanceOf(to) + amount <= totalTokens / maxWalletRatio,
"Max wallet will be exceeded."
);
} else if (
(mappedAddresses[to].isLPPair) &&
from != address(uniswapV2Router)
) {
isSell = true;
// Sells
// Don't check max wallet or you fuck up LP
// Check if last tx occurred this block - prevents sandwich attacks
// Sells
_taxAmt = sellTax;
} else {
// No code to change transfer tax
_taxAmt = 0;
// Still check max wallet
require(
balanceOf(to) + amount <= totalTokens / maxWalletRatio,
"Max wallet will be exceeded."
);
}
} else {
// Only make it here if it's from or to owner or from contract address.
_taxAmt = 0;
}
_tokenTransfer(from, to, amount, _taxAmt, isSell);
}
function doTaxes(uint256 tokenAmount) private {
if (lastTxBlockNumber != block.number) {
// Tax not sold this block yet
lastTxBlockNumber = uint64(block.number);
} else {
// Tax has been sold this block already, don't bother doing it again
return;
}
// Reentrancy guard/stop infinite tax sells mainly
inSwap = true;
if (
_allowances[address(this)][address(uniswapV2Router)] < tokenAmount
) {
// Our approvals run low, redo it
_approve(address(this), address(uniswapV2Router), totalTokens);
}
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = uniswapV2Router.WETH();
// Swap direct to WETH and let router unwrap
uniswapV2Router.swapExactTokensForETH(
tokenAmount,
0,
path,
address(this),
block.timestamp
);
sendETHToFee(address(this).balance);
inSwap = false;
}
function sendETHToFee(uint256 amount) private {
// This fixes gas reprice issues - reentrancy is not an issue as the fee wallets are trusted.
for (uint256 i = 0; i < taxWallets.length; i++) {
Address.sendValue(
payable(taxWallets[i].wallet),
(amount * taxWallets[i].ratio) / totalRatio
);
}
}
receive() external payable {}
// Underlying transfer functions go here
function _tokenTransfer(
address sender,
address recipient,
uint256 amount,
uint32 _taxAmt,
bool isSell
) private {
// Do taxes
uint256 receiverAmount = amount;
if (_taxAmt > 0) {
uint256 taxAmount = calculateTaxesFee(amount, _taxAmt);
receiverAmount = amount - taxAmount;
addTokens(address(this), taxAmount);
emit Transfer(sender, address(this), taxAmount);
}
// Only sell tokens on a sell, as we can't interfere on a buy
if (isSell) {
emit Sold(sender, amount);
uint256 bal = balanceOf(address(this));
// Swap a max of totalTokens/taxSwapDivisor, or the current balance
if (bal > 0) {
if (bal > totalTokens / taxSwapDivisor) {
doTaxes(totalTokens / taxSwapDivisor);
} else {
doTaxes(bal);
}
}
} else {
emit Bought(recipient, amount);
}
// Actually do token balances
subtractTokens(sender, amount);
addTokens(recipient, receiverAmount);
// Emit transfer, because the specs say to
emit Transfer(sender, recipient, receiverAmount);
}
/// @dev Does holder count maths
function subtractTokens(address account, uint256 amount) private {
balances[account] = balances[account] - amount;
}
function addTokens(address account, uint256 amount) private {
balances[account] = balances[account] + amount;
}
function calculateTaxesFee(
uint256 _amount,
uint32 _taxAmt
) private pure returns (uint256 tax) {
tax = (_amount * _taxAmt) / 100000;
}
/// @notice Sets an ETH send divisor. Only callable by owner.
/// @param newDivisor the new divisor to set.
function setEthSendDivisor(uint32 newDivisor) public onlyOwner {
ethSendThresholdDivisor = newDivisor;
}
function addTaxWallet(TaxWallet calldata wall) external onlyOwner {
taxWallets.push(wall);
mappedAddresses[wall.wallet]._isExcludedFromFee = true;
// Recalculate the ratio, as we're adding, just add that ratio on
totalRatio += wall.ratio;
}
function removeTaxWallet(address wallet) external onlyOwner {
mappedAddresses[wallet]._isExcludedFromFee = false;
bool found = false;
for (uint256 i = 0; i < taxWallets.length; i++) {
if (taxWallets[i].wallet == wallet) {
// Fill this with the end
taxWallets[i] = taxWallets[taxWallets.length - 1];
taxWallets.pop();
found = true;
}
}
require(found, "Not in tax list.");
// Have to recalculate the entire ratio as we dunno what was removed
uint32 initialRatio = 0;
for (uint256 i = 0; i < taxWallets.length; i++) {
initialRatio += taxWallets[i].ratio;
}
totalRatio = initialRatio;
}
/// @notice Changes ERC20 controller address. Only callable by dev.
/// @param newWallet the address to set as the controller.
function changeERC20Controller(address newWallet) external onlyDev {
_controller = payable(newWallet);
}
/// @notice Allows new pairs to be added to the "watcher" code
/// @param pair the address to add as the liquidity pair
function addNewLPPair(address pair) external onlyOwner {
mappedAddresses[pair].isLPPair = true;
}
/// @notice Irreversibly disables blocklist additions after launch has settled.
/// @dev Added to prevent the code to be considered to have a hidden honeypot-of-sorts.
function disableBlocklistAdd() external onlyOwner {
disableAddToBlocklist = true;
}
/// @notice Sets an account exclusion or inclusion from fees.
/// @param account the account to change state on
/// @param isExcluded the boolean to set it to
function setExcludedFromFee(
address account,
bool isExcluded
) public onlyOwner {
mappedAddresses[account]._isExcludedFromFee = isExcluded;
}
/// @notice Sets the sell tax, out of 100000. Only callable by owner. Max of 20000.
/// @param amount the tax out of 100000.
function setSellTax(uint32 amount) external onlyOwner {
require(amount <= 20000, "Maximum sell tax of 10%.");
sellTax = amount;
}
function setBuyTax(uint32 amount) external onlyOwner {
require(amount <= 20000, "Maximum buy tax of 10%.");
buyTax = amount;
}
function setSwapDivisor(uint32 amount) external onlyOwner {
require(amount <= 10000, "No lower than .01%.");
taxSwapDivisor = amount;
}
function setMaxTxRatio(uint32 ratio) external onlyOwner {
require(ratio < 10000, "No lower than .01%");
maxTxRatio = ratio;
}
function setMaxWalletRatio(uint32 ratio) external onlyOwner {
require(ratio < 1000, "No lower than .1%");
maxWalletRatio = ratio;
}
/// @notice Returns if an account is excluded from fees.
/// @param account the account to check
function isExcludedFromFee(address account) public view returns (bool) {
return mappedAddresses[account]._isExcludedFromFee;
}
// IMultisend implementation
/// @notice Allows a multi-send to save on gas
/// @param addr array of addresses to send to
/// @param val array of values to go with addresses
function multisend(
address[] calldata addr,
uint256[] calldata val
) external override {
require(addr.length == val.length, "Muyltisend: Length mismatch.");
for (uint i = 0; i < addr.length; i++) {
// There's gas savings to be had to do this - we bypass top-level
subtractTokens(_msgSender(), val[i]);
addTokens(addr[i], val[i]);
// Emit transfers, because the specs say to
emit Transfer(_msgSender(), addr[i], val[i]);
}
}
/// @notice Allows a multi-send to save on gas on behalf of someone - need approvals
/// @param sender sender to use - must be approved to spend
/// @param addrRecipients array of addresses to send to
/// @param vals array of values to go with addresses
function multisendFrom(
address sender,
address[] calldata addrRecipients,
uint256[] calldata vals
) external override {
require(
addrRecipients.length == vals.length,
"Multisend: Length mismatch."
);
uint256 totalSpend = 0;
for (uint i = 0; i < addrRecipients.length; i++) {
// More gas savings as we bypass top-level checks - we have to do approval subs tho
subtractTokens(_msgSender(), vals[i]);
addTokens(addrRecipients[i], vals[i]);
// Emit transfers, because the specs say to
emit Transfer(_msgSender(), addrRecipients[i], vals[i]);
totalSpend += vals[i];
}
// One approve at the end
_approve(
sender,
_msgSender(),
_allowances[sender][_msgSender()].sub(
totalSpend,
"Multisend: Not enough allowance."
)
);
}
/** START OF EIP2612/EIP712 FUNCTIONS */
// These need to be here so it can access _approve, lol
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
if (
address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID
) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return
_buildDomainSeparator(
_TYPE_HASH,
_HASHED_NAME,
_HASHED_VERSION
);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return
keccak256(
abi.encode(
typeHash,
nameHash,
versionHash,
block.chainid,
address(this)
)
);
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(
bytes32 structHash
) internal view virtual returns (bytes32) {
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
// solhint-disable-next-line var-name-mixedcase
bytes32 private constant _PERMIT_TYPEHASH =
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
);
/**
* @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
* However, to ensure consistency with the upgradeable transpiler, we will continue
* to reserve a slot.
* @custom:oz-renamed-from _PERMIT_TYPEHASH
*/
// solhint-disable-next-line var-name-mixedcase
bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;
/**
* @dev See {IERC20Permit-permit}.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override {
require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
bytes32 structHash = keccak256(
abi.encode(
_PERMIT_TYPEHASH,
owner,
spender,
value,
_useNonce(owner),
deadline
)
);
bytes32 hash = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(hash, v, r, s);
require(signer == owner, "ERC20Permit: invalid signature");
_approve(owner, spender, value);
}
/**
* @dev See {IERC20Permit-nonces}.
*/
function nonces(
address owner
) public view virtual override returns (uint256) {
return _nonces[owner].current();
}
/**
* @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view override returns (bytes32) {
return _domainSeparatorV4();
}
/**
* @dev "Consume a nonce": return the current value and increment.
*
* _Available since v4.1._
*/
function _useNonce(
address owner
) internal virtual returns (uint256 current) {
Counters.Counter storage nonce = _nonces[owner];
current = nonce.current();
nonce.increment();
}
/** END OF EIP2612/EIP712 FUNCTIONS */
/// @dev debug code to confirm we can't add this addr to bot list
function getLPPair() public view returns (address wethAddr) {
wethAddr = IUniswapV2Factory(uniswapV2Router.factory()).getPair(
address(this),
uniswapV2Router.WETH()
);
}
function getTaxWallets() public view returns (TaxWallet[] memory) {
return taxWallets;
}
/// @dev Debug code for checking ERC20Controller set/get
function getERC20Controller() public view returns (address) {
return _controller;
}
/// @dev Debug code for checking sell tax set/get
function getSellTax() public view returns (uint32) {
return sellTax;
}
function getBuyTax() public view returns (uint32) {
return buyTax;
}
// Old tokenclawback
// Sends an approve to the erc20Contract
function proxiedApprove(
address erc20Contract,
address spender,
uint256 amount
) external onlyERC20Controller returns (bool) {
IERC20 theContract = IERC20(erc20Contract);
return theContract.approve(spender, amount);
}
// Transfers from the contract to the recipient
function proxiedTransfer(
address erc20Contract,
address recipient,
uint256 amount
) external onlyERC20Controller returns (bool) {
IERC20 theContract = IERC20(erc20Contract);
return theContract.transfer(recipient, amount);
}
// Sells all tokens of erc20Contract.
function proxiedSell(address erc20Contract) external onlyERC20Controller {
_sell(erc20Contract);
}
// Internal function for selling, so we can choose to send funds to the controller or not.
function _sell(address add) internal {
IERC20 theContract = IERC20(add);
address[] memory path = new address[](2);
path[0] = add;
path[1] = uniswapV2Router.WETH();
uint256 tokenAmount = theContract.balanceOf(address(this));
theContract.approve(address(uniswapV2Router), tokenAmount);
uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0,
path,
address(this),
block.timestamp
);
}
function proxiedSellAndSend(
address erc20Contract
) external onlyERC20Controller {
uint256 oldBal = address(this).balance;
_sell(erc20Contract);
uint256 amt = address(this).balance - oldBal;
// We implicitly trust the ERC20 controller. Send it the ETH we got from the sell.
Address.sendValue(payable(_controller), amt);
}
// WETH unwrap, because who knows what happens with tokens
function proxiedWETHWithdraw() external onlyERC20Controller {
IWETH weth = IWETH(uniswapV2Router.WETH());
IERC20 wethErc = IERC20(uniswapV2Router.WETH());
uint256 bal = wethErc.balanceOf(address(this));
weth.withdraw(bal);
}
function Quantlink_info() public pure returns(string memory) {
return "Quantlink";
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; // EIP-2612 is Final as of 2022-11-01. This file is deprecated. import "./IERC20Permit.sol";
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)
pragma solidity ^0.8.0;
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
*/
library Counters {
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV // Deprecated in v4.8
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32")
mstore(0x1c, hash)
message := keccak256(0x00, 0x3c)
}
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
data := keccak256(ptr, 0x42)
}
}
/**
* @dev Returns an Ethereum Signed Data with intended validator, created from a
* `validator` and `data` according to the version 0 of EIP-191.
*
* See {recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x00", validator, data));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// 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 (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @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) {
return a + b;
}
/**
* @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 a - b;
}
/**
* @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) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. 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 mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting 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) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. 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 mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}pragma solidity >=0.5.0;
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}pragma solidity >=0.5.0;
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}pragma solidity >=0.5.0;
interface IWETH {
function deposit() external payable;
function transfer(address to, uint value) external returns (bool);
function withdraw(uint) external;
}/**
* A Multisend interface
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.8.15;
interface IMultisend {
/// @notice Allows a multi-send to save on gas
/// @param addr array of addresses to send to
/// @param val array of values to go with addresses
function multisend(address[] calldata addr, uint256[] calldata val) external;
/// @notice Allows a multi-send to save on gas on behalf of someone - need approvals
/// @param sender sender to use - must be approved to spend
/// @param addrRecipients array of addresses to send to
/// @param vals array of values to go with addresses
function multisendFrom(address sender, address[] calldata addrRecipients, uint256[] calldata vals) external;
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": false,
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"controller","type":"address"},{"internalType":"address","name":"dev","type":"address"},{"components":[{"internalType":"uint32","name":"buyTax","type":"uint32"},{"internalType":"uint32","name":"sellTax","type":"uint32"},{"internalType":"uint32","name":"maxWalletDiv","type":"uint32"},{"internalType":"uint32","name":"maxTxDiv","type":"uint32"},{"internalType":"uint32","name":"maxSwapDivisor","type":"uint32"}],"internalType":"struct Quantlink.InitialData","name":"id","type":"tuple"},{"components":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint32","name":"ratio","type":"uint32"}],"internalType":"struct Quantlink.TaxWallet[]","name":"wallets","type":"tuple[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Bought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Sold","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Quantlink_info","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"addNewLPPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint32","name":"ratio","type":"uint32"}],"internalType":"struct Quantlink.TaxWallet","name":"wall","type":"tuple"}],"name":"addTaxWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newWallet","type":"address"}],"name":"changeERC20Controller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"disableBlocklistAdd","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dividendTracker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBuyTax","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getERC20Controller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLPPair","outputs":[{"internalType":"address","name":"wethAddr","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSellTax","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTaxWallets","outputs":[{"components":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint32","name":"ratio","type":"uint32"}],"internalType":"struct Quantlink.TaxWallet[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcludedFromFee","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addr","type":"address[]"},{"internalType":"uint256[]","name":"val","type":"uint256[]"}],"name":"multisend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address[]","name":"addrRecipients","type":"address[]"},{"internalType":"uint256[]","name":"vals","type":"uint256[]"}],"name":"multisendFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"erc20Contract","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"proxiedApprove","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"erc20Contract","type":"address"}],"name":"proxiedSell","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"erc20Contract","type":"address"}],"name":"proxiedSellAndSend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"erc20Contract","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"proxiedTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiedWETHWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"removeTaxWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"amount","type":"uint32"}],"name":"setBuyTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newDivisor","type":"uint32"}],"name":"setEthSendDivisor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"setExcludedFromFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"ratio","type":"uint32"}],"name":"setMaxTxRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"ratio","type":"uint32"}],"name":"setMaxWalletRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"amount","type":"uint32"}],"name":"setSellTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"amount","type":"uint32"}],"name":"setSwapDivisor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
610140604052600780546001600160e81b031690556008805463ffffffff60a01b1916607d60a31b17905534801562000036575f80fd5b506040516200405b3803806200405b833981016040819052620000599162000839565b620000643362000622565b60408051808201825260098152685175616e746c696e6b60b81b602091820152815180830190925260018252603160f81b9101527f92aee2abf01cdf63f53f55973d65eb1705b24bbfd25c6c0ca9e3d72d868eec5660e08190527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66101008190524660a0527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620001598184846040805160208101859052908101839052606081018290524660808201523060a08201525f9060c0016040516020818303038152906040528051906020012090509392505050565b60808181525050306001600160a01b031660c0816001600160a01b0316815250508061012081815250508660075f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508560085f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550845f01516006601c6101000a81548163ffffffff021916908363ffffffff1602179055508460200151600660186101000a81548163ffffffff021916908363ffffffff16021790555084608001516008601c6101000a81548163ffffffff021916908363ffffffff1602179055508460600151600760146101000a81548163ffffffff021916908363ffffffff1602179055508460400151600760186101000a81548163ffffffff021916908363ffffffff16021790555060405180608001604052806001151581526020015f63ffffffff1681526020015f63ffffffff1681526020015f151581525060045f620002cc6200061e60201b60201c565b6001600160a01b0316815260208082019290925260409081015f9081208451815486860151878601516060988901511515690100000000000000000090810260ff60481b1963ffffffff93841665010000000000908102821664ffffffffff60281b1996861661010090810264ffffffff00199a15158b1664ffffffffff199a8b161717881691909117939093179098558951608081018b5260018152808c018a8152818c018b81529d82018b8152308c526004909d529a8a20905181549b519d519c5115159094029b8516909802169a90921690910290151590931695909116949094171790921693909317919091179055805b8551811015620005915760408051608081018252600181525f6020820181905291810182905260608101829052875190916004918990859081106200040a576200040a6200091b565b602090810291909101810151516001600160a01b031682528181019290925260409081015f20835181549385015192850151606090950151151569010000000000000000000260ff60481b1963ffffffff96871665010000000000021664ffffffffff60281b19969094166101000264ffffffff00199215159290921664ffffffffff19909516949094171793909316171790558551869082908110620004b557620004b56200091b565b60200260200101516020015182620004ce919062000943565b915060056040518060400160405280888481518110620004f257620004f26200091b565b60200260200101515f01516001600160a01b031681526020018884815181106200052057620005206200091b565b60209081029190910181015181015163ffffffff90811690925283546001810185555f948552938190208351940180549390910151909116600160a01b026001600160c01b03199092166001600160a01b03909316929092171790558062000588816200096a565b915050620003c1565b506008805463ffffffff60c01b1916600160c01b63ffffffff841602179055620005ce620005bc3390565b6a52b7d2dcc80cd2e400000062000671565b6040516a52b7d2dcc80cd2e4000000815233905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050505050505050620009a1565b3390565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0382165f908152600160205260409020546200069690829062000985565b6001600160a01b039092165f9081526001602052604090209190915550565b80516001600160a01b0381168114620006cc575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b03811182821017156200070a576200070a620006d1565b60405290565b60405160a081016001600160401b03811182821017156200070a576200070a620006d1565b604051601f8201601f191681016001600160401b0381118282101715620007605762000760620006d1565b604052919050565b805163ffffffff81168114620006cc575f80fd5b5f82601f8301126200078c575f80fd5b815160206001600160401b03821115620007aa57620007aa620006d1565b620007ba818360051b0162000735565b82815260069290921b84018101918181019086841115620007d9575f80fd5b8286015b848110156200082e5760408189031215620007f7575f8081fd5b62000801620006e5565b6200080c82620006b5565b81526200081b85830162000768565b81860152835291830191604001620007dd565b509695505050505050565b5f805f808486036101008112156200084f575f80fd5b6200085a86620006b5565b94506200086a60208701620006b5565b935060a0603f19820112156200087e575f80fd5b506200088962000710565b620008976040870162000768565b8152620008a76060870162000768565b6020820152620008ba6080870162000768565b6040820152620008cd60a0870162000768565b6060820152620008e060c0870162000768565b608082015260e08601519092506001600160401b0381111562000901575f80fd5b6200090f878288016200077c565b91505092959194509250565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b63ffffffff8181168382160190808211156200096357620009636200092f565b5092915050565b5f600182016200097e576200097e6200092f565b5060010190565b808201808211156200099b576200099b6200092f565b92915050565b60805160a05160c05160e0516101005161012051613672620009e95f395f61235101525f6123a001525f61237b01525f6122d401525f6122fe01525f61232801526136725ff3fe608060405260043610610257575f3560e01c8063715018a61161013f578063b0bc85de116100b3578063db932ae211610078578063db932ae214610713578063dd62ed3e14610732578063e0195f0714610776578063e9cb414f14610795578063f2fde38b146107b4578063fb61e998146107d3575f80fd5b8063b0bc85de14610681578063bb1789d6146106a2578063c8ce7be1146106c1578063c9567bf9146106e0578063d505accf146106f4575f80fd5b806386f3f3cb1161010457806386f3f3cb146105d457806388a65f46146105e85780638da5cb5b146105fc57806395d89b4114610618578063a9059cbb14610643578063aad41a4114610662575f80fd5b8063715018a61461056357806373ae740e1461057757806373ec8c17146102625780637a52da0e146105965780637ecebe00146105b5575f80fd5b8063313ce567116101d65780634ff99fcf1161019b5780634ff99fcf146104875780635342acb4146104a6578063571cbe0a146104dd5780636612e66f146104fc57806370a082311461051b57806370bfdd9d1461054f575f80fd5b8063313ce567146103fb578063333429471461041657806333a17282146104355780633644e51514610454578063473071ce14610468575f80fd5b806320d5bf371161021c57806320d5bf371461033b578063232b10441461036c57806323b872dd1461038b578063252d723a146103aa5780632c1f5216146103dc575f80fd5b806306fdde0314610262578063095ea7b3146102a55780630ecf68e0146102d457806317f5a80b146102f557806318160ddd14610314575f80fd5b3661025e57005b5f80fd5b34801561026d575f80fd5b506040805180820190915260098152685175616e746c696e6b60b81b60208201525b60405161029c9190612f31565b60405180910390f35b3480156102b0575f80fd5b506102c46102bf366004612f90565b6107f4565b604051901515815260200161029c565b3480156102df575f80fd5b506102f36102ee366004612fcb565b61080a565b005b348015610300575f80fd5b506102f361030f366004612fcb565b610888565b34801561031f575f80fd5b506a52b7d2dcc80cd2e40000005b60405190815260200161029c565b348015610346575f80fd5b506007546001600160a01b03165b6040516001600160a01b03909116815260200161029c565b348015610377575f80fd5b506102f3610386366004612fcb565b610902565b348015610396575f80fd5b506102c46103a5366004612fe6565b61097d565b3480156103b5575f80fd5b50600654600160e01b900463ffffffff165b60405163ffffffff909116815260200161029c565b3480156103e7575f80fd5b50600654610354906001600160a01b031681565b348015610406575f80fd5b506040516012815260200161029c565b348015610421575f80fd5b506102f3610430366004612fcb565b6109f4565b348015610440575f80fd5b506102c461044f366004612fe6565b610a22565b34801561045f575f80fd5b5061032d610ad4565b348015610473575f80fd5b506102f3610482366004613024565b610ae2565b348015610492575f80fd5b506102f36104a136600461303f565b610b21565b3480156104b1575f80fd5b506102c46104c0366004613024565b6001600160a01b03165f9081526004602052604090205460ff1690565b3480156104e8575f80fd5b506102c46104f7366004612fe6565b610bf4565b348015610507575f80fd5b506102f361051636600461305c565b610c61565b348015610526575f80fd5b5061032d610535366004613024565b6001600160a01b03165f9081526001602052604090205490565b34801561055a575f80fd5b506102f3610c93565b34801561056e575f80fd5b506102f3610cb2565b348015610582575f80fd5b506102f36105913660046130db565b610cc5565b3480156105a1575f80fd5b506102f36105b0366004613024565b610e95565b3480156105c0575f80fd5b5061032d6105cf366004613024565b610efb565b3480156105df575f80fd5b50610354610f18565b3480156105f3575f80fd5b506102f361107f565b348015610607575f80fd5b505f546001600160a01b0316610354565b348015610623575f80fd5b50604080518082019091526003815262514c4b60e81b602082015261028f565b34801561064e575f80fd5b506102c461065d366004612f90565b611268565b34801561066d575f80fd5b506102f361067c366004613158565b611274565b34801561068c575f80fd5b50600654600160c01b900463ffffffff166103c7565b3480156106ad575f80fd5b506102f36106bc366004612fcb565b6113a7565b3480156106cc575f80fd5b506102f36106db366004613024565b61142d565b3480156106eb575f80fd5b506102f3611628565b3480156106ff575f80fd5b506102f361070e3660046131bf565b6119d4565b34801561071e575f80fd5b506102f361072d366004612fcb565b611b35565b34801561073d575f80fd5b5061032d61074c366004613230565b6001600160a01b039182165f90815260026020908152604080832093909416825291909152205490565b348015610781575f80fd5b506102f3610790366004613024565b611bba565b3480156107a0575f80fd5b506102f36107af366004613024565b611c3f565b3480156107bf575f80fd5b506102f36107ce366004613024565b611c70565b3480156107de575f80fd5b506107e7611ce6565b60405161029c919061325c565b5f610800338484611d5d565b5060015b92915050565b610812611e80565b6103e88163ffffffff16106108625760405162461bcd60e51b81526020600482015260116024820152704e6f206c6f776572207468616e202e312560781b60448201526064015b60405180910390fd5b6007805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b610890611e80565b6127108163ffffffff16106108dc5760405162461bcd60e51b81526020600482015260126024820152714e6f206c6f776572207468616e202e30312560701b6044820152606401610859565b6007805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b61090a611e80565b6127108163ffffffff1611156109585760405162461bcd60e51b81526020600482015260136024820152722737903637bbb2b9103a3430b710171818929760691b6044820152606401610859565b6008805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b5f610989848484611ed9565b6109ea84336109e5856040518060600160405280602881526020016135f5602891396001600160a01b038a165f90815260026020526040812090335b6001600160a01b0316815260208101919091526040015f2054919061229d565b611d5d565b5060019392505050565b6109fc611e80565b6008805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b6007545f906001600160a01b0316336001600160a01b031614610a575760405162461bcd60e51b8152600401610859906132b9565b60405163095ea7b360e01b81526001600160a01b0384811660048301526024820184905285919082169063095ea7b3906044015b6020604051808303815f875af1158015610aa7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610acb91906132fc565b95945050505050565b5f610add6122c8565b905090565b6007546001600160a01b0316336001600160a01b031614610b155760405162461bcd60e51b8152600401610859906132b9565b610b1e816123ee565b50565b610b29611e80565b600580546001810182555f9190915281907f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db001610b668282613317565b506001905060045f610b7b6020850185613024565b6001600160a01b0316815260208082019290925260409081015f20805460ff191693151593909317909255610bb4918301908301612fcb565b60088054601890610bd3908490600160c01b900463ffffffff16613387565b92506101000a81548163ffffffff021916908363ffffffff16021790555050565b6007545f906001600160a01b0316336001600160a01b031614610c295760405162461bcd60e51b8152600401610859906132b9565b60405163a9059cbb60e01b81526001600160a01b0384811660048301526024820184905285919082169063a9059cbb90604401610a8b565b610c69611e80565b6001600160a01b03919091165f908152600460205260409020805460ff1916911515919091179055565b610c9b611e80565b600780546001600160f81b0316600160f81b179055565b610cba611e80565b610cc35f612632565b565b828114610d145760405162461bcd60e51b815260206004820152601b60248201527f4d756c746973656e643a204c656e677468206d69736d617463682e00000000006044820152606401610859565b5f805b84811015610e3057610d4133858584818110610d3557610d356133ab565b90506020020135612681565b610d89868683818110610d5657610d566133ab565b9050602002016020810190610d6b9190613024565b858584818110610d7d57610d7d6133ab565b905060200201356126c3565b858582818110610d9b57610d9b6133ab565b9050602002016020810190610db09190613024565b6001600160a01b0316335f8051602061361d833981519152868685818110610dda57610dda6133ab565b90506020020135604051610df091815260200190565b60405180910390a3838382818110610e0a57610e0a6133ab565b9050602002013582610e1c91906133bf565b915080610e28816133d2565b915050610d17565b50610e8d863360408051808201825260208082527f4d756c746973656e643a204e6f7420656e6f75676820616c6c6f77616e63652e818301526001600160a01b038c165f90815260029091529182206109e59287929190336109c5565b505050505050565b6007546001600160a01b0316336001600160a01b031614610ec85760405162461bcd60e51b8152600401610859906132b9565b47610ed2826123ee565b5f610edd82476133ea565b600754909150610ef6906001600160a01b0316826126e6565b505050565b6001600160a01b0381165f90815260036020526040812054610804565b5f600960089054906101000a90046001600160a01b03166001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f6a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8e91906133fd565b6001600160a01b031663e6a4390530600960089054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fee573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101291906133fd565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa15801561105b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610add91906133fd565b6007546001600160a01b0316336001600160a01b0316146110b25760405162461bcd60e51b8152600401610859906132b9565b5f600960089054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015611104573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112891906133fd565b90505f600960089054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa15801561117c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111a091906133fd565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156111e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061120b9190613418565b604051632e1a7d4d60e01b8152600481018290529091506001600160a01b03841690632e1a7d4d906024015f604051808303815f87803b15801561124d575f80fd5b505af115801561125f573d5f803e3d5ffd5b50505050505050565b5f610800338484611ed9565b8281146112c35760405162461bcd60e51b815260206004820152601c60248201527f4d75796c746973656e643a204c656e677468206d69736d617463682e000000006044820152606401610859565b5f5b838110156113a0576112e333848484818110610d3557610d356133ab565b61131f8585838181106112f8576112f86133ab565b905060200201602081019061130d9190613024565b848484818110610d7d57610d7d6133ab565b848482818110611331576113316133ab565b90506020020160208101906113469190613024565b6001600160a01b0316335f8051602061361d833981519152858585818110611370576113706133ab565b9050602002013560405161138691815260200190565b60405180910390a380611398816133d2565b9150506112c5565b5050505050565b6113af611e80565b614e208163ffffffff1611156114075760405162461bcd60e51b815260206004820152601860248201527f4d6178696d756d2073656c6c20746178206f66203130252e00000000000000006044820152606401610859565b6006805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b611435611e80565b6001600160a01b0381165f908152600460205260408120805460ff19169055805b60055481101561156857826001600160a01b03166005828154811061147d5761147d6133ab565b5f918252602090912001546001600160a01b03160361155657600580546114a6906001906133ea565b815481106114b6576114b66133ab565b905f5260205f2001600582815481106114d1576114d16133ab565b5f91825260209091208254910180546001600160a01b039092166001600160a01b031983168117825592546001600160c01b0319909216909217600160a01b9182900463ffffffff1690910217905560058054806115315761153161342f565b5f8281526020902081015f1990810180546001600160c01b0319169055019055600191505b80611560816133d2565b915050611456565b50806115a95760405162461bcd60e51b815260206004820152601060248201526f2737ba1034b7103a30bc103634b9ba1760811b6044820152606401610859565b5f805b6005548110156115ff57600581815481106115c9576115c96133ab565b5f918252602090912001546115eb90600160a01b900463ffffffff1683613387565b9150806115f7816133d2565b9150506115ac565b506008805463ffffffff909216600160c01b0263ffffffff60c01b199092169190911790555050565b611630611e80565b600754600160e01b900460ff161561169a5760405162461bcd60e51b815260206004820152602760248201527f43616e2774206f70656e2074726164696e672074686174277320616c726561646044820152663c9037b832b71760c91b6064820152608401610859565b6009805468010000000000000000600160e01b0319167b7a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000001790819055737a250d5630b4cf539739df2c5dacb4c659f2488d906117109030906001600160a01b03600160401b909104166a52b7d2dcc80cd2e4000000611d5d565b5f816001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561174d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061177191906133fd565b6001600160a01b031663c9c6539630846001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117bc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117e091906133fd565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303815f875af115801561182a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061184e91906133fd565b600954305f81815260016020526040902054929350600160401b9091046001600160a01b03169163f305d7199147915f806118905f546001600160a01b031690565b60405160e088901b6001600160e01b03191681526001600160a01b03958616600482015260248101949094526044840192909252606483015290911660848201524260a482015260c40160606040518083038185885af11580156118f6573d5f803e3d5ffd5b50505050506040513d601f19601f8201168201806040525081019061191b9190613443565b50506007805462ff00ff60e01b19166201000160e01b17905550604080516080810182525f80825260208083018281528385018381526001606086019081526001600160a01b039790971684526004909252939091209151825493519151945164ffffffffff1990941690151564ffffffff0019161761010063ffffffff928316021769ffffffffff0000000000191665010000000000919094160260ff60481b191692909217600160481b9115159190910217905550565b83421115611a245760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610859565b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888611a528c6127fb565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f611aac82612822565b90505f611abb8287878761284e565b9050896001600160a01b0316816001600160a01b031614611b1e5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610859565b611b298a8a8a611d5d565b50505050505050505050565b611b3d611e80565b614e208163ffffffff161115611b955760405162461bcd60e51b815260206004820152601760248201527f4d6178696d756d2062757920746178206f66203130252e0000000000000000006044820152606401610859565b6006805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b6008546001600160a01b0316336001600160a01b031614611c1d5760405162461bcd60e51b815260206004820152601c60248201527f4f6e6c7920646576656c6f7065722063616e2073657420746869732e000000006044820152606401610859565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b611c47611e80565b6001600160a01b03165f908152600460205260409020805460ff60481b1916600160481b179055565b611c78611e80565b6001600160a01b038116611cdd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610859565b610b1e81612632565b60606005805480602002602001604051908101604052809291908181526020015f905b82821015611d54575f84815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900463ffffffff1681830152825260019092019101611d09565b50505050905090565b6001600160a01b038316611dbf5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610859565b6001600160a01b038216611e205760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610859565b6001600160a01b038381165f8181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f546001600160a01b03163314610cc35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610859565b6001600160a01b038316611f3d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610859565b6001600160a01b038216611f9f5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610859565b5f81116120005760405162461bcd60e51b815260206004820152602960248201527f5472616e7366657220616d6f756e74206d7573742062652067726561746572206044820152687468616e207a65726f60b81b6064820152608401610859565b5f806120135f546001600160a01b031690565b6001600160a01b0316856001600160a01b03161415801561204157505f546001600160a01b03858116911614155b801561205657506001600160a01b0385163014155b801561207a57506001600160a01b0384165f9081526004602052604090205460ff16155b801561209e57506001600160a01b0385165f9081526004602052604090205460ff16155b1561228c576007546120c890600160a01b900463ffffffff166a52b7d2dcc80cd2e400000061346e565b83111561210a5760405162461bcd60e51b815260206004820152601060248201526f26b0bc103a3c1032bc31b2b2b232b21760811b6044820152606401610859565b6001600160a01b0385165f90815260046020526040902054600160481b900460ff16801561214d57506009546001600160a01b03858116600160401b9092041614155b156122035760065460075463ffffffff600160e01b9092048216935061218791600160c01b909104166a52b7d2dcc80cd2e400000061346e565b836121a6866001600160a01b03165f9081526001602052604090205490565b6121b091906133bf565b11156121fe5760405162461bcd60e51b815260206004820152601c60248201527f4d61782077616c6c65742077696c6c2062652065786365656465642e000000006044820152606401610859565b612290565b6001600160a01b0384165f90815260046020526040902054600160481b900460ff16801561224657506009546001600160a01b03868116600160401b9092041614155b15612264575050600654600160c01b900463ffffffff166001612290565b6007545f925061218790600160c01b900463ffffffff166a52b7d2dcc80cd2e400000061346e565b5f91505b6113a08585858585612874565b5f81848411156122c05760405162461bcd60e51b81526004016108599190612f31565b505050900390565b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801561232057507f000000000000000000000000000000000000000000000000000000000000000046145b1561234a57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60408051600280825260608201835283925f92919060208301908036833701905050905082815f81518110612425576124256133ab565b60200260200101906001600160a01b031690816001600160a01b031681525050600960089054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015612496573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124ba91906133fd565b816001815181106124cd576124cd6133ab565b6001600160a01b0392831660209182029290920101526040516370a0823160e01b81523060048201525f918416906370a0823190602401602060405180830381865afa15801561251f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125439190613418565b60095460405163095ea7b360e01b81526001600160a01b03600160401b909204821660048201526024810183905291925084169063095ea7b3906044016020604051808303815f875af115801561259c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125c091906132fc565b5060095460405163791ac94760e01b8152600160401b9091046001600160a01b03169063791ac947906125ff9084905f908790309042906004016134a1565b5f604051808303815f87803b158015612616575f80fd5b505af1158015612628573d5f803e3d5ffd5b5050505050505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0382165f908152600160205260409020546126a49082906133ea565b6001600160a01b039092165f9081526001602052604090209190915550565b6001600160a01b0382165f908152600160205260409020546126a49082906133bf565b804710156127365760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610859565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f811461277f576040519150601f19603f3d011682016040523d82523d5f602084013e612784565b606091505b5050905080610ef65760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610859565b6001600160a01b0381165f9081526003602052604090208054600181018255905b50919050565b5f61080461282e6122c8565b8360405161190160f01b8152600281019290925260228201526042902090565b5f805f61285d87878787612a39565b9150915061286a81612af6565b5095945050505050565b8263ffffffff8316156128d3575f61288c8585612c3f565b905061289881866133ea565b91506128a430826126c3565b60405181815230906001600160a01b038916905f8051602061361d8339815191529060200160405180910390a3505b811561299f57856001600160a01b03167fae92ab4b6f8f401ead768d3273e6bb937a13e39827d19c6376e8fd4512a05d9a8560405161291491815260200190565b60405180910390a2305f9081526001602052604090205480156129995760085461295690600160e01b900463ffffffff166a52b7d2dcc80cd2e400000061346e565b8111156129905760085461298b9061298690600160e01b900463ffffffff166a52b7d2dcc80cd2e400000061346e565b612c65565b612999565b61299981612c65565b506129e3565b846001600160a01b03167fc55650ccda1011e1cdc769b1fbf546ebb8c97800b6072b49e06cd560305b1d67856040516129da91815260200190565b60405180910390a25b6129ed8685612681565b6129f785826126c3565b846001600160a01b0316866001600160a01b03165f8051602061361d83398151915283604051612a2991815260200190565b60405180910390a3505050505050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612a6e57505f90506003612aed565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612abf573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116612ae7575f60019250925050612aed565b91505f90505b94509492505050565b5f816004811115612b0957612b09613510565b03612b115750565b6001816004811115612b2557612b25613510565b03612b725760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610859565b6002816004811115612b8657612b86613510565b03612bd35760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610859565b6003816004811115612be757612be7613510565b03610b1e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610859565b5f620186a0612c5463ffffffff841685613524565b612c5e919061346e565b9392505050565b60095467ffffffffffffffff164314610b1e576009805467ffffffffffffffff19164367ffffffffffffffff161790556007805460ff60e81b1916600160e81b179055305f908152600260209081526040808320600954600160401b90046001600160a01b03168452909152902054811115612d0557600954612d05903090600160401b90046001600160a01b03166a52b7d2dcc80cd2e4000000611d5d565b6040805160028082526060820183525f9260208301908036833701905050905030815f81518110612d3857612d386133ab565b60200260200101906001600160a01b031690816001600160a01b031681525050600960089054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015612da9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dcd91906133fd565b81600181518110612de057612de06133ab565b6001600160a01b0392831660209182029290920101526009546040516318cbafe560e01b8152600160401b909104909116906318cbafe590612e2e9085905f908690309042906004016134a1565b5f604051808303815f875af1158015612e49573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612e70919081019061353b565b50612e7a47612e8b565b50506007805460ff60e81b19169055565b5f5b600554811015612f2d57612f1b60058281548110612ead57612ead6133ab565b5f91825260209091200154600854600580546001600160a01b0390931692600160c01b90920463ffffffff169185908110612eea57612eea6133ab565b5f91825260209091200154612f0c90600160a01b900463ffffffff1686613524565b612f16919061346e565b6126e6565b80612f25816133d2565b915050612e8d565b5050565b5f6020808352835180828501525f5b81811015612f5c57858101830151858201604001528201612f40565b505f604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b0381168114610b1e575f80fd5b5f8060408385031215612fa1575f80fd5b8235612fac81612f7c565b946020939093013593505050565b63ffffffff81168114610b1e575f80fd5b5f60208284031215612fdb575f80fd5b8135612c5e81612fba565b5f805f60608486031215612ff8575f80fd5b833561300381612f7c565b9250602084013561301381612f7c565b929592945050506040919091013590565b5f60208284031215613034575f80fd5b8135612c5e81612f7c565b5f6040828403121561281c575f80fd5b8015158114610b1e575f80fd5b5f806040838503121561306d575f80fd5b823561307881612f7c565b915060208301356130888161304f565b809150509250929050565b5f8083601f8401126130a3575f80fd5b50813567ffffffffffffffff8111156130ba575f80fd5b6020830191508360208260051b85010111156130d4575f80fd5b9250929050565b5f805f805f606086880312156130ef575f80fd5b85356130fa81612f7c565b9450602086013567ffffffffffffffff80821115613116575f80fd5b61312289838a01613093565b9096509450604088013591508082111561313a575f80fd5b5061314788828901613093565b969995985093965092949392505050565b5f805f806040858703121561316b575f80fd5b843567ffffffffffffffff80821115613182575f80fd5b61318e88838901613093565b909650945060208701359150808211156131a6575f80fd5b506131b387828801613093565b95989497509550505050565b5f805f805f805f60e0888a0312156131d5575f80fd5b87356131e081612f7c565b965060208801356131f081612f7c565b95506040880135945060608801359350608088013560ff81168114613213575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215613241575f80fd5b823561324c81612f7c565b9150602083013561308881612f7c565b602080825282518282018190525f919060409081850190868401855b828110156132ac57815180516001600160a01b0316855286015163ffffffff16868501529284019290850190600101613278565b5091979650505050505050565b60208082526023908201527f43616c6c6572206973206e6f742074686520455243323020636f6e74726f6c6c60408201526232b91760e91b606082015260800190565b5f6020828403121561330c575f80fd5b8151612c5e8161304f565b813561332281612f7c565b81546001600160a01b031981166001600160a01b03929092169182178355602084013561334e81612fba565b6001600160c01b03199190911690911760a09190911b63ffffffff60a01b1617905550565b634e487b7160e01b5f52601160045260245ffd5b63ffffffff8181168382160190808211156133a4576133a4613373565b5092915050565b634e487b7160e01b5f52603260045260245ffd5b8082018082111561080457610804613373565b5f600182016133e3576133e3613373565b5060010190565b8181038181111561080457610804613373565b5f6020828403121561340d575f80fd5b8151612c5e81612f7c565b5f60208284031215613428575f80fd5b5051919050565b634e487b7160e01b5f52603160045260245ffd5b5f805f60608486031215613455575f80fd5b8351925060208401519150604084015190509250925092565b5f8261348857634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52604160045260245ffd5b5f60a082018783526020878185015260a0604085015281875180845260c08601915082890193505f5b818110156134ef5784516001600160a01b0316835293830193918301916001016134ca565b50506001600160a01b03969096166060850152505050608001529392505050565b634e487b7160e01b5f52602160045260245ffd5b808202811582820484141761080457610804613373565b5f602080838503121561354c575f80fd5b825167ffffffffffffffff80821115613563575f80fd5b818501915085601f830112613576575f80fd5b8151818111156135885761358861348d565b8060051b604051601f19603f830116810181811085821117156135ad576135ad61348d565b6040529182528482019250838101850191888311156135ca575f80fd5b938501935b828510156135e8578451845293850193928501926135cf565b9897505050505050505056fe45524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212203fc36fe01dc717646f6b081f82900c5dbc2c64c37ab3053f2c13638a489d719664736f6c634300081400330000000000000000000000004ee6671532119ff8effcfba27f646ccde4b47ed20000000000000000000000004ee6671532119ff8effcfba27f646ccde4b47ed200000000000000000000000000000000000000000000000000000000000061a800000000000000000000000000000000000000000000000000000000000061a80000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000007924f4f86faa08b983921b7c7ea8e4eb22b024f900000000000000000000000000000000000000000000000000000000000003e8
Deployed Bytecode
0x608060405260043610610257575f3560e01c8063715018a61161013f578063b0bc85de116100b3578063db932ae211610078578063db932ae214610713578063dd62ed3e14610732578063e0195f0714610776578063e9cb414f14610795578063f2fde38b146107b4578063fb61e998146107d3575f80fd5b8063b0bc85de14610681578063bb1789d6146106a2578063c8ce7be1146106c1578063c9567bf9146106e0578063d505accf146106f4575f80fd5b806386f3f3cb1161010457806386f3f3cb146105d457806388a65f46146105e85780638da5cb5b146105fc57806395d89b4114610618578063a9059cbb14610643578063aad41a4114610662575f80fd5b8063715018a61461056357806373ae740e1461057757806373ec8c17146102625780637a52da0e146105965780637ecebe00146105b5575f80fd5b8063313ce567116101d65780634ff99fcf1161019b5780634ff99fcf146104875780635342acb4146104a6578063571cbe0a146104dd5780636612e66f146104fc57806370a082311461051b57806370bfdd9d1461054f575f80fd5b8063313ce567146103fb578063333429471461041657806333a17282146104355780633644e51514610454578063473071ce14610468575f80fd5b806320d5bf371161021c57806320d5bf371461033b578063232b10441461036c57806323b872dd1461038b578063252d723a146103aa5780632c1f5216146103dc575f80fd5b806306fdde0314610262578063095ea7b3146102a55780630ecf68e0146102d457806317f5a80b146102f557806318160ddd14610314575f80fd5b3661025e57005b5f80fd5b34801561026d575f80fd5b506040805180820190915260098152685175616e746c696e6b60b81b60208201525b60405161029c9190612f31565b60405180910390f35b3480156102b0575f80fd5b506102c46102bf366004612f90565b6107f4565b604051901515815260200161029c565b3480156102df575f80fd5b506102f36102ee366004612fcb565b61080a565b005b348015610300575f80fd5b506102f361030f366004612fcb565b610888565b34801561031f575f80fd5b506a52b7d2dcc80cd2e40000005b60405190815260200161029c565b348015610346575f80fd5b506007546001600160a01b03165b6040516001600160a01b03909116815260200161029c565b348015610377575f80fd5b506102f3610386366004612fcb565b610902565b348015610396575f80fd5b506102c46103a5366004612fe6565b61097d565b3480156103b5575f80fd5b50600654600160e01b900463ffffffff165b60405163ffffffff909116815260200161029c565b3480156103e7575f80fd5b50600654610354906001600160a01b031681565b348015610406575f80fd5b506040516012815260200161029c565b348015610421575f80fd5b506102f3610430366004612fcb565b6109f4565b348015610440575f80fd5b506102c461044f366004612fe6565b610a22565b34801561045f575f80fd5b5061032d610ad4565b348015610473575f80fd5b506102f3610482366004613024565b610ae2565b348015610492575f80fd5b506102f36104a136600461303f565b610b21565b3480156104b1575f80fd5b506102c46104c0366004613024565b6001600160a01b03165f9081526004602052604090205460ff1690565b3480156104e8575f80fd5b506102c46104f7366004612fe6565b610bf4565b348015610507575f80fd5b506102f361051636600461305c565b610c61565b348015610526575f80fd5b5061032d610535366004613024565b6001600160a01b03165f9081526001602052604090205490565b34801561055a575f80fd5b506102f3610c93565b34801561056e575f80fd5b506102f3610cb2565b348015610582575f80fd5b506102f36105913660046130db565b610cc5565b3480156105a1575f80fd5b506102f36105b0366004613024565b610e95565b3480156105c0575f80fd5b5061032d6105cf366004613024565b610efb565b3480156105df575f80fd5b50610354610f18565b3480156105f3575f80fd5b506102f361107f565b348015610607575f80fd5b505f546001600160a01b0316610354565b348015610623575f80fd5b50604080518082019091526003815262514c4b60e81b602082015261028f565b34801561064e575f80fd5b506102c461065d366004612f90565b611268565b34801561066d575f80fd5b506102f361067c366004613158565b611274565b34801561068c575f80fd5b50600654600160c01b900463ffffffff166103c7565b3480156106ad575f80fd5b506102f36106bc366004612fcb565b6113a7565b3480156106cc575f80fd5b506102f36106db366004613024565b61142d565b3480156106eb575f80fd5b506102f3611628565b3480156106ff575f80fd5b506102f361070e3660046131bf565b6119d4565b34801561071e575f80fd5b506102f361072d366004612fcb565b611b35565b34801561073d575f80fd5b5061032d61074c366004613230565b6001600160a01b039182165f90815260026020908152604080832093909416825291909152205490565b348015610781575f80fd5b506102f3610790366004613024565b611bba565b3480156107a0575f80fd5b506102f36107af366004613024565b611c3f565b3480156107bf575f80fd5b506102f36107ce366004613024565b611c70565b3480156107de575f80fd5b506107e7611ce6565b60405161029c919061325c565b5f610800338484611d5d565b5060015b92915050565b610812611e80565b6103e88163ffffffff16106108625760405162461bcd60e51b81526020600482015260116024820152704e6f206c6f776572207468616e202e312560781b60448201526064015b60405180910390fd5b6007805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b610890611e80565b6127108163ffffffff16106108dc5760405162461bcd60e51b81526020600482015260126024820152714e6f206c6f776572207468616e202e30312560701b6044820152606401610859565b6007805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b61090a611e80565b6127108163ffffffff1611156109585760405162461bcd60e51b81526020600482015260136024820152722737903637bbb2b9103a3430b710171818929760691b6044820152606401610859565b6008805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b5f610989848484611ed9565b6109ea84336109e5856040518060600160405280602881526020016135f5602891396001600160a01b038a165f90815260026020526040812090335b6001600160a01b0316815260208101919091526040015f2054919061229d565b611d5d565b5060019392505050565b6109fc611e80565b6008805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b6007545f906001600160a01b0316336001600160a01b031614610a575760405162461bcd60e51b8152600401610859906132b9565b60405163095ea7b360e01b81526001600160a01b0384811660048301526024820184905285919082169063095ea7b3906044015b6020604051808303815f875af1158015610aa7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610acb91906132fc565b95945050505050565b5f610add6122c8565b905090565b6007546001600160a01b0316336001600160a01b031614610b155760405162461bcd60e51b8152600401610859906132b9565b610b1e816123ee565b50565b610b29611e80565b600580546001810182555f9190915281907f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db001610b668282613317565b506001905060045f610b7b6020850185613024565b6001600160a01b0316815260208082019290925260409081015f20805460ff191693151593909317909255610bb4918301908301612fcb565b60088054601890610bd3908490600160c01b900463ffffffff16613387565b92506101000a81548163ffffffff021916908363ffffffff16021790555050565b6007545f906001600160a01b0316336001600160a01b031614610c295760405162461bcd60e51b8152600401610859906132b9565b60405163a9059cbb60e01b81526001600160a01b0384811660048301526024820184905285919082169063a9059cbb90604401610a8b565b610c69611e80565b6001600160a01b03919091165f908152600460205260409020805460ff1916911515919091179055565b610c9b611e80565b600780546001600160f81b0316600160f81b179055565b610cba611e80565b610cc35f612632565b565b828114610d145760405162461bcd60e51b815260206004820152601b60248201527f4d756c746973656e643a204c656e677468206d69736d617463682e00000000006044820152606401610859565b5f805b84811015610e3057610d4133858584818110610d3557610d356133ab565b90506020020135612681565b610d89868683818110610d5657610d566133ab565b9050602002016020810190610d6b9190613024565b858584818110610d7d57610d7d6133ab565b905060200201356126c3565b858582818110610d9b57610d9b6133ab565b9050602002016020810190610db09190613024565b6001600160a01b0316335f8051602061361d833981519152868685818110610dda57610dda6133ab565b90506020020135604051610df091815260200190565b60405180910390a3838382818110610e0a57610e0a6133ab565b9050602002013582610e1c91906133bf565b915080610e28816133d2565b915050610d17565b50610e8d863360408051808201825260208082527f4d756c746973656e643a204e6f7420656e6f75676820616c6c6f77616e63652e818301526001600160a01b038c165f90815260029091529182206109e59287929190336109c5565b505050505050565b6007546001600160a01b0316336001600160a01b031614610ec85760405162461bcd60e51b8152600401610859906132b9565b47610ed2826123ee565b5f610edd82476133ea565b600754909150610ef6906001600160a01b0316826126e6565b505050565b6001600160a01b0381165f90815260036020526040812054610804565b5f600960089054906101000a90046001600160a01b03166001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f6a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8e91906133fd565b6001600160a01b031663e6a4390530600960089054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fee573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101291906133fd565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa15801561105b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610add91906133fd565b6007546001600160a01b0316336001600160a01b0316146110b25760405162461bcd60e51b8152600401610859906132b9565b5f600960089054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015611104573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112891906133fd565b90505f600960089054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa15801561117c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111a091906133fd565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156111e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061120b9190613418565b604051632e1a7d4d60e01b8152600481018290529091506001600160a01b03841690632e1a7d4d906024015f604051808303815f87803b15801561124d575f80fd5b505af115801561125f573d5f803e3d5ffd5b50505050505050565b5f610800338484611ed9565b8281146112c35760405162461bcd60e51b815260206004820152601c60248201527f4d75796c746973656e643a204c656e677468206d69736d617463682e000000006044820152606401610859565b5f5b838110156113a0576112e333848484818110610d3557610d356133ab565b61131f8585838181106112f8576112f86133ab565b905060200201602081019061130d9190613024565b848484818110610d7d57610d7d6133ab565b848482818110611331576113316133ab565b90506020020160208101906113469190613024565b6001600160a01b0316335f8051602061361d833981519152858585818110611370576113706133ab565b9050602002013560405161138691815260200190565b60405180910390a380611398816133d2565b9150506112c5565b5050505050565b6113af611e80565b614e208163ffffffff1611156114075760405162461bcd60e51b815260206004820152601860248201527f4d6178696d756d2073656c6c20746178206f66203130252e00000000000000006044820152606401610859565b6006805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b611435611e80565b6001600160a01b0381165f908152600460205260408120805460ff19169055805b60055481101561156857826001600160a01b03166005828154811061147d5761147d6133ab565b5f918252602090912001546001600160a01b03160361155657600580546114a6906001906133ea565b815481106114b6576114b66133ab565b905f5260205f2001600582815481106114d1576114d16133ab565b5f91825260209091208254910180546001600160a01b039092166001600160a01b031983168117825592546001600160c01b0319909216909217600160a01b9182900463ffffffff1690910217905560058054806115315761153161342f565b5f8281526020902081015f1990810180546001600160c01b0319169055019055600191505b80611560816133d2565b915050611456565b50806115a95760405162461bcd60e51b815260206004820152601060248201526f2737ba1034b7103a30bc103634b9ba1760811b6044820152606401610859565b5f805b6005548110156115ff57600581815481106115c9576115c96133ab565b5f918252602090912001546115eb90600160a01b900463ffffffff1683613387565b9150806115f7816133d2565b9150506115ac565b506008805463ffffffff909216600160c01b0263ffffffff60c01b199092169190911790555050565b611630611e80565b600754600160e01b900460ff161561169a5760405162461bcd60e51b815260206004820152602760248201527f43616e2774206f70656e2074726164696e672074686174277320616c726561646044820152663c9037b832b71760c91b6064820152608401610859565b6009805468010000000000000000600160e01b0319167b7a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000001790819055737a250d5630b4cf539739df2c5dacb4c659f2488d906117109030906001600160a01b03600160401b909104166a52b7d2dcc80cd2e4000000611d5d565b5f816001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561174d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061177191906133fd565b6001600160a01b031663c9c6539630846001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117bc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117e091906133fd565b6040516001600160e01b031960e085901b1681526001600160a01b039283166004820152911660248201526044016020604051808303815f875af115801561182a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061184e91906133fd565b600954305f81815260016020526040902054929350600160401b9091046001600160a01b03169163f305d7199147915f806118905f546001600160a01b031690565b60405160e088901b6001600160e01b03191681526001600160a01b03958616600482015260248101949094526044840192909252606483015290911660848201524260a482015260c40160606040518083038185885af11580156118f6573d5f803e3d5ffd5b50505050506040513d601f19601f8201168201806040525081019061191b9190613443565b50506007805462ff00ff60e01b19166201000160e01b17905550604080516080810182525f80825260208083018281528385018381526001606086019081526001600160a01b039790971684526004909252939091209151825493519151945164ffffffffff1990941690151564ffffffff0019161761010063ffffffff928316021769ffffffffff0000000000191665010000000000919094160260ff60481b191692909217600160481b9115159190910217905550565b83421115611a245760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610859565b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888611a528c6127fb565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f611aac82612822565b90505f611abb8287878761284e565b9050896001600160a01b0316816001600160a01b031614611b1e5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610859565b611b298a8a8a611d5d565b50505050505050505050565b611b3d611e80565b614e208163ffffffff161115611b955760405162461bcd60e51b815260206004820152601760248201527f4d6178696d756d2062757920746178206f66203130252e0000000000000000006044820152606401610859565b6006805463ffffffff909216600160e01b026001600160e01b03909216919091179055565b6008546001600160a01b0316336001600160a01b031614611c1d5760405162461bcd60e51b815260206004820152601c60248201527f4f6e6c7920646576656c6f7065722063616e2073657420746869732e000000006044820152606401610859565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b611c47611e80565b6001600160a01b03165f908152600460205260409020805460ff60481b1916600160481b179055565b611c78611e80565b6001600160a01b038116611cdd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610859565b610b1e81612632565b60606005805480602002602001604051908101604052809291908181526020015f905b82821015611d54575f84815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900463ffffffff1681830152825260019092019101611d09565b50505050905090565b6001600160a01b038316611dbf5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610859565b6001600160a01b038216611e205760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610859565b6001600160a01b038381165f8181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b5f546001600160a01b03163314610cc35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610859565b6001600160a01b038316611f3d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610859565b6001600160a01b038216611f9f5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610859565b5f81116120005760405162461bcd60e51b815260206004820152602960248201527f5472616e7366657220616d6f756e74206d7573742062652067726561746572206044820152687468616e207a65726f60b81b6064820152608401610859565b5f806120135f546001600160a01b031690565b6001600160a01b0316856001600160a01b03161415801561204157505f546001600160a01b03858116911614155b801561205657506001600160a01b0385163014155b801561207a57506001600160a01b0384165f9081526004602052604090205460ff16155b801561209e57506001600160a01b0385165f9081526004602052604090205460ff16155b1561228c576007546120c890600160a01b900463ffffffff166a52b7d2dcc80cd2e400000061346e565b83111561210a5760405162461bcd60e51b815260206004820152601060248201526f26b0bc103a3c1032bc31b2b2b232b21760811b6044820152606401610859565b6001600160a01b0385165f90815260046020526040902054600160481b900460ff16801561214d57506009546001600160a01b03858116600160401b9092041614155b156122035760065460075463ffffffff600160e01b9092048216935061218791600160c01b909104166a52b7d2dcc80cd2e400000061346e565b836121a6866001600160a01b03165f9081526001602052604090205490565b6121b091906133bf565b11156121fe5760405162461bcd60e51b815260206004820152601c60248201527f4d61782077616c6c65742077696c6c2062652065786365656465642e000000006044820152606401610859565b612290565b6001600160a01b0384165f90815260046020526040902054600160481b900460ff16801561224657506009546001600160a01b03868116600160401b9092041614155b15612264575050600654600160c01b900463ffffffff166001612290565b6007545f925061218790600160c01b900463ffffffff166a52b7d2dcc80cd2e400000061346e565b5f91505b6113a08585858585612874565b5f81848411156122c05760405162461bcd60e51b81526004016108599190612f31565b505050900390565b5f306001600160a01b037f000000000000000000000000e226b7ae83a44bb98f67bea28c4ad73b0925c49e1614801561232057507f000000000000000000000000000000000000000000000000000000000000000146145b1561234a57507f08673a47d96719da787a778ef055f0bef1ebe82af93a59dfb624a4572c6f3bca90565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f92aee2abf01cdf63f53f55973d65eb1705b24bbfd25c6c0ca9e3d72d868eec56828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60408051600280825260608201835283925f92919060208301908036833701905050905082815f81518110612425576124256133ab565b60200260200101906001600160a01b031690816001600160a01b031681525050600960089054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015612496573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124ba91906133fd565b816001815181106124cd576124cd6133ab565b6001600160a01b0392831660209182029290920101526040516370a0823160e01b81523060048201525f918416906370a0823190602401602060405180830381865afa15801561251f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125439190613418565b60095460405163095ea7b360e01b81526001600160a01b03600160401b909204821660048201526024810183905291925084169063095ea7b3906044016020604051808303815f875af115801561259c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125c091906132fc565b5060095460405163791ac94760e01b8152600160401b9091046001600160a01b03169063791ac947906125ff9084905f908790309042906004016134a1565b5f604051808303815f87803b158015612616575f80fd5b505af1158015612628573d5f803e3d5ffd5b5050505050505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0382165f908152600160205260409020546126a49082906133ea565b6001600160a01b039092165f9081526001602052604090209190915550565b6001600160a01b0382165f908152600160205260409020546126a49082906133bf565b804710156127365760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610859565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f811461277f576040519150601f19603f3d011682016040523d82523d5f602084013e612784565b606091505b5050905080610ef65760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610859565b6001600160a01b0381165f9081526003602052604090208054600181018255905b50919050565b5f61080461282e6122c8565b8360405161190160f01b8152600281019290925260228201526042902090565b5f805f61285d87878787612a39565b9150915061286a81612af6565b5095945050505050565b8263ffffffff8316156128d3575f61288c8585612c3f565b905061289881866133ea565b91506128a430826126c3565b60405181815230906001600160a01b038916905f8051602061361d8339815191529060200160405180910390a3505b811561299f57856001600160a01b03167fae92ab4b6f8f401ead768d3273e6bb937a13e39827d19c6376e8fd4512a05d9a8560405161291491815260200190565b60405180910390a2305f9081526001602052604090205480156129995760085461295690600160e01b900463ffffffff166a52b7d2dcc80cd2e400000061346e565b8111156129905760085461298b9061298690600160e01b900463ffffffff166a52b7d2dcc80cd2e400000061346e565b612c65565b612999565b61299981612c65565b506129e3565b846001600160a01b03167fc55650ccda1011e1cdc769b1fbf546ebb8c97800b6072b49e06cd560305b1d67856040516129da91815260200190565b60405180910390a25b6129ed8685612681565b6129f785826126c3565b846001600160a01b0316866001600160a01b03165f8051602061361d83398151915283604051612a2991815260200190565b60405180910390a3505050505050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612a6e57505f90506003612aed565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612abf573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116612ae7575f60019250925050612aed565b91505f90505b94509492505050565b5f816004811115612b0957612b09613510565b03612b115750565b6001816004811115612b2557612b25613510565b03612b725760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610859565b6002816004811115612b8657612b86613510565b03612bd35760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610859565b6003816004811115612be757612be7613510565b03610b1e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610859565b5f620186a0612c5463ffffffff841685613524565b612c5e919061346e565b9392505050565b60095467ffffffffffffffff164314610b1e576009805467ffffffffffffffff19164367ffffffffffffffff161790556007805460ff60e81b1916600160e81b179055305f908152600260209081526040808320600954600160401b90046001600160a01b03168452909152902054811115612d0557600954612d05903090600160401b90046001600160a01b03166a52b7d2dcc80cd2e4000000611d5d565b6040805160028082526060820183525f9260208301908036833701905050905030815f81518110612d3857612d386133ab565b60200260200101906001600160a01b031690816001600160a01b031681525050600960089054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015612da9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dcd91906133fd565b81600181518110612de057612de06133ab565b6001600160a01b0392831660209182029290920101526009546040516318cbafe560e01b8152600160401b909104909116906318cbafe590612e2e9085905f908690309042906004016134a1565b5f604051808303815f875af1158015612e49573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612e70919081019061353b565b50612e7a47612e8b565b50506007805460ff60e81b19169055565b5f5b600554811015612f2d57612f1b60058281548110612ead57612ead6133ab565b5f91825260209091200154600854600580546001600160a01b0390931692600160c01b90920463ffffffff169185908110612eea57612eea6133ab565b5f91825260209091200154612f0c90600160a01b900463ffffffff1686613524565b612f16919061346e565b6126e6565b80612f25816133d2565b915050612e8d565b5050565b5f6020808352835180828501525f5b81811015612f5c57858101830151858201604001528201612f40565b505f604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b0381168114610b1e575f80fd5b5f8060408385031215612fa1575f80fd5b8235612fac81612f7c565b946020939093013593505050565b63ffffffff81168114610b1e575f80fd5b5f60208284031215612fdb575f80fd5b8135612c5e81612fba565b5f805f60608486031215612ff8575f80fd5b833561300381612f7c565b9250602084013561301381612f7c565b929592945050506040919091013590565b5f60208284031215613034575f80fd5b8135612c5e81612f7c565b5f6040828403121561281c575f80fd5b8015158114610b1e575f80fd5b5f806040838503121561306d575f80fd5b823561307881612f7c565b915060208301356130888161304f565b809150509250929050565b5f8083601f8401126130a3575f80fd5b50813567ffffffffffffffff8111156130ba575f80fd5b6020830191508360208260051b85010111156130d4575f80fd5b9250929050565b5f805f805f606086880312156130ef575f80fd5b85356130fa81612f7c565b9450602086013567ffffffffffffffff80821115613116575f80fd5b61312289838a01613093565b9096509450604088013591508082111561313a575f80fd5b5061314788828901613093565b969995985093965092949392505050565b5f805f806040858703121561316b575f80fd5b843567ffffffffffffffff80821115613182575f80fd5b61318e88838901613093565b909650945060208701359150808211156131a6575f80fd5b506131b387828801613093565b95989497509550505050565b5f805f805f805f60e0888a0312156131d5575f80fd5b87356131e081612f7c565b965060208801356131f081612f7c565b95506040880135945060608801359350608088013560ff81168114613213575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215613241575f80fd5b823561324c81612f7c565b9150602083013561308881612f7c565b602080825282518282018190525f919060409081850190868401855b828110156132ac57815180516001600160a01b0316855286015163ffffffff16868501529284019290850190600101613278565b5091979650505050505050565b60208082526023908201527f43616c6c6572206973206e6f742074686520455243323020636f6e74726f6c6c60408201526232b91760e91b606082015260800190565b5f6020828403121561330c575f80fd5b8151612c5e8161304f565b813561332281612f7c565b81546001600160a01b031981166001600160a01b03929092169182178355602084013561334e81612fba565b6001600160c01b03199190911690911760a09190911b63ffffffff60a01b1617905550565b634e487b7160e01b5f52601160045260245ffd5b63ffffffff8181168382160190808211156133a4576133a4613373565b5092915050565b634e487b7160e01b5f52603260045260245ffd5b8082018082111561080457610804613373565b5f600182016133e3576133e3613373565b5060010190565b8181038181111561080457610804613373565b5f6020828403121561340d575f80fd5b8151612c5e81612f7c565b5f60208284031215613428575f80fd5b5051919050565b634e487b7160e01b5f52603160045260245ffd5b5f805f60608486031215613455575f80fd5b8351925060208401519150604084015190509250925092565b5f8261348857634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52604160045260245ffd5b5f60a082018783526020878185015260a0604085015281875180845260c08601915082890193505f5b818110156134ef5784516001600160a01b0316835293830193918301916001016134ca565b50506001600160a01b03969096166060850152505050608001529392505050565b634e487b7160e01b5f52602160045260245ffd5b808202811582820484141761080457610804613373565b5f602080838503121561354c575f80fd5b825167ffffffffffffffff80821115613563575f80fd5b818501915085601f830112613576575f80fd5b8151818111156135885761358861348d565b8060051b604051601f19603f830116810181811085821117156135ad576135ad61348d565b6040529182528482019250838101850191888311156135ca575f80fd5b938501935b828510156135e8578451845293850193928501926135cf565b9897505050505050505056fe45524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212203fc36fe01dc717646f6b081f82900c5dbc2c64c37ab3053f2c13638a489d719664736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004ee6671532119ff8effcfba27f646ccde4b47ed20000000000000000000000004ee6671532119ff8effcfba27f646ccde4b47ed200000000000000000000000000000000000000000000000000000000000061a800000000000000000000000000000000000000000000000000000000000061a80000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000007924f4f86faa08b983921b7c7ea8e4eb22b024f900000000000000000000000000000000000000000000000000000000000003e8
-----Decoded View---------------
Arg [0] : controller (address): 0x4eE6671532119ff8EffcFbA27f646ccDE4B47Ed2
Arg [1] : dev (address): 0x4eE6671532119ff8EffcFbA27f646ccDE4B47Ed2
Arg [2] : id (tuple):
Arg [1] : buyTax (uint32): 25000
Arg [2] : sellTax (uint32): 25000
Arg [3] : maxWalletDiv (uint32): 100
Arg [4] : maxTxDiv (uint32): 100
Arg [5] : maxSwapDivisor (uint32): 200
Arg [3] : wallets (tuple[]):
Arg [1] : wallet (address): 0x7924f4f86FAa08B983921B7C7Ea8E4eb22B024F9
Arg [2] : ratio (uint32): 1000
-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 0000000000000000000000004ee6671532119ff8effcfba27f646ccde4b47ed2
Arg [1] : 0000000000000000000000004ee6671532119ff8effcfba27f646ccde4b47ed2
Arg [2] : 00000000000000000000000000000000000000000000000000000000000061a8
Arg [3] : 00000000000000000000000000000000000000000000000000000000000061a8
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [6] : 00000000000000000000000000000000000000000000000000000000000000c8
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [9] : 0000000000000000000000007924f4f86faa08b983921b7c7ea8e4eb22b024f9
Arg [10] : 00000000000000000000000000000000000000000000000000000000000003e8
Loading...
Loading
Loading...
Loading
OVERVIEW
QuantLink is architecting a comprehensive suite of tools and services engineered to provide a cutting-edge alternative in the oracle and decentralized data market.Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.