Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 6 from a total of 6 transactions
Latest 2 internal transactions
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
To
|
|||
|---|---|---|---|---|---|---|---|
| 0x60806040 | 23361861 | 53 days ago | Contract Creation | 0 ETH | |||
| 0x60806040 | 23361861 | 53 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
BUSD
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity Multiple files format)
// SPDX-License-Identifier: MIT
/*
( (
( )\ ) )\ )
( )\ ( (()/((()/(
)((_) )\ /(_))/(_))
((_)_ _ ((_)(_)) (_))_
| _ )| | | |/ __| | \
| _ \| |_| |\__ \ | |) |
|___/ \___/ |___/ |___/
by steviep.eth
2025
*/
import "./Dependencies.sol";
import "./BurnCeremony.sol";
import "./ProofOfBurn.sol";
pragma solidity ^0.8.28;
interface IBurnAgreement {
function ownerOf(uint256) external view returns (address);
function markAgreementUsed(uint256) external;
}
/// @title Burnt US Dollars (bUSD)
/// @author steviep.eth
/// @notice Burnt US Dollars ($bUSD) is a coin that represents the value of burned US Dollars.
contract BUSD is ERC20, Ownable {
BurnCeremony public ceremony;
ProofOfBurn public proofOfBurn;
/// @notice BUSD can no longer be issued once the contract is locked
bool public isLocked;
/// @notice Keeps track of which addresses burned the most bUSD
mapping(address => uint256) public busdBurnedBy;
constructor() ERC20('Burnt US Dollars', 'bUSD') {
ceremony = new BurnCeremony();
proofOfBurn = new ProofOfBurn();
ceremony.init(owner(), proofOfBurn);
}
/// @notice Issue new bUSD
/// @param account Address to issue bUSD to
/// @param amount Amount of bUSD to issue
/// @dev This can only be called by the BurnCeremony address
function issue(address account, uint256 amount) external {
require(!isLocked, 'New issuance is locked');
require(msg.sender == address(ceremony), 'Can only issue through official Burn Ceremony');
_mint(account, amount);
}
/// @notice Burn bUSD along with a Proof of Burn token
/// @param account Address to burn bUSD from
/// @param amount Amount of bUSD to burn
/// @dev This can only be called by the ProofOfBurn contract
function burnFrom(address account, uint256 amount) external {
require(msg.sender == address(proofOfBurn));
busdBurnedBy[account] += amount;
_burn(account, amount);
}
/// @notice Change the BurnCeremony contract
/// @param newCeremony New BurnCeremony contract address
function modifyCeremony(address newCeremony) external onlyOwner {
ceremony = BurnCeremony(newCeremony);
}
/// @notice Lock new bUSD issuance
/// @dev This is one way. Issuance cnanot be unlocked
function lockIssuance() external onlyOwner {
isLocked = true;
}
string private _contractURI = 'data:application/json;utf8,{"name":"Burnt US Dollars"}';
event ContractURIUpdated();
function contractURI() external view returns (string memory) {
return _contractURI;
}
function updateContractURI(string calldata newURI) external onlyOwner {
_contractURI = newURI;
emit ContractURIUpdated();
}
}
// SPDX-License-Identifier: MIT
/*
( (
( )\ ) )\ )
( )\ ( (()/((()/(
)((_) )\ /(_))/(_))
((_)_ _ ((_)(_)) (_))_
| _ )| | | |/ __| | \
| _ \| |_| |\__ \ | |) |
|___/ \___/ |___/ |___/
by steviep.eth
2025
*/
import "./Dependencies.sol";
pragma solidity ^0.8.28;
/// @title Burn Agreement (bUSD)
/// @author steviep.eth
/// @notice Terms and conditions for engaging with the bUSD project. Owning a Burn Agreement token can be used to streamline the bUSD issuance process. Ownership of this NFT does not guarantee participation in a Burn Ceremony
contract BurnAgreement is ERC721, Ownable {
uint256 public totalSupply = 1;
string public activeAgreementVersion = '1.0.0';
address public burnCeremony;
BurnAgreementURI public uri;
BurnAgreementMinter public minter;
/// @notice Map a Burn Agreement token to the agreement version
mapping(uint256 => string) public tokenIdToAgreementVersion;
/// @notice Map an agreement version to the agreement content uri
mapping(string => string) public agreementVersionToMetadata;
/// @notice Keeps track of whether an agreement token has been used in a Ceremony
mapping(uint256 => bool) public agreementUsed;
event MetadataUpdate(uint256 _tokenId);
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
/// @dev Mints #0 to the contract deployer
constructor(address ceremony) ERC721('Burn Agreement', 'BA') {
burnCeremony = ceremony;
uri = new BurnAgreementURI();
minter = new BurnAgreementMinter();
_safeMint(msg.sender, 0);
tokenIdToAgreementVersion[0] = activeAgreementVersion;
}
/// @notice Checks if given token ID exists
/// @param tokenId Token to run existence check on
/// @return True if token exists
function exists(uint256 tokenId) external view returns (bool) {
return _exists(tokenId);
}
/// @notice Mints a Burn Agreement token to the recipient
/// @param recipient Address to sent token to
/// @dev Can only be called by the BurnAgreementMinter
function mint(address recipient) external payable {
require(msg.sender == address(minter), 'Only minting address can mint');
tokenIdToAgreementVersion[totalSupply] = activeAgreementVersion;
_safeMint(recipient, totalSupply);
totalSupply++;
}
/// @notice Marks an Agreement as "used" as part of a burn ceremony
/// @dev Can only be called by the BurnCeremony
function markAgreementUsed(uint256 tokenId) external {
require(msg.sender == burnCeremony, 'Only burn ceremony can use agreement');
require(!agreementUsed[tokenId], 'Agreement already used');
agreementUsed[tokenId] = true;
emit MetadataUpdate(tokenId);
}
function setMinter(BurnAgreementMinter newMinter) external onlyOwner {
minter = newMinter;
}
function setBurnCeremony(address _burnCeremony) external onlyOwner {
burnCeremony = _burnCeremony;
}
function setActiveAgreement(string calldata _activeAgreementVersion) external onlyOwner {
activeAgreementVersion = _activeAgreementVersion;
}
function setAgreementMetadata(string calldata agreementVersion, string calldata metadata) external onlyOwner {
agreementVersionToMetadata[agreementVersion] = metadata;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
return uri.tokenURI(tokenId);
}
function setURI(address newURI) external onlyOwner {
uri = BurnAgreementURI(newURI);
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721) returns (bool) {
return interfaceId == bytes4(0x49064906) || super.supportsInterface(interfaceId);
}
}
/// @title Burn Agreement Minter (bUSD)
/// @author steviep.eth
/// @notice Interface for minting bUSD Burn Agreement NFTs
contract BurnAgreementMinter {
uint256 public price = 0.01 ether;
BurnAgreement public burnAgreement;
constructor() {
burnAgreement = BurnAgreement(msg.sender);
}
modifier onlyOwner {
require(msg.sender == burnAgreement.owner(), "Ownable: caller is not the owner");
_;
}
function mint() external payable {
require(msg.value >= price, 'Invalid value');
burnAgreement.mint(msg.sender);
}
function withdraw(uint256 balance) external onlyOwner {
payable(burnAgreement.owner()).call{value: balance}('');
}
function setPrice(uint256 _price) external onlyOwner {
price = _price;
}
}
contract BurnAgreementURI {
BurnAgreement public agreement;
constructor() {
agreement = BurnAgreement(msg.sender);
}
function tokenURI(uint256 tokenId) public view returns (string memory) {
bool agreementUsed = agreement.agreementUsed(tokenId);
string memory agreementVersion = agreement.tokenIdToAgreementVersion(tokenId);
string memory bg = agreementUsed ? '#000' : '#fff';
string memory text = agreementUsed ? '#ef791f' : '#000';
bytes memory thumbnail = abi.encodePacked(
'data:image/svg+xml;base64,',
Base64.encode(abi.encodePacked(
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 850 1100">'
'<style>text{font:bold 50px sans-serif;fill:', text, ';text-anchor: middle}</style>'
'<rect width="850" height="1100" x="0" y="0" fill="', bg,'" stroke="none"/>'
'<rect x="150" y="150" width="550" height="800" style="fill:none;stroke:', text,';stroke-width:7.5px"/>'
'<text x="425" y="450">BURN</text>'
'<text x="425" y="550">AGREEMENT</text>'
'<text x="425" y="650">v', agreementVersion, '</text>'
'</svg>'
))
);
string memory attrs = string.concat(
'[',
string.concat('{ "trait_type": "Agreement Version", "value": "', agreementVersion, '" },'),
string.concat('{ "trait_type": "Agreement Used", "value": "', agreementUsed ? 'True' : 'False', '" }'),
']'
);
return string(abi.encodePacked(
'data:application/json;utf8,'
'{"name": "Burn Agreement v', agreementVersion,
'", "description": "By purchasing this token you implicitly agree to the terms of this agreement. Ownership of this NFT does not guarantee participation in a Burn Ceremony. Participation shall be left to the full discretion of the Burn Agent.'
'", "image": "', thumbnail,
'", "animation_url": "', agreement.agreementVersionToMetadata(agreementVersion),
'", "attributes":', attrs,
'}'
));
}
}// SPDX-License-Identifier: MIT
/*
( (
( )\ ) )\ )
( )\ ( (()/((()/(
)((_) )\ /(_))/(_))
((_)_ _ ((_)(_)) (_))_
| _ )| | | |/ __| | \
| _ \| |_| |\__ \ | |) |
|___/ \___/ |___/ |___/
by steviep.eth
2025
*/
import "./BUSD.sol";
import "./ProofOfBurn.sol";
pragma solidity ^0.8.28;
/// @title Burn Ceremony (bUSD)
/// @author steviep.eth
/// @notice Interface for issuing new bUSD and Proofs of Burn
contract BurnCeremony {
BUSD public busd;
ProofOfBurn public proofOfBurn;
IBurnAgreement public burnAgreement;
address public burnAgent;
event Issuance(address indexed account, uint256 indexed denomination, string indexed serial);
constructor() {
busd = BUSD(msg.sender);
}
/// @dev This is necessary due to some weird solidity quirk during instantiation. Should only be called once
function init(address owner, ProofOfBurn pob) external {
require(burnAgent == address(0));
burnAgent = owner;
proofOfBurn = pob;
}
modifier onlyAgent {
require(msg.sender == burnAgent, 'Caller is not Burn Agent');
_;
}
/// @notice Set the Burn Agent role
function setBurnAgent(address _agent) external {
require(msg.sender == busd.owner(), 'Ownable: caller is not BUSD owner');
burnAgent = _agent;
}
/// @notice Designate the Burn Agreement contract
function setBurnAgreement(address agreement) external {
require(msg.sender == busd.owner(), 'Ownable: caller is not BUSD owner');
burnAgreement = IBurnAgreement(agreement);
}
/// @notice Issue new bUSD. This may only be called during the completion of an official Burn Ceremony
/// @param account Address to send the POB token to
/// @param denomination Denomination of the burnt bill
/// @param serial Serial number of the bunt bill
function issue(
address account,
uint256 denomination,
string calldata serial
) external onlyAgent {
busd.issue(account, denomination * 1 ether);
proofOfBurn.mint(account, denomination, serial);
emit Issuance(account, denomination, serial);
}
/// @notice Issue new bUSD using a Burn Agreement NFT. This may only be called during the completion of an official Burn Ceremony
/// @param agreementTokenId Issue bUSD to the owner of this token
/// @param denomination Denomination of the burnt bill
/// @param serial Serial number of the bunt bill
function issueWithAgreement(
uint256 agreementTokenId,
uint256 denomination,
string calldata serial
) external onlyAgent {
address account = burnAgreement.ownerOf(agreementTokenId);
burnAgreement.markAgreementUsed(agreementTokenId);
busd.issue(account, denomination * 1 ether);
proofOfBurn.mint(account, denomination, serial);
emit Issuance(account, denomination, serial);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
// /**
// * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
// * `recipient`, forwarding all available gas and reverting on errors.
// *
// * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
// * of certain opcodes, possibly making contracts go over the 2300 gas limit
// * imposed by `transfer`, making them unable to receive funds via
// * `transfer`. {sendValue} removes this limitation.
// *
// * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
// *
// * IMPORTANT: because control is transferred to `recipient`, care must be
// * taken to not create reentrancy vulnerabilities. Consider using
// * {ReentrancyGuard} or the
// * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
// */
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
// /**
// * @dev Performs a Solidity function call using a low level `call`. A
// * plain `call` is an unsafe replacement for a function call: use this
// * function instead.
// *
// * If `target` reverts with a revert reason, it is bubbled up by this
// * function (like regular Solidity function calls).
// *
// * Returns the raw returned data. To convert to the expected return value,
// * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
// *
// * Requirements:
// *
// * - `target` must be a contract.
// * - calling `target` with `data` must not revert.
// *
// * _Available since v3.1._
// */
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
// /**
// * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
// * `errorMessage` as a fallback revert reason when `target` reverts.
// *
// * _Available since v3.1._
// */
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
// /**
// * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
// * but also transferring `value` wei to `target`.
// *
// * Requirements:
// *
// * - the calling contract must have an ETH balance of at least `value`.
// * - the called Solidity function must be `payable`.
// *
// * _Available since v3.1._
// */
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
// *
// * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
// * with `errorMessage` as a fallback revert reason when `target` reverts.
// *
// * _Available since v3.1._
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
// /**
// * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
// * but performing a static call.
// *
// * _Available since v3.3._
// */
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
// /**
// * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
// * but performing a static call.
// *
// * _Available since v3.3._
// */
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
// /**
// * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
// * but performing a delegate call.
// *
// * _Available since v3.4._
// */
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
// /**
// * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
// * but performing a delegate call.
// *
// * _Available since v3.4._
// */
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
// /**
// * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
// * revert reason using the provided one.
// *
// * _Available since v4.3._
// */
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
/**
* @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;
}
}
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 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);
}
// Don't need these
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <[email protected]>
library Base64 {
bytes internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/// @notice Encodes some bytes to the base64 representation
function encode(bytes memory data) internal pure returns (string memory) {
uint256 len = data.length;
if (len == 0) return "";
// multiply by 4/3 rounded up
uint256 encodedLen = 4 * ((len + 2) / 3);
// Add some extra buffer at the end
bytes memory result = new bytes(encodedLen + 32);
bytes memory table = TABLE;
assembly {
let tablePtr := add(table, 1)
let resultPtr := add(result, 32)
for {
let i := 0
} lt(i, len) {
} {
i := add(i, 3)
let input := and(mload(add(data, i)), 0xffffff)
let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
out := shl(8, out)
out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))
out := shl(8, out)
out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))
out := shl(8, out)
out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))
out := shl(224, out)
mstore(resultPtr, out)
resultPtr := add(resultPtr, 4)
}
switch mod(len, 3)
case 1 {
mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
}
case 2 {
mstore(sub(resultPtr, 1), shl(248, 0x3d))
}
mstore(result, encodedLen)
}
return string(result);
}
}
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_setOwner(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
require(operator != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
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);
}
/**
* @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}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* 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.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => 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 override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override 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 override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override 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 `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` 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 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
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 `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `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.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` 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.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}
// SPDX-License-Identifier: MIT
/*
( (
( )\ ) )\ )
( )\ ( (()/((()/(
)((_) )\ /(_))/(_))
((_)_ _ ((_)(_)) (_))_
| _ )| | | |/ __| | \
| _ \| |_| |\__ \ | |) |
|___/ \___/ |___/ |___/
by steviep.eth
2025
*/
import "./Dependencies.sol";
import "./BUSD.sol";
pragma solidity ^0.8.28;
/// @title Proof of Burn (bUSD)
/// @author steviep.eth
/// @notice Archival NFTs representing the proof that specific bills were burned in an official bUSD Burn Ceremony
contract ProofOfBurn is ERC721, Ownable {
BUSD public busd;
uint256 public billsBurned;
uint256 public proofsBurned;
ProofOfBurnURI public uri;
/// @notice Mapping of tokenIds to serial numbers of burnt bills
mapping(uint256 => string) public serials;
/// @notice Mapping of tokenIds to denominations of burnt bills
mapping(uint256 => uint8) public denominations;
/// @notice Mapping of tokenIds to metadata
mapping(uint256 => string) public proofs;
/// @notice Timestamp of the completion of the bill's Burn Ceremony
mapping(uint256 => uint256) public timestamps;
/// @notice Notes regarding the bill's Burn Ceremony
mapping(uint256 => string) public memos;
/// @notice A record of which Proofs of Burn were burned by which addresses
mapping(uint256 => address) public burnedBy;
/// @notice A log of serial numbers alreay burned
mapping(string => bool) public serialUsed;
uint256[] public sessionEnds;
event MetadataUpdate(uint256 _tokenId);
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
event Burn(address burner, uint256 tokenId, uint256 amount);
constructor() ERC721('Proof of Burn (bUSD)', 'POB') {
busd = BUSD(msg.sender);
uri = new ProofOfBurnURI();
transferOwnership(tx.origin);
}
/// @notice Checks if given token ID exists
/// @param tokenId Token to run existence check on
/// @return True if token exists
function exists(uint256 tokenId) external view returns (bool) {
return _exists(tokenId);
}
/// @notice Total circulating supply of Proof of Burn tokens
function totalSupply() external view returns (uint256) {
return billsBurned - proofsBurned;
}
modifier onlyAgent {
address burnAgent = busd.ceremony().burnAgent();
require(msg.sender == burnAgent, 'Caller is not Burn Agent');
_;
}
/// @notice Total unique burn sessions completed
function totalSessions() public view returns (uint256) {
return sessionEnds.length;
}
/// @notice Finds the burn session a specific bill
function tokenIdToSessionId(uint256 tokenId) public view returns (uint256) {
uint256 ts = timestamps[tokenId];
for (uint256 i; i < sessionEnds.length; ++i) {
if (ts < sessionEnds[i]) return i;
}
return sessionEnds.length;
}
/// @notice Mark the end of a "session" (i.e. a series of Burn Ceremonies)
function markSessionEnd() external onlyAgent {
sessionEnds.push(block.timestamp);
}
/// @notice Add the metadata to a specific Proof of Burn token
function addProof(uint256 tokenId, string calldata proof) external onlyAgent {
proofs[tokenId] = proof;
emit MetadataUpdate(tokenId);
}
/// @notice Add the metadata to a batch of Proof of Burn tokens
function addProofBatch(uint256[] calldata tokenIds, string calldata baseURI, string calldata ext) external onlyAgent {
for (uint256 i; i < tokenIds.length; ++i) {
proofs[tokenIds[i]] = string.concat(baseURI, Strings.toString(tokenIds[i]), ext);
}
emit BatchMetadataUpdate(0, billsBurned);
}
/// @notice Add a memo to
function addMemo(uint256 tokenId, string calldata memo) external onlyAgent {
memos[tokenId] = memo;
}
/// @notice Mint a new Proof of Burn token
/// @dev This can only be called by the BurnCeremony contract
/// @param account Address to send the POB token to
/// @param denomination Denomination of the burnt bill
/// @param serial Serial number of the bunt bill
function mint(
address account,
uint256 denomination,
string calldata serial
) external {
require(msg.sender == address(busd.ceremony()), 'Invalid minter');
require(!serialUsed[serial], 'Serial already used');
denominations[billsBurned] = uint8(denomination);
serials[billsBurned] = serial;
serialUsed[serial] = true;
timestamps[billsBurned] = block.timestamp;
_safeMint(account, billsBurned);
billsBurned += 1;
}
/// @notice Burn a specific Proof of Burn token. This will also burn a an amount of the owner's bUSD corresponding to the bill's denomination
/// @dev This can be delegated to an operator
function burn(uint256 tokenId) public virtual {
require(_isApprovedOrOwner(msg.sender, tokenId), 'ERC721: caller is not token owner or approved');
uint256 amount = uint256(denominations[tokenId]) * 1 ether;
busd.burnFrom(ownerOf(tokenId), amount);
burnedBy[tokenId] = ownerOf(tokenId);
proofsBurned += 1;
_burn(tokenId);
emit Burn(burnedBy[tokenId], tokenId, amount);
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
return uri.tokenURI(tokenId);
}
function setURI(address newURI) external {
require(msg.sender == busd.owner(), 'Caller is not BUSD Owner');
uri = ProofOfBurnURI(newURI);
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721) returns (bool) {
return interfaceId == bytes4(0x49064906) || super.supportsInterface(interfaceId);
}
string private _contractURI = 'data:application/json;utf8,{"name":"Proof of Burn (bUSD)"}';
event ContractURIUpdated();
function contractURI() external view returns (string memory) {
return _contractURI;
}
function updateContractURI(string calldata newURI) external onlyOwner {
_contractURI = newURI;
emit ContractURIUpdated();
}
}
contract ProofOfBurnURI {
ProofOfBurn public pob;
constructor() {
pob = ProofOfBurn(msg.sender);
}
function tokenURI(uint256 tokenId) external view returns (string memory) {
string memory denomination = Strings.toString(pob.denominations(tokenId));
string memory timestampString = Strings.toString(pob.timestamps(tokenId));
string memory serial = pob.serials(tokenId);
string memory memo = pob.memos(tokenId);
string memory sessionId = Strings.toString(pob.tokenIdToSessionId(tokenId));
string memory tokenIdStr = Strings.toString(tokenId);
bool hasMemo = bytes(memo).length > 0;
string memory description = string.concat('Proof of Burn #', tokenIdStr, ' for bill: ', serial, ', issuing ', denomination, ' bUSD at timestamp ', timestampString, hasMemo ? string.concat('. Included Memo: ', memo) : '.');
bytes memory proof = bytes(pob.proofs(tokenId));
if (proof.length == 0) {
proof = abi.encodePacked(
'data:image/svg+xml;base64,',
Base64.encode(abi.encodePacked(
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 180">'
'<rect x="0" y="0" width="100%" height="100%" fill="#000"></rect>'
'<text x="50%" y="43%" font-size="20px" fill="#fff" font-family="monospace" dominant-baseline="middle" text-anchor="middle">Proof of Burn #', tokenIdStr,'</text>'
'<text x="50%" y="57%" font-size="20px" fill="#fff" font-family="monospace" dominant-baseline="middle" text-anchor="middle">',
serial, ' $', denomination,
'</text>'
'</svg>'
))
);
}
string memory attrs = string.concat(
'[',
string.concat('{ "trait_type": "Serial", "value": "', serial, '" },'),
string.concat('{ "trait_type": "Denomination", "value": "', denomination, '" },'),
string.concat('{ "trait_type": "Burned at", "value": "', timestampString, '" },'),
string.concat('{ "trait_type": "Session ID", "value": "', sessionId, '" }'),
hasMemo ? string.concat(',{ "trait_type": "Burn Memo", "value": "', memo, '" }') : '',
']'
);
return string(abi.encodePacked(
'data:application/json;utf8,'
'{"name": "Proof of Burn #', string.concat(tokenIdStr, ' (', serial, ', $', denomination, ')'),
'", "description": "', description,
'", "image": "', proof,
'", "animation_url": "', proof,
'", "attributes":', attrs,
'}'
));
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"ContractURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"busdBurnedBy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ceremony","outputs":[{"internalType":"contract BurnCeremony","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"issue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockIssuance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCeremony","type":"address"}],"name":"modifyCeremony","outputs":[],"stateMutability":"nonpayable","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":"proofOfBurn","outputs":[{"internalType":"contract ProofOfBurn","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","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":"amount","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":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newURI","type":"string"}],"name":"updateContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405260405180606001604052806036815260200161b049603691396009908161002b91906105b1565b50348015610037575f5ffd5b506040518060400160405280601081526020017f4275726e7420555320446f6c6c617273000000000000000000000000000000008152506040518060400160405280600481526020017f625553440000000000000000000000000000000000000000000000000000000081525081600390816100b391906105b1565b5080600490816100c391906105b1565b5050506100e26100d761026860201b60201c565b61026f60201b60201c565b6040516100ee9061035a565b604051809103905ff080158015610107573d5f5f3e3d5ffd5b5060065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405161015390610367565b604051809103905ff08015801561016c573d5f5f3e3d5ffd5b5060075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f09a40166101f761033260201b60201c565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518363ffffffff1660e01b8152600401610236929190610711565b5f604051808303815f87803b15801561024d575f5ffd5b505af115801561025f573d5f5f3e3d5ffd5b50505050610738565b5f33905090565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6111c380612cca83390190565b6171bc80613e8d83390190565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806103ef57607f821691505b602082108103610402576104016103ab565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026104647fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610429565b61046e8683610429565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6104b26104ad6104a884610486565b61048f565b610486565b9050919050565b5f819050919050565b6104cb83610498565b6104df6104d7826104b9565b848454610435565b825550505050565b5f5f905090565b6104f66104e7565b6105018184846104c2565b505050565b5b81811015610524576105195f826104ee565b600181019050610507565b5050565b601f8211156105695761053a81610408565b6105438461041a565b81016020851015610552578190505b61056661055e8561041a565b830182610506565b50505b505050565b5f82821c905092915050565b5f6105895f198460080261056e565b1980831691505092915050565b5f6105a1838361057a565b9150826002028217905092915050565b6105ba82610374565b67ffffffffffffffff8111156105d3576105d261037e565b5b6105dd82546103d8565b6105e8828285610528565b5f60209050601f831160018114610619575f8415610607578287015190505b6106118582610596565b865550610678565b601f19841661062786610408565b5f5b8281101561064e57848901518255600182019150602085019450602081019050610629565b8683101561066b5784890151610667601f89168261057a565b8355505b6001600288020188555050505b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6106a982610680565b9050919050565b6106b98161069f565b82525050565b5f6106d96106d46106cf84610680565b61048f565b610680565b9050919050565b5f6106ea826106bf565b9050919050565b5f6106fb826106e0565b9050919050565b61070b816106f1565b82525050565b5f6040820190506107245f8301856106b0565b6107316020830184610702565b9392505050565b612585806107455f395ff3fe608060405234801561000f575f5ffd5b5060043610610156575f3560e01c806379cc6790116100c1578063a4e2d6341161007a578063a4e2d634146103b4578063a9059cbb146103d2578063d3a7383314610402578063dd62ed3e1461041e578063e8a3d4851461044e578063f2fde38b1461046c57610156565b806379cc6790146102f45780637e5b1e2414610310578063867904b41461032c5780638da5cb5b1461034857806395d89b4114610366578063a457c2d71461038457610156565b806325f3d2771161011357806325f3d2771461021e578063313ce5671461023c578063395093511461025a57806360486d761461028a57806370a08231146102ba578063715018a6146102ea57610156565b806306133c651461015a57806306fdde0314610178578063095ea7b31461019657806318160ddd146101c6578063234b8d0e146101e457806323b872dd146101ee575b5f5ffd5b610162610488565b60405161016f9190611719565b60405180910390f35b6101806104ad565b60405161018d91906117a2565b60405180910390f35b6101b060048036038101906101ab9190611838565b61053d565b6040516101bd9190611890565b60405180910390f35b6101ce61055f565b6040516101db91906118b8565b60405180910390f35b6101ec610568565b005b610208600480360381019061020391906118d1565b610601565b6040516102159190611890565b60405180910390f35b61022661062f565b6040516102339190611941565b60405180910390f35b610244610654565b6040516102519190611975565b60405180910390f35b610274600480360381019061026f9190611838565b61065c565b6040516102819190611890565b60405180910390f35b6102a4600480360381019061029f919061198e565b610692565b6040516102b191906118b8565b60405180910390f35b6102d460048036038101906102cf919061198e565b6106a7565b6040516102e191906118b8565b60405180910390f35b6102f26106ec565b005b61030e60048036038101906103099190611838565b610773565b005b61032a60048036038101906103259190611a1a565b61082c565b005b61034660048036038101906103419190611838565b6108ea565b005b6103506109d7565b60405161035d9190611a74565b60405180910390f35b61036e6109ff565b60405161037b91906117a2565b60405180910390f35b61039e60048036038101906103999190611838565b610a8f565b6040516103ab9190611890565b60405180910390f35b6103bc610b04565b6040516103c99190611890565b60405180910390f35b6103ec60048036038101906103e79190611838565b610b17565b6040516103f99190611890565b60405180910390f35b61041c6004803603810190610417919061198e565b610b39565b005b61043860048036038101906104339190611a8d565b610bf8565b60405161044591906118b8565b60405180910390f35b610456610c7a565b60405161046391906117a2565b60405180910390f35b6104866004803603810190610481919061198e565b610d0a565b005b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600380546104bc90611af8565b80601f01602080910402602001604051908101604052809291908181526020018280546104e890611af8565b80156105335780601f1061050a57610100808354040283529160200191610533565b820191905f5260205f20905b81548152906001019060200180831161051657829003601f168201915b5050505050905090565b5f5f610547610e00565b9050610554818585610e07565b600191505092915050565b5f600254905090565b610570610e00565b73ffffffffffffffffffffffffffffffffffffffff1661058e6109d7565b73ffffffffffffffffffffffffffffffffffffffff16146105e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105db90611b72565b60405180910390fd5b6001600760146101000a81548160ff021916908315150217905550565b5f5f61060b610e00565b9050610618858285610fca565b610623858585611055565b60019150509392505050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f6012905090565b5f5f610666610e00565b90506106878185856106788589610bf8565b6106829190611bbd565b610e07565b600191505092915050565b6008602052805f5260405f205f915090505481565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6106f4610e00565b73ffffffffffffffffffffffffffffffffffffffff166107126109d7565b73ffffffffffffffffffffffffffffffffffffffff1614610768576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161075f90611b72565b60405180910390fd5b6107715f6112c1565b565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107cb575f5ffd5b8060085f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546108179190611bbd565b925050819055506108288282611384565b5050565b610834610e00565b73ffffffffffffffffffffffffffffffffffffffff166108526109d7565b73ffffffffffffffffffffffffffffffffffffffff16146108a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089f90611b72565b60405180910390fd5b8181600991826108b9929190611dbe565b507fa5d4097edda6d87cb9329af83fb3712ef77eeb13738ffe43cc35a4ce305ad96260405160405180910390a15050565b600760149054906101000a900460ff161561093a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093190611ed5565b60405180910390fd5b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109c090611f63565b60405180910390fd5b6109d38282611547565b5050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060048054610a0e90611af8565b80601f0160208091040260200160405190810160405280929190818152602001828054610a3a90611af8565b8015610a855780601f10610a5c57610100808354040283529160200191610a85565b820191905f5260205f20905b815481529060010190602001808311610a6857829003601f168201915b5050505050905090565b5f5f610a99610e00565b90505f610aa68286610bf8565b905083811015610aeb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae290611ff1565b60405180910390fd5b610af88286868403610e07565b60019250505092915050565b600760149054906101000a900460ff1681565b5f5f610b21610e00565b9050610b2e818585611055565b600191505092915050565b610b41610e00565b73ffffffffffffffffffffffffffffffffffffffff16610b5f6109d7565b73ffffffffffffffffffffffffffffffffffffffff1614610bb5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bac90611b72565b60405180910390fd5b8060065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b606060098054610c8990611af8565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb590611af8565b8015610d005780601f10610cd757610100808354040283529160200191610d00565b820191905f5260205f20905b815481529060010190602001808311610ce357829003601f168201915b5050505050905090565b610d12610e00565b73ffffffffffffffffffffffffffffffffffffffff16610d306109d7565b73ffffffffffffffffffffffffffffffffffffffff1614610d86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7d90611b72565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610df4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610deb9061207f565b60405180910390fd5b610dfd816112c1565b50565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e75576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e6c9061210d565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610ee3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eda9061219b565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051610fbd91906118b8565b60405180910390a3505050565b5f610fd58484610bf8565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461104f5781811015611041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161103890612203565b60405180910390fd5b61104e8484848403610e07565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ba90612291565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611131576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111289061231f565b60405180910390fd5b61113c838383611695565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156111bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111b6906123ad565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550815f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516112a891906118b8565b60405180910390a36112bb84848461169a565b50505050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036113f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e99061243b565b60405180910390fd5b6113fd825f83611695565b5f5f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015611480576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611477906124c9565b60405180910390fd5b8181035f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508160025f82825403925050819055505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161152f91906118b8565b60405180910390a3611542835f8461169a565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036115b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ac90612531565b60405180910390fd5b6115c05f8383611695565b8060025f8282546115d19190611bbd565b92505081905550805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055508173ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161167e91906118b8565b60405180910390a36116915f838361169a565b5050565b505050565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f6116e16116dc6116d78461169f565b6116be565b61169f565b9050919050565b5f6116f2826116c7565b9050919050565b5f611703826116e8565b9050919050565b611713816116f9565b82525050565b5f60208201905061172c5f83018461170a565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61177482611732565b61177e818561173c565b935061178e81856020860161174c565b6117978161175a565b840191505092915050565b5f6020820190508181035f8301526117ba818461176a565b905092915050565b5f5ffd5b5f5ffd5b5f6117d48261169f565b9050919050565b6117e4816117ca565b81146117ee575f5ffd5b50565b5f813590506117ff816117db565b92915050565b5f819050919050565b61181781611805565b8114611821575f5ffd5b50565b5f813590506118328161180e565b92915050565b5f5f6040838503121561184e5761184d6117c2565b5b5f61185b858286016117f1565b925050602061186c85828601611824565b9150509250929050565b5f8115159050919050565b61188a81611876565b82525050565b5f6020820190506118a35f830184611881565b92915050565b6118b281611805565b82525050565b5f6020820190506118cb5f8301846118a9565b92915050565b5f5f5f606084860312156118e8576118e76117c2565b5b5f6118f5868287016117f1565b9350506020611906868287016117f1565b925050604061191786828701611824565b9150509250925092565b5f61192b826116e8565b9050919050565b61193b81611921565b82525050565b5f6020820190506119545f830184611932565b92915050565b5f60ff82169050919050565b61196f8161195a565b82525050565b5f6020820190506119885f830184611966565b92915050565b5f602082840312156119a3576119a26117c2565b5b5f6119b0848285016117f1565b91505092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126119da576119d96119b9565b5b8235905067ffffffffffffffff8111156119f7576119f66119bd565b5b602083019150836001820283011115611a1357611a126119c1565b5b9250929050565b5f5f60208385031215611a3057611a2f6117c2565b5b5f83013567ffffffffffffffff811115611a4d57611a4c6117c6565b5b611a59858286016119c5565b92509250509250929050565b611a6e816117ca565b82525050565b5f602082019050611a875f830184611a65565b92915050565b5f5f60408385031215611aa357611aa26117c2565b5b5f611ab0858286016117f1565b9250506020611ac1858286016117f1565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680611b0f57607f821691505b602082108103611b2257611b21611acb565b5b50919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725f82015250565b5f611b5c60208361173c565b9150611b6782611b28565b602082019050919050565b5f6020820190508181035f830152611b8981611b50565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611bc782611805565b9150611bd283611805565b9250828201905080821115611bea57611be9611b90565b5b92915050565b5f82905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302611c837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611c48565b611c8d8683611c48565b95508019841693508086168417925050509392505050565b5f611cbf611cba611cb584611805565b6116be565b611805565b9050919050565b5f819050919050565b611cd883611ca5565b611cec611ce482611cc6565b848454611c54565b825550505050565b5f5f905090565b611d03611cf4565b611d0e818484611ccf565b505050565b5b81811015611d3157611d265f82611cfb565b600181019050611d14565b5050565b601f821115611d7657611d4781611c27565b611d5084611c39565b81016020851015611d5f578190505b611d73611d6b85611c39565b830182611d13565b50505b505050565b5f82821c905092915050565b5f611d965f1984600802611d7b565b1980831691505092915050565b5f611dae8383611d87565b9150826002028217905092915050565b611dc88383611bf0565b67ffffffffffffffff811115611de157611de0611bfa565b5b611deb8254611af8565b611df6828285611d35565b5f601f831160018114611e23575f8415611e11578287013590505b611e1b8582611da3565b865550611e82565b601f198416611e3186611c27565b5f5b82811015611e5857848901358255600182019150602085019450602081019050611e33565b86831015611e755784890135611e71601f891682611d87565b8355505b6001600288020188555050505b50505050505050565b7f4e65772069737375616e6365206973206c6f636b6564000000000000000000005f82015250565b5f611ebf60168361173c565b9150611eca82611e8b565b602082019050919050565b5f6020820190508181035f830152611eec81611eb3565b9050919050565b7f43616e206f6e6c79206973737565207468726f756768206f6666696369616c205f8201527f4275726e20436572656d6f6e7900000000000000000000000000000000000000602082015250565b5f611f4d602d8361173c565b9150611f5882611ef3565b604082019050919050565b5f6020820190508181035f830152611f7a81611f41565b9050919050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f775f8201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b5f611fdb60258361173c565b9150611fe682611f81565b604082019050919050565b5f6020820190508181035f83015261200881611fcf565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20615f8201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b5f61206960268361173c565b91506120748261200f565b604082019050919050565b5f6020820190508181035f8301526120968161205d565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f206164645f8201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b5f6120f760248361173c565b91506121028261209d565b604082019050919050565b5f6020820190508181035f830152612124816120eb565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f2061646472655f8201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b5f61218560228361173c565b91506121908261212b565b604082019050919050565b5f6020820190508181035f8301526121b281612179565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000005f82015250565b5f6121ed601d8361173c565b91506121f8826121b9565b602082019050919050565b5f6020820190508181035f83015261221a816121e1565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f2061645f8201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b5f61227b60258361173c565b915061228682612221565b604082019050919050565b5f6020820190508181035f8301526122a88161226f565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f20616464725f8201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b5f61230960238361173c565b9150612314826122af565b604082019050919050565b5f6020820190508181035f830152612336816122fd565b9050919050565b7f45524332303a207472616e7366657220616d6f756e74206578636565647320625f8201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b5f61239760268361173c565b91506123a28261233d565b604082019050919050565b5f6020820190508181035f8301526123c48161238b565b9050919050565b7f45524332303a206275726e2066726f6d20746865207a65726f206164647265735f8201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b5f61242560218361173c565b9150612430826123cb565b604082019050919050565b5f6020820190508181035f83015261245281612419565b9050919050565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e5f8201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b5f6124b360228361173c565b91506124be82612459565b604082019050919050565b5f6020820190508181035f8301526124e0816124a7565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f2061646472657373005f82015250565b5f61251b601f8361173c565b9150612526826124e7565b602082019050919050565b5f6020820190508181035f8301526125488161250f565b905091905056fea2646970667358221220fb34ca6026fa64e0dce7ed7ccebb6f910afc5ba8058de90060e58ab346680e8164736f6c634300081c00336080604052348015600e575f5ffd5b50335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506111688061005b5f395ff3fe608060405234801561000f575f5ffd5b5060043610610091575f3560e01c8063accca1dc11610064578063accca1dc14610109578063c365f4af14610127578063e98407e014610145578063ebf469dc14610161578063f09a40161461017d57610091565b80632436dbcc1461009557806325f3d277146100b15780633ca5b234146100cf5780636f5885d0146100ed575b5f5ffd5b6100af60048036038101906100aa9190610b74565b610199565b005b6100b96104d6565b6040516100c69190610c5f565b60405180910390f35b6100d76104fb565b6040516100e49190610c98565b60405180910390f35b61010760048036038101906101029190610cec565b61051f565b005b61011161065c565b60405161011e9190610d37565b60405180910390f35b61012f610681565b60405161013c9190610d5f565b60405180910390f35b61015f600480360381019061015a9190610cec565b6106a6565b005b61017b60048036038101906101769190610d78565b6107e3565b005b61019760048036038101906101929190610e24565b6109fc565b005b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610228576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161021f90610ebc565b60405180910390fd5b5f60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e866040518263ffffffff1660e01b81526004016102839190610ee9565b602060405180830381865afa15801561029e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102c29190610f16565b905060025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635a20e1ac866040518263ffffffff1660e01b815260040161031e9190610ee9565b5f604051808303815f87803b158015610335575f5ffd5b505af1158015610347573d5f5f3e3d5ffd5b505050505f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663867904b482670de0b6b3a76400008761039c9190610f6e565b6040518363ffffffff1660e01b81526004016103b9929190610faf565b5f604051808303815f87803b1580156103d0575f5ffd5b505af11580156103e2573d5f5f3e3d5ffd5b5050505060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d3fc9864828686866040518563ffffffff1660e01b81526004016104469493929190611020565b5f604051808303815f87803b15801561045d575f5ffd5b505af115801561046f573d5f5f3e3d5ffd5b50505050828260405161048392919061108c565b6040518091039020848273ffffffffffffffffffffffffffffffffffffffff167f56efce5854bf1d184d330cc0c05667850247efb9dd786f6efac4c3cf93e7e60f60405160405180910390a45050505050565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610588573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105ac9190610f16565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610619576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061090611114565b60405180910390fd5b8060035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561070f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107339190610f16565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079790611114565b60405180910390fd5b8060025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610872576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161086990610ebc565b60405180910390fd5b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663867904b485670de0b6b3a7640000866108c39190610f6e565b6040518363ffffffff1660e01b81526004016108e0929190610faf565b5f604051808303815f87803b1580156108f7575f5ffd5b505af1158015610909573d5f5f3e3d5ffd5b5050505060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d3fc9864858585856040518563ffffffff1660e01b815260040161096d9493929190611020565b5f604051808303815f87803b158015610984575f5ffd5b505af1158015610996573d5f5f3e3d5ffd5b5050505081816040516109aa92919061108c565b6040518091039020838573ffffffffffffffffffffffffffffffffffffffff167f56efce5854bf1d184d330cc0c05667850247efb9dd786f6efac4c3cf93e7e60f60405160405180910390a450505050565b5f73ffffffffffffffffffffffffffffffffffffffff1660035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a54575f5ffd5b8160035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b5f5ffd5b5f5ffd5b5f819050919050565b610af281610ae0565b8114610afc575f5ffd5b50565b5f81359050610b0d81610ae9565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112610b3457610b33610b13565b5b8235905067ffffffffffffffff811115610b5157610b50610b17565b5b602083019150836001820283011115610b6d57610b6c610b1b565b5b9250929050565b5f5f5f5f60608587031215610b8c57610b8b610ad8565b5b5f610b9987828801610aff565b9450506020610baa87828801610aff565b935050604085013567ffffffffffffffff811115610bcb57610bca610adc565b5b610bd787828801610b1f565b925092505092959194509250565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f610c27610c22610c1d84610be5565b610c04565b610be5565b9050919050565b5f610c3882610c0d565b9050919050565b5f610c4982610c2e565b9050919050565b610c5981610c3f565b82525050565b5f602082019050610c725f830184610c50565b92915050565b5f610c8282610c2e565b9050919050565b610c9281610c78565b82525050565b5f602082019050610cab5f830184610c89565b92915050565b5f610cbb82610be5565b9050919050565b610ccb81610cb1565b8114610cd5575f5ffd5b50565b5f81359050610ce681610cc2565b92915050565b5f60208284031215610d0157610d00610ad8565b5b5f610d0e84828501610cd8565b91505092915050565b5f610d2182610c2e565b9050919050565b610d3181610d17565b82525050565b5f602082019050610d4a5f830184610d28565b92915050565b610d5981610cb1565b82525050565b5f602082019050610d725f830184610d50565b92915050565b5f5f5f5f60608587031215610d9057610d8f610ad8565b5b5f610d9d87828801610cd8565b9450506020610dae87828801610aff565b935050604085013567ffffffffffffffff811115610dcf57610dce610adc565b5b610ddb87828801610b1f565b925092505092959194509250565b5f610df382610cb1565b9050919050565b610e0381610de9565b8114610e0d575f5ffd5b50565b5f81359050610e1e81610dfa565b92915050565b5f5f60408385031215610e3a57610e39610ad8565b5b5f610e4785828601610cd8565b9250506020610e5885828601610e10565b9150509250929050565b5f82825260208201905092915050565b7f43616c6c6572206973206e6f74204275726e204167656e7400000000000000005f82015250565b5f610ea6601883610e62565b9150610eb182610e72565b602082019050919050565b5f6020820190508181035f830152610ed381610e9a565b9050919050565b610ee381610ae0565b82525050565b5f602082019050610efc5f830184610eda565b92915050565b5f81519050610f1081610cc2565b92915050565b5f60208284031215610f2b57610f2a610ad8565b5b5f610f3884828501610f02565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610f7882610ae0565b9150610f8383610ae0565b9250828202610f9181610ae0565b91508282048414831517610fa857610fa7610f41565b5b5092915050565b5f604082019050610fc25f830185610d50565b610fcf6020830184610eda565b9392505050565b828183375f83830152505050565b5f601f19601f8301169050919050565b5f610fff8385610e62565b935061100c838584610fd6565b61101583610fe4565b840190509392505050565b5f6060820190506110335f830187610d50565b6110406020830186610eda565b8181036040830152611053818486610ff4565b905095945050505050565b5f81905092915050565b5f611073838561105e565b9350611080838584610fd6565b82840190509392505050565b5f611098828486611068565b91508190509392505050565b7f4f776e61626c653a2063616c6c6572206973206e6f742042555344206f776e655f8201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b5f6110fe602183610e62565b9150611109826110a4565b604082019050919050565b5f6020820190508181035f83015261112b816110f2565b905091905056fea26469706673582212201e57253ad40eda64a2843be39c0aaf72756a80314b7961111141ab204dd493fb64736f6c634300081c003360806040526040518060600160405280603a8152602001617182603a91396013908161002b91906105de565b50348015610037575f5ffd5b506040518060400160405280601481526020017f50726f6f66206f66204275726e202862555344290000000000000000000000008152506040518060400160405280600381526020017f504f420000000000000000000000000000000000000000000000000000000000815250815f90816100b291906105de565b5080600190816100c291906105de565b5050506100e16100d661019a60201b60201c565b6101a160201b60201c565b3360075f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405161012d90610394565b604051809103905ff080158015610146573d5f5f3e3d5ffd5b50600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101953261026460201b60201c565b6107b3565b5f33905090565b5f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61027261019a60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1661029661036c60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16146102ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102e390610707565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035190610795565b60405180910390fd5b610369816101a160201b60201c565b50565b5f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611cee8061549483390190565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061041c57607f821691505b60208210810361042f5761042e6103d8565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026104917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610456565b61049b8683610456565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6104df6104da6104d5846104b3565b6104bc565b6104b3565b9050919050565b5f819050919050565b6104f8836104c5565b61050c610504826104e6565b848454610462565b825550505050565b5f5f905090565b610523610514565b61052e8184846104ef565b505050565b5b81811015610551576105465f8261051b565b600181019050610534565b5050565b601f8211156105965761056781610435565b61057084610447565b8101602085101561057f578190505b61059361058b85610447565b830182610533565b50505b505050565b5f82821c905092915050565b5f6105b65f198460080261059b565b1980831691505092915050565b5f6105ce83836105a7565b9150826002028217905092915050565b6105e7826103a1565b67ffffffffffffffff811115610600576105ff6103ab565b5b61060a8254610405565b610615828285610555565b5f60209050601f831160018114610646575f8415610634578287015190505b61063e85826105c3565b8655506106a5565b601f19841661065486610435565b5f5b8281101561067b57848901518255600182019150602085019450602081019050610656565b868310156106985784890151610694601f8916826105a7565b8355505b6001600288020188555050505b505050505050565b5f82825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725f82015250565b5f6106f16020836106ad565b91506106fc826106bd565b602082019050919050565b5f6020820190508181035f83015261071e816106e5565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20615f8201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b5f61077f6026836106ad565b915061078a82610725565b604082019050919050565b5f6020820190508181035f8301526107ac81610773565b9050919050565b614cd4806107c05f395ff3fe608060405234801561000f575f5ffd5b5060043610610251575f3560e01c80637e5b1e2411610144578063c3062ce7116100c1578063e985e9c511610085578063e985e9c51461072f578063eac989f81461075f578063f2fde38b1461077d578063f3ce61ad14610799578063f93e4ec8146107c9578063f9f3d0d9146107e557610251565b8063c3062ce714610665578063c87b56dd14610695578063d3fc9864146106c5578063e8a3d485146106e1578063e8dfdf04146106ff57610251565b8063997fe50711610108578063997fe507146105d75780639ddaf5aa146105f3578063a22cb46514610623578063a547b48e1461063f578063b88d4fde1461064957610251565b80637e5b1e241461051f5780638bc33af31461053b5780638da5cb5b1461056b57806395d89b411461058957806398cd96af146105a757610251565b806342966c68116101d25780636c1a1779116101965780636c1a17791461047b5780636dbf6e3b146104975780636f5db0b5146104c757806370a08231146104e5578063715018a61461051557610251565b806342966c68146103b157806343470a89146103cd5780634f558e79146103fd5780635213f7211461042d5780636352211e1461044b57610251565b806323b872dd1161021957806323b872dd1461030d5780632583f5361461032957806339920528146103595780633ca5b2341461037757806342842e0e1461039557610251565b806301ffc9a71461025557806306fdde0314610285578063081812fc146102a3578063095ea7b3146102d357806318160ddd146102ef575b5f5ffd5b61026f600480360381019061026a919061306a565b610801565b60405161027c91906130af565b60405180910390f35b61028d610861565b60405161029a9190613138565b60405180910390f35b6102bd60048036038101906102b8919061318b565b6108f0565b6040516102ca91906131f5565b60405180910390f35b6102ed60048036038101906102e89190613238565b610971565b005b6102f7610a87565b6040516103049190613285565b60405180910390f35b6103276004803603810190610322919061329e565b610a9d565b005b610343600480360381019061033e919061341a565b610afd565b60405161035091906130af565b60405180910390f35b610361610b32565b60405161036e9190613285565b60405180910390f35b61037f610b38565b60405161038c91906134bc565b60405180910390f35b6103af60048036038101906103aa919061329e565b610b5d565b005b6103cb60048036038101906103c6919061318b565b610b7c565b005b6103e760048036038101906103e2919061318b565b610d75565b6040516103f491906131f5565b60405180910390f35b6104176004803603810190610412919061318b565b610da5565b60405161042491906130af565b60405180910390f35b610435610db6565b6040516104429190613285565b60405180910390f35b6104656004803603810190610460919061318b565b610dbc565b60405161047291906131f5565b60405180910390f35b610495600480360381019061049091906134d5565b610e68565b005b6104b160048036038101906104ac919061318b565b610fa6565b6040516104be9190613285565b60405180910390f35b6104cf610fc6565b6040516104dc9190613285565b60405180910390f35b6104ff60048036038101906104fa91906134d5565b610fd2565b60405161050c9190613285565b60405180910390f35b61051d611086565b005b6105396004803603810190610534919061355d565b61110d565b005b6105556004803603810190610550919061318b565b6111cb565b6040516105629190613285565b60405180910390f35b6105736111e0565b60405161058091906131f5565b60405180910390f35b610591611208565b60405161059e9190613138565b60405180910390f35b6105c160048036038101906105bc919061318b565b611298565b6040516105ce9190613138565b60405180910390f35b6105f160048036038101906105ec91906135fd565b611333565b005b61060d6004803603810190610608919061318b565b61157b565b60405161061a9190613138565b60405180910390f35b61063d600480360381019061063891906136d7565b611616565b005b610647611791565b005b610663600480360381019061065e91906137b3565b611925565b005b61067f600480360381019061067a919061318b565b611987565b60405161068c9190613285565b60405180910390f35b6106af60048036038101906106aa919061318b565b6119f5565b6040516106bc9190613138565b60405180910390f35b6106df60048036038101906106da9190613833565b611a9a565b005b6106e9611ccb565b6040516106f69190613138565b60405180910390f35b6107196004803603810190610714919061318b565b611d5b565b6040516107269190613138565b60405180910390f35b610749600480360381019061074491906138a4565b611df6565b60405161075691906130af565b60405180910390f35b610767611e84565b6040516107749190613902565b60405180910390f35b610797600480360381019061079291906134d5565b611ea9565b005b6107b360048036038101906107ae919061318b565b611f9f565b6040516107c09190613936565b60405180910390f35b6107e360048036038101906107de919061394f565b611fbc565b005b6107ff60048036038101906107fa919061394f565b61214e565b005b5f634906490660e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061085a575061085982612317565b5b9050919050565b60605f805461086f906139d9565b80601f016020809104026020016040519081016040528092919081815260200182805461089b906139d9565b80156108e65780601f106108bd576101008083540402835291602001916108e6565b820191905f5260205f20905b8154815290600101906020018083116108c957829003601f168201915b5050505050905090565b5f6108fa826123f8565b610939576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093090613a79565b60405180910390fd5b60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f61097b82610dbc565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036109eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109e290613b07565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610a0a612460565b73ffffffffffffffffffffffffffffffffffffffff161480610a395750610a3881610a33612460565b611df6565b5b610a78576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6f90613b95565b60405180910390fd5b610a828383612467565b505050565b5f600954600854610a989190613be0565b905090565b610aae610aa8612460565b8261251d565b610aed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae490613c83565b60405180910390fd5b610af88383836125f9565b505050565b6011818051602081018201805184825260208301602085012081835280955050505050505f915054906101000a900460ff1681565b60085481565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610b7783838360405180602001604052805f815250611925565b505050565b610b86338261251d565b610bc5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bbc90613d11565b60405180910390fd5b5f670de0b6b3a7640000600c5f8481526020019081526020015f205f9054906101000a900460ff1660ff16610bfa9190613d2f565b905060075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379cc6790610c4284610dbc565b836040518363ffffffff1660e01b8152600401610c60929190613d70565b5f604051808303815f87803b158015610c77575f5ffd5b505af1158015610c89573d5f5f3e3d5ffd5b50505050610c9682610dbc565b60105f8481526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160095f828254610cf69190613d97565b92505081905550610d0682612849565b7f49995e5dd6158cf69ad3e9777c46755a1a826a446c6416992167462dad033b2a60105f8481526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168383604051610d6993929190613dca565b60405180910390a15050565b6010602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f610daf826123f8565b9050919050565b60095481565b5f5f60025f8481526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e5690613e6f565b60405180910390fd5b80915050919050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ed2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef69190613ea1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610f63576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f5a90613f16565b60405180910390fd5b80600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60128181548110610fb5575f80fd5b905f5260205f20015f915090505481565b5f601280549050905090565b5f5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161103890613fa4565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b61108e612460565b73ffffffffffffffffffffffffffffffffffffffff166110ac6111e0565b73ffffffffffffffffffffffffffffffffffffffff1614611102576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f99061400c565b60405180910390fd5b61110b5f612950565b565b611115612460565b73ffffffffffffffffffffffffffffffffffffffff166111336111e0565b73ffffffffffffffffffffffffffffffffffffffff1614611189576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111809061400c565b60405180910390fd5b81816013918261119a9291906141cb565b507fa5d4097edda6d87cb9329af83fb3712ef77eeb13738ffe43cc35a4ce305ad96260405160405180910390a15050565b600e602052805f5260405f205f915090505481565b5f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060018054611217906139d9565b80601f0160208091040260200160405190810160405280929190818152602001828054611243906139d9565b801561128e5780601f106112655761010080835404028352916020019161128e565b820191905f5260205f20905b81548152906001019060200180831161127157829003601f168201915b5050505050905090565b600b602052805f5260405f205f9150905080546112b4906139d9565b80601f01602080910402602001604051908101604052809291908181526020018280546112e0906139d9565b801561132b5780601f106113025761010080835404028352916020019161132b565b820191905f5260205f20905b81548152906001019060200180831161130e57829003601f168201915b505050505081565b5f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306133c656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561139e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113c291906142d3565b73ffffffffffffffffffffffffffffffffffffffff1663c365f4af6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561140a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061142e9190613ea1565b90508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149590614348565b60405180910390fd5b5f5b878790508110156115365785856114cf8a8a858181106114c3576114c2614366565b5b90506020020135612a13565b86866040516020016114e59594939291906143f1565b604051602081830303815290604052600d5f8a8a8581811061150a57611509614366565b5b9050602002013581526020019081526020015f20908161152a9190614425565b508060010190506114a0565b507f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c5f60085460405161156a92919061452d565b60405180910390a150505050505050565b600d602052805f5260405f205f915090508054611597906139d9565b80601f01602080910402602001604051908101604052809291908181526020018280546115c3906139d9565b801561160e5780601f106115e55761010080835404028352916020019161160e565b820191905f5260205f20905b8154815290600101906020018083116115f157829003601f168201915b505050505081565b61161e612460565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361168b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116829061459e565b60405180910390fd5b8060055f611697612460565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611740612460565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161178591906130af565b60405180910390a35050565b5f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306133c656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117fc573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061182091906142d3565b73ffffffffffffffffffffffffffffffffffffffff1663c365f4af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611868573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061188c9190613ea1565b90508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118f390614348565b60405180910390fd5b601242908060018154018082558091505060019003905f5260205f20015f909190919091505550565b611936611930612460565b8361251d565b611975576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161196c90613c83565b60405180910390fd5b61198184848484612b6c565b50505050565b5f5f600e5f8481526020019081526020015f205490505f5b6012805490508110156119e557601281815481106119c0576119bf614366565b5b905f5260205f2001548210156119da5780925050506119f0565b80600101905061199f565b506012805490509150505b919050565b6060600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c87b56dd836040518263ffffffff1660e01b8152600401611a519190613285565b5f60405180830381865afa158015611a6b573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f82011682018060405250810190611a93919061462a565b9050919050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306133c656040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b04573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b2891906142d3565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b95576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b8c906146bb565b60405180910390fd5b60118282604051611ba79291906146d9565b90815260200160405180910390205f9054906101000a900460ff1615611c02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf99061473b565b60405180910390fd5b82600c5f60085481526020019081526020015f205f6101000a81548160ff021916908360ff1602179055508181600b5f60085481526020019081526020015f209182611c4f9291906141cb565b50600160118383604051611c649291906146d9565b90815260200160405180910390205f6101000a81548160ff02191690831515021790555042600e5f60085481526020019081526020015f2081905550611cac84600854612bc8565b600160085f828254611cbe9190613d97565b9250508190555050505050565b606060138054611cda906139d9565b80601f0160208091040260200160405190810160405280929190818152602001828054611d06906139d9565b8015611d515780601f10611d2857610100808354040283529160200191611d51565b820191905f5260205f20905b815481529060010190602001808311611d3457829003601f168201915b5050505050905090565b600f602052805f5260405f205f915090508054611d77906139d9565b80601f0160208091040260200160405190810160405280929190818152602001828054611da3906139d9565b8015611dee5780601f10611dc557610100808354040283529160200191611dee565b820191905f5260205f20905b815481529060010190602001808311611dd157829003601f168201915b505050505081565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611eb1612460565b73ffffffffffffffffffffffffffffffffffffffff16611ecf6111e0565b73ffffffffffffffffffffffffffffffffffffffff1614611f25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1c9061400c565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611f93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8a906147c9565b60405180910390fd5b611f9c81612950565b50565b600c602052805f5260405f205f915054906101000a900460ff1681565b5f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306133c656040518163ffffffff1660e01b8152600401602060405180830381865afa158015612027573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061204b91906142d3565b73ffffffffffffffffffffffffffffffffffffffff1663c365f4af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612093573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120b79190613ea1565b90508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612127576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161211e90614348565b60405180910390fd5b8282600f5f8781526020019081526020015f2091826121479291906141cb565b5050505050565b5f60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166306133c656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121b9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121dd91906142d3565b73ffffffffffffffffffffffffffffffffffffffff1663c365f4af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612225573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122499190613ea1565b90508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146122b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b090614348565b60405180910390fd5b8282600d5f8781526020019081526020015f2091826122d99291906141cb565b507ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7846040516123099190613285565b60405180910390a150505050565b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806123e157507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806123f157506123f082612be5565b5b9050919050565b5f5f73ffffffffffffffffffffffffffffffffffffffff1660025f8481526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b5f33905090565b8160045f8381526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166124d783610dbc565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b5f612527826123f8565b612566576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161255d90614857565b60405180910390fd5b5f61257083610dbc565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806125df57508373ffffffffffffffffffffffffffffffffffffffff166125c7846108f0565b73ffffffffffffffffffffffffffffffffffffffff16145b806125f057506125ef8185611df6565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661261982610dbc565b73ffffffffffffffffffffffffffffffffffffffff161461266f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612666906148e5565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036126dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126d490614973565b60405180910390fd5b6126e8838383612c4e565b6126f25f82612467565b600160035f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461273f9190613be0565b92505081905550600160035f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546127939190613d97565b925050819055508160025f8381526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b5f61285382610dbc565b9050612860815f84612c4e565b61286a5f83612467565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546128b79190613be0565b9250508190555060025f8381526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055815f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b5f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60605f8203612a59576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612b67565b5f8290505f5b5f8214612a88578080612a7190614991565b915050600a82612a819190614a05565b9150612a5f565b5f8167ffffffffffffffff811115612aa357612aa26132f6565b5b6040519080825280601f01601f191660200182016040528015612ad55781602001600182028036833780820191505090505b5090505b5f8514612b6057600182612aed9190613be0565b9150600a85612afc9190614a35565b6030612b089190613d97565b60f81b818381518110612b1e57612b1d614366565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a85612b599190614a05565b9450612ad9565b8093505050505b919050565b612b778484846125f9565b612b8384848484612c53565b612bc2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb990614ad5565b60405180910390fd5b50505050565b612be1828260405180602001604052805f815250612dd5565b5050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b505050565b5f612c738473ffffffffffffffffffffffffffffffffffffffff16612e2f565b15612dc8578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612c9c612460565b8786866040518563ffffffff1660e01b8152600401612cbe9493929190614b45565b6020604051808303815f875af1925050508015612cf957506040513d601f19601f82011682018060405250810190612cf69190614ba3565b60015b612d78573d805f8114612d27576040519150601f19603f3d011682016040523d82523d5f602084013e612d2c565b606091505b505f815103612d70576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d6790614ad5565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050612dcd565b600190505b949350505050565b612ddf8383612e40565b612deb5f848484612c53565b612e2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2190614ad5565b60405180910390fd5b505050565b5f5f823b90505f8111915050919050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612eae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ea590614c18565b60405180910390fd5b612eb7816123f8565b15612ef7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eee90614c80565b60405180910390fd5b612f025f8383612c4e565b600160035f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612f4f9190613d97565b925050819055508160025f8381526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b5f604051905090565b5f5ffd5b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61304981613015565b8114613053575f5ffd5b50565b5f8135905061306481613040565b92915050565b5f6020828403121561307f5761307e61300d565b5b5f61308c84828501613056565b91505092915050565b5f8115159050919050565b6130a981613095565b82525050565b5f6020820190506130c25f8301846130a0565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61310a826130c8565b61311481856130d2565b93506131248185602086016130e2565b61312d816130f0565b840191505092915050565b5f6020820190508181035f8301526131508184613100565b905092915050565b5f819050919050565b61316a81613158565b8114613174575f5ffd5b50565b5f8135905061318581613161565b92915050565b5f602082840312156131a05761319f61300d565b5b5f6131ad84828501613177565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6131df826131b6565b9050919050565b6131ef816131d5565b82525050565b5f6020820190506132085f8301846131e6565b92915050565b613217816131d5565b8114613221575f5ffd5b50565b5f813590506132328161320e565b92915050565b5f5f6040838503121561324e5761324d61300d565b5b5f61325b85828601613224565b925050602061326c85828601613177565b9150509250929050565b61327f81613158565b82525050565b5f6020820190506132985f830184613276565b92915050565b5f5f5f606084860312156132b5576132b461300d565b5b5f6132c286828701613224565b93505060206132d386828701613224565b92505060406132e486828701613177565b9150509250925092565b5f5ffd5b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61332c826130f0565b810181811067ffffffffffffffff8211171561334b5761334a6132f6565b5b80604052505050565b5f61335d613004565b90506133698282613323565b919050565b5f67ffffffffffffffff821115613388576133876132f6565b5b613391826130f0565b9050602081019050919050565b828183375f83830152505050565b5f6133be6133b98461336e565b613354565b9050828152602081018484840111156133da576133d96132f2565b5b6133e584828561339e565b509392505050565b5f82601f830112613401576134006132ee565b5b81356134118482602086016133ac565b91505092915050565b5f6020828403121561342f5761342e61300d565b5b5f82013567ffffffffffffffff81111561344c5761344b613011565b5b613458848285016133ed565b91505092915050565b5f819050919050565b5f61348461347f61347a846131b6565b613461565b6131b6565b9050919050565b5f6134958261346a565b9050919050565b5f6134a68261348b565b9050919050565b6134b68161349c565b82525050565b5f6020820190506134cf5f8301846134ad565b92915050565b5f602082840312156134ea576134e961300d565b5b5f6134f784828501613224565b91505092915050565b5f5ffd5b5f5ffd5b5f5f83601f84011261351d5761351c6132ee565b5b8235905067ffffffffffffffff81111561353a57613539613500565b5b60208301915083600182028301111561355657613555613504565b5b9250929050565b5f5f602083850312156135735761357261300d565b5b5f83013567ffffffffffffffff8111156135905761358f613011565b5b61359c85828601613508565b92509250509250929050565b5f5f83601f8401126135bd576135bc6132ee565b5b8235905067ffffffffffffffff8111156135da576135d9613500565b5b6020830191508360208202830111156135f6576135f5613504565b5b9250929050565b5f5f5f5f5f5f606087890312156136175761361661300d565b5b5f87013567ffffffffffffffff81111561363457613633613011565b5b61364089828a016135a8565b9650965050602087013567ffffffffffffffff81111561366357613662613011565b5b61366f89828a01613508565b9450945050604087013567ffffffffffffffff81111561369257613691613011565b5b61369e89828a01613508565b92509250509295509295509295565b6136b681613095565b81146136c0575f5ffd5b50565b5f813590506136d1816136ad565b92915050565b5f5f604083850312156136ed576136ec61300d565b5b5f6136fa85828601613224565b925050602061370b858286016136c3565b9150509250929050565b5f67ffffffffffffffff82111561372f5761372e6132f6565b5b613738826130f0565b9050602081019050919050565b5f61375761375284613715565b613354565b905082815260208101848484011115613773576137726132f2565b5b61377e84828561339e565b509392505050565b5f82601f83011261379a576137996132ee565b5b81356137aa848260208601613745565b91505092915050565b5f5f5f5f608085870312156137cb576137ca61300d565b5b5f6137d887828801613224565b94505060206137e987828801613224565b93505060406137fa87828801613177565b925050606085013567ffffffffffffffff81111561381b5761381a613011565b5b61382787828801613786565b91505092959194509250565b5f5f5f5f6060858703121561384b5761384a61300d565b5b5f61385887828801613224565b945050602061386987828801613177565b935050604085013567ffffffffffffffff81111561388a57613889613011565b5b61389687828801613508565b925092505092959194509250565b5f5f604083850312156138ba576138b961300d565b5b5f6138c785828601613224565b92505060206138d885828601613224565b9150509250929050565b5f6138ec8261348b565b9050919050565b6138fc816138e2565b82525050565b5f6020820190506139155f8301846138f3565b92915050565b5f60ff82169050919050565b6139308161391b565b82525050565b5f6020820190506139495f830184613927565b92915050565b5f5f5f604084860312156139665761396561300d565b5b5f61397386828701613177565b935050602084013567ffffffffffffffff81111561399457613993613011565b5b6139a086828701613508565b92509250509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806139f057607f821691505b602082108103613a0357613a026139ac565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e65785f8201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b5f613a63602c836130d2565b9150613a6e82613a09565b604082019050919050565b5f6020820190508181035f830152613a9081613a57565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e655f8201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b5f613af16021836130d2565b9150613afc82613a97565b604082019050919050565b5f6020820190508181035f830152613b1e81613ae5565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f775f8201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b5f613b7f6038836130d2565b9150613b8a82613b25565b604082019050919050565b5f6020820190508181035f830152613bac81613b73565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f613bea82613158565b9150613bf583613158565b9250828203905081811115613c0d57613c0c613bb3565b5b92915050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f5f8201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b5f613c6d6031836130d2565b9150613c7882613c13565b604082019050919050565b5f6020820190508181035f830152613c9a81613c61565b9050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e655f8201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b5f613cfb602d836130d2565b9150613d0682613ca1565b604082019050919050565b5f6020820190508181035f830152613d2881613cef565b9050919050565b5f613d3982613158565b9150613d4483613158565b9250828202613d5281613158565b91508282048414831517613d6957613d68613bb3565b5b5092915050565b5f604082019050613d835f8301856131e6565b613d906020830184613276565b9392505050565b5f613da182613158565b9150613dac83613158565b9250828201905080821115613dc457613dc3613bb3565b5b92915050565b5f606082019050613ddd5f8301866131e6565b613dea6020830185613276565b613df76040830184613276565b949350505050565b7f4552433732313a206f776e657220717565727920666f72206e6f6e65786973745f8201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b5f613e596029836130d2565b9150613e6482613dff565b604082019050919050565b5f6020820190508181035f830152613e8681613e4d565b9050919050565b5f81519050613e9b8161320e565b92915050565b5f60208284031215613eb657613eb561300d565b5b5f613ec384828501613e8d565b91505092915050565b7f43616c6c6572206973206e6f742042555344204f776e657200000000000000005f82015250565b5f613f006018836130d2565b9150613f0b82613ecc565b602082019050919050565b5f6020820190508181035f830152613f2d81613ef4565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a655f8201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b5f613f8e602a836130d2565b9150613f9982613f34565b604082019050919050565b5f6020820190508181035f830152613fbb81613f82565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725f82015250565b5f613ff66020836130d2565b915061400182613fc2565b602082019050919050565b5f6020820190508181035f83015261402381613fea565b9050919050565b5f82905092915050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026140907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614055565b61409a8683614055565b95508019841693508086168417925050509392505050565b5f6140cc6140c76140c284613158565b613461565b613158565b9050919050565b5f819050919050565b6140e5836140b2565b6140f96140f1826140d3565b848454614061565b825550505050565b5f5f905090565b614110614101565b61411b8184846140dc565b505050565b5b8181101561413e576141335f82614108565b600181019050614121565b5050565b601f8211156141835761415481614034565b61415d84614046565b8101602085101561416c578190505b61418061417885614046565b830182614120565b50505b505050565b5f82821c905092915050565b5f6141a35f1984600802614188565b1980831691505092915050565b5f6141bb8383614194565b9150826002028217905092915050565b6141d5838361402a565b67ffffffffffffffff8111156141ee576141ed6132f6565b5b6141f882546139d9565b614203828285614142565b5f601f831160018114614230575f841561421e578287013590505b61422885826141b0565b86555061428f565b601f19841661423e86614034565b5f5b8281101561426557848901358255600182019150602085019450602081019050614240565b86831015614282578489013561427e601f891682614194565b8355505b6001600288020188555050505b50505050505050565b5f6142a2826131d5565b9050919050565b6142b281614298565b81146142bc575f5ffd5b50565b5f815190506142cd816142a9565b92915050565b5f602082840312156142e8576142e761300d565b5b5f6142f5848285016142bf565b91505092915050565b7f43616c6c6572206973206e6f74204275726e204167656e7400000000000000005f82015250565b5f6143326018836130d2565b915061433d826142fe565b602082019050919050565b5f6020820190508181035f83015261435f81614326565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f81905092915050565b5f6143a88385614393565b93506143b583858461339e565b82840190509392505050565b5f6143cb826130c8565b6143d58185614393565b93506143e58185602086016130e2565b80840191505092915050565b5f6143fd82878961439d565b915061440982866143c1565b915061441682848661439d565b91508190509695505050505050565b61442e826130c8565b67ffffffffffffffff811115614447576144466132f6565b5b61445182546139d9565b61445c828285614142565b5f60209050601f83116001811461448d575f841561447b578287015190505b61448585826141b0565b8655506144ec565b601f19841661449b86614034565b5f5b828110156144c25784890151825560018201915060208501945060208101905061449d565b868310156144df57848901516144db601f891682614194565b8355505b6001600288020188555050505b505050505050565b5f819050919050565b5f61451761451261450d846144f4565b613461565b613158565b9050919050565b614527816144fd565b82525050565b5f6040820190506145405f83018561451e565b61454d6020830184613276565b9392505050565b7f4552433732313a20617070726f766520746f2063616c6c6572000000000000005f82015250565b5f6145886019836130d2565b915061459382614554565b602082019050919050565b5f6020820190508181035f8301526145b58161457c565b9050919050565b5f6145ce6145c98461336e565b613354565b9050828152602081018484840111156145ea576145e96132f2565b5b6145f58482856130e2565b509392505050565b5f82601f830112614611576146106132ee565b5b81516146218482602086016145bc565b91505092915050565b5f6020828403121561463f5761463e61300d565b5b5f82015167ffffffffffffffff81111561465c5761465b613011565b5b614668848285016145fd565b91505092915050565b7f496e76616c6964206d696e7465720000000000000000000000000000000000005f82015250565b5f6146a5600e836130d2565b91506146b082614671565b602082019050919050565b5f6020820190508181035f8301526146d281614699565b9050919050565b5f6146e582848661439d565b91508190509392505050565b7f53657269616c20616c72656164792075736564000000000000000000000000005f82015250565b5f6147256013836130d2565b9150614730826146f1565b602082019050919050565b5f6020820190508181035f83015261475281614719565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20615f8201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b5f6147b36026836130d2565b91506147be82614759565b604082019050919050565b5f6020820190508181035f8301526147e0816147a7565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e65785f8201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b5f614841602c836130d2565b915061484c826147e7565b604082019050919050565b5f6020820190508181035f83015261486e81614835565b9050919050565b7f4552433732313a207472616e73666572206f6620746f6b656e207468617420695f8201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b5f6148cf6029836130d2565b91506148da82614875565b604082019050919050565b5f6020820190508181035f8301526148fc816148c3565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f206164645f8201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b5f61495d6024836130d2565b915061496882614903565b604082019050919050565b5f6020820190508181035f83015261498a81614951565b9050919050565b5f61499b82613158565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149cd576149cc613bb3565b5b600182019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f614a0f82613158565b9150614a1a83613158565b925082614a2a57614a296149d8565b5b828204905092915050565b5f614a3f82613158565b9150614a4a83613158565b925082614a5a57614a596149d8565b5b828206905092915050565b7f4552433732313a207472616e7366657220746f206e6f6e2045524337323152655f8201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b5f614abf6032836130d2565b9150614aca82614a65565b604082019050919050565b5f6020820190508181035f830152614aec81614ab3565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f614b1782614af3565b614b218185614afd565b9350614b318185602086016130e2565b614b3a816130f0565b840191505092915050565b5f608082019050614b585f8301876131e6565b614b6560208301866131e6565b614b726040830185613276565b8181036060830152614b848184614b0d565b905095945050505050565b5f81519050614b9d81613040565b92915050565b5f60208284031215614bb857614bb761300d565b5b5f614bc584828501614b8f565b91505092915050565b7f4552433732313a206d696e7420746f20746865207a65726f20616464726573735f82015250565b5f614c026020836130d2565b9150614c0d82614bce565b602082019050919050565b5f6020820190508181035f830152614c2f81614bf6565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e746564000000005f82015250565b5f614c6a601c836130d2565b9150614c7582614c36565b602082019050919050565b5f6020820190508181035f830152614c9781614c5e565b905091905056fea26469706673582212203a459bb8f390945aad17b6c4b2d99984329d09f9a01b219d9b6066e912294cee64736f6c634300081c00336080604052348015600e575f5ffd5b50335f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611c938061005b5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c80632b4ef78214610038578063c87b56dd14610056575b5f5ffd5b610040610086565b60405161004d9190610a05565b60405180910390f35b610070600480360381019061006b9190610a62565b6100aa565b60405161007d9190610afd565b60405180910390f35b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60605f6101505f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f3ce61ad856040518263ffffffff1660e01b81526004016101099190610b2c565b602060405180830381865afa158015610124573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101489190610b7b565b60ff166106a2565b90505f6101f35f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638bc33af3866040518263ffffffff1660e01b81526004016101af9190610b2c565b602060405180830381865afa1580156101ca573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101ee9190610bba565b6106a2565b90505f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166398cd96af866040518263ffffffff1660e01b815260040161024f9190610b2c565b5f60405180830381865afa158015610269573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f820116820180604052508101906102919190610d03565b90505f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e8dfdf04876040518263ffffffff1660e01b81526004016102ed9190610b2c565b5f60405180830381865afa158015610307573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061032f9190610d03565b90505f6103d25f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c3062ce7896040518263ffffffff1660e01b815260040161038e9190610b2c565b602060405180830381865afa1580156103a9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103cd9190610bba565b6106a2565b90505f6103de886106a2565b90505f5f84511190505f828689898561042c576040518060400160405280600181526020017f2e0000000000000000000000000000000000000000000000000000000000000081525061044d565b8860405160200161043d9190610daa565b6040516020818303038152906040525b604051602001610461959493929190610e67565b60405160208183030381529060405290505f5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639ddaf5aa8c6040518263ffffffff1660e01b81526004016104cc9190610b2c565b5f60405180830381865afa1580156104e6573d5f5f3e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061050e9190610d03565b90505f8151036105665761054484888b604051602001610530939291906111e0565b6040516020818303038152906040526107fb565b6040516020016105549190611286565b60405160208183030381529060405290505b5f87604051602001610578919061133d565b6040516020818303038152906040528a60405160200161059891906113dd565b6040516020818303038152906040528a6040516020016105b8919061147d565b604051602081830303815290604052886040516020016105d89190611543565b604051602081830303815290604052876106005760405180602001604052805f815250610621565b8a60405160200161061191906115e3565b6040516020818303038152906040525b60405160200161063595949392919061165f565b604051602081830303815290604052905084888b60405160200161065b93929190611739565b604051602081830303815290604052838384846040516020016106829594939291906119bc565b6040516020818303038152906040529a5050505050505050505050919050565b60605f82036106e8576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506107f6565b5f8290505f5b5f821461071757808061070090611a75565b915050600a826107109190611ae9565b91506106ee565b5f8167ffffffffffffffff81111561073257610731610bed565b5b6040519080825280601f01601f1916602001820160405280156107645781602001600182028036833780820191505090505b5090505b5f85146107ef5760018261077c9190611b19565b9150600a8561078b9190611b4c565b60306107979190611b7c565b60f81b8183815181106107ad576107ac611baf565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a856107e89190611ae9565b9450610768565b8093505050505b919050565b60605f825190505f81036108205760405180602001604052805f815250915050610986565b5f60036002836108309190611b7c565b61083a9190611ae9565b60046108469190611bdc565b90505f6020826108569190611b7c565b67ffffffffffffffff81111561086f5761086e610bed565b5b6040519080825280601f01601f1916602001820160405280156108a15781602001600182028036833780820191505090505b5090505f604051806060016040528060408152602001611c1e60409139905060018101602083015f5b868110156109435760038101905062ffffff818a015116603f8160121c168401518060081b905060ff603f83600c1c1686015116810190508060081b905060ff603f8360061c1686015116810190508060081b905060ff603f831686015116810190508060e01b905080845260048401935050506108ca565b50600386066001811461095d576002811461096d57610978565b613d3d60f01b6002830352610978565b603d60f81b60018303525b508484525050819450505050505b919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f6109cd6109c86109c38461098b565b6109aa565b61098b565b9050919050565b5f6109de826109b3565b9050919050565b5f6109ef826109d4565b9050919050565b6109ff816109e5565b82525050565b5f602082019050610a185f8301846109f6565b92915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f819050919050565b610a4181610a2f565b8114610a4b575f5ffd5b50565b5f81359050610a5c81610a38565b92915050565b5f60208284031215610a7757610a76610a27565b5b5f610a8484828501610a4e565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610acf82610a8d565b610ad98185610a97565b9350610ae9818560208601610aa7565b610af281610ab5565b840191505092915050565b5f6020820190508181035f830152610b158184610ac5565b905092915050565b610b2681610a2f565b82525050565b5f602082019050610b3f5f830184610b1d565b92915050565b5f60ff82169050919050565b610b5a81610b45565b8114610b64575f5ffd5b50565b5f81519050610b7581610b51565b92915050565b5f60208284031215610b9057610b8f610a27565b5b5f610b9d84828501610b67565b91505092915050565b5f81519050610bb481610a38565b92915050565b5f60208284031215610bcf57610bce610a27565b5b5f610bdc84828501610ba6565b91505092915050565b5f5ffd5b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610c2382610ab5565b810181811067ffffffffffffffff82111715610c4257610c41610bed565b5b80604052505050565b5f610c54610a1e565b9050610c608282610c1a565b919050565b5f67ffffffffffffffff821115610c7f57610c7e610bed565b5b610c8882610ab5565b9050602081019050919050565b5f610ca7610ca284610c65565b610c4b565b905082815260208101848484011115610cc357610cc2610be9565b5b610cce848285610aa7565b509392505050565b5f82601f830112610cea57610ce9610be5565b5b8151610cfa848260208601610c95565b91505092915050565b5f60208284031215610d1857610d17610a27565b5b5f82015167ffffffffffffffff811115610d3557610d34610a2b565b5b610d4184828501610cd6565b91505092915050565b7f2e20496e636c75646564204d656d6f3a20000000000000000000000000000000815250565b5f81905092915050565b5f610d8482610a8d565b610d8e8185610d70565b9350610d9e818560208601610aa7565b80840191505092915050565b5f610db482610d4a565b601182019150610dc48284610d7a565b915081905092915050565b7f50726f6f66206f66204275726e20230000000000000000000000000000000000815250565b7f20666f722062696c6c3a20000000000000000000000000000000000000000000815250565b7f2c2069737375696e672000000000000000000000000000000000000000000000815250565b7f20625553442061742074696d657374616d702000000000000000000000000000815250565b5f610e7182610dcf565b600f82019150610e818288610d7a565b9150610e8c82610df5565b600b82019150610e9c8287610d7a565b9150610ea782610e1b565b600a82019150610eb78286610d7a565b9150610ec282610e41565b601382019150610ed28285610d7a565b9150610ede8284610d7a565b91508190509695505050505050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f32305f8201527f30302f737667222076696577426f783d223020302033323020313830223e3c7260208201527f65637420783d22302220793d2230222077696474683d2231303025222068656960408201527f6768743d2231303025222066696c6c3d2223303030223e3c2f726563743e3c7460608201527f65787420783d223530252220793d223433252220666f6e742d73697a653d223260808201527f307078222066696c6c3d22236666662220666f6e742d66616d696c793d226d6f60a08201527f6e6f73706163652220646f6d696e616e742d626173656c696e653d226d69646460c08201527f6c652220746578742d616e63686f723d226d6964646c65223e50726f6f66206f60e08201527f66204275726e202300000000000000000000000000000000000000000000000061010082015250565b5f61105361010883610d70565b915061105e82610eed565b61010882019050919050565b7f3c2f746578743e3c7465787420783d223530252220793d223537252220666f6e5f8201527f742d73697a653d2232307078222066696c6c3d22236666662220666f6e742d6660208201527f616d696c793d226d6f6e6f73706163652220646f6d696e616e742d626173656c60408201527f696e653d226d6964646c652220746578742d616e63686f723d226d6964646c6560608201527f223e000000000000000000000000000000000000000000000000000000000000608082015250565b5f611136608283610d70565b91506111418261106a565b608282019050919050565b7f20240000000000000000000000000000000000000000000000000000000000005f82015250565b5f611180600283610d70565b915061118b8261114c565b600282019050919050565b7f3c2f746578743e3c2f7376673e000000000000000000000000000000000000005f82015250565b5f6111ca600d83610d70565b91506111d582611196565b600d82019050919050565b5f6111ea82611046565b91506111f68286610d7a565b91506112018261112a565b915061120d8285610d7a565b915061121882611174565b91506112248284610d7a565b915061122f826111be565b9150819050949350505050565b7f646174613a696d6167652f7376672b786d6c3b6261736536342c0000000000005f82015250565b5f611270601a83610d70565b915061127b8261123c565b601a82019050919050565b5f61129082611264565b915061129c8284610d7a565b915081905092915050565b7f7b202274726169745f74797065223a202253657269616c222c202276616c75655f8201527f223a202200000000000000000000000000000000000000000000000000000000602082015250565b5f611301602483610d70565b915061130c826112a7565b602482019050919050565b7f22207d2c00000000000000000000000000000000000000000000000000000000815250565b5f611347826112f5565b91506113538284610d7a565b915061135e82611317565b60048201915081905092915050565b7f7b202274726169745f74797065223a202244656e6f6d696e6174696f6e222c205f8201527f2276616c7565223a202200000000000000000000000000000000000000000000602082015250565b5f6113c7602a83610d70565b91506113d28261136d565b602a82019050919050565b5f6113e7826113bb565b91506113f38284610d7a565b91506113fe82611317565b60048201915081905092915050565b7f7b202274726169745f74797065223a20224275726e6564206174222c202276615f8201527f6c7565223a202200000000000000000000000000000000000000000000000000602082015250565b5f611467602783610d70565b91506114728261140d565b602782019050919050565b5f6114878261145b565b91506114938284610d7a565b915061149e82611317565b60048201915081905092915050565b7f7b202274726169745f74797065223a202253657373696f6e204944222c2022765f8201527f616c7565223a2022000000000000000000000000000000000000000000000000602082015250565b5f611507602883610d70565b9150611512826114ad565b602882019050919050565b7f22207d0000000000000000000000000000000000000000000000000000000000815250565b5f61154d826114fb565b91506115598284610d7a565b91506115648261151d565b60038201915081905092915050565b7f2c7b202274726169745f74797065223a20224275726e204d656d6f222c2022765f8201527f616c7565223a2022000000000000000000000000000000000000000000000000602082015250565b5f6115cd602883610d70565b91506115d882611573565b602882019050919050565b5f6115ed826115c1565b91506115f98284610d7a565b91506116048261151d565b60038201915081905092915050565b7f5b00000000000000000000000000000000000000000000000000000000000000815250565b7f5d00000000000000000000000000000000000000000000000000000000000000815250565b5f61166982611613565b6001820191506116798288610d7a565b91506116858287610d7a565b91506116918286610d7a565b915061169d8285610d7a565b91506116a98284610d7a565b91506116b482611639565b6001820191508190509695505050505050565b7f2028000000000000000000000000000000000000000000000000000000000000815250565b7f2c20240000000000000000000000000000000000000000000000000000000000815250565b7f2900000000000000000000000000000000000000000000000000000000000000815250565b5f6117448286610d7a565b915061174f826116c7565b60028201915061175f8285610d7a565b915061176a826116ed565b60038201915061177a8284610d7a565b915061178582611713565b600182019150819050949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b757466382c7b226e616d5f8201527f65223a202250726f6f66206f66204275726e2023000000000000000000000000602082015250565b5f6117f0603483610d70565b91506117fb82611796565b603482019050919050565b7f222c20226465736372697074696f6e223a2022000000000000000000000000005f82015250565b5f61183a601383610d70565b915061184582611806565b601382019050919050565b7f222c2022696d616765223a2022000000000000000000000000000000000000005f82015250565b5f611884600d83610d70565b915061188f82611850565b600d82019050919050565b5f81519050919050565b5f81905092915050565b5f6118b88261189a565b6118c281856118a4565b93506118d2818560208601610aa7565b80840191505092915050565b7f222c2022616e696d6174696f6e5f75726c223a202200000000000000000000005f82015250565b5f611912601583610d70565b915061191d826118de565b601582019050919050565b7f222c202261747472696275746573223a000000000000000000000000000000005f82015250565b5f61195c601083610d70565b915061196782611928565b601082019050919050565b7f7d000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6119a6600183610d70565b91506119b182611972565b600182019050919050565b5f6119c6826117e4565b91506119d28288610d7a565b91506119dd8261182e565b91506119e98287610d7a565b91506119f482611878565b9150611a0082866118ae565b9150611a0b82611906565b9150611a1782856118ae565b9150611a2282611950565b9150611a2e8284610d7a565b9150611a398261199a565b91508190509695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611a7f82610a2f565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611ab157611ab0611a48565b5b600182019050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f611af382610a2f565b9150611afe83610a2f565b925082611b0e57611b0d611abc565b5b828204905092915050565b5f611b2382610a2f565b9150611b2e83610a2f565b9250828203905081811115611b4657611b45611a48565b5b92915050565b5f611b5682610a2f565b9150611b6183610a2f565b925082611b7157611b70611abc565b5b828206905092915050565b5f611b8682610a2f565b9150611b9183610a2f565b9250828201905080821115611ba957611ba8611a48565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f611be682610a2f565b9150611bf183610a2f565b9250828202611bff81610a2f565b91508282048414831517611c1657611c15611a48565b5b509291505056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220069c705c4a98c772316bc62943a1577edaff35f6adc002d0f96e3763e337967764736f6c634300081c0033646174613a6170706c69636174696f6e2f6a736f6e3b757466382c7b226e616d65223a2250726f6f66206f66204275726e20286255534429227d646174613a6170706c69636174696f6e2f6a736f6e3b757466382c7b226e616d65223a224275726e7420555320446f6c6c617273227d
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610156575f3560e01c806379cc6790116100c1578063a4e2d6341161007a578063a4e2d634146103b4578063a9059cbb146103d2578063d3a7383314610402578063dd62ed3e1461041e578063e8a3d4851461044e578063f2fde38b1461046c57610156565b806379cc6790146102f45780637e5b1e2414610310578063867904b41461032c5780638da5cb5b1461034857806395d89b4114610366578063a457c2d71461038457610156565b806325f3d2771161011357806325f3d2771461021e578063313ce5671461023c578063395093511461025a57806360486d761461028a57806370a08231146102ba578063715018a6146102ea57610156565b806306133c651461015a57806306fdde0314610178578063095ea7b31461019657806318160ddd146101c6578063234b8d0e146101e457806323b872dd146101ee575b5f5ffd5b610162610488565b60405161016f9190611719565b60405180910390f35b6101806104ad565b60405161018d91906117a2565b60405180910390f35b6101b060048036038101906101ab9190611838565b61053d565b6040516101bd9190611890565b60405180910390f35b6101ce61055f565b6040516101db91906118b8565b60405180910390f35b6101ec610568565b005b610208600480360381019061020391906118d1565b610601565b6040516102159190611890565b60405180910390f35b61022661062f565b6040516102339190611941565b60405180910390f35b610244610654565b6040516102519190611975565b60405180910390f35b610274600480360381019061026f9190611838565b61065c565b6040516102819190611890565b60405180910390f35b6102a4600480360381019061029f919061198e565b610692565b6040516102b191906118b8565b60405180910390f35b6102d460048036038101906102cf919061198e565b6106a7565b6040516102e191906118b8565b60405180910390f35b6102f26106ec565b005b61030e60048036038101906103099190611838565b610773565b005b61032a60048036038101906103259190611a1a565b61082c565b005b61034660048036038101906103419190611838565b6108ea565b005b6103506109d7565b60405161035d9190611a74565b60405180910390f35b61036e6109ff565b60405161037b91906117a2565b60405180910390f35b61039e60048036038101906103999190611838565b610a8f565b6040516103ab9190611890565b60405180910390f35b6103bc610b04565b6040516103c99190611890565b60405180910390f35b6103ec60048036038101906103e79190611838565b610b17565b6040516103f99190611890565b60405180910390f35b61041c6004803603810190610417919061198e565b610b39565b005b61043860048036038101906104339190611a8d565b610bf8565b60405161044591906118b8565b60405180910390f35b610456610c7a565b60405161046391906117a2565b60405180910390f35b6104866004803603810190610481919061198e565b610d0a565b005b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060600380546104bc90611af8565b80601f01602080910402602001604051908101604052809291908181526020018280546104e890611af8565b80156105335780601f1061050a57610100808354040283529160200191610533565b820191905f5260205f20905b81548152906001019060200180831161051657829003601f168201915b5050505050905090565b5f5f610547610e00565b9050610554818585610e07565b600191505092915050565b5f600254905090565b610570610e00565b73ffffffffffffffffffffffffffffffffffffffff1661058e6109d7565b73ffffffffffffffffffffffffffffffffffffffff16146105e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105db90611b72565b60405180910390fd5b6001600760146101000a81548160ff021916908315150217905550565b5f5f61060b610e00565b9050610618858285610fca565b610623858585611055565b60019150509392505050565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f6012905090565b5f5f610666610e00565b90506106878185856106788589610bf8565b6106829190611bbd565b610e07565b600191505092915050565b6008602052805f5260405f205f915090505481565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6106f4610e00565b73ffffffffffffffffffffffffffffffffffffffff166107126109d7565b73ffffffffffffffffffffffffffffffffffffffff1614610768576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161075f90611b72565b60405180910390fd5b6107715f6112c1565b565b60075f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107cb575f5ffd5b8060085f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546108179190611bbd565b925050819055506108288282611384565b5050565b610834610e00565b73ffffffffffffffffffffffffffffffffffffffff166108526109d7565b73ffffffffffffffffffffffffffffffffffffffff16146108a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089f90611b72565b60405180910390fd5b8181600991826108b9929190611dbe565b507fa5d4097edda6d87cb9329af83fb3712ef77eeb13738ffe43cc35a4ce305ad96260405160405180910390a15050565b600760149054906101000a900460ff161561093a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093190611ed5565b60405180910390fd5b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109c090611f63565b60405180910390fd5b6109d38282611547565b5050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060048054610a0e90611af8565b80601f0160208091040260200160405190810160405280929190818152602001828054610a3a90611af8565b8015610a855780601f10610a5c57610100808354040283529160200191610a85565b820191905f5260205f20905b815481529060010190602001808311610a6857829003601f168201915b5050505050905090565b5f5f610a99610e00565b90505f610aa68286610bf8565b905083811015610aeb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae290611ff1565b60405180910390fd5b610af88286868403610e07565b60019250505092915050565b600760149054906101000a900460ff1681565b5f5f610b21610e00565b9050610b2e818585611055565b600191505092915050565b610b41610e00565b73ffffffffffffffffffffffffffffffffffffffff16610b5f6109d7565b73ffffffffffffffffffffffffffffffffffffffff1614610bb5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bac90611b72565b60405180910390fd5b8060065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b606060098054610c8990611af8565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb590611af8565b8015610d005780601f10610cd757610100808354040283529160200191610d00565b820191905f5260205f20905b815481529060010190602001808311610ce357829003601f168201915b5050505050905090565b610d12610e00565b73ffffffffffffffffffffffffffffffffffffffff16610d306109d7565b73ffffffffffffffffffffffffffffffffffffffff1614610d86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7d90611b72565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610df4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610deb9061207f565b60405180910390fd5b610dfd816112c1565b50565b5f33905090565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e75576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e6c9061210d565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610ee3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eda9061219b565b60405180910390fd5b8060015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051610fbd91906118b8565b60405180910390a3505050565b5f610fd58484610bf8565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461104f5781811015611041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161103890612203565b60405180910390fd5b61104e8484848403610e07565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036110c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ba90612291565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611131576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111289061231f565b60405180910390fd5b61113c838383611695565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050818110156111bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111b6906123ad565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550815f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516112a891906118b8565b60405180910390a36112bb84848461169a565b50505050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036113f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e99061243b565b60405180910390fd5b6113fd825f83611695565b5f5f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015611480576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611477906124c9565b60405180910390fd5b8181035f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508160025f82825403925050819055505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161152f91906118b8565b60405180910390a3611542835f8461169a565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036115b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ac90612531565b60405180910390fd5b6115c05f8383611695565b8060025f8282546115d19190611bbd565b92505081905550805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055508173ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161167e91906118b8565b60405180910390a36116915f838361169a565b5050565b505050565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f6116e16116dc6116d78461169f565b6116be565b61169f565b9050919050565b5f6116f2826116c7565b9050919050565b5f611703826116e8565b9050919050565b611713816116f9565b82525050565b5f60208201905061172c5f83018461170a565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61177482611732565b61177e818561173c565b935061178e81856020860161174c565b6117978161175a565b840191505092915050565b5f6020820190508181035f8301526117ba818461176a565b905092915050565b5f5ffd5b5f5ffd5b5f6117d48261169f565b9050919050565b6117e4816117ca565b81146117ee575f5ffd5b50565b5f813590506117ff816117db565b92915050565b5f819050919050565b61181781611805565b8114611821575f5ffd5b50565b5f813590506118328161180e565b92915050565b5f5f6040838503121561184e5761184d6117c2565b5b5f61185b858286016117f1565b925050602061186c85828601611824565b9150509250929050565b5f8115159050919050565b61188a81611876565b82525050565b5f6020820190506118a35f830184611881565b92915050565b6118b281611805565b82525050565b5f6020820190506118cb5f8301846118a9565b92915050565b5f5f5f606084860312156118e8576118e76117c2565b5b5f6118f5868287016117f1565b9350506020611906868287016117f1565b925050604061191786828701611824565b9150509250925092565b5f61192b826116e8565b9050919050565b61193b81611921565b82525050565b5f6020820190506119545f830184611932565b92915050565b5f60ff82169050919050565b61196f8161195a565b82525050565b5f6020820190506119885f830184611966565b92915050565b5f602082840312156119a3576119a26117c2565b5b5f6119b0848285016117f1565b91505092915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f8401126119da576119d96119b9565b5b8235905067ffffffffffffffff8111156119f7576119f66119bd565b5b602083019150836001820283011115611a1357611a126119c1565b5b9250929050565b5f5f60208385031215611a3057611a2f6117c2565b5b5f83013567ffffffffffffffff811115611a4d57611a4c6117c6565b5b611a59858286016119c5565b92509250509250929050565b611a6e816117ca565b82525050565b5f602082019050611a875f830184611a65565b92915050565b5f5f60408385031215611aa357611aa26117c2565b5b5f611ab0858286016117f1565b9250506020611ac1858286016117f1565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680611b0f57607f821691505b602082108103611b2257611b21611acb565b5b50919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725f82015250565b5f611b5c60208361173c565b9150611b6782611b28565b602082019050919050565b5f6020820190508181035f830152611b8981611b50565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f611bc782611805565b9150611bd283611805565b9250828201905080821115611bea57611be9611b90565b5b92915050565b5f82905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302611c837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611c48565b611c8d8683611c48565b95508019841693508086168417925050509392505050565b5f611cbf611cba611cb584611805565b6116be565b611805565b9050919050565b5f819050919050565b611cd883611ca5565b611cec611ce482611cc6565b848454611c54565b825550505050565b5f5f905090565b611d03611cf4565b611d0e818484611ccf565b505050565b5b81811015611d3157611d265f82611cfb565b600181019050611d14565b5050565b601f821115611d7657611d4781611c27565b611d5084611c39565b81016020851015611d5f578190505b611d73611d6b85611c39565b830182611d13565b50505b505050565b5f82821c905092915050565b5f611d965f1984600802611d7b565b1980831691505092915050565b5f611dae8383611d87565b9150826002028217905092915050565b611dc88383611bf0565b67ffffffffffffffff811115611de157611de0611bfa565b5b611deb8254611af8565b611df6828285611d35565b5f601f831160018114611e23575f8415611e11578287013590505b611e1b8582611da3565b865550611e82565b601f198416611e3186611c27565b5f5b82811015611e5857848901358255600182019150602085019450602081019050611e33565b86831015611e755784890135611e71601f891682611d87565b8355505b6001600288020188555050505b50505050505050565b7f4e65772069737375616e6365206973206c6f636b6564000000000000000000005f82015250565b5f611ebf60168361173c565b9150611eca82611e8b565b602082019050919050565b5f6020820190508181035f830152611eec81611eb3565b9050919050565b7f43616e206f6e6c79206973737565207468726f756768206f6666696369616c205f8201527f4275726e20436572656d6f6e7900000000000000000000000000000000000000602082015250565b5f611f4d602d8361173c565b9150611f5882611ef3565b604082019050919050565b5f6020820190508181035f830152611f7a81611f41565b9050919050565b7f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f775f8201527f207a65726f000000000000000000000000000000000000000000000000000000602082015250565b5f611fdb60258361173c565b9150611fe682611f81565b604082019050919050565b5f6020820190508181035f83015261200881611fcf565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20615f8201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b5f61206960268361173c565b91506120748261200f565b604082019050919050565b5f6020820190508181035f8301526120968161205d565b9050919050565b7f45524332303a20617070726f76652066726f6d20746865207a65726f206164645f8201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b5f6120f760248361173c565b91506121028261209d565b604082019050919050565b5f6020820190508181035f830152612124816120eb565b9050919050565b7f45524332303a20617070726f766520746f20746865207a65726f2061646472655f8201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b5f61218560228361173c565b91506121908261212b565b604082019050919050565b5f6020820190508181035f8301526121b281612179565b9050919050565b7f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000005f82015250565b5f6121ed601d8361173c565b91506121f8826121b9565b602082019050919050565b5f6020820190508181035f83015261221a816121e1565b9050919050565b7f45524332303a207472616e736665722066726f6d20746865207a65726f2061645f8201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b5f61227b60258361173c565b915061228682612221565b604082019050919050565b5f6020820190508181035f8301526122a88161226f565b9050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f20616464725f8201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b5f61230960238361173c565b9150612314826122af565b604082019050919050565b5f6020820190508181035f830152612336816122fd565b9050919050565b7f45524332303a207472616e7366657220616d6f756e74206578636565647320625f8201527f616c616e63650000000000000000000000000000000000000000000000000000602082015250565b5f61239760268361173c565b91506123a28261233d565b604082019050919050565b5f6020820190508181035f8301526123c48161238b565b9050919050565b7f45524332303a206275726e2066726f6d20746865207a65726f206164647265735f8201527f7300000000000000000000000000000000000000000000000000000000000000602082015250565b5f61242560218361173c565b9150612430826123cb565b604082019050919050565b5f6020820190508181035f83015261245281612419565b9050919050565b7f45524332303a206275726e20616d6f756e7420657863656564732062616c616e5f8201527f6365000000000000000000000000000000000000000000000000000000000000602082015250565b5f6124b360228361173c565b91506124be82612459565b604082019050919050565b5f6020820190508181035f8301526124e0816124a7565b9050919050565b7f45524332303a206d696e7420746f20746865207a65726f2061646472657373005f82015250565b5f61251b601f8361173c565b9150612526826124e7565b602082019050919050565b5f6020820190508181035f8301526125488161250f565b905091905056fea2646970667358221220fb34ca6026fa64e0dce7ed7ccebb6f910afc5ba8058de90060e58ab346680e8164736f6c634300081c0033
Deployed Bytecode Sourcemap
668:2043:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;704:28;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;40345:98:3;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;42631:197;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41442:106;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2286:69:0;;;:::i;:::-;;43390:256:3;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;736:30:0;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41291:91:3;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;44041:234;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;933:47:0;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41606:125:3;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;21789:92;;;:::i;:::-;;1787:180:0;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2575:133;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1338:235;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;21157:85:3;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;40556:102;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;44762:427;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;842:20:0;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;41927:189:3;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2077:111:0;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;42174:149:3;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2480:91:0;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;22030:189:3;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;704:28:0;;;;;;;;;;;;;:::o;40345:98:3:-;40399:13;40431:5;40424:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40345:98;:::o;42631:197::-;42714:4;42730:13;42746:12;:10;:12::i;:::-;42730:28;;42768:32;42777:5;42784:7;42793:6;42768:8;:32::i;:::-;42817:4;42810:11;;;42631:197;;;;:::o;41442:106::-;41503:7;41529:12;;41522:19;;41442:106;:::o;2286:69:0:-;21380:12:3;:10;:12::i;:::-;21369:23;;:7;:5;:7::i;:::-;:23;;;21361:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;2346:4:0::1;2335:8;;:15;;;;;;;;;;;;;;;;;;2286:69::o:0;43390:256:3:-;43487:4;43503:15;43521:12;:10;:12::i;:::-;43503:30;;43543:38;43559:4;43565:7;43574:6;43543:15;:38::i;:::-;43591:27;43601:4;43607:2;43611:6;43591:9;:27::i;:::-;43635:4;43628:11;;;43390:256;;;;;:::o;736:30:0:-;;;;;;;;;;;;;:::o;41291:91:3:-;41349:5;41373:2;41366:9;;41291:91;:::o;44041:234::-;44129:4;44145:13;44161:12;:10;:12::i;:::-;44145:28;;44183:64;44192:5;44199:7;44236:10;44208:25;44218:5;44225:7;44208:9;:25::i;:::-;:38;;;;:::i;:::-;44183:8;:64::i;:::-;44264:4;44257:11;;;44041:234;;;;:::o;933:47:0:-;;;;;;;;;;;;;;;;;:::o;41606:125:3:-;41680:7;41706:9;:18;41716:7;41706:18;;;;;;;;;;;;;;;;41699:25;;41606:125;;;:::o;21789:92::-;21380:12;:10;:12::i;:::-;21369:23;;:7;:5;:7::i;:::-;:23;;;21361:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;21853:21:::1;21871:1;21853:9;:21::i;:::-;21789:92::o:0;1787:180:0:-;1883:11;;;;;;;;;;;1861:34;;:10;:34;;;1853:43;;;;;;1928:6;1903:12;:21;1916:7;1903:21;;;;;;;;;;;;;;;;:31;;;;;;;:::i;:::-;;;;;;;;1940:22;1946:7;1955:6;1940:5;:22::i;:::-;1787:180;;:::o;2575:133::-;21380:12:3;:10;:12::i;:::-;21369:23;;:7;:5;:7::i;:::-;:23;;;21361:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;2666:6:0::1;;2651:12;:21;;;;;;;:::i;:::-;;2683:20;;;;;;;;;;2575:133:::0;;:::o;1338:235::-;1410:8;;;;;;;;;;;1409:9;1401:44;;;;;;;;;;;;:::i;:::-;;;;;;;;;1481:8;;;;;;;;;;;1459:31;;:10;:31;;;1451:89;;;;;;;;;;;;:::i;:::-;;;;;;;;;1546:22;1552:7;1561:6;1546:5;:22::i;:::-;1338:235;;:::o;21157:85:3:-;21203:7;21229:6;;;;;;;;;;;21222:13;;21157:85;:::o;40556:102::-;40612:13;40644:7;40637:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40556:102;:::o;44762:427::-;44855:4;44871:13;44887:12;:10;:12::i;:::-;44871:28;;44909:24;44936:25;44946:5;44953:7;44936:9;:25::i;:::-;44909:52;;44999:15;44979:16;:35;;44971:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;45090:60;45099:5;45106:7;45134:15;45115:16;:34;45090:8;:60::i;:::-;45178:4;45171:11;;;;44762:427;;;;:::o;842:20:0:-;;;;;;;;;;;;;:::o;41927:189:3:-;42006:4;42022:13;42038:12;:10;:12::i;:::-;42022:28;;42060;42070:5;42077:2;42081:6;42060:9;:28::i;:::-;42105:4;42098:11;;;41927:189;;;;:::o;2077:111:0:-;21380:12:3;:10;:12::i;:::-;21369:23;;:7;:5;:7::i;:::-;:23;;;21361:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;2171:11:0::1;2147:8;;:36;;;;;;;;;;;;;;;;;;2077:111:::0;:::o;42174:149:3:-;42263:7;42289:11;:18;42301:5;42289:18;;;;;;;;;;;;;;;:27;42308:7;42289:27;;;;;;;;;;;;;;;;42282:34;;42174:149;;;;:::o;2480:91:0:-;2526:13;2554:12;2547:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2480:91;:::o;22030:189:3:-;21380:12;:10;:12::i;:::-;21369:23;;:7;:5;:7::i;:::-;:23;;;21361:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;22138:1:::1;22118:22;;:8;:22;;::::0;22110:73:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;22193:19;22203:8;22193:9;:19::i;:::-;22030:189:::0;:::o;15379:96::-;15432:7;15458:10;15451:17;;15379:96;:::o;48644:340::-;48762:1;48745:19;;:5;:19;;;48737:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;48842:1;48823:21;;:7;:21;;;48815:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;48924:6;48894:11;:18;48906:5;48894:18;;;;;;;;;;;;;;;:27;48913:7;48894:27;;;;;;;;;;;;;;;:36;;;;48961:7;48945:32;;48954:5;48945:32;;;48970:6;48945:32;;;;;;:::i;:::-;;;;;;;;48644:340;;;:::o;49265:411::-;49365:24;49392:25;49402:5;49409:7;49392:9;:25::i;:::-;49365:52;;49451:17;49431:16;:37;49427:243;;49512:6;49492:16;:26;;49484:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;49594:51;49603:5;49610:7;49638:6;49619:16;:25;49594:8;:51::i;:::-;49427:243;49355:321;49265:411;;;:::o;45643:788::-;45755:1;45739:18;;:4;:18;;;45731:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;45831:1;45817:16;;:2;:16;;;45809:64;;;;;;;;;;;;:::i;:::-;;;;;;;;;45884:38;45905:4;45911:2;45915:6;45884:20;:38::i;:::-;45933:19;45955:9;:15;45965:4;45955:15;;;;;;;;;;;;;;;;45933:37;;46003:6;45988:11;:21;;45980:72;;;;;;;;;;;;:::i;:::-;;;;;;;;;46118:6;46104:11;:20;46086:9;:15;46096:4;46086:15;;;;;;;;;;;;;;;:38;;;;46318:6;46301:9;:13;46311:2;46301:13;;;;;;;;;;;;;;;;:23;;;;;;;;;;;46365:2;46350:26;;46359:4;46350:26;;;46369:6;46350:26;;;;;;:::i;:::-;;;;;;;;46387:37;46407:4;46413:2;46417:6;46387:19;:37::i;:::-;45721:710;45643:788;;;:::o;22225:169::-;22280:16;22299:6;;;;;;;;;;;22280:25;;22324:8;22315:6;;:17;;;;;;;;;;;;;;;;;;22378:8;22347:40;;22368:8;22347:40;;;;;;;;;;;;22270:124;22225:169;:::o;47562:659::-;47664:1;47645:21;;:7;:21;;;47637:67;;;;;;;;;;;;:::i;:::-;;;;;;;;;47715:49;47736:7;47753:1;47757:6;47715:20;:49::i;:::-;47775:22;47800:9;:18;47810:7;47800:18;;;;;;;;;;;;;;;;47775:43;;47854:6;47836:14;:24;;47828:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;47971:6;47954:14;:23;47933:9;:18;47943:7;47933:18;;;;;;;;;;;;;;;:44;;;;48086:6;48070:12;;:22;;;;;;;;;;;48144:1;48118:37;;48127:7;48118:37;;;48148:6;48118:37;;;;;;:::i;:::-;;;;;;;;48166:48;48186:7;48203:1;48207:6;48166:19;:48::i;:::-;47627:594;47562:659;;:::o;46707:535::-;46809:1;46790:21;;:7;:21;;;46782:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;46858:49;46887:1;46891:7;46900:6;46858:20;:49::i;:::-;46934:6;46918:12;;:22;;;;;;;:::i;:::-;;;;;;;;47108:6;47086:9;:18;47096:7;47086:18;;;;;;;;;;;;;;;;:28;;;;;;;;;;;47160:7;47139:37;;47156:1;47139:37;;;47169:6;47139:37;;;;;;:::i;:::-;;;;;;;;47187:48;47215:1;47219:7;47228:6;47187:19;:48::i;:::-;46707:535;;:::o;50260:91::-;;;;:::o;50939:90::-;;;;:::o;7:126:5:-;44:7;84:42;77:5;73:54;62:65;;7:126;;;:::o;139:60::-;167:3;188:5;181:12;;139:60;;;:::o;205:142::-;255:9;288:53;306:34;315:24;333:5;315:24;:::i;:::-;306:34;:::i;:::-;288:53;:::i;:::-;275:66;;205:142;;;:::o;353:126::-;403:9;436:37;467:5;436:37;:::i;:::-;423:50;;353:126;;;:::o;485:146::-;555:9;588:37;619:5;588:37;:::i;:::-;575:50;;485:146;;;:::o;637:171::-;744:57;795:5;744:57;:::i;:::-;739:3;732:70;637:171;;:::o;814:262::-;927:4;965:2;954:9;950:18;942:26;;978:91;1066:1;1055:9;1051:17;1042:6;978:91;:::i;:::-;814:262;;;;:::o;1082:99::-;1134:6;1168:5;1162:12;1152:22;;1082:99;;;:::o;1187:169::-;1271:11;1305:6;1300:3;1293:19;1345:4;1340:3;1336:14;1321:29;;1187:169;;;;:::o;1362:139::-;1451:6;1446:3;1441;1435:23;1492:1;1483:6;1478:3;1474:16;1467:27;1362:139;;;:::o;1507:102::-;1548:6;1599:2;1595:7;1590:2;1583:5;1579:14;1575:28;1565:38;;1507:102;;;:::o;1615:377::-;1703:3;1731:39;1764:5;1731:39;:::i;:::-;1786:71;1850:6;1845:3;1786:71;:::i;:::-;1779:78;;1866:65;1924:6;1919:3;1912:4;1905:5;1901:16;1866:65;:::i;:::-;1956:29;1978:6;1956:29;:::i;:::-;1951:3;1947:39;1940:46;;1707:285;1615:377;;;;:::o;1998:313::-;2111:4;2149:2;2138:9;2134:18;2126:26;;2198:9;2192:4;2188:20;2184:1;2173:9;2169:17;2162:47;2226:78;2299:4;2290:6;2226:78;:::i;:::-;2218:86;;1998:313;;;;:::o;2398:117::-;2507:1;2504;2497:12;2521:117;2630:1;2627;2620:12;2644:96;2681:7;2710:24;2728:5;2710:24;:::i;:::-;2699:35;;2644:96;;;:::o;2746:122::-;2819:24;2837:5;2819:24;:::i;:::-;2812:5;2809:35;2799:63;;2858:1;2855;2848:12;2799:63;2746:122;:::o;2874:139::-;2920:5;2958:6;2945:20;2936:29;;2974:33;3001:5;2974:33;:::i;:::-;2874:139;;;;:::o;3019:77::-;3056:7;3085:5;3074:16;;3019:77;;;:::o;3102:122::-;3175:24;3193:5;3175:24;:::i;:::-;3168:5;3165:35;3155:63;;3214:1;3211;3204:12;3155:63;3102:122;:::o;3230:139::-;3276:5;3314:6;3301:20;3292:29;;3330:33;3357:5;3330:33;:::i;:::-;3230:139;;;;:::o;3375:474::-;3443:6;3451;3500:2;3488:9;3479:7;3475:23;3471:32;3468:119;;;3506:79;;:::i;:::-;3468:119;3626:1;3651:53;3696:7;3687:6;3676:9;3672:22;3651:53;:::i;:::-;3641:63;;3597:117;3753:2;3779:53;3824:7;3815:6;3804:9;3800:22;3779:53;:::i;:::-;3769:63;;3724:118;3375:474;;;;;:::o;3855:90::-;3889:7;3932:5;3925:13;3918:21;3907:32;;3855:90;;;:::o;3951:109::-;4032:21;4047:5;4032:21;:::i;:::-;4027:3;4020:34;3951:109;;:::o;4066:210::-;4153:4;4191:2;4180:9;4176:18;4168:26;;4204:65;4266:1;4255:9;4251:17;4242:6;4204:65;:::i;:::-;4066:210;;;;:::o;4282:118::-;4369:24;4387:5;4369:24;:::i;:::-;4364:3;4357:37;4282:118;;:::o;4406:222::-;4499:4;4537:2;4526:9;4522:18;4514:26;;4550:71;4618:1;4607:9;4603:17;4594:6;4550:71;:::i;:::-;4406:222;;;;:::o;4634:619::-;4711:6;4719;4727;4776:2;4764:9;4755:7;4751:23;4747:32;4744:119;;;4782:79;;:::i;:::-;4744:119;4902:1;4927:53;4972:7;4963:6;4952:9;4948:22;4927:53;:::i;:::-;4917:63;;4873:117;5029:2;5055:53;5100:7;5091:6;5080:9;5076:22;5055:53;:::i;:::-;5045:63;;5000:118;5157:2;5183:53;5228:7;5219:6;5208:9;5204:22;5183:53;:::i;:::-;5173:63;;5128:118;4634:619;;;;;:::o;5259:146::-;5329:9;5362:37;5393:5;5362:37;:::i;:::-;5349:50;;5259:146;;;:::o;5411:171::-;5518:57;5569:5;5518:57;:::i;:::-;5513:3;5506:70;5411:171;;:::o;5588:262::-;5701:4;5739:2;5728:9;5724:18;5716:26;;5752:91;5840:1;5829:9;5825:17;5816:6;5752:91;:::i;:::-;5588:262;;;;:::o;5856:86::-;5891:7;5931:4;5924:5;5920:16;5909:27;;5856:86;;;:::o;5948:112::-;6031:22;6047:5;6031:22;:::i;:::-;6026:3;6019:35;5948:112;;:::o;6066:214::-;6155:4;6193:2;6182:9;6178:18;6170:26;;6206:67;6270:1;6259:9;6255:17;6246:6;6206:67;:::i;:::-;6066:214;;;;:::o;6286:329::-;6345:6;6394:2;6382:9;6373:7;6369:23;6365:32;6362:119;;;6400:79;;:::i;:::-;6362:119;6520:1;6545:53;6590:7;6581:6;6570:9;6566:22;6545:53;:::i;:::-;6535:63;;6491:117;6286:329;;;;:::o;6621:117::-;6730:1;6727;6720:12;6744:117;6853:1;6850;6843:12;6867:117;6976:1;6973;6966:12;7004:553;7062:8;7072:6;7122:3;7115:4;7107:6;7103:17;7099:27;7089:122;;7130:79;;:::i;:::-;7089:122;7243:6;7230:20;7220:30;;7273:18;7265:6;7262:30;7259:117;;;7295:79;;:::i;:::-;7259:117;7409:4;7401:6;7397:17;7385:29;;7463:3;7455:4;7447:6;7443:17;7433:8;7429:32;7426:41;7423:128;;;7470:79;;:::i;:::-;7423:128;7004:553;;;;;:::o;7563:529::-;7634:6;7642;7691:2;7679:9;7670:7;7666:23;7662:32;7659:119;;;7697:79;;:::i;:::-;7659:119;7845:1;7834:9;7830:17;7817:31;7875:18;7867:6;7864:30;7861:117;;;7897:79;;:::i;:::-;7861:117;8010:65;8067:7;8058:6;8047:9;8043:22;8010:65;:::i;:::-;7992:83;;;;7788:297;7563:529;;;;;:::o;8098:118::-;8185:24;8203:5;8185:24;:::i;:::-;8180:3;8173:37;8098:118;;:::o;8222:222::-;8315:4;8353:2;8342:9;8338:18;8330:26;;8366:71;8434:1;8423:9;8419:17;8410:6;8366:71;:::i;:::-;8222:222;;;;:::o;8450:474::-;8518:6;8526;8575:2;8563:9;8554:7;8550:23;8546:32;8543:119;;;8581:79;;:::i;:::-;8543:119;8701:1;8726:53;8771:7;8762:6;8751:9;8747:22;8726:53;:::i;:::-;8716:63;;8672:117;8828:2;8854:53;8899:7;8890:6;8879:9;8875:22;8854:53;:::i;:::-;8844:63;;8799:118;8450:474;;;;;:::o;8930:180::-;8978:77;8975:1;8968:88;9075:4;9072:1;9065:15;9099:4;9096:1;9089:15;9116:320;9160:6;9197:1;9191:4;9187:12;9177:22;;9244:1;9238:4;9234:12;9265:18;9255:81;;9321:4;9313:6;9309:17;9299:27;;9255:81;9383:2;9375:6;9372:14;9352:18;9349:38;9346:84;;9402:18;;:::i;:::-;9346:84;9167:269;9116:320;;;:::o;9442:182::-;9582:34;9578:1;9570:6;9566:14;9559:58;9442:182;:::o;9630:366::-;9772:3;9793:67;9857:2;9852:3;9793:67;:::i;:::-;9786:74;;9869:93;9958:3;9869:93;:::i;:::-;9987:2;9982:3;9978:12;9971:19;;9630:366;;;:::o;10002:419::-;10168:4;10206:2;10195:9;10191:18;10183:26;;10255:9;10249:4;10245:20;10241:1;10230:9;10226:17;10219:47;10283:131;10409:4;10283:131;:::i;:::-;10275:139;;10002:419;;;:::o;10427:180::-;10475:77;10472:1;10465:88;10572:4;10569:1;10562:15;10596:4;10593:1;10586:15;10613:191;10653:3;10672:20;10690:1;10672:20;:::i;:::-;10667:25;;10706:20;10724:1;10706:20;:::i;:::-;10701:25;;10749:1;10746;10742:9;10735:16;;10770:3;10767:1;10764:10;10761:36;;;10777:18;;:::i;:::-;10761:36;10613:191;;;;:::o;10810:97::-;10869:6;10897:3;10887:13;;10810:97;;;;:::o;10913:180::-;10961:77;10958:1;10951:88;11058:4;11055:1;11048:15;11082:4;11079:1;11072:15;11099:141;11148:4;11171:3;11163:11;;11194:3;11191:1;11184:14;11228:4;11225:1;11215:18;11207:26;;11099:141;;;:::o;11246:93::-;11283:6;11330:2;11325;11318:5;11314:14;11310:23;11300:33;;11246:93;;;:::o;11345:107::-;11389:8;11439:5;11433:4;11429:16;11408:37;;11345:107;;;;:::o;11458:393::-;11527:6;11577:1;11565:10;11561:18;11600:97;11630:66;11619:9;11600:97;:::i;:::-;11718:39;11748:8;11737:9;11718:39;:::i;:::-;11706:51;;11790:4;11786:9;11779:5;11775:21;11766:30;;11839:4;11829:8;11825:19;11818:5;11815:30;11805:40;;11534:317;;11458:393;;;;;:::o;11857:142::-;11907:9;11940:53;11958:34;11967:24;11985:5;11967:24;:::i;:::-;11958:34;:::i;:::-;11940:53;:::i;:::-;11927:66;;11857:142;;;:::o;12005:75::-;12048:3;12069:5;12062:12;;12005:75;;;:::o;12086:269::-;12196:39;12227:7;12196:39;:::i;:::-;12257:91;12306:41;12330:16;12306:41;:::i;:::-;12298:6;12291:4;12285:11;12257:91;:::i;:::-;12251:4;12244:105;12162:193;12086:269;;;:::o;12361:73::-;12406:3;12427:1;12420:8;;12361:73;:::o;12440:189::-;12517:32;;:::i;:::-;12558:65;12616:6;12608;12602:4;12558:65;:::i;:::-;12493:136;12440:189;;:::o;12635:186::-;12695:120;12712:3;12705:5;12702:14;12695:120;;;12766:39;12803:1;12796:5;12766:39;:::i;:::-;12739:1;12732:5;12728:13;12719:22;;12695:120;;;12635:186;;:::o;12827:543::-;12928:2;12923:3;12920:11;12917:446;;;12962:38;12994:5;12962:38;:::i;:::-;13046:29;13064:10;13046:29;:::i;:::-;13036:8;13032:44;13229:2;13217:10;13214:18;13211:49;;;13250:8;13235:23;;13211:49;13273:80;13329:22;13347:3;13329:22;:::i;:::-;13319:8;13315:37;13302:11;13273:80;:::i;:::-;12932:431;;12917:446;12827:543;;;:::o;13376:117::-;13430:8;13480:5;13474:4;13470:16;13449:37;;13376:117;;;;:::o;13499:169::-;13543:6;13576:51;13624:1;13620:6;13612:5;13609:1;13605:13;13576:51;:::i;:::-;13572:56;13657:4;13651;13647:15;13637:25;;13550:118;13499:169;;;;:::o;13673:295::-;13749:4;13895:29;13920:3;13914:4;13895:29;:::i;:::-;13887:37;;13957:3;13954:1;13950:11;13944:4;13941:21;13933:29;;13673:295;;;;:::o;13973:1403::-;14097:44;14137:3;14132;14097:44;:::i;:::-;14206:18;14198:6;14195:30;14192:56;;;14228:18;;:::i;:::-;14192:56;14272:38;14304:4;14298:11;14272:38;:::i;:::-;14357:67;14417:6;14409;14403:4;14357:67;:::i;:::-;14451:1;14480:2;14472:6;14469:14;14497:1;14492:632;;;;15168:1;15185:6;15182:84;;;15241:9;15236:3;15232:19;15219:33;15210:42;;15182:84;15292:67;15352:6;15345:5;15292:67;:::i;:::-;15286:4;15279:81;15141:229;14462:908;;14492:632;14544:4;14540:9;14532:6;14528:22;14578:37;14610:4;14578:37;:::i;:::-;14637:1;14651:215;14665:7;14662:1;14659:14;14651:215;;;14751:9;14746:3;14742:19;14729:33;14721:6;14714:49;14802:1;14794:6;14790:14;14780:24;;14849:2;14838:9;14834:18;14821:31;;14688:4;14685:1;14681:12;14676:17;;14651:215;;;14894:6;14885:7;14882:19;14879:186;;;14959:9;14954:3;14950:19;14937:33;15002:48;15044:4;15036:6;15032:17;15021:9;15002:48;:::i;:::-;14994:6;14987:64;14902:163;14879:186;15111:1;15107;15099:6;15095:14;15091:22;15085:4;15078:36;14499:625;;;14462:908;;14072:1304;;;13973:1403;;;:::o;15382:172::-;15522:24;15518:1;15510:6;15506:14;15499:48;15382:172;:::o;15560:366::-;15702:3;15723:67;15787:2;15782:3;15723:67;:::i;:::-;15716:74;;15799:93;15888:3;15799:93;:::i;:::-;15917:2;15912:3;15908:12;15901:19;;15560:366;;;:::o;15932:419::-;16098:4;16136:2;16125:9;16121:18;16113:26;;16185:9;16179:4;16175:20;16171:1;16160:9;16156:17;16149:47;16213:131;16339:4;16213:131;:::i;:::-;16205:139;;15932:419;;;:::o;16357:232::-;16497:34;16493:1;16485:6;16481:14;16474:58;16566:15;16561:2;16553:6;16549:15;16542:40;16357:232;:::o;16595:366::-;16737:3;16758:67;16822:2;16817:3;16758:67;:::i;:::-;16751:74;;16834:93;16923:3;16834:93;:::i;:::-;16952:2;16947:3;16943:12;16936:19;;16595:366;;;:::o;16967:419::-;17133:4;17171:2;17160:9;17156:18;17148:26;;17220:9;17214:4;17210:20;17206:1;17195:9;17191:17;17184:47;17248:131;17374:4;17248:131;:::i;:::-;17240:139;;16967:419;;;:::o;17392:224::-;17532:34;17528:1;17520:6;17516:14;17509:58;17601:7;17596:2;17588:6;17584:15;17577:32;17392:224;:::o;17622:366::-;17764:3;17785:67;17849:2;17844:3;17785:67;:::i;:::-;17778:74;;17861:93;17950:3;17861:93;:::i;:::-;17979:2;17974:3;17970:12;17963:19;;17622:366;;;:::o;17994:419::-;18160:4;18198:2;18187:9;18183:18;18175:26;;18247:9;18241:4;18237:20;18233:1;18222:9;18218:17;18211:47;18275:131;18401:4;18275:131;:::i;:::-;18267:139;;17994:419;;;:::o;18419:225::-;18559:34;18555:1;18547:6;18543:14;18536:58;18628:8;18623:2;18615:6;18611:15;18604:33;18419:225;:::o;18650:366::-;18792:3;18813:67;18877:2;18872:3;18813:67;:::i;:::-;18806:74;;18889:93;18978:3;18889:93;:::i;:::-;19007:2;19002:3;18998:12;18991:19;;18650:366;;;:::o;19022:419::-;19188:4;19226:2;19215:9;19211:18;19203:26;;19275:9;19269:4;19265:20;19261:1;19250:9;19246:17;19239:47;19303:131;19429:4;19303:131;:::i;:::-;19295:139;;19022:419;;;:::o;19447:223::-;19587:34;19583:1;19575:6;19571:14;19564:58;19656:6;19651:2;19643:6;19639:15;19632:31;19447:223;:::o;19676:366::-;19818:3;19839:67;19903:2;19898:3;19839:67;:::i;:::-;19832:74;;19915:93;20004:3;19915:93;:::i;:::-;20033:2;20028:3;20024:12;20017:19;;19676:366;;;:::o;20048:419::-;20214:4;20252:2;20241:9;20237:18;20229:26;;20301:9;20295:4;20291:20;20287:1;20276:9;20272:17;20265:47;20329:131;20455:4;20329:131;:::i;:::-;20321:139;;20048:419;;;:::o;20473:221::-;20613:34;20609:1;20601:6;20597:14;20590:58;20682:4;20677:2;20669:6;20665:15;20658:29;20473:221;:::o;20700:366::-;20842:3;20863:67;20927:2;20922:3;20863:67;:::i;:::-;20856:74;;20939:93;21028:3;20939:93;:::i;:::-;21057:2;21052:3;21048:12;21041:19;;20700:366;;;:::o;21072:419::-;21238:4;21276:2;21265:9;21261:18;21253:26;;21325:9;21319:4;21315:20;21311:1;21300:9;21296:17;21289:47;21353:131;21479:4;21353:131;:::i;:::-;21345:139;;21072:419;;;:::o;21497:179::-;21637:31;21633:1;21625:6;21621:14;21614:55;21497:179;:::o;21682:366::-;21824:3;21845:67;21909:2;21904:3;21845:67;:::i;:::-;21838:74;;21921:93;22010:3;21921:93;:::i;:::-;22039:2;22034:3;22030:12;22023:19;;21682:366;;;:::o;22054:419::-;22220:4;22258:2;22247:9;22243:18;22235:26;;22307:9;22301:4;22297:20;22293:1;22282:9;22278:17;22271:47;22335:131;22461:4;22335:131;:::i;:::-;22327:139;;22054:419;;;:::o;22479:224::-;22619:34;22615:1;22607:6;22603:14;22596:58;22688:7;22683:2;22675:6;22671:15;22664:32;22479:224;:::o;22709:366::-;22851:3;22872:67;22936:2;22931:3;22872:67;:::i;:::-;22865:74;;22948:93;23037:3;22948:93;:::i;:::-;23066:2;23061:3;23057:12;23050:19;;22709:366;;;:::o;23081:419::-;23247:4;23285:2;23274:9;23270:18;23262:26;;23334:9;23328:4;23324:20;23320:1;23309:9;23305:17;23298:47;23362:131;23488:4;23362:131;:::i;:::-;23354:139;;23081:419;;;:::o;23506:222::-;23646:34;23642:1;23634:6;23630:14;23623:58;23715:5;23710:2;23702:6;23698:15;23691:30;23506:222;:::o;23734:366::-;23876:3;23897:67;23961:2;23956:3;23897:67;:::i;:::-;23890:74;;23973:93;24062:3;23973:93;:::i;:::-;24091:2;24086:3;24082:12;24075:19;;23734:366;;;:::o;24106:419::-;24272:4;24310:2;24299:9;24295:18;24287:26;;24359:9;24353:4;24349:20;24345:1;24334:9;24330:17;24323:47;24387:131;24513:4;24387:131;:::i;:::-;24379:139;;24106:419;;;:::o;24531:225::-;24671:34;24667:1;24659:6;24655:14;24648:58;24740:8;24735:2;24727:6;24723:15;24716:33;24531:225;:::o;24762:366::-;24904:3;24925:67;24989:2;24984:3;24925:67;:::i;:::-;24918:74;;25001:93;25090:3;25001:93;:::i;:::-;25119:2;25114:3;25110:12;25103:19;;24762:366;;;:::o;25134:419::-;25300:4;25338:2;25327:9;25323:18;25315:26;;25387:9;25381:4;25377:20;25373:1;25362:9;25358:17;25351:47;25415:131;25541:4;25415:131;:::i;:::-;25407:139;;25134:419;;;:::o;25559:220::-;25699:34;25695:1;25687:6;25683:14;25676:58;25768:3;25763:2;25755:6;25751:15;25744:28;25559:220;:::o;25785:366::-;25927:3;25948:67;26012:2;26007:3;25948:67;:::i;:::-;25941:74;;26024:93;26113:3;26024:93;:::i;:::-;26142:2;26137:3;26133:12;26126:19;;25785:366;;;:::o;26157:419::-;26323:4;26361:2;26350:9;26346:18;26338:26;;26410:9;26404:4;26400:20;26396:1;26385:9;26381:17;26374:47;26438:131;26564:4;26438:131;:::i;:::-;26430:139;;26157:419;;;:::o;26582:221::-;26722:34;26718:1;26710:6;26706:14;26699:58;26791:4;26786:2;26778:6;26774:15;26767:29;26582:221;:::o;26809:366::-;26951:3;26972:67;27036:2;27031:3;26972:67;:::i;:::-;26965:74;;27048:93;27137:3;27048:93;:::i;:::-;27166:2;27161:3;27157:12;27150:19;;26809:366;;;:::o;27181:419::-;27347:4;27385:2;27374:9;27370:18;27362:26;;27434:9;27428:4;27424:20;27420:1;27409:9;27405:17;27398:47;27462:131;27588:4;27462:131;:::i;:::-;27454:139;;27181:419;;;:::o;27606:181::-;27746:33;27742:1;27734:6;27730:14;27723:57;27606:181;:::o;27793:366::-;27935:3;27956:67;28020:2;28015:3;27956:67;:::i;:::-;27949:74;;28032:93;28121:3;28032:93;:::i;:::-;28150:2;28145:3;28141:12;28134:19;;27793:366;;;:::o;28165:419::-;28331:4;28369:2;28358:9;28354:18;28346:26;;28418:9;28412:4;28408:20;28404:1;28393:9;28389:17;28382:47;28446:131;28572:4;28446:131;:::i;:::-;28438:139;;28165:419;;;:::o
Swarm Source
ipfs://069c705c4a98c772316bc62943a1577edaff35f6adc002d0f96e3763e3379677
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.