Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 86 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Transfer | 21397074 | 9 days ago | IN | 0 ETH | 0.00249237 | ||||
Transfer | 20741115 | 101 days ago | IN | 0 ETH | 0.00051013 | ||||
Approve | 20693486 | 107 days ago | IN | 0 ETH | 0.00277231 | ||||
Approve | 20693485 | 107 days ago | IN | 0 ETH | 0.00059734 | ||||
Approve | 20693484 | 107 days ago | IN | 0 ETH | 0.0004192 | ||||
Approve | 20693483 | 107 days ago | IN | 0 ETH | 0.0004604 | ||||
Approve | 20693482 | 107 days ago | IN | 0 ETH | 0.00061239 | ||||
Approve | 20693482 | 107 days ago | IN | 0 ETH | 0.00061239 | ||||
Approve | 20693482 | 107 days ago | IN | 0 ETH | 0.00108571 | ||||
Approve | 20693482 | 107 days ago | IN | 0 ETH | 0.00274233 | ||||
Approve | 20693481 | 107 days ago | IN | 0 ETH | 0.0004603 | ||||
Approve | 20693481 | 107 days ago | IN | 0 ETH | 0.00050768 | ||||
Approve | 20693480 | 107 days ago | IN | 0 ETH | 0.00043338 | ||||
Approve | 20693480 | 107 days ago | IN | 0 ETH | 0.00060225 | ||||
Approve | 20693480 | 107 days ago | IN | 0 ETH | 0.00060225 | ||||
Approve | 20693480 | 107 days ago | IN | 0 ETH | 0.00064678 | ||||
Approve | 20693478 | 107 days ago | IN | 0 ETH | 0.00062597 | ||||
Approve | 20693476 | 107 days ago | IN | 0 ETH | 0.00062225 | ||||
Approve | 20693475 | 107 days ago | IN | 0 ETH | 0.00053515 | ||||
Approve | 20693474 | 107 days ago | IN | 0 ETH | 0.00061382 | ||||
Approve | 20693472 | 107 days ago | IN | 0 ETH | 0.00044732 | ||||
Approve | 20693472 | 107 days ago | IN | 0 ETH | 0.00047477 | ||||
Approve | 20693472 | 107 days ago | IN | 0 ETH | 0.00052086 | ||||
Approve | 20693472 | 107 days ago | IN | 0 ETH | 0.00066066 | ||||
Approve | 20693471 | 107 days ago | IN | 0 ETH | 0.00047413 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Flower
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "./Token.sol"; import "./Breed.sol"; contract HoldersList { mapping(uint index => address holder) _holders; mapping(address holder => uint index) _holder_index; uint public holders_count; function get_holders_list( uint index, uint count ) external view returns (uint page_count, address[] memory accounts) { if (index >= holders_count) return (0, new address[](0)); uint end = index + count; if (end > holders_count) { end = holders_count; } page_count = end - index; accounts = new address[](page_count); uint i; for (i = index; i < page_count; ++i) { accounts[i] = _holders[index + i]; } } function add_holder(address value) internal { uint index = holders_count++; _holders[index] = value; _holder_index[value] = index; } function remove_holder(address value) internal { if (holders_count == 0) return; uint removingIndex = _holder_index[value]; if (removingIndex != holders_count - 1) { address lastHolder = _holders[holders_count - 1]; _holders[removingIndex] = lastHolder; _holder_index[lastHolder] = removingIndex; } --holders_count; delete _holder_index[value]; delete _holders[holders_count]; } } contract Flower is Token, ReentrancyGuard, HoldersList { uint constant MAX_GENS_START = 1000; uint public constant GEN_MIN = 1; uint public constant gen_max = MAX_GENS_START; uint public gen = MAX_GENS_START; uint public constant max_breed = 1000; mapping(address owner => mapping(uint index => Breed)) public breeds; mapping(address owner => uint) public counts; uint public breed_total_count; uint breed_id; constructor() Token("Flowers", "F") {} function _add_breed_to_owner(address account, Breed memory breed) private { if (account == _pair) return; if (++counts[account] == 1) add_holder(account); ++breed_total_count; uint index = counts[account] - 1; breeds[account][index] = breed; } function _remove_breed_from_owner_by_index( address account, uint index ) private { if (account == _pair) return; if (--counts[account] == 0) remove_holder(account); --breed_total_count; uint last_index = counts[account]; if (index != last_index) { Breed memory last_breed = breeds[account][last_index]; breeds[account][index] = last_breed; } delete breeds[account][last_index]; } function _transfer_breed_from_to_by_index( address account, uint index, address to ) private { Breed memory breed = breeds[account][index]; super.transfer_internal(account, to, 10 ** DECIMALS); _remove_breed_from_owner_by_index(account, index); _add_breed_to_owner(to, breed); } function transfer_breed_from_to_by_index(uint index, address to) external { require(index < counts[msg.sender], "incorrect index"); _transfer_breed_from_to_by_index(msg.sender, index, to); } function gen_mode(uint value) private returns (uint) { value = (value * gen) / gen_max; if (value == 0) value = 1; if (gen > GEN_MIN) --gen; return value; } function buy( address to, uint256 amount ) internal virtual override nonReentrant { uint last_balance = balanceOf(to); uint balance = last_balance + amount; uint count = balance / (10 ** decimals()) - last_balance / (10 ** decimals()); uint i; for (i = 0; i < count; ++i) { Breed memory breed = Breed(++breed_id, gen_mode(max_breed)); _add_breed_to_owner(to, breed); } super.buy(to, amount); } function sell( address from, uint256 amount ) internal virtual override lockFee nonReentrant { uint last_balance = balanceOf(from); uint balance = last_balance - amount; uint count = last_balance / (10 ** decimals()) - balance / (10 ** decimals()); uint i; uint owner_count = counts[from]; for (i = 0; i < count; ++i) { if (gen < gen_max) ++gen; if (owner_count > 0) _remove_breed_from_owner_by_index(from, --owner_count); } super._transfer(from, _pair, amount); } function transfer_internal( address from, address to, uint256 amount ) internal virtual override nonReentrant { uint last_balance_from = balanceOf(from); uint balance_from = last_balance_from - amount; uint last_balance_to = balanceOf(to); uint balance_to = last_balance_to + amount; if (to == address(0) || to == DEAD_ADDRESS) { last_balance_to = 0; balance_to = 0; } uint count_from = last_balance_from / (10 ** decimals()) - balance_from / (10 ** decimals()); uint count_to = balance_to / (10 ** decimals()) - last_balance_to / (10 ** decimals()); // calculate transfer count uint transfer_count = count_from; if (transfer_count > count_to) transfer_count = count_to; // transfer uint i; uint owner_count = counts[from]; for (i = 0; i < transfer_count; ++i) { if (owner_count == 0) break; uint from_index = --owner_count; Breed memory breed = breeds[from][from_index]; _remove_breed_from_owner_by_index(from, from_index); _add_breed_to_owner(to, breed); } uint transfered = i; // remove from for (i = transfer_count; i < count_from; ++i) { uint from_index = --owner_count; _remove_breed_from_owner_by_index(from, from_index); } // generate to for (i = transfered; i < count_to; ++i) { Breed memory breed = Breed(++breed_id, gen_mode(max_breed)); _add_breed_to_owner(to, breed); } super.transfer_internal(from, to, amount); } function get_item_acc_index( address account, uint index ) external view returns (ItemData memory) { return this.get_item(breeds[account][index]); } function get_svg_acc_index( address account, uint index ) external view returns (string memory) { return toSvg(this.get_item_acc_index(account, index)); } function get_account_breeds( address account, uint index, uint count ) external view returns (uint page_count, Breed[] memory accounts) { uint account_count = counts[account]; if (index >= account_count) return (0, new Breed[](0)); uint end = index + count; if (end > account_count) { end = account_count; } page_count = end - index; accounts = new Breed[](page_count); uint i; for (i = 0; i < page_count; ++i) { accounts[i] = breeds[account][index + i]; } } function get_account_items( address account, uint index, uint count ) external view returns (uint page_count, ItemData[] memory accounts) { uint account_count = counts[account]; if (index >= account_count) return (0, new ItemData[](0)); uint end = index + count; if (end > account_count) { end = account_count; } page_count = end - index; accounts = new ItemData[](page_count); uint i; for (i = 0; i < page_count; ++i) { accounts[i] = this.get_item(breeds[account][index + i]); } } function get_account_svgs( address account, uint index, uint count ) external view returns (uint page_count, string[] memory accounts) { uint account_count = counts[account]; if (index >= account_count) return (0, new string[](0)); uint end = index + count; if (end > account_count) { end = account_count; page_count = index - end; } accounts = new string[](page_count); uint i; uint n = 0; for (i = index; i < end; ++i) { accounts[n++] = toSvg(this.get_item(breeds[account][i])); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; struct Breed { uint serial_number; // serial number uint breed2; // value breed }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import "./ERC20Token.sol"; import "./Generator.sol"; address constant DEAD_ADDRESS = 0x000000000000000000000000000000000000dEaD; contract Token is ERC20Token, Generator { uint8 constant DECIMALS = 9; uint256 constant _startTotalSupply = 1000 * (10 ** DECIMALS); uint256 constant _startMaxBuyCount = (_startTotalSupply * 5) / 10000; uint256 constant _addMaxBuyPercentPerSec = 1; // 100%=_addMaxBuyPrecesion add 0.005%/second uint256 constant _addMaxBuyPrecesion = 10000; uint256 constant _taxPrecesion = 1000; uint256 constant _transferZeroTaxSeconds = 1000; // zero tax transfer time address internal _pair; address immutable _deployer; bool internal _feeLocked; uint256 internal _startTime; constructor( string memory name_, string memory symbol_ ) ERC20Token(name_, symbol_) { _deployer = msg.sender; _mint(msg.sender, _startTotalSupply); } modifier maxBuyLimit(uint256 amount) { require(amount <= maxBuy(), "max buy"); _; } modifier lockFee() { _feeLocked = true; _; _feeLocked = false; } function decimals() public pure override returns (uint8) { return DECIMALS; } function start(address pair) external onlyOwner { _pair = pair; _startTime = block.timestamp; } function isStarted() public view returns (bool) { return _pair != address(0); } receive() external payable { bool sent; (sent, ) = payable(_deployer).call{value: msg.value}(""); require(sent, "can not get ether"); } function maxBuy() public view returns (uint256) { if (!isStarted()) return _startTotalSupply; uint256 count = _startMaxBuyCount + (_startTotalSupply * (block.timestamp - _startTime) * _addMaxBuyPercentPerSec) / _addMaxBuyPrecesion; if (count > _startTotalSupply) count = _startTotalSupply; return count; } function _transfer( address from, address to, uint256 amount ) internal override { // allow burning if (to == address(0) || to == DEAD_ADDRESS) { transfer_internal(from, to, amount); return; } // system transfers if ( !isStarted() && (from == address(0) || from == address(this) || from == _deployer || to == _deployer) ) { super._transfer(from, to, amount); return; } // transfers with fee if (_feeLocked) { super._transfer(from, to, amount); return; } else { if (from == _pair) { buy(to, amount); return; } else if (to == _pair) { sell(from, amount); return; } else transfer_internal(from, to, amount); } } function buy( address to, uint256 amount ) internal virtual maxBuyLimit(amount) lockFee { super._transfer(_pair, to, amount); } function sell(address from, uint256 amount) internal virtual lockFee { super._transfer(from, _pair, amount); } function transfer_internal( address from, address to, uint256 amount ) internal virtual lockFee { if (to == address(0) || to == DEAD_ADDRESS) { _burn(from, amount); return; } super._transfer(from, to, amount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "./Path.sol"; import "./String.sol"; import "./Files.sol"; import "./Colors.sol"; import "./IGenerator.sol"; import "./Breed.sol"; import "./Random.sol"; import "./Ownable.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; uint8 constant PIXELS_COUNT = 100; contract Generator is Ownable { using FilesLib for mapping(uint => Path[]); using PathLib for Path; using PathLib for Path[]; using RandLib for Rand; using RandLib for string[]; string[] public background_colors = [ "#20a826", "#f4910a", "#003cff", "#f8e424", "#a0301d", "#4bcadd", "#ff2a2a", "#7400a4", "#78c59b", "#f8Bac7" ]; string[] public petal_colors = ["#FF6347", "#FFD700", "#ADFF2F", "#FF69B4", "#00BFFF"]; string[] public center_colors = ["#FFFF00", "#FF4500"]; uint color_step_base = 1000; uint MAX = 1000; function set_max_base(uint max) external onlyOwner { MAX = max; } function set_color_step_base(uint step_base) external onlyOwner { color_step_base = step_base; } function pick_0(uint count, uint random) internal pure returns (uint) { return random % count; } function pick_1(uint count, uint random) internal pure returns (uint) { return (random % count) + 1; } function get_step(uint breed2) internal view returns (uint) { if (breed2 < color_step_base) return color_step_base - breed2; return 1; } function pick_color( string[] storage colors, uint random_value ) private view returns (string memory) { uint index = random_value % colors.length; return colors[index]; } function get_item(Breed calldata breed) external view returns (ItemData memory) { Rand memory rnd = Rand(breed, 0); return ItemData({ petalCount: rnd.next() % 8 + 4, petalSize: rnd.next() % 20 + 10, petalColor: pick_color(petal_colors, rnd.next()), centerColor: pick_color(center_colors, rnd.next()) }); } function getSvg(Breed calldata breed) external view returns (string memory) { return toSvg(this.get_item(breed)); } function toSvg(ItemData memory data) internal view returns (string memory) { string memory petals; for (uint i = 0; i < data.petalCount; i++) { uint x = 50 + uint(30 * i); // Substitua por uma fórmula de posição mais simples uint y = 50 + uint(30 * i); // Substitua por uma fórmula de posição mais simples petals = string(abi.encodePacked( petals, "<circle cx='", Strings.toString(x), "' cy='", Strings.toString(y), "' r='", Strings.toString(data.petalSize), "' fill='", data.petalColor, "' />" )); } return string(abi.encodePacked( "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>", "<rect width='100' height='100' fill='", background_colors[0], "'/>", // Fundo "<circle cx='50' cy='50' r='15' fill='", data.centerColor, "' />", // Centro da flor petals, "</svg>" )); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20Token is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal virtual { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @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), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(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) { uint256 localValue = value; 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] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } 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 bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract Ownable { address _owner; event RenounceOwnership(); constructor() { _owner = msg.sender; } modifier onlyOwner() { require(_owner == msg.sender, "only owner"); _; } function owner() external view virtual returns (address) { return _owner; } function ownerRenounce() public onlyOwner { _owner = address(0); emit RenounceOwnership(); } function transferOwnership(address newOwner) external onlyOwner { _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "./Breed.sol"; struct Rand { Breed breed; uint nonce; } library RandLib { function next(Rand memory rnd) internal pure returns (uint) { return uint( keccak256( abi.encodePacked( rnd.breed.serial_number, rnd.breed.breed2, rnd.nonce++ ) ) ); } function next_breed2_clamped(Rand memory rnd) internal pure returns (uint) { return next(rnd) % rnd.breed.breed2; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "./Breed.sol"; import "./ItemData.sol"; interface IGenerator { function get_item( Breed calldata seed_data ) external view returns (ItemData memory); function getSvg( Breed calldata seed_data ) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; library ColorConvert { function toSvgColor(uint24 value) internal pure returns (string memory) { return string(abi.encodePacked("#", toHex(value))); } function toHex(uint24 value) internal pure returns (bytes memory) { bytes memory buffer = new bytes(6); for (uint i = 0; i < 3; ++i) { buffer[5 - i * 2] = hexChar(uint8(value) & 0x0f); buffer[4 - i * 2] = hexChar((uint8(value) >> 4) & 0x0f); value >>= 8; } return buffer; } function hexChar(uint8 value) internal pure returns (bytes1) { if (value < 10) return bytes1(uint8(48 + (uint(value) % 10))); return bytes1(uint8(65 + uint256((value - 10) % 6))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import './Path.sol'; struct FileData { uint file; Path[] paths; } library FilesLib { function set_file( mapping(uint => Path[]) storage paths, FileData calldata input, uint8 count ) internal returns (uint8) { Path[] storage storageFile = paths[input.file]; if (storageFile.length > 0) delete paths[input.file - 1]; else ++count; for (uint i = 0; i < input.paths.length; ++i) { storageFile.push(input.paths[i]); } return count; } function set_files( mapping(uint => Path[]) storage paths, FileData[] calldata input, uint8 count ) internal returns (uint8) { if (input.length == 0) return count; uint i; for (i = 0; i < input.length; ++i) count = set_file(paths, input[i], count); return count; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; library StringLib { function equals( string memory s1, string memory s2 ) internal pure returns (bool) { return (keccak256(abi.encodePacked((s1))) == keccak256(abi.encodePacked((s2)))); } } library StringConverter { function toString(uint value) internal pure returns (string memory) { if (value == 0) { return "0"; } uint temp = value; uint digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import "./Path.sol"; import "./String.sol"; import "./Colors.sol"; import "./Random.sol"; struct Path { string fill; string data; } library PathLib { using PathLib for Path; using RandLib for Rand; using RandLib for string[]; using StringConverter for uint8; using ColorConvert for uint24; using StringLib for string; function toSvg(Path memory p) internal pure returns (string memory) { return string( abi.encodePacked("<path fill='", p.fill, "' d='", p.data, "'/>") ); } function toSvg( Path memory p, string memory color ) internal pure returns (string memory) { return string( abi.encodePacked( "<path fill='", color, "' d='", p.data, color, "'/>" ) ); } function toSvg( Path[] storage paths, string memory color ) internal view returns (string memory) { string memory res; for (uint i = 0; i < paths.length; ++i) { res = string(abi.encodePacked(res, paths[i].toSvg(color))); } return res; } function toSvg(Path[] storage paths) internal view returns (string memory) { string memory res; for (uint i = 0; i < paths.length; ++i) { res = string(abi.encodePacked(res, paths[i].toSvg())); } return res; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; struct ItemData { uint petalSize; uint petalCount; string petalColor; string centerColor; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @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 v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ 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. */ 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. */ 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. */ 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. */ 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 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 towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (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 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) 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. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 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. uint256 twos = denominator & (0 - denominator); 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 (unsignedRoundsUp(rounding) && 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 * towards zero. * * 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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * 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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * 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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * 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 + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"RenounceOwnership","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":"GEN_MIN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"background_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"breed_total_count","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"breeds","outputs":[{"internalType":"uint256","name":"serial_number","type":"uint256"},{"internalType":"uint256","name":"breed2","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"center_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"counts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"gen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gen_max","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"serial_number","type":"uint256"},{"internalType":"uint256","name":"breed2","type":"uint256"}],"internalType":"struct Breed","name":"breed","type":"tuple"}],"name":"getSvg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"get_account_breeds","outputs":[{"internalType":"uint256","name":"page_count","type":"uint256"},{"components":[{"internalType":"uint256","name":"serial_number","type":"uint256"},{"internalType":"uint256","name":"breed2","type":"uint256"}],"internalType":"struct Breed[]","name":"accounts","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"get_account_items","outputs":[{"internalType":"uint256","name":"page_count","type":"uint256"},{"components":[{"internalType":"uint256","name":"petalSize","type":"uint256"},{"internalType":"uint256","name":"petalCount","type":"uint256"},{"internalType":"string","name":"petalColor","type":"string"},{"internalType":"string","name":"centerColor","type":"string"}],"internalType":"struct ItemData[]","name":"accounts","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"get_account_svgs","outputs":[{"internalType":"uint256","name":"page_count","type":"uint256"},{"internalType":"string[]","name":"accounts","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"get_holders_list","outputs":[{"internalType":"uint256","name":"page_count","type":"uint256"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"serial_number","type":"uint256"},{"internalType":"uint256","name":"breed2","type":"uint256"}],"internalType":"struct Breed","name":"breed","type":"tuple"}],"name":"get_item","outputs":[{"components":[{"internalType":"uint256","name":"petalSize","type":"uint256"},{"internalType":"uint256","name":"petalCount","type":"uint256"},{"internalType":"string","name":"petalColor","type":"string"},{"internalType":"string","name":"centerColor","type":"string"}],"internalType":"struct ItemData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"get_item_acc_index","outputs":[{"components":[{"internalType":"uint256","name":"petalSize","type":"uint256"},{"internalType":"uint256","name":"petalCount","type":"uint256"},{"internalType":"string","name":"petalColor","type":"string"},{"internalType":"string","name":"centerColor","type":"string"}],"internalType":"struct ItemData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"get_svg_acc_index","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"holders_count","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"max_breed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownerRenounce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"petal_colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"step_base","type":"uint256"}],"name":"set_color_step_base","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"max","type":"uint256"}],"name":"set_max_base","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"start","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","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"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"transfer_breed_from_to_by_index","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040526040518061014001604052806040518060400160405280600781526020017f233230613832360000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f236634393130610000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f233030336366660000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f236638653432340000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f236130333031640000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f233462636164640000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f236666326132610000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f233734303061340000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f233738633539620000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f2366384261633700000000000000000000000000000000000000000000000000815250815250600690600a61026c929190610837565b506040518060a001604052806040518060400160405280600781526020017f234646363334370000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f234646443730300000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f234144464632460000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f234646363942340000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f233030424646460000000000000000000000000000000000000000000000000081525081525060079060056103ad92919061088e565b5060405180604001604052806040518060400160405280600781526020017f234646464630300000000000000000000000000000000000000000000000000081525081526020016040518060400160405280600781526020017f2346463435303000000000000000000000000000000000000000000000000000815250815250600890600261043d9291906108e5565b506103e86009556103e8600a556103e860115534801561045b575f80fd5b506040518060400160405280600781526020017f466c6f77657273000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f4600000000000000000000000000000000000000000000000000000000000000815250818181600390816104d99190610bf1565b5080600490816104e99190610bf1565b5050503360055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff168152505061058a336009600a6105729190610e28565b6103e861057f9190610e72565b61059960201b60201c565b50506001600d81905550610f9b565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610609575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016106009190610ef2565b60405180910390fd5b61061a5f838361061e60201b60201c565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361066e578060025f8282546106629190610f0b565b9250508190555061073c565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156106f7578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016106ee93929190610f4d565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610783578060025f82825403925050819055506107cd565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161082a9190610f82565b60405180910390a3505050565b828054828255905f5260205f2090810192821561087d579160200282015b8281111561087c57825182908161086c9190610bf1565b5091602001919060010190610855565b5b50905061088a919061093c565b5090565b828054828255905f5260205f209081019282156108d4579160200282015b828111156108d35782518290816108c39190610bf1565b50916020019190600101906108ac565b5b5090506108e1919061093c565b5090565b828054828255905f5260205f2090810192821561092b579160200282015b8281111561092a57825182908161091a9190610bf1565b5091602001919060010190610903565b5b509050610938919061093c565b5090565b5b8082111561095b575f8181610952919061095f565b5060010161093d565b5090565b50805461096b90610a1b565b5f825580601f1061097c5750610999565b601f0160209004905f5260205f2090810190610998919061099c565b5b50565b5b808211156109b3575f815f90555060010161099d565b5090565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610a3257607f821691505b602082108103610a4557610a446109ee565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302610aa77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610a6c565b610ab18683610a6c565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f610af5610af0610aeb84610ac9565b610ad2565b610ac9565b9050919050565b5f819050919050565b610b0e83610adb565b610b22610b1a82610afc565b848454610a78565b825550505050565b5f90565b610b36610b2a565b610b41818484610b05565b505050565b5b81811015610b6457610b595f82610b2e565b600181019050610b47565b5050565b601f821115610ba957610b7a81610a4b565b610b8384610a5d565b81016020851015610b92578190505b610ba6610b9e85610a5d565b830182610b46565b50505b505050565b5f82821c905092915050565b5f610bc95f1984600802610bae565b1980831691505092915050565b5f610be18383610bba565b9150826002028217905092915050565b610bfa826109b7565b67ffffffffffffffff811115610c1357610c126109c1565b5b610c1d8254610a1b565b610c28828285610b68565b5f60209050601f831160018114610c59575f8415610c47578287015190505b610c518582610bd6565b865550610cb8565b601f198416610c6786610a4b565b5f5b82811015610c8e57848901518255600182019150602085019450602081019050610c69565b86831015610cab5784890151610ca7601f891682610bba565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f808291508390505b6001851115610d4257808604811115610d1e57610d1d610cc0565b5b6001851615610d2d5780820291505b8081029050610d3b85610ced565b9450610d02565b94509492505050565b5f82610d5a5760019050610e15565b81610d67575f9050610e15565b8160018114610d7d5760028114610d8757610db6565b6001915050610e15565b60ff841115610d9957610d98610cc0565b5b8360020a915084821115610db057610daf610cc0565b5b50610e15565b5060208310610133831016604e8410600b8410161715610deb5782820a905083811115610de657610de5610cc0565b5b610e15565b610df88484846001610cf9565b92509050818404811115610e0f57610e0e610cc0565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610e3282610ac9565b9150610e3d83610e1c565b9250610e6a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484610d4b565b905092915050565b5f610e7c82610ac9565b9150610e8783610ac9565b9250828202610e9581610ac9565b91508282048414831517610eac57610eab610cc0565b5b5092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610edc82610eb3565b9050919050565b610eec81610ed2565b82525050565b5f602082019050610f055f830184610ee3565b92915050565b5f610f1582610ac9565b9150610f2083610ac9565b9250828201905080821115610f3857610f37610cc0565b5b92915050565b610f4781610ac9565b82525050565b5f606082019050610f605f830186610ee3565b610f6d6020830185610f3e565b610f7a6040830184610f3e565b949350505050565b5f602082019050610f955f830184610f3e565b92915050565b60805161533d610fc15f395f8181610225015281816121010152612157015261533d5ff3fe60806040526004361061021d575f3560e01c806370db69d611610122578063af504def116100aa578063d5a426061161006e578063d5a426061461093c578063dd0b281e14610979578063dd62ed3e146109a1578063dde415fa146109dd578063f2fde38b14610a07576102ee565b8063af504def1461085c578063b42781ee14610886578063b42dfa0d146108ae578063b4377a3e146108d8578063b4f243a414610900576102ee565b80638da5cb5b116100f15780638da5cb5b146107655780638fdada4a1461078f57806395d89b41146107b957806398bafaa3146107e3578063a9059cbb14610820576102ee565b806370db69d614610686578063750e8d10146106b05780637673bfa4146106ed5780637c3b3b8714610729576102ee565b8063333a0072116101a557806344cc09081161017457806344cc09081461057f578063544736e6146105bb5780635e927ceb146105e55780636a29f5e51461060d57806370a082311461064a576102ee565b8063333a0072146104b45780633860a393146104ca5780633fc0fdcb14610507578063422b9e2314610543576102ee565b806318160ddd116101ec57806318160ddd146103be57806323b872dd146103e857806325072d68146104245780632d12d34b14610460578063313ce5671461048a576102ee565b8063018a3741146102f25780630568e65e1461031c57806306fdde0314610358578063095ea7b314610382576102ee565b366102ee575f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163460405161026790613ad1565b5f6040518083038185875af1925050503d805f81146102a1576040519150601f19603f3d011682016040523d82523d5f602084013e6102a6565b606091505b505080915050806102ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102e390613b3f565b60405180910390fd5b005b5f80fd5b3480156102fd575f80fd5b50610306610a2f565b6040516103139190613b75565b60405180910390f35b348015610327575f80fd5b50610342600480360381019061033d9190613bf9565b610a35565b60405161034f9190613b75565b60405180910390f35b348015610363575f80fd5b5061036c610a4a565b6040516103799190613c84565b60405180910390f35b34801561038d575f80fd5b506103a860048036038101906103a39190613cce565b610ada565b6040516103b59190613d26565b60405180910390f35b3480156103c9575f80fd5b506103d2610afc565b6040516103df9190613b75565b60405180910390f35b3480156103f3575f80fd5b5061040e60048036038101906104099190613d3f565b610b05565b60405161041b9190613d26565b60405180910390f35b34801561042f575f80fd5b5061044a60048036038101906104459190613d8f565b610b33565b6040516104579190613c84565b60405180910390f35b34801561046b575f80fd5b50610474610bd9565b6040516104819190613b75565b60405180910390f35b348015610495575f80fd5b5061049e610bde565b6040516104ab9190613dd5565b60405180910390f35b3480156104bf575f80fd5b506104c8610be6565b005b3480156104d5575f80fd5b506104f060048036038101906104eb9190613dee565b610ce3565b6040516104fe929190613ee3565b60405180910390f35b348015610512575f80fd5b5061052d60048036038101906105289190613cce565b610e65565b60405161053a9190613fcf565b60405180910390f35b34801561054e575f80fd5b5061056960048036038101906105649190614011565b610f3b565b6040516105769190613c84565b60405180910390f35b34801561058a575f80fd5b506105a560048036038101906105a09190613d8f565b610fc7565b6040516105b29190613c84565b60405180910390f35b3480156105c6575f80fd5b506105cf61106d565b6040516105dc9190613d26565b60405180910390f35b3480156105f0575f80fd5b5061060b60048036038101906106069190613d8f565b6110c4565b005b348015610618575f80fd5b50610633600480360381019061062e9190613cce565b61115d565b60405161064192919061403c565b60405180910390f35b348015610655575f80fd5b50610670600480360381019061066b9190613bf9565b611188565b60405161067d9190613b75565b60405180910390f35b348015610691575f80fd5b5061069a6111cd565b6040516106a79190613b75565b60405180910390f35b3480156106bb575f80fd5b506106d660048036038101906106d19190614063565b6112d1565b6040516106e49291906141d5565b60405180910390f35b3480156106f8575f80fd5b50610713600480360381019061070e9190613d8f565b61150a565b6040516107209190613c84565b60405180910390f35b348015610734575f80fd5b5061074f600480360381019061074a9190614011565b6115b0565b60405161075c9190613fcf565b60405180910390f35b348015610770575f80fd5b5061077961166d565b6040516107869190614212565b60405180910390f35b34801561079a575f80fd5b506107a3611695565b6040516107b09190613b75565b60405180910390f35b3480156107c4575f80fd5b506107cd61169b565b6040516107da9190613c84565b60405180910390f35b3480156107ee575f80fd5b5061080960048036038101906108049190614063565b61172b565b604051610817929190614300565b60405180910390f35b34801561082b575f80fd5b5061084660048036038101906108419190613cce565b611908565b6040516108539190613d26565b60405180910390f35b348015610867575f80fd5b5061087061192a565b60405161087d9190613b75565b60405180910390f35b348015610891575f80fd5b506108ac60048036038101906108a79190613d8f565b611930565b005b3480156108b9575f80fd5b506108c26119c9565b6040516108cf9190613b75565b60405180910390f35b3480156108e3575f80fd5b506108fe60048036038101906108f9919061432e565b6119cf565b005b34801561090b575f80fd5b5061092660048036038101906109219190613cce565b611a5d565b6040516109339190613c84565b60405180910390f35b348015610947575f80fd5b50610962600480360381019061095d9190614063565b611aec565b604051610970929190614427565b60405180910390f35b348015610984575f80fd5b5061099f600480360381019061099a9190613bf9565b611d2a565b005b3480156109ac575f80fd5b506109c760048036038101906109c29190614455565b611e03565b6040516109d49190613b75565b60405180910390f35b3480156109e8575f80fd5b506109f1611e85565b6040516109fe9190613b75565b60405180910390f35b348015610a12575f80fd5b50610a2d6004803603810190610a289190613bf9565b611e8b565b005b60105481565b6013602052805f5260405f205f915090505481565b606060038054610a59906144c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610a85906144c0565b8015610ad05780601f10610aa757610100808354040283529160200191610ad0565b820191905f5260205f20905b815481529060010190602001808311610ab357829003601f168201915b5050505050905090565b5f80610ae4611f5d565b9050610af1818585611f64565b600191505092915050565b5f600254905090565b5f80610b0f611f5d565b9050610b1c858285611f76565b610b27858585612008565b60019150509392505050565b60078181548110610b42575f80fd5b905f5260205f20015f915090508054610b5a906144c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610b86906144c0565b8015610bd15780601f10610ba857610100808354040283529160200191610bd1565b820191905f5260205f20905b815481529060010190602001808311610bb457829003601f168201915b505050505081565b600181565b5f6009905090565b3373ffffffffffffffffffffffffffffffffffffffff1660055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610c75576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6c9061453a565b60405180910390fd5b5f60055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f6e4ee811a17215345b89e3506064ff2d62f4feedff3566e9d09219cda7e8cadb60405160405180910390a1565b5f60606010548410610d42575f8067ffffffffffffffff811115610d0a57610d09614558565b5b604051908082528060200260200182016040528015610d385781602001602082028036833780820191505090505b5091509150610e5e565b5f8385610d4f91906145b2565b9050601054811115610d615760105490505b8481610d6d91906145e5565b92508267ffffffffffffffff811115610d8957610d88614558565b5b604051908082528060200260200182016040528015610db75781602001602082028036833780820191505090505b5091505f8590505b83811015610e5b57600e5f8288610dd691906145b2565b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16838281518110610e1657610e15614618565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050806001019050610dbf565b50505b9250929050565b610e6d613a66565b3073ffffffffffffffffffffffffffffffffffffffff16637c3b3b8760125f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f206040518263ffffffff1660e01b8152600401610ef191906146b7565b5f60405180830381865afa158015610f0b573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610f33919061488a565b905092915050565b6060610fc03073ffffffffffffffffffffffffffffffffffffffff16637c3b3b87846040518263ffffffff1660e01b8152600401610f799190614924565b5f60405180830381865afa158015610f93573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610fbb919061488a565b6122b7565b9050919050565b60088181548110610fd6575f80fd5b905f5260205f20015f915090508054610fee906144c0565b80601f016020809104026020016040519081016040528092919081815260200182805461101a906144c0565b80156110655780601f1061103c57610100808354040283529160200191611065565b820191905f5260205f20905b81548152906001019060200180831161104857829003601f168201915b505050505081565b5f8073ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415905090565b3373ffffffffffffffffffffffffffffffffffffffff1660055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611153576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114a9061453a565b60405180910390fd5b80600a8190555050565b6012602052815f5260405f20602052805f5260405f205f9150915050805f0154908060010154905082565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b5f6111d661106d565b6111fc576009600a6111e89190614a6c565b6103e86111f59190614ab6565b90506112ce565b5f6127106001600c544261121091906145e5565b6009600a61121e9190614a6c565b6103e861122b9190614ab6565b6112359190614ab6565b61123f9190614ab6565b6112499190614b24565b61271060056009600a61125c9190614a6c565b6103e86112699190614ab6565b6112739190614ab6565b61127d9190614b24565b61128791906145b2565b90506009600a6112979190614a6c565b6103e86112a49190614ab6565b8111156112c9576009600a6112b99190614a6c565b6103e86112c69190614ab6565b90505b809150505b90565b5f60605f60135f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905080851061137b575f8067ffffffffffffffff81111561133757611336614558565b5b60405190808252806020026020018201604052801561137057816020015b61135d613a66565b8152602001906001900390816113555790505b509250925050611502565b5f848661138891906145b2565b905081811115611396578190505b85816113a291906145e5565b93508367ffffffffffffffff8111156113be576113bd614558565b5b6040519080825280602002602001820160405280156113f757816020015b6113e4613a66565b8152602001906001900390816113dc5790505b5092505f5b848110156114fe573073ffffffffffffffffffffffffffffffffffffffff16637c3b3b8760125f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f848b61146a91906145b2565b81526020019081526020015f206040518263ffffffff1660e01b815260040161149391906146b7565b5f60405180830381865afa1580156114ad573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906114d5919061488a565b8482815181106114e8576114e7614618565b5b60200260200101819052508060010190506113fc565b5050505b935093915050565b60068181548110611519575f80fd5b905f5260205f20015f915090508054611531906144c0565b80601f016020809104026020016040519081016040528092919081815260200182805461155d906144c0565b80156115a85780601f1061157f576101008083540402835291602001916115a8565b820191905f5260205f20905b81548152906001019060200180831161158b57829003601f168201915b505050505081565b6115b8613a66565b5f6040518060400160405280848036038101906115d59190614ba1565b81526020015f81525090506040518060800160405280600a60146115f8856123a4565b6116029190614bcc565b61160c91906145b2565b81526020016004600861161e856123a4565b6116289190614bcc565b61163291906145b2565b815260200161164a6007611645856123a4565b6123fa565b8152602001611662600861165d856123a4565b6123fa565b815250915050919050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6103e881565b6060600480546116aa906144c0565b80601f01602080910402602001604051908101604052809291908181526020018280546116d6906144c0565b80156117215780601f106116f857610100808354040283529160200191611721565b820191905f5260205f20905b81548152906001019060200180831161170457829003601f168201915b5050505050905090565b5f60605f60135f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508085106117d5575f8067ffffffffffffffff81111561179157611790614558565b5b6040519080825280602002602001820160405280156117ca57816020015b6117b7613a8c565b8152602001906001900390816117af5790505b509250925050611900565b5f84866117e291906145b2565b9050818111156117f0578190505b85816117fc91906145e5565b93508367ffffffffffffffff81111561181857611817614558565b5b60405190808252806020026020018201604052801561185157816020015b61183e613a8c565b8152602001906001900390816118365790505b5092505f5b848110156118fc5760125f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82896118a891906145b2565b81526020019081526020015f206040518060400160405290815f82015481526020016001820154815250508482815181106118e6576118e5614618565b5b6020026020010181905250806001019050611856565b5050505b935093915050565b5f80611912611f5d565b905061191f818585612008565b600191505092915050565b60145481565b3373ffffffffffffffffffffffffffffffffffffffff1660055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119b69061453a565b60405180910390fd5b8060098190555050565b60115481565b60135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20548210611a4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a4590614c46565b60405180910390fd5b611a593383836124ba565b5050565b6060611ae43073ffffffffffffffffffffffffffffffffffffffff16633fc0fdcb85856040518363ffffffff1660e01b8152600401611a9d929190614c64565b5f60405180830381865afa158015611ab7573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611adf919061488a565b6122b7565b905092915050565b5f60605f60135f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050808510611b90575f8067ffffffffffffffff811115611b5257611b51614558565b5b604051908082528060200260200182016040528015611b8557816020015b6060815260200190600190039081611b705790505b509250925050611d22565b5f8486611b9d91906145b2565b905081811115611bb9578190508086611bb691906145e5565b93505b8367ffffffffffffffff811115611bd357611bd2614558565b5b604051908082528060200260200182016040528015611c0657816020015b6060815260200190600190039081611bf15790505b5092505f805f90508791505b82821015611d1d57611ce83073ffffffffffffffffffffffffffffffffffffffff16637c3b3b8760125f8d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f206040518263ffffffff1660e01b8152600401611ca191906146b7565b5f60405180830381865afa158015611cbb573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611ce3919061488a565b6122b7565b858280611cf490614c8b565b935081518110611d0757611d06614618565b5b6020026020010181905250816001019150611c12565b505050505b935093915050565b3373ffffffffffffffffffffffffffffffffffffffff1660055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611db9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611db09061453a565b60405180910390fd5b80600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555042600c8190555050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b6103e881565b3373ffffffffffffffffffffffffffffffffffffffff1660055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611f1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f119061453a565b60405180910390fd5b8060055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f33905090565b611f718383836001612559565b505050565b5f611f818484611e03565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146120025781811015611ff3578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401611fea93929190614cd2565b60405180910390fd5b61200184848484035f612559565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16148061206f575061dead73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b156120845761207f838383612728565b6122b2565b61208c61106d565b1580156121a657505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614806120f957503073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b8061214f57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b806121a557507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b5b156121bb576121b6838383612a22565b6122b2565b600b60149054906101000a900460ff16156121e0576121db838383612a22565b6122b2565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036122435761223e8282612b12565b6122b2565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036122a6576122a18382612bef565b6122b2565b6122b1838383612728565b5b505050565b6060805f5b8360200151811015612358575f81601e6122d69190614ab6565b60326122e291906145b2565b90505f82601e6122f29190614ab6565b60326122fe91906145b2565b90508361230a83612d69565b61231383612d69565b61231f895f0151612d69565b8960400151604051602001612338959493929190614eb3565b6040516020818303038152906040529350505080806001019150506122bc565b5060065f8154811061236d5761236c614618565b5b905f5260205f200183606001518260405160200161238d939291906151aa565b604051602081830303815290604052915050919050565b5f815f01515f0151825f0151602001518360200180518091906123c690614c8b565b8152506040516020016123db9392919061523c565b604051602081830303815290604052805190602001205f1c9050919050565b60605f83805490508361240d9190614bcc565b905083818154811061242257612421614618565b5b905f5260205f20018054612435906144c0565b80601f0160208091040260200160405190810160405280929190818152602001828054612461906144c0565b80156124ac5780601f10612483576101008083540402835291602001916124ac565b820191905f5260205f20905b81548152906001019060200180831161248f57829003601f168201915b505050505091505092915050565b5f60125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f206040518060400160405290815f8201548152602001600182015481525050905061253f84836009600a61253a9190614a6c565b612e33565b6125498484612ef4565b6125538282613138565b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036125c9575f6040517fe602df050000000000000000000000000000000000000000000000000000000081526004016125c09190614212565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612639575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016126309190614212565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015612722578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516127199190613b75565b60405180910390a35b50505050565b6127306132b7565b5f61273a84611188565b90505f828261274991906145e5565b90505f61275585611188565b90505f848261276491906145b2565b90505f73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614806127cd575061dead73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16145b156127d9575f91505f90505b5f6127e2610bde565b600a6127ee9190614a6c565b846127f99190614b24565b612801610bde565b600a61280d9190614a6c565b866128189190614b24565b61282291906145e5565b90505f61282d610bde565b600a6128399190614a6c565b846128449190614b24565b61284c610bde565b600a6128589190614a6c565b846128639190614b24565b61286d91906145e5565b90505f8290508181111561287f578190505b5f8060135f8d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f91505b82821015612973575f810315612973575f816128e090615278565b91508190505f60125f8f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f206040518060400160405290815f8201548152602001600182015481525050905061295c8e83612ef4565b6129668d82613138565b50508160010191506128c5565b5f8290508392505b858310156129a9575f8261298e90615278565b925082905061299d8e82612ef4565b5082600101925061297b565b8092505b84831015612a00575f604051806040016040528060155f81546129cf90614c8b565b91905081905581526020016129e56103e86132fd565b81525090506129f48d82613138565b508260010192506129ad565b612a0b8d8d8d612e33565b50505050505050505050612a1d613350565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612a92575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401612a899190614212565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612b02575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401612af99190614212565b60405180910390fd5b612b0d83838361335a565b505050565b612b1a6132b7565b5f612b2483611188565b90505f8282612b3391906145b2565b90505f612b3e610bde565b600a612b4a9190614a6c565b83612b559190614b24565b612b5d610bde565b600a612b699190614a6c565b83612b749190614b24565b612b7e91906145e5565b90505f5b81811015612bd5575f604051806040016040528060155f8154612ba490614c8b565b9190508190558152602001612bba6103e86132fd565b8152509050612bc98782613138565b50806001019050612b82565b612bdf8686613573565b50505050612beb613350565b5050565b6001600b60146101000a81548160ff021916908315150217905550612c126132b7565b5f612c1c83611188565b90505f8282612c2b91906145e5565b90505f612c36610bde565b600a612c429190614a6c565b82612c4d9190614b24565b612c55610bde565b600a612c619190614a6c565b84612c6c9190614b24565b612c7691906145e5565b90505f8060135f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f91505b82821015612d12576103e86011541015612ce85760115f8154612ce090614c8b565b919050819055505b5f811115612d0757612d068782612cfe90615278565b925082612ef4565b5b816001019150612cbe565b612d3e87600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688612008565b5050505050612d4b613350565b5f600b60146101000a81548160ff0219169083151502179055505050565b60605f6001612d7784613624565b0190505f8167ffffffffffffffff811115612d9557612d94614558565b5b6040519080825280601f01601f191660200182016040528015612dc75781602001600182028036833780820191505090505b5090505f82602001820190505b600115612e28578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612e1d57612e1c614af7565b5b0494505f8503612dd4575b819350505050919050565b6001600b60146101000a81548160ff0219169083151502179055505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480612eb5575061dead73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b15612ec957612ec48382613775565b612ed5565b612ed4838383612a22565b5b5f600b60146101000a81548160ff021916908315150217905550505050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160315613134575f60135f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154612f9390615278565b91905081905503612fa857612fa7826137f4565b5b60145f8154612fb690615278565b919050819055505f60135f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508082146130d6575f60125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f206040518060400160405290815f820154815260200160018201548152505090508060125f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f820151815f015560208201518160010155905050505b60125f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8281526020019081526020015f205f8082015f9055600182015f90555050505b5050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603156132b357600160135f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f81546131d890614c8b565b919050819055036131ed576131ec826139b8565b5b60145f81546131fb90614c8b565b919050819055505f600160135f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205461324d91906145e5565b90508160125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205f820151815f015560208201518160010155905050505b5050565b6002600d54036132f3576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600d81905550565b5f6103e86011548361330f9190614ab6565b6133199190614b24565b91505f820361332757600191505b600160115411156133485760115f815461334090615278565b919050819055505b819050919050565b6001600d81905550565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036133aa578060025f82825461339e91906145b2565b92505081905550613478565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015613433578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161342a93929190614cd2565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036134bf578060025f8282540392505081905550613509565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516135669190613b75565b60405180910390a3505050565b8061357c6111cd565b8111156135be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135b5906152e9565b60405180910390fd5b6001600b60146101000a81548160ff021916908315150217905550613605600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168484612a22565b5f600b60146101000a81548160ff021916908315150217905550505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310613680577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161367657613675614af7565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106136bd576d04ee2d6d415b85acef810000000083816136b3576136b2614af7565b5b0492506020810190505b662386f26fc1000083106136ec57662386f26fc1000083816136e2576136e1614af7565b5b0492506010810190505b6305f5e1008310613715576305f5e100838161370b5761370a614af7565b5b0492506008810190505b612710831061373a5761271083816137305761372f614af7565b5b0492506004810190505b6064831061375d576064838161375357613752614af7565b5b0492506002810190505b600a831061376c576001810190505b80915050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036137e5575f6040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016137dc9190614212565b60405180910390fd5b6137f0825f8361335a565b5050565b5f60105403156139b5575f600f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050600160105461384e91906145e5565b8114613929575f600e5f600160105461386791906145e5565b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080600e5f8481526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b60105f815461393790615278565b91905081905550600f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055600e5f60105481526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055505b50565b5f60105f8154809291906139cb90614c8b565b91905055905081600e5f8381526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505050565b60405180608001604052805f81526020015f815260200160608152602001606081525090565b60405180604001604052805f81526020015f81525090565b5f81905092915050565b50565b5f613abc5f83613aa4565b9150613ac782613aae565b5f82019050919050565b5f613adb82613ab1565b9150819050919050565b5f82825260208201905092915050565b7f63616e206e6f74206765742065746865720000000000000000000000000000005f82015250565b5f613b29601183613ae5565b9150613b3482613af5565b602082019050919050565b5f6020820190508181035f830152613b5681613b1d565b9050919050565b5f819050919050565b613b6f81613b5d565b82525050565b5f602082019050613b885f830184613b66565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613bc882613b9f565b9050919050565b613bd881613bbe565b8114613be2575f80fd5b50565b5f81359050613bf381613bcf565b92915050565b5f60208284031215613c0e57613c0d613b97565b5b5f613c1b84828501613be5565b91505092915050565b5f81519050919050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f613c5682613c24565b613c608185613ae5565b9350613c70818560208601613c2e565b613c7981613c3c565b840191505092915050565b5f6020820190508181035f830152613c9c8184613c4c565b905092915050565b613cad81613b5d565b8114613cb7575f80fd5b50565b5f81359050613cc881613ca4565b92915050565b5f8060408385031215613ce457613ce3613b97565b5b5f613cf185828601613be5565b9250506020613d0285828601613cba565b9150509250929050565b5f8115159050919050565b613d2081613d0c565b82525050565b5f602082019050613d395f830184613d17565b92915050565b5f805f60608486031215613d5657613d55613b97565b5b5f613d6386828701613be5565b9350506020613d7486828701613be5565b9250506040613d8586828701613cba565b9150509250925092565b5f60208284031215613da457613da3613b97565b5b5f613db184828501613cba565b91505092915050565b5f60ff82169050919050565b613dcf81613dba565b82525050565b5f602082019050613de85f830184613dc6565b92915050565b5f8060408385031215613e0457613e03613b97565b5b5f613e1185828601613cba565b9250506020613e2285828601613cba565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613e5e81613bbe565b82525050565b5f613e6f8383613e55565b60208301905092915050565b5f602082019050919050565b5f613e9182613e2c565b613e9b8185613e36565b9350613ea683613e46565b805f5b83811015613ed6578151613ebd8882613e64565b9750613ec883613e7b565b925050600181019050613ea9565b5085935050505092915050565b5f604082019050613ef65f830185613b66565b8181036020830152613f088184613e87565b90509392505050565b613f1a81613b5d565b82525050565b5f82825260208201905092915050565b5f613f3a82613c24565b613f448185613f20565b9350613f54818560208601613c2e565b613f5d81613c3c565b840191505092915050565b5f608083015f830151613f7d5f860182613f11565b506020830151613f906020860182613f11565b5060408301518482036040860152613fa88282613f30565b91505060608301518482036060860152613fc28282613f30565b9150508091505092915050565b5f6020820190508181035f830152613fe78184613f68565b905092915050565b5f80fd5b5f6040828403121561400857614007613fef565b5b81905092915050565b5f6040828403121561402657614025613b97565b5b5f61403384828501613ff3565b91505092915050565b5f60408201905061404f5f830185613b66565b61405c6020830184613b66565b9392505050565b5f805f6060848603121561407a57614079613b97565b5b5f61408786828701613be5565b935050602061409886828701613cba565b92505060406140a986828701613cba565b9150509250925092565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f608083015f8301516140f15f860182613f11565b5060208301516141046020860182613f11565b506040830151848203604086015261411c8282613f30565b915050606083015184820360608601526141368282613f30565b9150508091505092915050565b5f61414e83836140dc565b905092915050565b5f602082019050919050565b5f61416c826140b3565b61417681856140bd565b935083602082028501614188856140cd565b805f5b858110156141c357848403895281516141a48582614143565b94506141af83614156565b925060208a0199505060018101905061418b565b50829750879550505050505092915050565b5f6040820190506141e85f830185613b66565b81810360208301526141fa8184614162565b90509392505050565b61420c81613bbe565b82525050565b5f6020820190506142255f830184614203565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b604082015f8201516142685f850182613f11565b50602082015161427b6020850182613f11565b50505050565b5f61428c8383614254565b60408301905092915050565b5f602082019050919050565b5f6142ae8261422b565b6142b88185614235565b93506142c383614245565b805f5b838110156142f35781516142da8882614281565b97506142e583614298565b9250506001810190506142c6565b5085935050505092915050565b5f6040820190506143135f830185613b66565b818103602083015261432581846142a4565b90509392505050565b5f806040838503121561434457614343613b97565b5b5f61435185828601613cba565b925050602061436285828601613be5565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f6143a08383613f30565b905092915050565b5f602082019050919050565b5f6143be8261436c565b6143c88185614376565b9350836020820285016143da85614386565b805f5b8581101561441557848403895281516143f68582614395565b9450614401836143a8565b925060208a019950506001810190506143dd565b50829750879550505050505092915050565b5f60408201905061443a5f830185613b66565b818103602083015261444c81846143b4565b90509392505050565b5f806040838503121561446b5761446a613b97565b5b5f61447885828601613be5565b925050602061448985828601613be5565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806144d757607f821691505b6020821081036144ea576144e9614493565b5b50919050565b7f6f6e6c79206f776e6572000000000000000000000000000000000000000000005f82015250565b5f614524600a83613ae5565b915061452f826144f0565b602082019050919050565b5f6020820190508181035f83015261455181614518565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6145bc82613b5d565b91506145c783613b5d565b92508282019050808211156145df576145de614585565b5b92915050565b5f6145ef82613b5d565b91506145fa83613b5d565b925082820390508181111561461257614611614585565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f815f1c9050919050565b5f819050919050565b5f61466b61466683614645565b614650565b9050919050565b604082015f80830154905061468681614659565b6146925f860182613f11565b50600183015490506146a381614659565b6146b06020860182613f11565b5050505050565b5f6040820190506146ca5f830184614672565b92915050565b5f80fd5b6146dd82613c3c565b810181811067ffffffffffffffff821117156146fc576146fb614558565b5b80604052505050565b5f61470e613b8e565b905061471a82826146d4565b919050565b5f80fd5b5f8151905061473181613ca4565b92915050565b5f80fd5b5f80fd5b5f67ffffffffffffffff82111561475957614758614558565b5b61476282613c3c565b9050602081019050919050565b5f61478161477c8461473f565b614705565b90508281526020810184848401111561479d5761479c61473b565b5b6147a8848285613c2e565b509392505050565b5f82601f8301126147c4576147c3614737565b5b81516147d484826020860161476f565b91505092915050565b5f608082840312156147f2576147f16146d0565b5b6147fc6080614705565b90505f61480b84828501614723565b5f83015250602061481e84828501614723565b602083015250604082015167ffffffffffffffff8111156148425761484161471f565b5b61484e848285016147b0565b604083015250606082015167ffffffffffffffff8111156148725761487161471f565b5b61487e848285016147b0565b60608301525092915050565b5f6020828403121561489f5761489e613b97565b5b5f82015167ffffffffffffffff8111156148bc576148bb613b9b565b5b6148c8848285016147dd565b91505092915050565b5f6148df6020840184613cba565b905092915050565b604082016148f75f8301836148d1565b6149035f850182613f11565b5061491160208301836148d1565b61491e6020850182613f11565b50505050565b5f6040820190506149375f8301846148e7565b92915050565b5f8160011c9050919050565b5f808291508390505b60018511156149925780860481111561496e5761496d614585565b5b600185161561497d5780820291505b808102905061498b8561493d565b9450614952565b94509492505050565b5f826149aa5760019050614a65565b816149b7575f9050614a65565b81600181146149cd57600281146149d757614a06565b6001915050614a65565b60ff8411156149e9576149e8614585565b5b8360020a915084821115614a00576149ff614585565b5b50614a65565b5060208310610133831016604e8410600b8410161715614a3b5782820a905083811115614a3657614a35614585565b5b614a65565b614a488484846001614949565b92509050818404811115614a5f57614a5e614585565b5b81810290505b9392505050565b5f614a7682613b5d565b9150614a8183613dba565b9250614aae7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848461499b565b905092915050565b5f614ac082613b5d565b9150614acb83613b5d565b9250828202614ad981613b5d565b91508282048414831517614af057614aef614585565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f614b2e82613b5d565b9150614b3983613b5d565b925082614b4957614b48614af7565b5b828204905092915050565b5f60408284031215614b6957614b686146d0565b5b614b736040614705565b90505f614b8284828501613cba565b5f830152506020614b9584828501613cba565b60208301525092915050565b5f60408284031215614bb657614bb5613b97565b5b5f614bc384828501614b54565b91505092915050565b5f614bd682613b5d565b9150614be183613b5d565b925082614bf157614bf0614af7565b5b828206905092915050565b7f696e636f727265637420696e64657800000000000000000000000000000000005f82015250565b5f614c30600f83613ae5565b9150614c3b82614bfc565b602082019050919050565b5f6020820190508181035f830152614c5d81614c24565b9050919050565b5f604082019050614c775f830185614203565b614c846020830184613b66565b9392505050565b5f614c9582613b5d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614cc757614cc6614585565b5b600182019050919050565b5f606082019050614ce55f830186614203565b614cf26020830185613b66565b614cff6040830184613b66565b949350505050565b5f81905092915050565b5f614d1b82613c24565b614d258185614d07565b9350614d35818560208601613c2e565b80840191505092915050565b7f3c636972636c652063783d2700000000000000000000000000000000000000005f82015250565b5f614d75600c83614d07565b9150614d8082614d41565b600c82019050919050565b7f272063793d2700000000000000000000000000000000000000000000000000005f82015250565b5f614dbf600683614d07565b9150614dca82614d8b565b600682019050919050565b7f2720723d270000000000000000000000000000000000000000000000000000005f82015250565b5f614e09600583614d07565b9150614e1482614dd5565b600582019050919050565b7f272066696c6c3d270000000000000000000000000000000000000000000000005f82015250565b5f614e53600883614d07565b9150614e5e82614e1f565b600882019050919050565b7f27202f3e000000000000000000000000000000000000000000000000000000005f82015250565b5f614e9d600483614d07565b9150614ea882614e69565b600482019050919050565b5f614ebe8288614d11565b9150614ec982614d69565b9150614ed58287614d11565b9150614ee082614db3565b9150614eec8286614d11565b9150614ef782614dfd565b9150614f038285614d11565b9150614f0e82614e47565b9150614f1a8284614d11565b9150614f2582614e91565b91508190509695505050505050565b7f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f32305f8201527f30302f737667272076696577426f783d273020302031303020313030273e0000602082015250565b5f614f8e603e83614d07565b9150614f9982614f34565b603e82019050919050565b7f3c726563742077696474683d2731303027206865696768743d273130302720665f8201527f696c6c3d27000000000000000000000000000000000000000000000000000000602082015250565b5f614ffe602583614d07565b915061500982614fa4565b602582019050919050565b5f819050815f5260205f209050919050565b5f8154615032816144c0565b61503c8186614d07565b9450600182165f8114615056576001811461506b5761509d565b60ff198316865281151582028601935061509d565b61507485615014565b5f5b8381101561509557815481890152600182019150602081019050615076565b838801955050505b50505092915050565b7f272f3e00000000000000000000000000000000000000000000000000000000005f82015250565b5f6150da600383614d07565b91506150e5826150a6565b600382019050919050565b7f3c636972636c652063783d273530272063793d2735302720723d2731352720665f8201527f696c6c3d27000000000000000000000000000000000000000000000000000000602082015250565b5f61514a602583614d07565b9150615155826150f0565b602582019050919050565b7f3c2f7376673e00000000000000000000000000000000000000000000000000005f82015250565b5f615194600683614d07565b915061519f82615160565b600682019050919050565b5f6151b482614f82565b91506151bf82614ff2565b91506151cb8286615026565b91506151d6826150ce565b91506151e18261513e565b91506151ed8285614d11565b91506151f882614e91565b91506152048284614d11565b915061520f82615188565b9150819050949350505050565b5f819050919050565b61523661523182613b5d565b61521c565b82525050565b5f6152478286615225565b6020820191506152578285615225565b6020820191506152678284615225565b602082019150819050949350505050565b5f61528282613b5d565b91505f820361529457615293614585565b5b600182039050919050565b7f6d617820627579000000000000000000000000000000000000000000000000005f82015250565b5f6152d3600783613ae5565b91506152de8261529f565b602082019050919050565b5f6020820190508181035f830152615300816152c7565b905091905056fea26469706673582212200ac28cd5a91a0ed25c4d3006ad3ed096ab8e379f729d331d62c8f74a3106e51264736f6c63430008190033
Deployed Bytecode
0x60806040526004361061021d575f3560e01c806370db69d611610122578063af504def116100aa578063d5a426061161006e578063d5a426061461093c578063dd0b281e14610979578063dd62ed3e146109a1578063dde415fa146109dd578063f2fde38b14610a07576102ee565b8063af504def1461085c578063b42781ee14610886578063b42dfa0d146108ae578063b4377a3e146108d8578063b4f243a414610900576102ee565b80638da5cb5b116100f15780638da5cb5b146107655780638fdada4a1461078f57806395d89b41146107b957806398bafaa3146107e3578063a9059cbb14610820576102ee565b806370db69d614610686578063750e8d10146106b05780637673bfa4146106ed5780637c3b3b8714610729576102ee565b8063333a0072116101a557806344cc09081161017457806344cc09081461057f578063544736e6146105bb5780635e927ceb146105e55780636a29f5e51461060d57806370a082311461064a576102ee565b8063333a0072146104b45780633860a393146104ca5780633fc0fdcb14610507578063422b9e2314610543576102ee565b806318160ddd116101ec57806318160ddd146103be57806323b872dd146103e857806325072d68146104245780632d12d34b14610460578063313ce5671461048a576102ee565b8063018a3741146102f25780630568e65e1461031c57806306fdde0314610358578063095ea7b314610382576102ee565b366102ee575f7f000000000000000000000000ee423e5888f51d7a3248904ad232499ce1d10ff173ffffffffffffffffffffffffffffffffffffffff163460405161026790613ad1565b5f6040518083038185875af1925050503d805f81146102a1576040519150601f19603f3d011682016040523d82523d5f602084013e6102a6565b606091505b505080915050806102ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102e390613b3f565b60405180910390fd5b005b5f80fd5b3480156102fd575f80fd5b50610306610a2f565b6040516103139190613b75565b60405180910390f35b348015610327575f80fd5b50610342600480360381019061033d9190613bf9565b610a35565b60405161034f9190613b75565b60405180910390f35b348015610363575f80fd5b5061036c610a4a565b6040516103799190613c84565b60405180910390f35b34801561038d575f80fd5b506103a860048036038101906103a39190613cce565b610ada565b6040516103b59190613d26565b60405180910390f35b3480156103c9575f80fd5b506103d2610afc565b6040516103df9190613b75565b60405180910390f35b3480156103f3575f80fd5b5061040e60048036038101906104099190613d3f565b610b05565b60405161041b9190613d26565b60405180910390f35b34801561042f575f80fd5b5061044a60048036038101906104459190613d8f565b610b33565b6040516104579190613c84565b60405180910390f35b34801561046b575f80fd5b50610474610bd9565b6040516104819190613b75565b60405180910390f35b348015610495575f80fd5b5061049e610bde565b6040516104ab9190613dd5565b60405180910390f35b3480156104bf575f80fd5b506104c8610be6565b005b3480156104d5575f80fd5b506104f060048036038101906104eb9190613dee565b610ce3565b6040516104fe929190613ee3565b60405180910390f35b348015610512575f80fd5b5061052d60048036038101906105289190613cce565b610e65565b60405161053a9190613fcf565b60405180910390f35b34801561054e575f80fd5b5061056960048036038101906105649190614011565b610f3b565b6040516105769190613c84565b60405180910390f35b34801561058a575f80fd5b506105a560048036038101906105a09190613d8f565b610fc7565b6040516105b29190613c84565b60405180910390f35b3480156105c6575f80fd5b506105cf61106d565b6040516105dc9190613d26565b60405180910390f35b3480156105f0575f80fd5b5061060b60048036038101906106069190613d8f565b6110c4565b005b348015610618575f80fd5b50610633600480360381019061062e9190613cce565b61115d565b60405161064192919061403c565b60405180910390f35b348015610655575f80fd5b50610670600480360381019061066b9190613bf9565b611188565b60405161067d9190613b75565b60405180910390f35b348015610691575f80fd5b5061069a6111cd565b6040516106a79190613b75565b60405180910390f35b3480156106bb575f80fd5b506106d660048036038101906106d19190614063565b6112d1565b6040516106e49291906141d5565b60405180910390f35b3480156106f8575f80fd5b50610713600480360381019061070e9190613d8f565b61150a565b6040516107209190613c84565b60405180910390f35b348015610734575f80fd5b5061074f600480360381019061074a9190614011565b6115b0565b60405161075c9190613fcf565b60405180910390f35b348015610770575f80fd5b5061077961166d565b6040516107869190614212565b60405180910390f35b34801561079a575f80fd5b506107a3611695565b6040516107b09190613b75565b60405180910390f35b3480156107c4575f80fd5b506107cd61169b565b6040516107da9190613c84565b60405180910390f35b3480156107ee575f80fd5b5061080960048036038101906108049190614063565b61172b565b604051610817929190614300565b60405180910390f35b34801561082b575f80fd5b5061084660048036038101906108419190613cce565b611908565b6040516108539190613d26565b60405180910390f35b348015610867575f80fd5b5061087061192a565b60405161087d9190613b75565b60405180910390f35b348015610891575f80fd5b506108ac60048036038101906108a79190613d8f565b611930565b005b3480156108b9575f80fd5b506108c26119c9565b6040516108cf9190613b75565b60405180910390f35b3480156108e3575f80fd5b506108fe60048036038101906108f9919061432e565b6119cf565b005b34801561090b575f80fd5b5061092660048036038101906109219190613cce565b611a5d565b6040516109339190613c84565b60405180910390f35b348015610947575f80fd5b50610962600480360381019061095d9190614063565b611aec565b604051610970929190614427565b60405180910390f35b348015610984575f80fd5b5061099f600480360381019061099a9190613bf9565b611d2a565b005b3480156109ac575f80fd5b506109c760048036038101906109c29190614455565b611e03565b6040516109d49190613b75565b60405180910390f35b3480156109e8575f80fd5b506109f1611e85565b6040516109fe9190613b75565b60405180910390f35b348015610a12575f80fd5b50610a2d6004803603810190610a289190613bf9565b611e8b565b005b60105481565b6013602052805f5260405f205f915090505481565b606060038054610a59906144c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610a85906144c0565b8015610ad05780601f10610aa757610100808354040283529160200191610ad0565b820191905f5260205f20905b815481529060010190602001808311610ab357829003601f168201915b5050505050905090565b5f80610ae4611f5d565b9050610af1818585611f64565b600191505092915050565b5f600254905090565b5f80610b0f611f5d565b9050610b1c858285611f76565b610b27858585612008565b60019150509392505050565b60078181548110610b42575f80fd5b905f5260205f20015f915090508054610b5a906144c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610b86906144c0565b8015610bd15780601f10610ba857610100808354040283529160200191610bd1565b820191905f5260205f20905b815481529060010190602001808311610bb457829003601f168201915b505050505081565b600181565b5f6009905090565b3373ffffffffffffffffffffffffffffffffffffffff1660055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610c75576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6c9061453a565b60405180910390fd5b5f60055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f6e4ee811a17215345b89e3506064ff2d62f4feedff3566e9d09219cda7e8cadb60405160405180910390a1565b5f60606010548410610d42575f8067ffffffffffffffff811115610d0a57610d09614558565b5b604051908082528060200260200182016040528015610d385781602001602082028036833780820191505090505b5091509150610e5e565b5f8385610d4f91906145b2565b9050601054811115610d615760105490505b8481610d6d91906145e5565b92508267ffffffffffffffff811115610d8957610d88614558565b5b604051908082528060200260200182016040528015610db75781602001602082028036833780820191505090505b5091505f8590505b83811015610e5b57600e5f8288610dd691906145b2565b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16838281518110610e1657610e15614618565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050806001019050610dbf565b50505b9250929050565b610e6d613a66565b3073ffffffffffffffffffffffffffffffffffffffff16637c3b3b8760125f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f206040518263ffffffff1660e01b8152600401610ef191906146b7565b5f60405180830381865afa158015610f0b573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610f33919061488a565b905092915050565b6060610fc03073ffffffffffffffffffffffffffffffffffffffff16637c3b3b87846040518263ffffffff1660e01b8152600401610f799190614924565b5f60405180830381865afa158015610f93573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190610fbb919061488a565b6122b7565b9050919050565b60088181548110610fd6575f80fd5b905f5260205f20015f915090508054610fee906144c0565b80601f016020809104026020016040519081016040528092919081815260200182805461101a906144c0565b80156110655780601f1061103c57610100808354040283529160200191611065565b820191905f5260205f20905b81548152906001019060200180831161104857829003601f168201915b505050505081565b5f8073ffffffffffffffffffffffffffffffffffffffff16600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415905090565b3373ffffffffffffffffffffffffffffffffffffffff1660055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611153576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114a9061453a565b60405180910390fd5b80600a8190555050565b6012602052815f5260405f20602052805f5260405f205f9150915050805f0154908060010154905082565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b5f6111d661106d565b6111fc576009600a6111e89190614a6c565b6103e86111f59190614ab6565b90506112ce565b5f6127106001600c544261121091906145e5565b6009600a61121e9190614a6c565b6103e861122b9190614ab6565b6112359190614ab6565b61123f9190614ab6565b6112499190614b24565b61271060056009600a61125c9190614a6c565b6103e86112699190614ab6565b6112739190614ab6565b61127d9190614b24565b61128791906145b2565b90506009600a6112979190614a6c565b6103e86112a49190614ab6565b8111156112c9576009600a6112b99190614a6c565b6103e86112c69190614ab6565b90505b809150505b90565b5f60605f60135f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905080851061137b575f8067ffffffffffffffff81111561133757611336614558565b5b60405190808252806020026020018201604052801561137057816020015b61135d613a66565b8152602001906001900390816113555790505b509250925050611502565b5f848661138891906145b2565b905081811115611396578190505b85816113a291906145e5565b93508367ffffffffffffffff8111156113be576113bd614558565b5b6040519080825280602002602001820160405280156113f757816020015b6113e4613a66565b8152602001906001900390816113dc5790505b5092505f5b848110156114fe573073ffffffffffffffffffffffffffffffffffffffff16637c3b3b8760125f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f848b61146a91906145b2565b81526020019081526020015f206040518263ffffffff1660e01b815260040161149391906146b7565b5f60405180830381865afa1580156114ad573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906114d5919061488a565b8482815181106114e8576114e7614618565b5b60200260200101819052508060010190506113fc565b5050505b935093915050565b60068181548110611519575f80fd5b905f5260205f20015f915090508054611531906144c0565b80601f016020809104026020016040519081016040528092919081815260200182805461155d906144c0565b80156115a85780601f1061157f576101008083540402835291602001916115a8565b820191905f5260205f20905b81548152906001019060200180831161158b57829003601f168201915b505050505081565b6115b8613a66565b5f6040518060400160405280848036038101906115d59190614ba1565b81526020015f81525090506040518060800160405280600a60146115f8856123a4565b6116029190614bcc565b61160c91906145b2565b81526020016004600861161e856123a4565b6116289190614bcc565b61163291906145b2565b815260200161164a6007611645856123a4565b6123fa565b8152602001611662600861165d856123a4565b6123fa565b815250915050919050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6103e881565b6060600480546116aa906144c0565b80601f01602080910402602001604051908101604052809291908181526020018280546116d6906144c0565b80156117215780601f106116f857610100808354040283529160200191611721565b820191905f5260205f20905b81548152906001019060200180831161170457829003601f168201915b5050505050905090565b5f60605f60135f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508085106117d5575f8067ffffffffffffffff81111561179157611790614558565b5b6040519080825280602002602001820160405280156117ca57816020015b6117b7613a8c565b8152602001906001900390816117af5790505b509250925050611900565b5f84866117e291906145b2565b9050818111156117f0578190505b85816117fc91906145e5565b93508367ffffffffffffffff81111561181857611817614558565b5b60405190808252806020026020018201604052801561185157816020015b61183e613a8c565b8152602001906001900390816118365790505b5092505f5b848110156118fc5760125f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82896118a891906145b2565b81526020019081526020015f206040518060400160405290815f82015481526020016001820154815250508482815181106118e6576118e5614618565b5b6020026020010181905250806001019050611856565b5050505b935093915050565b5f80611912611f5d565b905061191f818585612008565b600191505092915050565b60145481565b3373ffffffffffffffffffffffffffffffffffffffff1660055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119b69061453a565b60405180910390fd5b8060098190555050565b60115481565b60135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20548210611a4e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a4590614c46565b60405180910390fd5b611a593383836124ba565b5050565b6060611ae43073ffffffffffffffffffffffffffffffffffffffff16633fc0fdcb85856040518363ffffffff1660e01b8152600401611a9d929190614c64565b5f60405180830381865afa158015611ab7573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611adf919061488a565b6122b7565b905092915050565b5f60605f60135f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050808510611b90575f8067ffffffffffffffff811115611b5257611b51614558565b5b604051908082528060200260200182016040528015611b8557816020015b6060815260200190600190039081611b705790505b509250925050611d22565b5f8486611b9d91906145b2565b905081811115611bb9578190508086611bb691906145e5565b93505b8367ffffffffffffffff811115611bd357611bd2614558565b5b604051908082528060200260200182016040528015611c0657816020015b6060815260200190600190039081611bf15790505b5092505f805f90508791505b82821015611d1d57611ce83073ffffffffffffffffffffffffffffffffffffffff16637c3b3b8760125f8d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f206040518263ffffffff1660e01b8152600401611ca191906146b7565b5f60405180830381865afa158015611cbb573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611ce3919061488a565b6122b7565b858280611cf490614c8b565b935081518110611d0757611d06614618565b5b6020026020010181905250816001019150611c12565b505050505b935093915050565b3373ffffffffffffffffffffffffffffffffffffffff1660055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611db9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611db09061453a565b60405180910390fd5b80600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555042600c8190555050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b6103e881565b3373ffffffffffffffffffffffffffffffffffffffff1660055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611f1a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f119061453a565b60405180910390fd5b8060055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f33905090565b611f718383836001612559565b505050565b5f611f818484611e03565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146120025781811015611ff3578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401611fea93929190614cd2565b60405180910390fd5b61200184848484035f612559565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16148061206f575061dead73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b156120845761207f838383612728565b6122b2565b61208c61106d565b1580156121a657505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614806120f957503073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b8061214f57507f000000000000000000000000ee423e5888f51d7a3248904ad232499ce1d10ff173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b806121a557507f000000000000000000000000ee423e5888f51d7a3248904ad232499ce1d10ff173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b5b156121bb576121b6838383612a22565b6122b2565b600b60149054906101000a900460ff16156121e0576121db838383612a22565b6122b2565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036122435761223e8282612b12565b6122b2565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036122a6576122a18382612bef565b6122b2565b6122b1838383612728565b5b505050565b6060805f5b8360200151811015612358575f81601e6122d69190614ab6565b60326122e291906145b2565b90505f82601e6122f29190614ab6565b60326122fe91906145b2565b90508361230a83612d69565b61231383612d69565b61231f895f0151612d69565b8960400151604051602001612338959493929190614eb3565b6040516020818303038152906040529350505080806001019150506122bc565b5060065f8154811061236d5761236c614618565b5b905f5260205f200183606001518260405160200161238d939291906151aa565b604051602081830303815290604052915050919050565b5f815f01515f0151825f0151602001518360200180518091906123c690614c8b565b8152506040516020016123db9392919061523c565b604051602081830303815290604052805190602001205f1c9050919050565b60605f83805490508361240d9190614bcc565b905083818154811061242257612421614618565b5b905f5260205f20018054612435906144c0565b80601f0160208091040260200160405190810160405280929190818152602001828054612461906144c0565b80156124ac5780601f10612483576101008083540402835291602001916124ac565b820191905f5260205f20905b81548152906001019060200180831161248f57829003601f168201915b505050505091505092915050565b5f60125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f206040518060400160405290815f8201548152602001600182015481525050905061253f84836009600a61253a9190614a6c565b612e33565b6125498484612ef4565b6125538282613138565b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036125c9575f6040517fe602df050000000000000000000000000000000000000000000000000000000081526004016125c09190614212565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612639575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016126309190614212565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015612722578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516127199190613b75565b60405180910390a35b50505050565b6127306132b7565b5f61273a84611188565b90505f828261274991906145e5565b90505f61275585611188565b90505f848261276491906145b2565b90505f73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614806127cd575061dead73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16145b156127d9575f91505f90505b5f6127e2610bde565b600a6127ee9190614a6c565b846127f99190614b24565b612801610bde565b600a61280d9190614a6c565b866128189190614b24565b61282291906145e5565b90505f61282d610bde565b600a6128399190614a6c565b846128449190614b24565b61284c610bde565b600a6128589190614a6c565b846128639190614b24565b61286d91906145e5565b90505f8290508181111561287f578190505b5f8060135f8d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f91505b82821015612973575f810315612973575f816128e090615278565b91508190505f60125f8f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f206040518060400160405290815f8201548152602001600182015481525050905061295c8e83612ef4565b6129668d82613138565b50508160010191506128c5565b5f8290508392505b858310156129a9575f8261298e90615278565b925082905061299d8e82612ef4565b5082600101925061297b565b8092505b84831015612a00575f604051806040016040528060155f81546129cf90614c8b565b91905081905581526020016129e56103e86132fd565b81525090506129f48d82613138565b508260010192506129ad565b612a0b8d8d8d612e33565b50505050505050505050612a1d613350565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612a92575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401612a899190614212565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612b02575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401612af99190614212565b60405180910390fd5b612b0d83838361335a565b505050565b612b1a6132b7565b5f612b2483611188565b90505f8282612b3391906145b2565b90505f612b3e610bde565b600a612b4a9190614a6c565b83612b559190614b24565b612b5d610bde565b600a612b699190614a6c565b83612b749190614b24565b612b7e91906145e5565b90505f5b81811015612bd5575f604051806040016040528060155f8154612ba490614c8b565b9190508190558152602001612bba6103e86132fd565b8152509050612bc98782613138565b50806001019050612b82565b612bdf8686613573565b50505050612beb613350565b5050565b6001600b60146101000a81548160ff021916908315150217905550612c126132b7565b5f612c1c83611188565b90505f8282612c2b91906145e5565b90505f612c36610bde565b600a612c429190614a6c565b82612c4d9190614b24565b612c55610bde565b600a612c619190614a6c565b84612c6c9190614b24565b612c7691906145e5565b90505f8060135f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f91505b82821015612d12576103e86011541015612ce85760115f8154612ce090614c8b565b919050819055505b5f811115612d0757612d068782612cfe90615278565b925082612ef4565b5b816001019150612cbe565b612d3e87600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688612008565b5050505050612d4b613350565b5f600b60146101000a81548160ff0219169083151502179055505050565b60605f6001612d7784613624565b0190505f8167ffffffffffffffff811115612d9557612d94614558565b5b6040519080825280601f01601f191660200182016040528015612dc75781602001600182028036833780820191505090505b5090505f82602001820190505b600115612e28578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612e1d57612e1c614af7565b5b0494505f8503612dd4575b819350505050919050565b6001600b60146101000a81548160ff0219169083151502179055505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480612eb5575061dead73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b15612ec957612ec48382613775565b612ed5565b612ed4838383612a22565b5b5f600b60146101000a81548160ff021916908315150217905550505050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160315613134575f60135f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8154612f9390615278565b91905081905503612fa857612fa7826137f4565b5b60145f8154612fb690615278565b919050819055505f60135f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508082146130d6575f60125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f206040518060400160405290815f820154815260200160018201548152505090508060125f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f820151815f015560208201518160010155905050505b60125f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8281526020019081526020015f205f8082015f9055600182015f90555050505b5050565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603156132b357600160135f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f81546131d890614c8b565b919050819055036131ed576131ec826139b8565b5b60145f81546131fb90614c8b565b919050819055505f600160135f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205461324d91906145e5565b90508160125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205f820151815f015560208201518160010155905050505b5050565b6002600d54036132f3576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600d81905550565b5f6103e86011548361330f9190614ab6565b6133199190614b24565b91505f820361332757600191505b600160115411156133485760115f815461334090615278565b919050819055505b819050919050565b6001600d81905550565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036133aa578060025f82825461339e91906145b2565b92505081905550613478565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015613433578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161342a93929190614cd2565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036134bf578060025f8282540392505081905550613509565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516135669190613b75565b60405180910390a3505050565b8061357c6111cd565b8111156135be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135b5906152e9565b60405180910390fd5b6001600b60146101000a81548160ff021916908315150217905550613605600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168484612a22565b5f600b60146101000a81548160ff021916908315150217905550505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310613680577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000838161367657613675614af7565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106136bd576d04ee2d6d415b85acef810000000083816136b3576136b2614af7565b5b0492506020810190505b662386f26fc1000083106136ec57662386f26fc1000083816136e2576136e1614af7565b5b0492506010810190505b6305f5e1008310613715576305f5e100838161370b5761370a614af7565b5b0492506008810190505b612710831061373a5761271083816137305761372f614af7565b5b0492506004810190505b6064831061375d576064838161375357613752614af7565b5b0492506002810190505b600a831061376c576001810190505b80915050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036137e5575f6040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016137dc9190614212565b60405180910390fd5b6137f0825f8361335a565b5050565b5f60105403156139b5575f600f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050600160105461384e91906145e5565b8114613929575f600e5f600160105461386791906145e5565b81526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080600e5f8481526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b60105f815461393790615278565b91905081905550600f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055600e5f60105481526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055505b50565b5f60105f8154809291906139cb90614c8b565b91905055905081600e5f8381526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505050565b60405180608001604052805f81526020015f815260200160608152602001606081525090565b60405180604001604052805f81526020015f81525090565b5f81905092915050565b50565b5f613abc5f83613aa4565b9150613ac782613aae565b5f82019050919050565b5f613adb82613ab1565b9150819050919050565b5f82825260208201905092915050565b7f63616e206e6f74206765742065746865720000000000000000000000000000005f82015250565b5f613b29601183613ae5565b9150613b3482613af5565b602082019050919050565b5f6020820190508181035f830152613b5681613b1d565b9050919050565b5f819050919050565b613b6f81613b5d565b82525050565b5f602082019050613b885f830184613b66565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613bc882613b9f565b9050919050565b613bd881613bbe565b8114613be2575f80fd5b50565b5f81359050613bf381613bcf565b92915050565b5f60208284031215613c0e57613c0d613b97565b5b5f613c1b84828501613be5565b91505092915050565b5f81519050919050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f613c5682613c24565b613c608185613ae5565b9350613c70818560208601613c2e565b613c7981613c3c565b840191505092915050565b5f6020820190508181035f830152613c9c8184613c4c565b905092915050565b613cad81613b5d565b8114613cb7575f80fd5b50565b5f81359050613cc881613ca4565b92915050565b5f8060408385031215613ce457613ce3613b97565b5b5f613cf185828601613be5565b9250506020613d0285828601613cba565b9150509250929050565b5f8115159050919050565b613d2081613d0c565b82525050565b5f602082019050613d395f830184613d17565b92915050565b5f805f60608486031215613d5657613d55613b97565b5b5f613d6386828701613be5565b9350506020613d7486828701613be5565b9250506040613d8586828701613cba565b9150509250925092565b5f60208284031215613da457613da3613b97565b5b5f613db184828501613cba565b91505092915050565b5f60ff82169050919050565b613dcf81613dba565b82525050565b5f602082019050613de85f830184613dc6565b92915050565b5f8060408385031215613e0457613e03613b97565b5b5f613e1185828601613cba565b9250506020613e2285828601613cba565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b613e5e81613bbe565b82525050565b5f613e6f8383613e55565b60208301905092915050565b5f602082019050919050565b5f613e9182613e2c565b613e9b8185613e36565b9350613ea683613e46565b805f5b83811015613ed6578151613ebd8882613e64565b9750613ec883613e7b565b925050600181019050613ea9565b5085935050505092915050565b5f604082019050613ef65f830185613b66565b8181036020830152613f088184613e87565b90509392505050565b613f1a81613b5d565b82525050565b5f82825260208201905092915050565b5f613f3a82613c24565b613f448185613f20565b9350613f54818560208601613c2e565b613f5d81613c3c565b840191505092915050565b5f608083015f830151613f7d5f860182613f11565b506020830151613f906020860182613f11565b5060408301518482036040860152613fa88282613f30565b91505060608301518482036060860152613fc28282613f30565b9150508091505092915050565b5f6020820190508181035f830152613fe78184613f68565b905092915050565b5f80fd5b5f6040828403121561400857614007613fef565b5b81905092915050565b5f6040828403121561402657614025613b97565b5b5f61403384828501613ff3565b91505092915050565b5f60408201905061404f5f830185613b66565b61405c6020830184613b66565b9392505050565b5f805f6060848603121561407a57614079613b97565b5b5f61408786828701613be5565b935050602061409886828701613cba565b92505060406140a986828701613cba565b9150509250925092565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f608083015f8301516140f15f860182613f11565b5060208301516141046020860182613f11565b506040830151848203604086015261411c8282613f30565b915050606083015184820360608601526141368282613f30565b9150508091505092915050565b5f61414e83836140dc565b905092915050565b5f602082019050919050565b5f61416c826140b3565b61417681856140bd565b935083602082028501614188856140cd565b805f5b858110156141c357848403895281516141a48582614143565b94506141af83614156565b925060208a0199505060018101905061418b565b50829750879550505050505092915050565b5f6040820190506141e85f830185613b66565b81810360208301526141fa8184614162565b90509392505050565b61420c81613bbe565b82525050565b5f6020820190506142255f830184614203565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b604082015f8201516142685f850182613f11565b50602082015161427b6020850182613f11565b50505050565b5f61428c8383614254565b60408301905092915050565b5f602082019050919050565b5f6142ae8261422b565b6142b88185614235565b93506142c383614245565b805f5b838110156142f35781516142da8882614281565b97506142e583614298565b9250506001810190506142c6565b5085935050505092915050565b5f6040820190506143135f830185613b66565b818103602083015261432581846142a4565b90509392505050565b5f806040838503121561434457614343613b97565b5b5f61435185828601613cba565b925050602061436285828601613be5565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f6143a08383613f30565b905092915050565b5f602082019050919050565b5f6143be8261436c565b6143c88185614376565b9350836020820285016143da85614386565b805f5b8581101561441557848403895281516143f68582614395565b9450614401836143a8565b925060208a019950506001810190506143dd565b50829750879550505050505092915050565b5f60408201905061443a5f830185613b66565b818103602083015261444c81846143b4565b90509392505050565b5f806040838503121561446b5761446a613b97565b5b5f61447885828601613be5565b925050602061448985828601613be5565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806144d757607f821691505b6020821081036144ea576144e9614493565b5b50919050565b7f6f6e6c79206f776e6572000000000000000000000000000000000000000000005f82015250565b5f614524600a83613ae5565b915061452f826144f0565b602082019050919050565b5f6020820190508181035f83015261455181614518565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6145bc82613b5d565b91506145c783613b5d565b92508282019050808211156145df576145de614585565b5b92915050565b5f6145ef82613b5d565b91506145fa83613b5d565b925082820390508181111561461257614611614585565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f815f1c9050919050565b5f819050919050565b5f61466b61466683614645565b614650565b9050919050565b604082015f80830154905061468681614659565b6146925f860182613f11565b50600183015490506146a381614659565b6146b06020860182613f11565b5050505050565b5f6040820190506146ca5f830184614672565b92915050565b5f80fd5b6146dd82613c3c565b810181811067ffffffffffffffff821117156146fc576146fb614558565b5b80604052505050565b5f61470e613b8e565b905061471a82826146d4565b919050565b5f80fd5b5f8151905061473181613ca4565b92915050565b5f80fd5b5f80fd5b5f67ffffffffffffffff82111561475957614758614558565b5b61476282613c3c565b9050602081019050919050565b5f61478161477c8461473f565b614705565b90508281526020810184848401111561479d5761479c61473b565b5b6147a8848285613c2e565b509392505050565b5f82601f8301126147c4576147c3614737565b5b81516147d484826020860161476f565b91505092915050565b5f608082840312156147f2576147f16146d0565b5b6147fc6080614705565b90505f61480b84828501614723565b5f83015250602061481e84828501614723565b602083015250604082015167ffffffffffffffff8111156148425761484161471f565b5b61484e848285016147b0565b604083015250606082015167ffffffffffffffff8111156148725761487161471f565b5b61487e848285016147b0565b60608301525092915050565b5f6020828403121561489f5761489e613b97565b5b5f82015167ffffffffffffffff8111156148bc576148bb613b9b565b5b6148c8848285016147dd565b91505092915050565b5f6148df6020840184613cba565b905092915050565b604082016148f75f8301836148d1565b6149035f850182613f11565b5061491160208301836148d1565b61491e6020850182613f11565b50505050565b5f6040820190506149375f8301846148e7565b92915050565b5f8160011c9050919050565b5f808291508390505b60018511156149925780860481111561496e5761496d614585565b5b600185161561497d5780820291505b808102905061498b8561493d565b9450614952565b94509492505050565b5f826149aa5760019050614a65565b816149b7575f9050614a65565b81600181146149cd57600281146149d757614a06565b6001915050614a65565b60ff8411156149e9576149e8614585565b5b8360020a915084821115614a00576149ff614585565b5b50614a65565b5060208310610133831016604e8410600b8410161715614a3b5782820a905083811115614a3657614a35614585565b5b614a65565b614a488484846001614949565b92509050818404811115614a5f57614a5e614585565b5b81810290505b9392505050565b5f614a7682613b5d565b9150614a8183613dba565b9250614aae7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff848461499b565b905092915050565b5f614ac082613b5d565b9150614acb83613b5d565b9250828202614ad981613b5d565b91508282048414831517614af057614aef614585565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f614b2e82613b5d565b9150614b3983613b5d565b925082614b4957614b48614af7565b5b828204905092915050565b5f60408284031215614b6957614b686146d0565b5b614b736040614705565b90505f614b8284828501613cba565b5f830152506020614b9584828501613cba565b60208301525092915050565b5f60408284031215614bb657614bb5613b97565b5b5f614bc384828501614b54565b91505092915050565b5f614bd682613b5d565b9150614be183613b5d565b925082614bf157614bf0614af7565b5b828206905092915050565b7f696e636f727265637420696e64657800000000000000000000000000000000005f82015250565b5f614c30600f83613ae5565b9150614c3b82614bfc565b602082019050919050565b5f6020820190508181035f830152614c5d81614c24565b9050919050565b5f604082019050614c775f830185614203565b614c846020830184613b66565b9392505050565b5f614c9582613b5d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614cc757614cc6614585565b5b600182019050919050565b5f606082019050614ce55f830186614203565b614cf26020830185613b66565b614cff6040830184613b66565b949350505050565b5f81905092915050565b5f614d1b82613c24565b614d258185614d07565b9350614d35818560208601613c2e565b80840191505092915050565b7f3c636972636c652063783d2700000000000000000000000000000000000000005f82015250565b5f614d75600c83614d07565b9150614d8082614d41565b600c82019050919050565b7f272063793d2700000000000000000000000000000000000000000000000000005f82015250565b5f614dbf600683614d07565b9150614dca82614d8b565b600682019050919050565b7f2720723d270000000000000000000000000000000000000000000000000000005f82015250565b5f614e09600583614d07565b9150614e1482614dd5565b600582019050919050565b7f272066696c6c3d270000000000000000000000000000000000000000000000005f82015250565b5f614e53600883614d07565b9150614e5e82614e1f565b600882019050919050565b7f27202f3e000000000000000000000000000000000000000000000000000000005f82015250565b5f614e9d600483614d07565b9150614ea882614e69565b600482019050919050565b5f614ebe8288614d11565b9150614ec982614d69565b9150614ed58287614d11565b9150614ee082614db3565b9150614eec8286614d11565b9150614ef782614dfd565b9150614f038285614d11565b9150614f0e82614e47565b9150614f1a8284614d11565b9150614f2582614e91565b91508190509695505050505050565b7f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f32305f8201527f30302f737667272076696577426f783d273020302031303020313030273e0000602082015250565b5f614f8e603e83614d07565b9150614f9982614f34565b603e82019050919050565b7f3c726563742077696474683d2731303027206865696768743d273130302720665f8201527f696c6c3d27000000000000000000000000000000000000000000000000000000602082015250565b5f614ffe602583614d07565b915061500982614fa4565b602582019050919050565b5f819050815f5260205f209050919050565b5f8154615032816144c0565b61503c8186614d07565b9450600182165f8114615056576001811461506b5761509d565b60ff198316865281151582028601935061509d565b61507485615014565b5f5b8381101561509557815481890152600182019150602081019050615076565b838801955050505b50505092915050565b7f272f3e00000000000000000000000000000000000000000000000000000000005f82015250565b5f6150da600383614d07565b91506150e5826150a6565b600382019050919050565b7f3c636972636c652063783d273530272063793d2735302720723d2731352720665f8201527f696c6c3d27000000000000000000000000000000000000000000000000000000602082015250565b5f61514a602583614d07565b9150615155826150f0565b602582019050919050565b7f3c2f7376673e00000000000000000000000000000000000000000000000000005f82015250565b5f615194600683614d07565b915061519f82615160565b600682019050919050565b5f6151b482614f82565b91506151bf82614ff2565b91506151cb8286615026565b91506151d6826150ce565b91506151e18261513e565b91506151ed8285614d11565b91506151f882614e91565b91506152048284614d11565b915061520f82615188565b9150819050949350505050565b5f819050919050565b61523661523182613b5d565b61521c565b82525050565b5f6152478286615225565b6020820191506152578285615225565b6020820191506152678284615225565b602082019150819050949350505050565b5f61528282613b5d565b91505f820361529457615293614585565b5b600182039050919050565b7f6d617820627579000000000000000000000000000000000000000000000000005f82015250565b5f6152d3600783613ae5565b91506152de8261529f565b602082019050919050565b5f6020820190508181035f830152615300816152c7565b905091905056fea26469706673582212200ac28cd5a91a0ed25c4d3006ad3ed096ab8e379f729d331d62c8f74a3106e51264736f6c63430008190033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.