Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
IonicToken
Compiler Version
v0.8.23+commit.f704f362
Contract Source Code (Solidity)
/** *Submitted for verification at SonicScan.org on 2025-02-26 */ // SPDX-License-Identifier: MIT pragma solidity <0.9.0 >=0.8.4 ^0.8.19 ^0.8.20; // lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); } // lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol) /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); } // lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); } // lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); } // lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); } // lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // lib/openzeppelin-contracts/contracts/utils/Address.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } } // lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } } // lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } } // lib/openzeppelin-contracts/contracts/utils/math/Math.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } } // lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } } // lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } } // src/IXERC20.sol interface IXERC20 { /** * @notice Emits when a lockbox is set * * @param _lockbox The address of the lockbox */ event LockboxSet(address _lockbox); /** * @notice Emits when a limit is set * * @param _mintingLimit The updated minting limit we are setting to the bridge * @param _burningLimit The updated burning limit we are setting to the bridge * @param _bridge The address of the bridge we are setting the limit too */ event BridgeLimitsSet( uint256 _mintingLimit, uint256 _burningLimit, address indexed _bridge ); /** * @notice Reverts when a user with too low of a limit tries to call mint/burn */ error IXERC20_NotHighEnoughLimits(); /** * @notice Reverts when caller is not the factory */ error IXERC20_NotFactory(); /** * @notice Reverts when limits are too high */ error IXERC20_LimitsTooHigh(); /** * @notice Contains the full minting and burning data for a particular bridge * * @param minterParams The minting parameters for the bridge * @param burnerParams The burning parameters for the bridge */ struct Bridge { BridgeParameters minterParams; BridgeParameters burnerParams; } /** * @notice Contains the mint or burn parameters for a bridge * * @param timestamp The timestamp of the last mint/burn * @param ratePerSecond The rate per second of the bridge * @param maxLimit The max limit of the bridge * @param currentLimit The current limit of the bridge */ struct BridgeParameters { uint256 timestamp; uint256 ratePerSecond; uint256 maxLimit; uint256 currentLimit; } /** * @notice Sets the lockbox address * * @param _lockbox The address of the lockbox */ function setLockbox(address _lockbox) external; /** * @notice Updates the limits of any bridge * @dev Can only be called by the owner * @param _mintingLimit The updated minting limit we are setting to the bridge * @param _burningLimit The updated burning limit we are setting to the bridge * @param _bridge The address of the bridge we are setting the limits too */ function setLimits( address _bridge, uint256 _mintingLimit, uint256 _burningLimit ) external; /** * @notice Returns the max limit of a minter * * @param _minter The minter we are viewing the limits of * @return _limit The limit the minter has */ function mintingMaxLimitOf( address _minter ) external view returns (uint256 _limit); /** * @notice Returns the max limit of a bridge * * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function burningMaxLimitOf( address _bridge ) external view returns (uint256 _limit); /** * @notice Returns the current limit of a minter * * @param _minter The minter we are viewing the limits of * @return _limit The limit the minter has */ function mintingCurrentLimitOf( address _minter ) external view returns (uint256 _limit); /** * @notice Returns the current limit of a bridge * * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function burningCurrentLimitOf( address _bridge ) external view returns (uint256 _limit); /** * @notice Mints tokens for a user * @dev Can only be called by a minter * @param _user The address of the user who needs tokens minted * @param _amount The amount of tokens being minted */ function mint(address _user, uint256 _amount) external; /** * @notice Burns tokens for a user * @dev Can only be called by a minter * @param _user The address of the user who needs tokens burned * @param _amount The amount of tokens being burned */ function burn(address _user, uint256 _amount) external; } // lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } // lib/openzeppelin-contracts-upgradeable/contracts/utils/NoncesUpgradeable.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol) /** * @dev Provides tracking nonces for addresses. Nonces will only increment. */ abstract contract NoncesUpgradeable is Initializable { /** * @dev The nonce used for an `account` is not the expected current nonce. */ error InvalidAccountNonce(address account, uint256 currentNonce); /// @custom:storage-location erc7201:openzeppelin.storage.Nonces struct NoncesStorage { mapping(address account => uint256) _nonces; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Nonces")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant NoncesStorageLocation = 0x5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00; function _getNoncesStorage() private pure returns (NoncesStorage storage $) { assembly { $.slot := NoncesStorageLocation } } function __Nonces_init() internal onlyInitializing { } function __Nonces_init_unchained() internal onlyInitializing { } /** * @dev Returns the next unused nonce for an address. */ function nonces(address owner) public view virtual returns (uint256) { NoncesStorage storage $ = _getNoncesStorage(); return $._nonces[owner]; } /** * @dev Consumes a nonce. * * Returns the current value and increments nonce. */ function _useNonce(address owner) internal virtual returns (uint256) { NoncesStorage storage $ = _getNoncesStorage(); // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be // decremented or reset. This guarantees that the nonce never overflows. unchecked { // It is important to do x++ and not ++x here. return $._nonces[owner]++; } } /** * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`. */ function _useCheckedNonce(address owner, uint256 nonce) internal virtual { uint256 current = _useNonce(owner); if (nonce != current) { revert InvalidAccountNonce(owner, current); } } } // lib/openzeppelin-contracts/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } } // lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. 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 OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol) /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. */ library ERC1967Utils { // We re-declare ERC-1967 events here because they can't be used directly from IERC1967. // This will be fixed in Solidity 0.8.21. At that point we should remove these events. /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } } // lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } } // lib/openzeppelin-contracts-upgradeable/contracts/access/Ownable2StepUpgradeable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable2Step struct Ownable2StepStorage { address _pendingOwner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable2Step")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant Ownable2StepStorageLocation = 0x237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00; function _getOwnable2StepStorage() private pure returns (Ownable2StepStorage storage $) { assembly { $.slot := Ownable2StepStorageLocation } } event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); function __Ownable2Step_init() internal onlyInitializing { } function __Ownable2Step_init_unchained() internal onlyInitializing { } /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); return $._pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); $._pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); delete $._pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } } // lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors { /// @custom:storage-location erc7201:openzeppelin.storage.ERC20 struct ERC20Storage { mapping(address account => uint256) _balances; mapping(address account => mapping(address spender => uint256)) _allowances; uint256 _totalSupply; string _name; string _symbol; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00; function _getERC20Storage() private pure returns (ERC20Storage storage $) { assembly { $.slot := ERC20StorageLocation } } /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { ERC20Storage storage $ = _getERC20Storage(); $._name = name_; $._symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { ERC20Storage storage $ = _getERC20Storage(); return $._name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { ERC20Storage storage $ = _getERC20Storage(); return $._symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows $._totalSupply += value; } else { uint256 fromBalance = $._balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. $._balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. $._totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. $._balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } $._allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } } // lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/UUPSUpgradeable.sol) /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. */ abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable __self = address(this); /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev The call is from an unauthorized context. */ error UUPSUnauthorizedCallContext(); /** * @dev The storage `slot` is unsupported as a UUID. */ error UUPSUnsupportedProxiableUUID(bytes32 slot); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { _checkProxy(); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { _checkNotDelegated(); _; } function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data); } /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC1967-compliant implementation pointing to self. * See {_onlyProxy}. */ function _checkProxy() internal view virtual { if ( address(this) == __self || // Must be called through delegatecall ERC1967Utils.getImplementation() != __self // Must be called through an active proxy ) { revert UUPSUnauthorizedCallContext(); } } /** * @dev Reverts if the execution is performed via delegatecall. * See {notDelegated}. */ function _checkNotDelegated() internal view virtual { if (address(this) != __self) { // Must not be called through delegatecall revert UUPSUnauthorizedCallContext(); } } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. * * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value * is expected to be the implementation slot in ERC1967. * * Emits an {IERC1967-Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { revert UUPSUnsupportedProxiableUUID(slot); } ERC1967Utils.upgradeToAndCall(newImplementation, data); } catch { // The implementation is not UUPS revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); } } } // lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/EIP712Upgradeable.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol) /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. */ abstract contract EIP712Upgradeable is Initializable, IERC5267 { bytes32 private constant TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); /// @custom:storage-location erc7201:openzeppelin.storage.EIP712 struct EIP712Storage { /// @custom:oz-renamed-from _HASHED_NAME bytes32 _hashedName; /// @custom:oz-renamed-from _HASHED_VERSION bytes32 _hashedVersion; string _name; string _version; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.EIP712")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant EIP712StorageLocation = 0xa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100; function _getEIP712Storage() private pure returns (EIP712Storage storage $) { assembly { $.slot := EIP712StorageLocation } } /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ function __EIP712_init(string memory name, string memory version) internal onlyInitializing { __EIP712_init_unchained(name, version); } function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing { EIP712Storage storage $ = _getEIP712Storage(); $._name = name; $._version = version; // Reset prior values in storage if upgrading $._hashedName = 0; $._hashedVersion = 0; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { return _buildDomainSeparator(); } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {IERC-5267}. */ function eip712Domain() public view virtual returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { EIP712Storage storage $ = _getEIP712Storage(); // If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized // and the EIP712 domain is not reliable, as it will be missing name and version. require($._hashedName == 0 && $._hashedVersion == 0, "EIP712: Uninitialized"); return ( hex"0f", // 01111 _EIP712Name(), _EIP712Version(), block.chainid, address(this), bytes32(0), new uint256[](0) ); } /** * @dev The name parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712Name() internal view virtual returns (string memory) { EIP712Storage storage $ = _getEIP712Storage(); return $._name; } /** * @dev The version parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712Version() internal view virtual returns (string memory) { EIP712Storage storage $ = _getEIP712Storage(); return $._version; } /** * @dev The hash of the name parameter for the EIP712 domain. * * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Name` instead. */ function _EIP712NameHash() internal view returns (bytes32) { EIP712Storage storage $ = _getEIP712Storage(); string memory name = _EIP712Name(); if (bytes(name).length > 0) { return keccak256(bytes(name)); } else { // If the name is empty, the contract may have been upgraded without initializing the new storage. // We return the name hash in storage if non-zero, otherwise we assume the name is empty by design. bytes32 hashedName = $._hashedName; if (hashedName != 0) { return hashedName; } else { return keccak256(""); } } } /** * @dev The hash of the version parameter for the EIP712 domain. * * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Version` instead. */ function _EIP712VersionHash() internal view returns (bytes32) { EIP712Storage storage $ = _getEIP712Storage(); string memory version = _EIP712Version(); if (bytes(version).length > 0) { return keccak256(bytes(version)); } else { // If the version is empty, the contract may have been upgraded without initializing the new storage. // We return the version hash in storage if non-zero, otherwise we assume the version is empty by design. bytes32 hashedVersion = $._hashedVersion; if (hashedVersion != 0) { return hashedVersion; } else { return keccak256(""); } } } } // lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20PermitUpgradeable.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Permit.sol) /** * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ abstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20Permit, EIP712Upgradeable, NoncesUpgradeable { bytes32 private constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); /** * @dev Permit deadline has expired. */ error ERC2612ExpiredSignature(uint256 deadline); /** * @dev Mismatched signature. */ error ERC2612InvalidSigner(address signer, address owner); /** * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. * * It's a good idea to use the same `name` that is defined as the ERC20 token name. */ function __ERC20Permit_init(string memory name) internal onlyInitializing { __EIP712_init_unchained(name, "1"); } function __ERC20Permit_init_unchained(string memory) internal onlyInitializing {} /** * @inheritdoc IERC20Permit */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { if (block.timestamp > deadline) { revert ERC2612ExpiredSignature(deadline); } bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); bytes32 hash = _hashTypedDataV4(structHash); address signer = ECDSA.recover(hash, v, r, s); if (signer != owner) { revert ERC2612InvalidSigner(signer, owner); } _approve(owner, spender, value); } /** * @inheritdoc IERC20Permit */ function nonces(address owner) public view virtual override(IERC20Permit, NoncesUpgradeable) returns (uint256) { return super.nonces(owner); } /** * @inheritdoc IERC20Permit */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view virtual returns (bytes32) { return _domainSeparatorV4(); } } // src/IonicToken.sol contract IonicToken is Initializable, ERC20Upgradeable, Ownable2StepUpgradeable, ERC20PermitUpgradeable, UUPSUpgradeable, IXERC20 { /** * @notice The duration it takes for the limits to fully replenish */ uint256 private constant _DURATION = 1 days; /** * @notice Maps bridge address to bridge configurations */ mapping(address => Bridge) public bridges; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize( address initialOwner, bool isCanonical ) public initializer { __ERC20_init("Ionic", "ION"); __Ownable_init(initialOwner); __ERC20Permit_init("Ionic"); __UUPSUpgradeable_init(); if (isCanonical) { _mint(msg.sender, 1_000_000_000 * 10 ** decimals()); } } /// XERC20 SPECIFIC FUNCTIONALITY /** * @notice Mints tokens for a user * @dev Can only be called by a bridge * @param _user The address of the user who needs tokens minted * @param _amount The amount of tokens being minted */ function mint(address _user, uint256 _amount) public { _mintWithCaller(msg.sender, _user, _amount); } /** * @notice Burns tokens for a user * @dev Can only be called by a bridge * @param _user The address of the user who needs tokens burned * @param _amount The amount of tokens being burned */ function burn(address _user, uint256 _amount) public { if (msg.sender != _user) { _spendAllowance(_user, msg.sender, _amount); } _burnWithCaller(msg.sender, _user, _amount); } /** * @notice Sets the lockbox address * @dev unimplemented */ function setLockbox(address /* _lockbox */) public pure { revert("Lockbox not necessary for this token"); } /** * @notice Updates the limits of any bridge * @dev Can only be called by the owner * @param _mintingLimit The updated minting limit we are setting to the bridge * @param _burningLimit The updated burning limit we are setting to the bridge * @param _bridge The address of the bridge we are setting the limits too */ function setLimits( address _bridge, uint256 _mintingLimit, uint256 _burningLimit ) external onlyOwner { if ( _mintingLimit > (type(uint256).max / 2) || _burningLimit > (type(uint256).max / 2) ) { revert IXERC20_LimitsTooHigh(); } _changeMinterLimit(_bridge, _mintingLimit); _changeBurnerLimit(_bridge, _burningLimit); emit BridgeLimitsSet(_mintingLimit, _burningLimit, _bridge); } /** * @notice Returns the max limit of a bridge * * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function mintingMaxLimitOf( address _bridge ) public view returns (uint256 _limit) { _limit = bridges[_bridge].minterParams.maxLimit; } /** * @notice Returns the max limit of a bridge * * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function burningMaxLimitOf( address _bridge ) public view returns (uint256 _limit) { _limit = bridges[_bridge].burnerParams.maxLimit; } /** * @notice Returns the current limit of a bridge * * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function mintingCurrentLimitOf( address _bridge ) public view returns (uint256 _limit) { _limit = _getCurrentLimit( bridges[_bridge].minterParams.currentLimit, bridges[_bridge].minterParams.maxLimit, bridges[_bridge].minterParams.timestamp, bridges[_bridge].minterParams.ratePerSecond ); } /** * @notice Returns the current limit of a bridge * * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function burningCurrentLimitOf( address _bridge ) public view returns (uint256 _limit) { _limit = _getCurrentLimit( bridges[_bridge].burnerParams.currentLimit, bridges[_bridge].burnerParams.maxLimit, bridges[_bridge].burnerParams.timestamp, bridges[_bridge].burnerParams.ratePerSecond ); } /** * @notice Uses the limit of any bridge * @param _bridge The address of the bridge who is being changed * @param _change The change in the limit */ function _useMinterLimits(address _bridge, uint256 _change) internal { uint256 _currentLimit = mintingCurrentLimitOf(_bridge); bridges[_bridge].minterParams.timestamp = block.timestamp; bridges[_bridge].minterParams.currentLimit = _currentLimit - _change; } /** * @notice Uses the limit of any bridge * @param _bridge The address of the bridge who is being changed * @param _change The change in the limit */ function _useBurnerLimits(address _bridge, uint256 _change) internal { uint256 _currentLimit = burningCurrentLimitOf(_bridge); bridges[_bridge].burnerParams.timestamp = block.timestamp; bridges[_bridge].burnerParams.currentLimit = _currentLimit - _change; } /** * @notice Updates the limit of any bridge * @dev Can only be called by the owner * @param _bridge The address of the bridge we are setting the limit too * @param _limit The updated limit we are setting to the bridge */ function _changeMinterLimit(address _bridge, uint256 _limit) internal { uint256 _oldLimit = bridges[_bridge].minterParams.maxLimit; uint256 _currentLimit = mintingCurrentLimitOf(_bridge); bridges[_bridge].minterParams.maxLimit = _limit; bridges[_bridge].minterParams.currentLimit = _calculateNewCurrentLimit( _limit, _oldLimit, _currentLimit ); bridges[_bridge].minterParams.ratePerSecond = _limit / _DURATION; bridges[_bridge].minterParams.timestamp = block.timestamp; } /** * @notice Updates the limit of any bridge * @dev Can only be called by the owner * @param _bridge The address of the bridge we are setting the limit too * @param _limit The updated limit we are setting to the bridge */ function _changeBurnerLimit(address _bridge, uint256 _limit) internal { uint256 _oldLimit = bridges[_bridge].burnerParams.maxLimit; uint256 _currentLimit = burningCurrentLimitOf(_bridge); bridges[_bridge].burnerParams.maxLimit = _limit; bridges[_bridge].burnerParams.currentLimit = _calculateNewCurrentLimit( _limit, _oldLimit, _currentLimit ); bridges[_bridge].burnerParams.ratePerSecond = _limit / _DURATION; bridges[_bridge].burnerParams.timestamp = block.timestamp; } /** * @notice Updates the current limit * * @param _limit The new limit * @param _oldLimit The old limit * @param _currentLimit The current limit * @return _newCurrentLimit The new current limit */ function _calculateNewCurrentLimit( uint256 _limit, uint256 _oldLimit, uint256 _currentLimit ) internal pure returns (uint256 _newCurrentLimit) { uint256 _difference; if (_oldLimit > _limit) { _difference = _oldLimit - _limit; _newCurrentLimit = _currentLimit > _difference ? _currentLimit - _difference : 0; } else { _difference = _limit - _oldLimit; _newCurrentLimit = _currentLimit + _difference; } } /** * @notice Gets the current limit * * @param _currentLimit The current limit * @param _maxLimit The max limit * @param _timestamp The timestamp of the last update * @param _ratePerSecond The rate per second * @return _limit The current limit */ function _getCurrentLimit( uint256 _currentLimit, uint256 _maxLimit, uint256 _timestamp, uint256 _ratePerSecond ) internal view returns (uint256 _limit) { _limit = _currentLimit; if (_limit == _maxLimit) { return _limit; } else if (_timestamp + _DURATION <= block.timestamp) { _limit = _maxLimit; } else if (_timestamp + _DURATION > block.timestamp) { uint256 _timePassed = block.timestamp - _timestamp; uint256 _calculatedLimit = _limit + (_timePassed * _ratePerSecond); _limit = _calculatedLimit > _maxLimit ? _maxLimit : _calculatedLimit; } } /** * @notice Internal function for burning tokens * * @param _caller The caller address * @param _user The user address * @param _amount The amount to burn */ function _burnWithCaller( address _caller, address _user, uint256 _amount ) internal { uint256 _currentLimit = burningCurrentLimitOf(_caller); if (_currentLimit < _amount) revert IXERC20_NotHighEnoughLimits(); _useBurnerLimits(_caller, _amount); _burn(_user, _amount); } /** * @notice Internal function for minting tokens * * @param _caller The caller address * @param _user The user address * @param _amount The amount to mint */ function _mintWithCaller( address _caller, address _user, uint256 _amount ) internal { uint256 _currentLimit = mintingCurrentLimitOf(_caller); if (_currentLimit < _amount) revert IXERC20_NotHighEnoughLimits(); _useMinterLimits(_caller, _amount); _mint(_user, _amount); } /// FOR UPGRADES function _authorizeUpgrade( address newImplementation ) internal override onlyOwner {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"IXERC20_LimitsTooHigh","type":"error"},{"inputs":[],"name":"IXERC20_NotFactory","type":"error"},{"inputs":[],"name":"IXERC20_NotHighEnoughLimits","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_mintingLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_burningLimit","type":"uint256"},{"indexed":true,"internalType":"address","name":"_bridge","type":"address"}],"name":"BridgeLimitsSet","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_lockbox","type":"address"}],"name":"LockboxSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","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":"","type":"address"}],"name":"bridges","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"ratePerSecond","type":"uint256"},{"internalType":"uint256","name":"maxLimit","type":"uint256"},{"internalType":"uint256","name":"currentLimit","type":"uint256"}],"internalType":"struct IXERC20.BridgeParameters","name":"minterParams","type":"tuple"},{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"ratePerSecond","type":"uint256"},{"internalType":"uint256","name":"maxLimit","type":"uint256"},{"internalType":"uint256","name":"currentLimit","type":"uint256"}],"internalType":"struct IXERC20.BridgeParameters","name":"burnerParams","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bridge","type":"address"}],"name":"burningCurrentLimitOf","outputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bridge","type":"address"}],"name":"burningMaxLimitOf","outputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"bool","name":"isCanonical","type":"bool"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bridge","type":"address"}],"name":"mintingCurrentLimitOf","outputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bridge","type":"address"}],"name":"mintingMaxLimitOf","outputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bridge","type":"address"},{"internalType":"uint256","name":"_mintingLimit","type":"uint256"},{"internalType":"uint256","name":"_burningLimit","type":"uint256"}],"name":"setLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"setLockbox","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60a06040523073ffffffffffffffffffffffffffffffffffffffff1660809073ffffffffffffffffffffffffffffffffffffffff1681525034801562000043575f80fd5b50620000546200005a60201b60201c565b620001c4565b5f6200006b6200015e60201b60201c565b9050805f0160089054906101000a900460ff1615620000b6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8016815f015f9054906101000a900467ffffffffffffffff1667ffffffffffffffff16146200015b5767ffffffffffffffff815f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d267ffffffffffffffff604051620001529190620001a9565b60405180910390a15b50565b5f7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00905090565b5f67ffffffffffffffff82169050919050565b620001a38162000185565b82525050565b5f602082019050620001be5f83018462000198565b92915050565b6080516144b1620001eb5f395f8181611996015281816119eb0152611ba501526144b15ff3fe6080604052600436106101d7575f3560e01c806379ba509711610101578063a9059cbb11610094578063d505accf11610063578063d505accf146106c4578063dd62ed3e146106ec578063e30c397814610728578063f2fde38b14610752576101d7565b8063a9059cbb146105e5578063ad3cb1cc14610621578063c1eb71371461064b578063ced67f0c14610687576101d7565b806395d89b41116100d057806395d89b411461052f578063998955d3146105595780639dc29fac14610595578063a08d5654146105bd576101d7565b806379ba5097146104835780637ecebe001461049957806384b0196e146104d55780638da5cb5b14610505576101d7565b8063400ada751161017957806352d1902d1161014857806352d1902d146103cb578063651fd268146103f557806370a0823114610431578063715018a61461046d576101d7565b8063400ada751461033757806340c10f191461035f578063435350b7146103875780634f1ef286146103af576101d7565b806318160ddd116101b557806318160ddd1461027d57806323b872dd146102a7578063313ce567146102e35780633644e5151461030d576101d7565b806306fdde03146101db578063095ea7b3146102055780630c05f82c14610241575b5f80fd5b3480156101e6575f80fd5b506101ef61077a565b6040516101fc91906133b7565b60405180910390f35b348015610210575f80fd5b5061022b60048036038101906102269190613475565b610818565b60405161023891906134cd565b60405180910390f35b34801561024c575f80fd5b50610267600480360381019061026291906134e6565b61083a565b6040516102749190613520565b60405180910390f35b348015610288575f80fd5b50610291610884565b60405161029e9190613520565b60405180910390f35b3480156102b2575f80fd5b506102cd60048036038101906102c89190613539565b61089b565b6040516102da91906134cd565b60405180910390f35b3480156102ee575f80fd5b506102f76108c9565b60405161030491906135a4565b60405180910390f35b348015610318575f80fd5b506103216108d1565b60405161032e91906135d5565b60405180910390f35b348015610342575f80fd5b5061035d60048036038101906103589190613618565b6108df565b005b34801561036a575f80fd5b5061038560048036038101906103809190613475565b610b4e565b005b348015610392575f80fd5b506103ad60048036038101906103a891906134e6565b610b5d565b005b6103c960048036038101906103c49190613782565b610b98565b005b3480156103d6575f80fd5b506103df610bb7565b6040516103ec91906135d5565b60405180910390f35b348015610400575f80fd5b5061041b600480360381019061041691906134e6565b610be8565b6040516104289190613520565b60405180910390f35b34801561043c575f80fd5b50610457600480360381019061045291906134e6565b610cff565b6040516104649190613520565b60405180910390f35b348015610478575f80fd5b50610481610d52565b005b34801561048e575f80fd5b50610497610d65565b005b3480156104a4575f80fd5b506104bf60048036038101906104ba91906134e6565b610df3565b6040516104cc9190613520565b60405180910390f35b3480156104e0575f80fd5b506104e9610e04565b6040516104fc97969594939291906138dc565b60405180910390f35b348015610510575f80fd5b50610519610f0d565b604051610526919061395e565b60405180910390f35b34801561053a575f80fd5b50610543610f42565b60405161055091906133b7565b60405180910390f35b348015610564575f80fd5b5061057f600480360381019061057a91906134e6565b610fe0565b60405161058c9190613520565b60405180910390f35b3480156105a0575f80fd5b506105bb60048036038101906105b69190613475565b6110fb565b005b3480156105c8575f80fd5b506105e360048036038101906105de9190613977565b611149565b005b3480156105f0575f80fd5b5061060b60048036038101906106069190613475565b611256565b60405161061891906134cd565b60405180910390f35b34801561062c575f80fd5b50610635611278565b60405161064291906133b7565b60405180910390f35b348015610656575f80fd5b50610671600480360381019061066c91906134e6565b6112b1565b60405161067e9190613520565b60405180910390f35b348015610692575f80fd5b506106ad60048036038101906106a891906134e6565b6112fc565b6040516106bb929190613a1a565b60405180910390f35b3480156106cf575f80fd5b506106ea60048036038101906106e59190613a96565b61137d565b005b3480156106f7575f80fd5b50610712600480360381019061070d9190613b33565b6114c2565b60405161071f9190613520565b60405180910390f35b348015610733575f80fd5b5061073c611552565b604051610749919061395e565b60405180910390f35b34801561075d575f80fd5b50610778600480360381019061077391906134e6565b611587565b005b60605f610785611640565b905080600301805461079690613b9e565b80601f01602080910402602001604051908101604052809291908181526020018280546107c290613b9e565b801561080d5780601f106107e45761010080835404028352916020019161080d565b820191905f5260205f20905b8154815290600101906020018083116107f057829003601f168201915b505050505091505090565b5f80610822611667565b905061082f81858561166e565b600191505092915050565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600201549050919050565b5f8061088e611640565b9050806002015491505090565b5f806108a5611667565b90506108b2858285611680565b6108bd858585611712565b60019150509392505050565b5f6012905090565b5f6108da611802565b905090565b5f6108e8611810565b90505f815f0160089054906101000a900460ff161590505f825f015f9054906101000a900467ffffffffffffffff1690505f808267ffffffffffffffff161480156109305750825b90505f60018367ffffffffffffffff1614801561096357505f3073ffffffffffffffffffffffffffffffffffffffff163b145b905081158015610971575080155b156109a8576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001855f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083156109f5576001855f0160086101000a81548160ff0219169083151502179055505b610a696040518060400160405280600581526020017f496f6e69630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f494f4e0000000000000000000000000000000000000000000000000000000000815250611837565b610a728761184d565b610ab06040518060400160405280600581526020017f496f6e6963000000000000000000000000000000000000000000000000000000815250611861565b610ab86118ab565b8515610aeb57610aea33610aca6108c9565b600a610ad69190613d2a565b633b9aca00610ae59190613d74565b6118b5565b5b8315610b45575f855f0160086101000a81548160ff0219169083151502179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d26001604051610b3c9190613e0a565b60405180910390a15b50505050505050565b610b59338383611934565b5050565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b8f90613e93565b60405180910390fd5b610ba0611994565b610ba982611a7a565b610bb38282611a85565b5050565b5f610bc0611ba3565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b905090565b5f610cf85f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600301545f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600201545f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f01545f808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160010154611c2a565b9050919050565b5f80610d09611640565b9050805f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054915050919050565b610d5a611cb0565b610d635f611d37565b565b5f610d6e611667565b90508073ffffffffffffffffffffffffffffffffffffffff16610d8f611552565b73ffffffffffffffffffffffffffffffffffffffff1614610de757806040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401610dde919061395e565b60405180910390fd5b610df081611d37565b50565b5f610dfd82611d74565b9050919050565b5f6060805f805f60605f610e16611dc7565b90505f801b815f0154148015610e3157505f801b8160010154145b610e70576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e6790613efb565b60405180910390fd5b610e78611dee565b610e80611e8c565b46305f801b5f67ffffffffffffffff811115610e9f57610e9e61365e565b5b604051908082528060200260200182016040528015610ecd5781602001602082028036833780820191505090505b507f0f0000000000000000000000000000000000000000000000000000000000000095949392919097509750975097509750975097505090919293949596565b5f80610f17611f2a565b9050805f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b60605f610f4d611640565b9050806004018054610f5e90613b9e565b80601f0160208091040260200160405190810160405280929190818152602001828054610f8a90613b9e565b8015610fd55780601f10610fac57610100808354040283529160200191610fd5565b820191905f5260205f20905b815481529060010190602001808311610fb857829003601f168201915b505050505091505090565b5f6110f45f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600301545f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600201545f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f01545f808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060040160010154611c2a565b9050919050565b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461113a57611139823383611680565b5b611145338383611f51565b5050565b611151611cb0565b60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61117e9190613f46565b8211806111b6575060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6111b39190613f46565b81115b156111ed576040517ff596480900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111f78383611fb1565b6112018382612137565b8273ffffffffffffffffffffffffffffffffffffffff167f93f3bbfe8cfb354ec059175107653f49f6eb479a8622a7d83866ea015435c9448383604051611249929190613f76565b60405180910390a2505050565b5f80611260611667565b905061126d818585611712565b600191505092915050565b6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600201549050919050565b5f602052805f5260405f205f91509050805f016040518060800160405290815f8201548152602001600182015481526020016002820154815260200160038201548152505090806004016040518060800160405290815f82015481526020016001820154815260200160028201548152602001600382015481525050905082565b834211156113c257836040517f627913020000000000000000000000000000000000000000000000000000000081526004016113b99190613520565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886113f08c6122c2565b8960405160200161140696959493929190613f9d565b6040516020818303038152906040528051906020012090505f61142882612322565b90505f6114378287878761233b565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146114ab57808a6040517f4b800e460000000000000000000000000000000000000000000000000000000081526004016114a2929190613ffc565b60405180910390fd5b6114b68a8a8a61166e565b50505050505050505050565b5f806114cc611640565b9050806001015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205491505092915050565b5f8061155c612369565b9050805f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b61158f611cb0565b5f611598612369565b905081815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff166115fa610f0d565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35050565b5f7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00905090565b5f33905090565b61167b8383836001612390565b505050565b5f61168b84846114c2565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461170c57818110156116fd578281836040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526004016116f493929190614023565b60405180910390fd5b61170b84848484035f612390565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611782575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611779919061395e565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036117f2575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016117e9919061395e565b60405180910390fd5b6117fd83838361256d565b505050565b5f61180b61279c565b905090565b5f7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00905090565b61183f6127ff565b611849828261283f565b5050565b6118556127ff565b61185e8161287b565b50565b6118696127ff565b6118a8816040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506128ff565b50565b6118b36127ff565b565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611925575f6040517fec442f0500000000000000000000000000000000000000000000000000000000815260040161191c919061395e565b60405180910390fd5b6119305f838361256d565b5050565b5f61193e84610be8565b90508181101561197a576040517f0b6842aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119848483612950565b61198e83836118b5565b50505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161480611a4157507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16611a286129f7565b73ffffffffffffffffffffffffffffffffffffffff1614155b15611a78576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b611a82611cb0565b50565b8173ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611aed57506040513d601f19601f82011682018060405250810190611aea919061406c565b60015b611b2e57816040517f4c9c8ce3000000000000000000000000000000000000000000000000000000008152600401611b25919061395e565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b8114611b9457806040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600401611b8b91906135d5565b60405180910390fd5b611b9e8383612a4a565b505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614611c28576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f84905083810315611ca857426201518084611c469190614097565b11611c5357839050611ca7565b426201518084611c639190614097565b1115611ca6575f8342611c7691906140ca565b90505f8382611c859190613d74565b83611c909190614097565b9050858111611c9f5780611ca1565b855b925050505b5b5b949350505050565b611cb8611667565b73ffffffffffffffffffffffffffffffffffffffff16611cd6610f0d565b73ffffffffffffffffffffffffffffffffffffffff1614611d3557611cf9611667565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611d2c919061395e565b60405180910390fd5b565b5f611d40612369565b9050805f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055611d7082612abc565b5050565b5f80611d7e612b8d565b9050805f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054915050919050565b5f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100905090565b60605f611df9611dc7565b9050806002018054611e0a90613b9e565b80601f0160208091040260200160405190810160405280929190818152602001828054611e3690613b9e565b8015611e815780601f10611e5857610100808354040283529160200191611e81565b820191905f5260205f20905b815481529060010190602001808311611e6457829003601f168201915b505050505091505090565b60605f611e97611dc7565b9050806003018054611ea890613b9e565b80601f0160208091040260200160405190810160405280929190818152602001828054611ed490613b9e565b8015611f1f5780601f10611ef657610100808354040283529160200191611f1f565b820191905f5260205f20905b815481529060010190602001808311611f0257829003601f168201915b505050505091505090565b5f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300905090565b5f611f5b84610fe0565b905081811015611f97576040517f0b6842aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611fa18483612bb4565b611fab8383612c5d565b50505050565b5f805f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016002015490505f61200084610be8565b9050825f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160020181905550612053838383612cdc565b5f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016003018190555062015180836120a79190613f46565b5f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160010181905550425f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f018190555050505050565b5f805f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016002015490505f61218784610fe0565b9050825f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600201819055506121db838383612cdc565b5f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016003018190555062015180836122309190613f46565b5f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060040160010181905550425f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f018190555050505050565b5f806122cc612b8d565b9050805f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f81548092919060010191905055915050919050565b5f61233461232e611802565b83612d3a565b9050919050565b5f805f8061234b88888888612d7a565b92509250925061235b8282612e61565b829350505050949350505050565b5f7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00905090565b5f612399611640565b90505f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361240b575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401612402919061395e565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361247b575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401612472919061395e565b60405180910390fd5b82816001015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508115612566578373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258560405161255d9190613520565b60405180910390a35b5050505050565b5f612576611640565b90505f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036125ca5781816002015f8282546125be9190614097565b9250508190555061269c565b5f815f015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905082811015612655578481846040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161264c93929190614023565b60405180910390fd5b828103825f015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036126e55781816002015f8282540392505081905550612731565b81815f015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161278e9190613520565b60405180910390a350505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6127c6612fc3565b6127ce613039565b46306040516020016127e49594939291906140fd565b60405160208183030381529060405280519060200120905090565b6128076130b0565b61283d576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6128476127ff565b5f612850611640565b90508281600301908161286391906142e2565b508181600401908161287591906142e2565b50505050565b6128836127ff565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036128f3575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016128ea919061395e565b60405180910390fd5b6128fc81611d37565b50565b6129076127ff565b5f612910611dc7565b90508281600201908161292391906142e2565b508181600301908161293591906142e2565b505f801b815f01819055505f801b8160010181905550505050565b5f61295a83610be8565b9050425f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f018190555081816129ad91906140ca565b5f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160030181905550505050565b5f612a237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b6130ce565b5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b612a53826130d7565b8173ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a25f81511115612aaf57612aa982826131a0565b50612ab8565b612ab7613220565b5b5050565b5f612ac5611f2a565b90505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b5f7f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00905090565b5f612bbe83610fe0565b9050425f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f01819055508181612c1291906140ca565b5f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060040160030181905550505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612ccd575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401612cc4919061395e565b60405180910390fd5b612cd8825f8361256d565b5050565b5f8084841115612d15578484612cf291906140ca565b9050808311612d01575f612d0e565b8083612d0d91906140ca565b5b9150612d32565b8385612d2191906140ca565b90508083612d2f9190614097565b91505b509392505050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115612db6575f600385925092509250612e57565b5f6001888888886040515f8152602001604052604051612dd994939291906143b1565b6020604051602081039080840390855afa158015612df9573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612e4a575f60015f801b93509350935050612e57565b805f805f1b935093509350505b9450945094915050565b5f6003811115612e7457612e736143f4565b5b826003811115612e8757612e866143f4565b5b0315612fbf5760016003811115612ea157612ea06143f4565b5b826003811115612eb457612eb36143f4565b5b03612eeb576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612eff57612efe6143f4565b5b826003811115612f1257612f116143f4565b5b03612f5657805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401612f4d9190613520565b60405180910390fd5b600380811115612f6957612f686143f4565b5b826003811115612f7c57612f7b6143f4565b5b03612fbe57806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612fb591906135d5565b60405180910390fd5b5b5050565b5f80612fcd611dc7565b90505f612fd8611dee565b90505f81511115612ff457808051906020012092505050613036565b5f825f015490505f801b811461300f57809350505050613036565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47093505050505b90565b5f80613043611dc7565b90505f61304e611e8c565b90505f8151111561306a578080519060200120925050506130ad565b5f826001015490505f801b8114613086578093505050506130ad565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47093505050505b90565b5f6130b9611810565b5f0160089054906101000a900460ff16905090565b5f819050919050565b5f8173ffffffffffffffffffffffffffffffffffffffff163b0361313257806040517f4c9c8ce3000000000000000000000000000000000000000000000000000000008152600401613129919061395e565b60405180910390fd5b8061315e7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b6130ce565b5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60605f808473ffffffffffffffffffffffffffffffffffffffff16846040516131c99190614465565b5f60405180830381855af49150503d805f8114613201576040519150601f19603f3d011682016040523d82523d5f602084013e613206565b606091505b509150915061321685838361325c565b9250505092915050565b5f34111561325a576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6060826132715761326c826132e9565b6132e1565b5f825114801561329757505f8473ffffffffffffffffffffffffffffffffffffffff163b145b156132d957836040517f9996b3150000000000000000000000000000000000000000000000000000000081526004016132d0919061395e565b60405180910390fd5b8190506132e2565b5b9392505050565b5f815111156132fb5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015613364578082015181840152602081019050613349565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6133898261332d565b6133938185613337565b93506133a3818560208601613347565b6133ac8161336f565b840191505092915050565b5f6020820190508181035f8301526133cf818461337f565b905092915050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613411826133e8565b9050919050565b61342181613407565b811461342b575f80fd5b50565b5f8135905061343c81613418565b92915050565b5f819050919050565b61345481613442565b811461345e575f80fd5b50565b5f8135905061346f8161344b565b92915050565b5f806040838503121561348b5761348a6133e0565b5b5f6134988582860161342e565b92505060206134a985828601613461565b9150509250929050565b5f8115159050919050565b6134c7816134b3565b82525050565b5f6020820190506134e05f8301846134be565b92915050565b5f602082840312156134fb576134fa6133e0565b5b5f6135088482850161342e565b91505092915050565b61351a81613442565b82525050565b5f6020820190506135335f830184613511565b92915050565b5f805f606084860312156135505761354f6133e0565b5b5f61355d8682870161342e565b935050602061356e8682870161342e565b925050604061357f86828701613461565b9150509250925092565b5f60ff82169050919050565b61359e81613589565b82525050565b5f6020820190506135b75f830184613595565b92915050565b5f819050919050565b6135cf816135bd565b82525050565b5f6020820190506135e85f8301846135c6565b92915050565b6135f7816134b3565b8114613601575f80fd5b50565b5f81359050613612816135ee565b92915050565b5f806040838503121561362e5761362d6133e0565b5b5f61363b8582860161342e565b925050602061364c85828601613604565b9150509250929050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6136948261336f565b810181811067ffffffffffffffff821117156136b3576136b261365e565b5b80604052505050565b5f6136c56133d7565b90506136d1828261368b565b919050565b5f67ffffffffffffffff8211156136f0576136ef61365e565b5b6136f98261336f565b9050602081019050919050565b828183375f83830152505050565b5f613726613721846136d6565b6136bc565b9050828152602081018484840111156137425761374161365a565b5b61374d848285613706565b509392505050565b5f82601f83011261376957613768613656565b5b8135613779848260208601613714565b91505092915050565b5f8060408385031215613798576137976133e0565b5b5f6137a58582860161342e565b925050602083013567ffffffffffffffff8111156137c6576137c56133e4565b5b6137d285828601613755565b9150509250929050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b613810816137dc565b82525050565b61381f81613407565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61385781613442565b82525050565b5f613868838361384e565b60208301905092915050565b5f602082019050919050565b5f61388a82613825565b613894818561382f565b935061389f8361383f565b805f5b838110156138cf5781516138b6888261385d565b97506138c183613874565b9250506001810190506138a2565b5085935050505092915050565b5f60e0820190506138ef5f83018a613807565b8181036020830152613901818961337f565b90508181036040830152613915818861337f565b90506139246060830187613511565b6139316080830186613816565b61393e60a08301856135c6565b81810360c08301526139508184613880565b905098975050505050505050565b5f6020820190506139715f830184613816565b92915050565b5f805f6060848603121561398e5761398d6133e0565b5b5f61399b8682870161342e565b93505060206139ac86828701613461565b92505060406139bd86828701613461565b9150509250925092565b608082015f8201516139db5f85018261384e565b5060208201516139ee602085018261384e565b506040820151613a01604085018261384e565b506060820151613a14606085018261384e565b50505050565b5f61010082019050613a2e5f8301856139c7565b613a3b60808301846139c7565b9392505050565b613a4b81613589565b8114613a55575f80fd5b50565b5f81359050613a6681613a42565b92915050565b613a75816135bd565b8114613a7f575f80fd5b50565b5f81359050613a9081613a6c565b92915050565b5f805f805f805f60e0888a031215613ab157613ab06133e0565b5b5f613abe8a828b0161342e565b9750506020613acf8a828b0161342e565b9650506040613ae08a828b01613461565b9550506060613af18a828b01613461565b9450506080613b028a828b01613a58565b93505060a0613b138a828b01613a82565b92505060c0613b248a828b01613a82565b91505092959891949750929550565b5f8060408385031215613b4957613b486133e0565b5b5f613b568582860161342e565b9250506020613b678582860161342e565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680613bb557607f821691505b602082108103613bc857613bc7613b71565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f808291508390505b6001851115613c5057808604811115613c2c57613c2b613bce565b5b6001851615613c3b5780820291505b8081029050613c4985613bfb565b9450613c10565b94509492505050565b5f82613c685760019050613d23565b81613c75575f9050613d23565b8160018114613c8b5760028114613c9557613cc4565b6001915050613d23565b60ff841115613ca757613ca6613bce565b5b8360020a915084821115613cbe57613cbd613bce565b5b50613d23565b5060208310610133831016604e8410600b8410161715613cf95782820a905083811115613cf457613cf3613bce565b5b613d23565b613d068484846001613c07565b92509050818404811115613d1d57613d1c613bce565b5b81810290505b9392505050565b5f613d3482613442565b9150613d3f83613589565b9250613d6c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484613c59565b905092915050565b5f613d7e82613442565b9150613d8983613442565b9250828202613d9781613442565b91508282048414831517613dae57613dad613bce565b5b5092915050565b5f819050919050565b5f67ffffffffffffffff82169050919050565b5f819050919050565b5f613df4613def613dea84613db5565b613dd1565b613dbe565b9050919050565b613e0481613dda565b82525050565b5f602082019050613e1d5f830184613dfb565b92915050565b7f4c6f636b626f78206e6f74206e656365737361727920666f72207468697320745f8201527f6f6b656e00000000000000000000000000000000000000000000000000000000602082015250565b5f613e7d602483613337565b9150613e8882613e23565b604082019050919050565b5f6020820190508181035f830152613eaa81613e71565b9050919050565b7f4549503731323a20556e696e697469616c697a656400000000000000000000005f82015250565b5f613ee5601583613337565b9150613ef082613eb1565b602082019050919050565b5f6020820190508181035f830152613f1281613ed9565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613f5082613442565b9150613f5b83613442565b925082613f6b57613f6a613f19565b5b828204905092915050565b5f604082019050613f895f830185613511565b613f966020830184613511565b9392505050565b5f60c082019050613fb05f8301896135c6565b613fbd6020830188613816565b613fca6040830187613816565b613fd76060830186613511565b613fe46080830185613511565b613ff160a0830184613511565b979650505050505050565b5f60408201905061400f5f830185613816565b61401c6020830184613816565b9392505050565b5f6060820190506140365f830186613816565b6140436020830185613511565b6140506040830184613511565b949350505050565b5f8151905061406681613a6c565b92915050565b5f60208284031215614081576140806133e0565b5b5f61408e84828501614058565b91505092915050565b5f6140a182613442565b91506140ac83613442565b92508282019050808211156140c4576140c3613bce565b5b92915050565b5f6140d482613442565b91506140df83613442565b92508282039050818111156140f7576140f6613bce565b5b92915050565b5f60a0820190506141105f8301886135c6565b61411d60208301876135c6565b61412a60408301866135c6565b6141376060830185613511565b6141446080830184613816565b9695505050505050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026141aa7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261416f565b6141b4868361416f565b95508019841693508086168417925050509392505050565b5f6141e66141e16141dc84613442565b613dd1565b613442565b9050919050565b5f819050919050565b6141ff836141cc565b61421361420b826141ed565b84845461417b565b825550505050565b5f90565b61422761421b565b6142328184846141f6565b505050565b5b818110156142555761424a5f8261421f565b600181019050614238565b5050565b601f82111561429a5761426b8161414e565b61427484614160565b81016020851015614283578190505b61429761428f85614160565b830182614237565b50505b505050565b5f82821c905092915050565b5f6142ba5f198460080261429f565b1980831691505092915050565b5f6142d283836142ab565b9150826002028217905092915050565b6142eb8261332d565b67ffffffffffffffff8111156143045761430361365e565b5b61430e8254613b9e565b614319828285614259565b5f60209050601f83116001811461434a575f8415614338578287015190505b61434285826142c7565b8655506143a9565b601f1984166143588661414e565b5f5b8281101561437f5784890151825560018201915060208501945060208101905061435a565b8683101561439c5784890151614398601f8916826142ab565b8355505b6001600288020188555050505b505050505050565b5f6080820190506143c45f8301876135c6565b6143d16020830186613595565b6143de60408301856135c6565b6143eb60608301846135c6565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f81519050919050565b5f81905092915050565b5f61443f82614421565b614449818561442b565b9350614459818560208601613347565b80840191505092915050565b5f6144708284614435565b91508190509291505056fea26469706673582212200935dde0b8eed7acd071d68af03f7276dbc7b66eb2cc826938fba17e4e76a20c64736f6c63430008170033
Deployed Bytecode
0x6080604052600436106101d7575f3560e01c806379ba509711610101578063a9059cbb11610094578063d505accf11610063578063d505accf146106c4578063dd62ed3e146106ec578063e30c397814610728578063f2fde38b14610752576101d7565b8063a9059cbb146105e5578063ad3cb1cc14610621578063c1eb71371461064b578063ced67f0c14610687576101d7565b806395d89b41116100d057806395d89b411461052f578063998955d3146105595780639dc29fac14610595578063a08d5654146105bd576101d7565b806379ba5097146104835780637ecebe001461049957806384b0196e146104d55780638da5cb5b14610505576101d7565b8063400ada751161017957806352d1902d1161014857806352d1902d146103cb578063651fd268146103f557806370a0823114610431578063715018a61461046d576101d7565b8063400ada751461033757806340c10f191461035f578063435350b7146103875780634f1ef286146103af576101d7565b806318160ddd116101b557806318160ddd1461027d57806323b872dd146102a7578063313ce567146102e35780633644e5151461030d576101d7565b806306fdde03146101db578063095ea7b3146102055780630c05f82c14610241575b5f80fd5b3480156101e6575f80fd5b506101ef61077a565b6040516101fc91906133b7565b60405180910390f35b348015610210575f80fd5b5061022b60048036038101906102269190613475565b610818565b60405161023891906134cd565b60405180910390f35b34801561024c575f80fd5b50610267600480360381019061026291906134e6565b61083a565b6040516102749190613520565b60405180910390f35b348015610288575f80fd5b50610291610884565b60405161029e9190613520565b60405180910390f35b3480156102b2575f80fd5b506102cd60048036038101906102c89190613539565b61089b565b6040516102da91906134cd565b60405180910390f35b3480156102ee575f80fd5b506102f76108c9565b60405161030491906135a4565b60405180910390f35b348015610318575f80fd5b506103216108d1565b60405161032e91906135d5565b60405180910390f35b348015610342575f80fd5b5061035d60048036038101906103589190613618565b6108df565b005b34801561036a575f80fd5b5061038560048036038101906103809190613475565b610b4e565b005b348015610392575f80fd5b506103ad60048036038101906103a891906134e6565b610b5d565b005b6103c960048036038101906103c49190613782565b610b98565b005b3480156103d6575f80fd5b506103df610bb7565b6040516103ec91906135d5565b60405180910390f35b348015610400575f80fd5b5061041b600480360381019061041691906134e6565b610be8565b6040516104289190613520565b60405180910390f35b34801561043c575f80fd5b50610457600480360381019061045291906134e6565b610cff565b6040516104649190613520565b60405180910390f35b348015610478575f80fd5b50610481610d52565b005b34801561048e575f80fd5b50610497610d65565b005b3480156104a4575f80fd5b506104bf60048036038101906104ba91906134e6565b610df3565b6040516104cc9190613520565b60405180910390f35b3480156104e0575f80fd5b506104e9610e04565b6040516104fc97969594939291906138dc565b60405180910390f35b348015610510575f80fd5b50610519610f0d565b604051610526919061395e565b60405180910390f35b34801561053a575f80fd5b50610543610f42565b60405161055091906133b7565b60405180910390f35b348015610564575f80fd5b5061057f600480360381019061057a91906134e6565b610fe0565b60405161058c9190613520565b60405180910390f35b3480156105a0575f80fd5b506105bb60048036038101906105b69190613475565b6110fb565b005b3480156105c8575f80fd5b506105e360048036038101906105de9190613977565b611149565b005b3480156105f0575f80fd5b5061060b60048036038101906106069190613475565b611256565b60405161061891906134cd565b60405180910390f35b34801561062c575f80fd5b50610635611278565b60405161064291906133b7565b60405180910390f35b348015610656575f80fd5b50610671600480360381019061066c91906134e6565b6112b1565b60405161067e9190613520565b60405180910390f35b348015610692575f80fd5b506106ad60048036038101906106a891906134e6565b6112fc565b6040516106bb929190613a1a565b60405180910390f35b3480156106cf575f80fd5b506106ea60048036038101906106e59190613a96565b61137d565b005b3480156106f7575f80fd5b50610712600480360381019061070d9190613b33565b6114c2565b60405161071f9190613520565b60405180910390f35b348015610733575f80fd5b5061073c611552565b604051610749919061395e565b60405180910390f35b34801561075d575f80fd5b50610778600480360381019061077391906134e6565b611587565b005b60605f610785611640565b905080600301805461079690613b9e565b80601f01602080910402602001604051908101604052809291908181526020018280546107c290613b9e565b801561080d5780601f106107e45761010080835404028352916020019161080d565b820191905f5260205f20905b8154815290600101906020018083116107f057829003601f168201915b505050505091505090565b5f80610822611667565b905061082f81858561166e565b600191505092915050565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600201549050919050565b5f8061088e611640565b9050806002015491505090565b5f806108a5611667565b90506108b2858285611680565b6108bd858585611712565b60019150509392505050565b5f6012905090565b5f6108da611802565b905090565b5f6108e8611810565b90505f815f0160089054906101000a900460ff161590505f825f015f9054906101000a900467ffffffffffffffff1690505f808267ffffffffffffffff161480156109305750825b90505f60018367ffffffffffffffff1614801561096357505f3073ffffffffffffffffffffffffffffffffffffffff163b145b905081158015610971575080155b156109a8576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001855f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083156109f5576001855f0160086101000a81548160ff0219169083151502179055505b610a696040518060400160405280600581526020017f496f6e69630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f494f4e0000000000000000000000000000000000000000000000000000000000815250611837565b610a728761184d565b610ab06040518060400160405280600581526020017f496f6e6963000000000000000000000000000000000000000000000000000000815250611861565b610ab86118ab565b8515610aeb57610aea33610aca6108c9565b600a610ad69190613d2a565b633b9aca00610ae59190613d74565b6118b5565b5b8315610b45575f855f0160086101000a81548160ff0219169083151502179055507fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d26001604051610b3c9190613e0a565b60405180910390a15b50505050505050565b610b59338383611934565b5050565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b8f90613e93565b60405180910390fd5b610ba0611994565b610ba982611a7a565b610bb38282611a85565b5050565b5f610bc0611ba3565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b905090565b5f610cf85f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600301545f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600201545f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f01545f808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160010154611c2a565b9050919050565b5f80610d09611640565b9050805f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054915050919050565b610d5a611cb0565b610d635f611d37565b565b5f610d6e611667565b90508073ffffffffffffffffffffffffffffffffffffffff16610d8f611552565b73ffffffffffffffffffffffffffffffffffffffff1614610de757806040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401610dde919061395e565b60405180910390fd5b610df081611d37565b50565b5f610dfd82611d74565b9050919050565b5f6060805f805f60605f610e16611dc7565b90505f801b815f0154148015610e3157505f801b8160010154145b610e70576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e6790613efb565b60405180910390fd5b610e78611dee565b610e80611e8c565b46305f801b5f67ffffffffffffffff811115610e9f57610e9e61365e565b5b604051908082528060200260200182016040528015610ecd5781602001602082028036833780820191505090505b507f0f0000000000000000000000000000000000000000000000000000000000000095949392919097509750975097509750975097505090919293949596565b5f80610f17611f2a565b9050805f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b60605f610f4d611640565b9050806004018054610f5e90613b9e565b80601f0160208091040260200160405190810160405280929190818152602001828054610f8a90613b9e565b8015610fd55780601f10610fac57610100808354040283529160200191610fd5565b820191905f5260205f20905b815481529060010190602001808311610fb857829003601f168201915b505050505091505090565b5f6110f45f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600301545f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600201545f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f01545f808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060040160010154611c2a565b9050919050565b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461113a57611139823383611680565b5b611145338383611f51565b5050565b611151611cb0565b60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61117e9190613f46565b8211806111b6575060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6111b39190613f46565b81115b156111ed576040517ff596480900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111f78383611fb1565b6112018382612137565b8273ffffffffffffffffffffffffffffffffffffffff167f93f3bbfe8cfb354ec059175107653f49f6eb479a8622a7d83866ea015435c9448383604051611249929190613f76565b60405180910390a2505050565b5f80611260611667565b905061126d818585611712565b600191505092915050565b6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600201549050919050565b5f602052805f5260405f205f91509050805f016040518060800160405290815f8201548152602001600182015481526020016002820154815260200160038201548152505090806004016040518060800160405290815f82015481526020016001820154815260200160028201548152602001600382015481525050905082565b834211156113c257836040517f627913020000000000000000000000000000000000000000000000000000000081526004016113b99190613520565b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886113f08c6122c2565b8960405160200161140696959493929190613f9d565b6040516020818303038152906040528051906020012090505f61142882612322565b90505f6114378287878761233b565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146114ab57808a6040517f4b800e460000000000000000000000000000000000000000000000000000000081526004016114a2929190613ffc565b60405180910390fd5b6114b68a8a8a61166e565b50505050505050505050565b5f806114cc611640565b9050806001015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205491505092915050565b5f8061155c612369565b9050805f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b61158f611cb0565b5f611598612369565b905081815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff166115fa610f0d565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35050565b5f7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00905090565b5f33905090565b61167b8383836001612390565b505050565b5f61168b84846114c2565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461170c57818110156116fd578281836040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526004016116f493929190614023565b60405180910390fd5b61170b84848484035f612390565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611782575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611779919061395e565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036117f2575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016117e9919061395e565b60405180910390fd5b6117fd83838361256d565b505050565b5f61180b61279c565b905090565b5f7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00905090565b61183f6127ff565b611849828261283f565b5050565b6118556127ff565b61185e8161287b565b50565b6118696127ff565b6118a8816040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506128ff565b50565b6118b36127ff565b565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611925575f6040517fec442f0500000000000000000000000000000000000000000000000000000000815260040161191c919061395e565b60405180910390fd5b6119305f838361256d565b5050565b5f61193e84610be8565b90508181101561197a576040517f0b6842aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119848483612950565b61198e83836118b5565b50505050565b7f00000000000000000000000004c21db52cca974df3dc019c92e52e522ce5715673ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161480611a4157507f00000000000000000000000004c21db52cca974df3dc019c92e52e522ce5715673ffffffffffffffffffffffffffffffffffffffff16611a286129f7565b73ffffffffffffffffffffffffffffffffffffffff1614155b15611a78576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b611a82611cb0565b50565b8173ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611aed57506040513d601f19601f82011682018060405250810190611aea919061406c565b60015b611b2e57816040517f4c9c8ce3000000000000000000000000000000000000000000000000000000008152600401611b25919061395e565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b8114611b9457806040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600401611b8b91906135d5565b60405180910390fd5b611b9e8383612a4a565b505050565b7f00000000000000000000000004c21db52cca974df3dc019c92e52e522ce5715673ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614611c28576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f84905083810315611ca857426201518084611c469190614097565b11611c5357839050611ca7565b426201518084611c639190614097565b1115611ca6575f8342611c7691906140ca565b90505f8382611c859190613d74565b83611c909190614097565b9050858111611c9f5780611ca1565b855b925050505b5b5b949350505050565b611cb8611667565b73ffffffffffffffffffffffffffffffffffffffff16611cd6610f0d565b73ffffffffffffffffffffffffffffffffffffffff1614611d3557611cf9611667565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401611d2c919061395e565b60405180910390fd5b565b5f611d40612369565b9050805f015f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055611d7082612abc565b5050565b5f80611d7e612b8d565b9050805f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054915050919050565b5f7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100905090565b60605f611df9611dc7565b9050806002018054611e0a90613b9e565b80601f0160208091040260200160405190810160405280929190818152602001828054611e3690613b9e565b8015611e815780601f10611e5857610100808354040283529160200191611e81565b820191905f5260205f20905b815481529060010190602001808311611e6457829003601f168201915b505050505091505090565b60605f611e97611dc7565b9050806003018054611ea890613b9e565b80601f0160208091040260200160405190810160405280929190818152602001828054611ed490613b9e565b8015611f1f5780601f10611ef657610100808354040283529160200191611f1f565b820191905f5260205f20905b815481529060010190602001808311611f0257829003601f168201915b505050505091505090565b5f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300905090565b5f611f5b84610fe0565b905081811015611f97576040517f0b6842aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611fa18483612bb4565b611fab8383612c5d565b50505050565b5f805f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016002015490505f61200084610be8565b9050825f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160020181905550612053838383612cdc565b5f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016003018190555062015180836120a79190613f46565b5f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160010181905550425f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f018190555050505050565b5f805f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016002015490505f61218784610fe0565b9050825f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600201819055506121db838383612cdc565b5f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016003018190555062015180836122309190613f46565b5f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060040160010181905550425f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f018190555050505050565b5f806122cc612b8d565b9050805f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f81548092919060010191905055915050919050565b5f61233461232e611802565b83612d3a565b9050919050565b5f805f8061234b88888888612d7a565b92509250925061235b8282612e61565b829350505050949350505050565b5f7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00905090565b5f612399611640565b90505f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361240b575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401612402919061395e565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361247b575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401612472919061395e565b60405180910390fd5b82816001015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508115612566578373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258560405161255d9190613520565b60405180910390a35b5050505050565b5f612576611640565b90505f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036125ca5781816002015f8282546125be9190614097565b9250508190555061269c565b5f815f015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905082811015612655578481846040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161264c93929190614023565b60405180910390fd5b828103825f015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036126e55781816002015f8282540392505081905550612731565b81815f015f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161278e9190613520565b60405180910390a350505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6127c6612fc3565b6127ce613039565b46306040516020016127e49594939291906140fd565b60405160208183030381529060405280519060200120905090565b6128076130b0565b61283d576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6128476127ff565b5f612850611640565b90508281600301908161286391906142e2565b508181600401908161287591906142e2565b50505050565b6128836127ff565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036128f3575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016128ea919061395e565b60405180910390fd5b6128fc81611d37565b50565b6129076127ff565b5f612910611dc7565b90508281600201908161292391906142e2565b508181600301908161293591906142e2565b505f801b815f01819055505f801b8160010181905550505050565b5f61295a83610be8565b9050425f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f018190555081816129ad91906140ca565b5f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160030181905550505050565b5f612a237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b6130ce565b5f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b612a53826130d7565b8173ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a25f81511115612aaf57612aa982826131a0565b50612ab8565b612ab7613220565b5b5050565b5f612ac5611f2a565b90505f815f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b5f7f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00905090565b5f612bbe83610fe0565b9050425f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f01819055508181612c1291906140ca565b5f808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060040160030181905550505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612ccd575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401612cc4919061395e565b60405180910390fd5b612cd8825f8361256d565b5050565b5f8084841115612d15578484612cf291906140ca565b9050808311612d01575f612d0e565b8083612d0d91906140ca565b5b9150612d32565b8385612d2191906140ca565b90508083612d2f9190614097565b91505b509392505050565b5f6040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115612db6575f600385925092509250612e57565b5f6001888888886040515f8152602001604052604051612dd994939291906143b1565b6020604051602081039080840390855afa158015612df9573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612e4a575f60015f801b93509350935050612e57565b805f805f1b935093509350505b9450945094915050565b5f6003811115612e7457612e736143f4565b5b826003811115612e8757612e866143f4565b5b0315612fbf5760016003811115612ea157612ea06143f4565b5b826003811115612eb457612eb36143f4565b5b03612eeb576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60026003811115612eff57612efe6143f4565b5b826003811115612f1257612f116143f4565b5b03612f5657805f1c6040517ffce698f7000000000000000000000000000000000000000000000000000000008152600401612f4d9190613520565b60405180910390fd5b600380811115612f6957612f686143f4565b5b826003811115612f7c57612f7b6143f4565b5b03612fbe57806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612fb591906135d5565b60405180910390fd5b5b5050565b5f80612fcd611dc7565b90505f612fd8611dee565b90505f81511115612ff457808051906020012092505050613036565b5f825f015490505f801b811461300f57809350505050613036565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47093505050505b90565b5f80613043611dc7565b90505f61304e611e8c565b90505f8151111561306a578080519060200120925050506130ad565b5f826001015490505f801b8114613086578093505050506130ad565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47093505050505b90565b5f6130b9611810565b5f0160089054906101000a900460ff16905090565b5f819050919050565b5f8173ffffffffffffffffffffffffffffffffffffffff163b0361313257806040517f4c9c8ce3000000000000000000000000000000000000000000000000000000008152600401613129919061395e565b60405180910390fd5b8061315e7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5f1b6130ce565b5f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60605f808473ffffffffffffffffffffffffffffffffffffffff16846040516131c99190614465565b5f60405180830381855af49150503d805f8114613201576040519150601f19603f3d011682016040523d82523d5f602084013e613206565b606091505b509150915061321685838361325c565b9250505092915050565b5f34111561325a576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6060826132715761326c826132e9565b6132e1565b5f825114801561329757505f8473ffffffffffffffffffffffffffffffffffffffff163b145b156132d957836040517f9996b3150000000000000000000000000000000000000000000000000000000081526004016132d0919061395e565b60405180910390fd5b8190506132e2565b5b9392505050565b5f815111156132fb5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015613364578082015181840152602081019050613349565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6133898261332d565b6133938185613337565b93506133a3818560208601613347565b6133ac8161336f565b840191505092915050565b5f6020820190508181035f8301526133cf818461337f565b905092915050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f613411826133e8565b9050919050565b61342181613407565b811461342b575f80fd5b50565b5f8135905061343c81613418565b92915050565b5f819050919050565b61345481613442565b811461345e575f80fd5b50565b5f8135905061346f8161344b565b92915050565b5f806040838503121561348b5761348a6133e0565b5b5f6134988582860161342e565b92505060206134a985828601613461565b9150509250929050565b5f8115159050919050565b6134c7816134b3565b82525050565b5f6020820190506134e05f8301846134be565b92915050565b5f602082840312156134fb576134fa6133e0565b5b5f6135088482850161342e565b91505092915050565b61351a81613442565b82525050565b5f6020820190506135335f830184613511565b92915050565b5f805f606084860312156135505761354f6133e0565b5b5f61355d8682870161342e565b935050602061356e8682870161342e565b925050604061357f86828701613461565b9150509250925092565b5f60ff82169050919050565b61359e81613589565b82525050565b5f6020820190506135b75f830184613595565b92915050565b5f819050919050565b6135cf816135bd565b82525050565b5f6020820190506135e85f8301846135c6565b92915050565b6135f7816134b3565b8114613601575f80fd5b50565b5f81359050613612816135ee565b92915050565b5f806040838503121561362e5761362d6133e0565b5b5f61363b8582860161342e565b925050602061364c85828601613604565b9150509250929050565b5f80fd5b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6136948261336f565b810181811067ffffffffffffffff821117156136b3576136b261365e565b5b80604052505050565b5f6136c56133d7565b90506136d1828261368b565b919050565b5f67ffffffffffffffff8211156136f0576136ef61365e565b5b6136f98261336f565b9050602081019050919050565b828183375f83830152505050565b5f613726613721846136d6565b6136bc565b9050828152602081018484840111156137425761374161365a565b5b61374d848285613706565b509392505050565b5f82601f83011261376957613768613656565b5b8135613779848260208601613714565b91505092915050565b5f8060408385031215613798576137976133e0565b5b5f6137a58582860161342e565b925050602083013567ffffffffffffffff8111156137c6576137c56133e4565b5b6137d285828601613755565b9150509250929050565b5f7fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b613810816137dc565b82525050565b61381f81613407565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61385781613442565b82525050565b5f613868838361384e565b60208301905092915050565b5f602082019050919050565b5f61388a82613825565b613894818561382f565b935061389f8361383f565b805f5b838110156138cf5781516138b6888261385d565b97506138c183613874565b9250506001810190506138a2565b5085935050505092915050565b5f60e0820190506138ef5f83018a613807565b8181036020830152613901818961337f565b90508181036040830152613915818861337f565b90506139246060830187613511565b6139316080830186613816565b61393e60a08301856135c6565b81810360c08301526139508184613880565b905098975050505050505050565b5f6020820190506139715f830184613816565b92915050565b5f805f6060848603121561398e5761398d6133e0565b5b5f61399b8682870161342e565b93505060206139ac86828701613461565b92505060406139bd86828701613461565b9150509250925092565b608082015f8201516139db5f85018261384e565b5060208201516139ee602085018261384e565b506040820151613a01604085018261384e565b506060820151613a14606085018261384e565b50505050565b5f61010082019050613a2e5f8301856139c7565b613a3b60808301846139c7565b9392505050565b613a4b81613589565b8114613a55575f80fd5b50565b5f81359050613a6681613a42565b92915050565b613a75816135bd565b8114613a7f575f80fd5b50565b5f81359050613a9081613a6c565b92915050565b5f805f805f805f60e0888a031215613ab157613ab06133e0565b5b5f613abe8a828b0161342e565b9750506020613acf8a828b0161342e565b9650506040613ae08a828b01613461565b9550506060613af18a828b01613461565b9450506080613b028a828b01613a58565b93505060a0613b138a828b01613a82565b92505060c0613b248a828b01613a82565b91505092959891949750929550565b5f8060408385031215613b4957613b486133e0565b5b5f613b568582860161342e565b9250506020613b678582860161342e565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680613bb557607f821691505b602082108103613bc857613bc7613b71565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f808291508390505b6001851115613c5057808604811115613c2c57613c2b613bce565b5b6001851615613c3b5780820291505b8081029050613c4985613bfb565b9450613c10565b94509492505050565b5f82613c685760019050613d23565b81613c75575f9050613d23565b8160018114613c8b5760028114613c9557613cc4565b6001915050613d23565b60ff841115613ca757613ca6613bce565b5b8360020a915084821115613cbe57613cbd613bce565b5b50613d23565b5060208310610133831016604e8410600b8410161715613cf95782820a905083811115613cf457613cf3613bce565b5b613d23565b613d068484846001613c07565b92509050818404811115613d1d57613d1c613bce565b5b81810290505b9392505050565b5f613d3482613442565b9150613d3f83613589565b9250613d6c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484613c59565b905092915050565b5f613d7e82613442565b9150613d8983613442565b9250828202613d9781613442565b91508282048414831517613dae57613dad613bce565b5b5092915050565b5f819050919050565b5f67ffffffffffffffff82169050919050565b5f819050919050565b5f613df4613def613dea84613db5565b613dd1565b613dbe565b9050919050565b613e0481613dda565b82525050565b5f602082019050613e1d5f830184613dfb565b92915050565b7f4c6f636b626f78206e6f74206e656365737361727920666f72207468697320745f8201527f6f6b656e00000000000000000000000000000000000000000000000000000000602082015250565b5f613e7d602483613337565b9150613e8882613e23565b604082019050919050565b5f6020820190508181035f830152613eaa81613e71565b9050919050565b7f4549503731323a20556e696e697469616c697a656400000000000000000000005f82015250565b5f613ee5601583613337565b9150613ef082613eb1565b602082019050919050565b5f6020820190508181035f830152613f1281613ed9565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f613f5082613442565b9150613f5b83613442565b925082613f6b57613f6a613f19565b5b828204905092915050565b5f604082019050613f895f830185613511565b613f966020830184613511565b9392505050565b5f60c082019050613fb05f8301896135c6565b613fbd6020830188613816565b613fca6040830187613816565b613fd76060830186613511565b613fe46080830185613511565b613ff160a0830184613511565b979650505050505050565b5f60408201905061400f5f830185613816565b61401c6020830184613816565b9392505050565b5f6060820190506140365f830186613816565b6140436020830185613511565b6140506040830184613511565b949350505050565b5f8151905061406681613a6c565b92915050565b5f60208284031215614081576140806133e0565b5b5f61408e84828501614058565b91505092915050565b5f6140a182613442565b91506140ac83613442565b92508282019050808211156140c4576140c3613bce565b5b92915050565b5f6140d482613442565b91506140df83613442565b92508282039050818111156140f7576140f6613bce565b5b92915050565b5f60a0820190506141105f8301886135c6565b61411d60208301876135c6565b61412a60408301866135c6565b6141376060830185613511565b6141446080830184613816565b9695505050505050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026141aa7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261416f565b6141b4868361416f565b95508019841693508086168417925050509392505050565b5f6141e66141e16141dc84613442565b613dd1565b613442565b9050919050565b5f819050919050565b6141ff836141cc565b61421361420b826141ed565b84845461417b565b825550505050565b5f90565b61422761421b565b6142328184846141f6565b505050565b5b818110156142555761424a5f8261421f565b600181019050614238565b5050565b601f82111561429a5761426b8161414e565b61427484614160565b81016020851015614283578190505b61429761428f85614160565b830182614237565b50505b505050565b5f82821c905092915050565b5f6142ba5f198460080261429f565b1980831691505092915050565b5f6142d283836142ab565b9150826002028217905092915050565b6142eb8261332d565b67ffffffffffffffff8111156143045761430361365e565b5b61430e8254613b9e565b614319828285614259565b5f60209050601f83116001811461434a575f8415614338578287015190505b61434285826142c7565b8655506143a9565b601f1984166143588661414e565b5f5b8281101561437f5784890151825560018201915060208501945060208101905061435a565b8683101561439c5784890151614398601f8916826142ab565b8355505b6001600288020188555050505b505050505050565b5f6080820190506143c45f8301876135c6565b6143d16020830186613595565b6143de60408301856135c6565b6143eb60608301846135c6565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f81519050919050565b5f81905092915050565b5f61443f82614421565b614449818561442b565b9350614459818560208601613347565b80840191505092915050565b5f6144708284614435565b91508190509291505056fea26469706673582212200935dde0b8eed7acd071d68af03f7276dbc7b66eb2cc826938fba17e4e76a20c64736f6c63430008170033
Deployed Bytecode Sourcemap
120020:10485:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92158:147;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;94731:190;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123082:163;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93372:155;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;95499:249;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93223:84;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;119874:114;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120576:368;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;121219:115;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;121886:121;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;105933:217;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;105466:136;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123802:378;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;93590:174;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;74960:103;;;;;;;;;;;;;:::i;:::-;;89201:235;;;;;;;;;;;;;:::i;:::-;;119605:156;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;113510:931;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;74225:147;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;92424:151;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124379:378;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;121570:222;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;122374:513;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;93969:182;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;103534:58;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123440:163;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;120409:41;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;118851:695;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;94214:198;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;88079:171;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;88449:251;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;92158:147;92203:13;92229:22;92254:18;:16;:18::i;:::-;92229:43;;92290:1;:7;;92283:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92158:147;:::o;94731:190::-;94804:4;94821:13;94837:12;:10;:12::i;:::-;94821:28;;94860:31;94869:5;94876:7;94885:5;94860:8;:31::i;:::-;94909:4;94902:11;;;94731:190;;;;:::o;123082:163::-;123163:14;123199:7;:16;123207:7;123199:16;;;;;;;;;;;;;;;:29;;:38;;;123190:47;;123082:163;;;:::o;93372:155::-;93424:7;93444:22;93469:18;:16;:18::i;:::-;93444:43;;93505:1;:14;;;93498:21;;;93372:155;:::o;95499:249::-;95586:4;95603:15;95621:12;:10;:12::i;:::-;95603:30;;95644:37;95660:4;95666:7;95675:5;95644:15;:37::i;:::-;95692:26;95702:4;95708:2;95712:5;95692:9;:26::i;:::-;95736:4;95729:11;;;95499:249;;;;;:::o;93223:84::-;93272:5;93297:2;93290:9;;93223:84;:::o;119874:114::-;119933:7;119960:20;:18;:20::i;:::-;119953:27;;119874:114;:::o;120576:368::-;55315:30;55348:26;:24;:26::i;:::-;55315:59;;55439:19;55462:1;:15;;;;;;;;;;;;55461:16;55439:38;;55488:18;55509:1;:14;;;;;;;;;;;;55488:35;;55874:17;55909:1;55894:11;:16;;;:34;;;;;55914:14;55894:34;55874:54;;55939:17;55974:1;55959:11;:16;;;:50;;;;;56008:1;55987:4;55979:25;;;:30;55959:50;55939:70;;56027:12;56026:13;:30;;;;;56044:12;56043:13;56026:30;56022:93;;;56080:23;;;;;;;;;;;;;;56022:93;56142:1;56125;:14;;;:18;;;;;;;;;;;;;;;;;;56158:14;56154:69;;;56207:4;56189:1;:15;;;:22;;;;;;;;;;;;;;;;;;56154:69;120691:28:::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;::::0;:12:::1;:28::i;:::-;120730;120745:12;120730:14;:28::i;:::-;120769:27;;;;;;;;;;;;;;;;;::::0;:18:::1;:27::i;:::-;120807:24;:22;:24::i;:::-;120846:11;120842:95;;;120874:51;120880:10;120914;:8;:10::i;:::-;120908:2;:16;;;;:::i;:::-;120892:13;:32;;;;:::i;:::-;120874:5;:51::i;:::-;120842:95;56249:14:::0;56245:104;;;56298:5;56280:1;:15;;;:23;;;;;;;;;;;;;;;;;;56323:14;56335:1;56323:14;;;;;;:::i;:::-;;;;;;;;56245:104;55247:1109;;;;;120576:368;;:::o;121219:115::-;121283:43;121299:10;121311:5;121318:7;121283:15;:43::i;:::-;121219:115;;:::o;121886:121::-;121953:46;;;;;;;;;;:::i;:::-;;;;;;;;105933:217;104388:13;:11;:13::i;:::-;106049:36:::1;106067:17;106049;:36::i;:::-;106096:46;106118:17;106137:4;106096:21;:46::i;:::-;105933:217:::0;;:::o;105466:136::-;105535:7;104668:20;:18;:20::i;:::-;77076:66:::1;105562:32;;105555:39;;105466:136:::0;:::o;123802:378::-;123887:14;123923:249;123954:7;:16;123962:7;123954:16;;;;;;;;;;;;;;;:29;;:42;;;124011:7;:16;124019:7;124011:16;;;;;;;;;;;;;;;:29;;:38;;;124064:7;:16;124072:7;124064:16;;;;;;;;;;;;;;;:29;;:39;;;124118:7;:16;124126:7;124118:16;;;;;;;;;;;;;;;:29;;:43;;;123923:16;:249::i;:::-;123914:258;;123802:378;;;:::o;93590:174::-;93655:7;93675:22;93700:18;:16;:18::i;:::-;93675:43;;93736:1;:11;;:20;93748:7;93736:20;;;;;;;;;;;;;;;;93729:27;;;93590:174;;;:::o;74960:103::-;74111:13;:11;:13::i;:::-;75025:30:::1;75052:1;75025:18;:30::i;:::-;74960:103::o:0;89201:235::-;89254:14;89271:12;:10;:12::i;:::-;89254:29;;89316:6;89298:24;;:14;:12;:14::i;:::-;:24;;;89294:98;;89373:6;89346:34;;;;;;;;;;;:::i;:::-;;;;;;;;89294:98;89402:26;89421:6;89402:18;:26::i;:::-;89243:193;89201:235::o;119605:156::-;119707:7;119734:19;119747:5;119734:12;:19::i;:::-;119727:26;;119605:156;;;:::o;113510:931::-;113613:13;113641:18;113674:21;113710:15;113740:25;113780:12;113807:27;113862:23;113888:19;:17;:19::i;:::-;113862:45;;114148:1;114131:18;;:1;:13;;;:18;:43;;;;;114173:1;114153:21;;:1;:16;;;:21;114131:43;114123:77;;;;;;;;;;;;:::i;:::-;;;;;;;;;114266:13;:11;:13::i;:::-;114294:16;:14;:16::i;:::-;114325:13;114361:4;114389:1;114381:10;;114420:1;114406:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;114213:220;;;;;;;;;;;;;;;;;;;;;;113510:931;;;;;;;:::o;74225:147::-;74271:7;74291:24;74318:20;:18;:20::i;:::-;74291:47;;74356:1;:8;;;;;;;;;;;;74349:15;;;74225:147;:::o;92424:151::-;92471:13;92497:22;92522:18;:16;:18::i;:::-;92497:43;;92558:1;:9;;92551:16;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92424:151;:::o;124379:378::-;124464:14;124500:249;124531:7;:16;124539:7;124531:16;;;;;;;;;;;;;;;:29;;:42;;;124588:7;:16;124596:7;124588:16;;;;;;;;;;;;;;;:29;;:38;;;124641:7;:16;124649:7;124641:16;;;;;;;;;;;;;;;:29;;:39;;;124695:7;:16;124703:7;124695:16;;;;;;;;;;;;;;;:29;;:43;;;124500:16;:249::i;:::-;124491:258;;124379:378;;;:::o;121570:222::-;121652:5;121638:19;;:10;:19;;;121634:95;;121674:43;121690:5;121697:10;121709:7;121674:15;:43::i;:::-;121634:95;121741:43;121757:10;121769:5;121776:7;121741:15;:43::i;:::-;121570:222;;:::o;122374:513::-;74111:13;:11;:13::i;:::-;122575:1:::1;122555:17;:21;;;;:::i;:::-;122538:13;:39;:95;;;;122631:1;122611:17;:21;;;;:::i;:::-;122594:13;:39;122538:95;122520:182;;;122667:23;;;;;;;;;;;;;;122520:182;122714:42;122733:7;122742:13;122714:18;:42::i;:::-;122767;122786:7;122795:13;122767:18;:42::i;:::-;122871:7;122825:54;;;122841:13;122856;122825:54;;;;;;;:::i;:::-;;;;;;;;122374:513:::0;;;:::o;93969:182::-;94038:4;94055:13;94071:12;:10;:12::i;:::-;94055:28;;94094:27;94104:5;94111:2;94115:5;94094:9;:27::i;:::-;94139:4;94132:11;;;93969:182;;;;:::o;103534:58::-;;;;;;;;;;;;;;;;;;;:::o;123440:163::-;123521:14;123557:7;:16;123565:7;123557:16;;;;;;;;;;;;;;;:29;;:38;;;123548:47;;123440:163;;;:::o;120409:41::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;118851:695::-;119081:8;119063:15;:26;119059:99;;;119137:8;119113:33;;;;;;;;;;;:::i;:::-;;;;;;;;119059:99;119170:18;118007:95;119229:5;119236:7;119245:5;119252:16;119262:5;119252:9;:16::i;:::-;119270:8;119201:78;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;119191:89;;;;;;119170:110;;119293:12;119308:28;119325:10;119308:16;:28::i;:::-;119293:43;;119349:14;119366:28;119380:4;119386:1;119389;119392;119366:13;:28::i;:::-;119349:45;;119419:5;119409:15;;:6;:15;;;119405:90;;119469:6;119477:5;119448:35;;;;;;;;;;;;:::i;:::-;;;;;;;;119405:90;119507:31;119516:5;119523:7;119532:5;119507:8;:31::i;:::-;119048:498;;;118851:695;;;;;;;:::o;94214:198::-;94294:7;94314:22;94339:18;:16;:18::i;:::-;94314:43;;94375:1;:13;;:20;94389:5;94375:20;;;;;;;;;;;;;;;:29;94396:7;94375:29;;;;;;;;;;;;;;;;94368:36;;;94214:198;;;;:::o;88079:171::-;88132:7;88152:29;88184:25;:23;:25::i;:::-;88152:57;;88227:1;:15;;;;;;;;;;;;88220:22;;;88079:171;:::o;88449:251::-;74111:13;:11;:13::i;:::-;88539:29:::1;88571:25;:23;:25::i;:::-;88539:57;;88625:8;88607:1;:15;;;:26;;;;;;;;;;;;;;;;;;88683:8;88649:43;;88674:7;:5;:7::i;:::-;88649:43;;;;;;;;;;;;88528:172;88449:251:::0;:::o;91364:157::-;91414:22;91483:20;91473:30;;91364:157;:::o;66048:98::-;66101:7;66128:10;66121:17;;66048:98;:::o;99622:130::-;99707:37;99716:5;99723:7;99732:5;99739:4;99707:8;:37::i;:::-;99622:130;;;:::o;101394:487::-;101494:24;101521:25;101531:5;101538:7;101521:9;:25::i;:::-;101494:52;;101581:17;101561:16;:37;101557:317;;101638:5;101619:16;:24;101615:132;;;101698:7;101707:16;101725:5;101671:60;;;;;;;;;;;;;:::i;:::-;;;;;;;;101615:132;101790:57;101799:5;101806:7;101834:5;101815:16;:24;101841:5;101790:8;:57::i;:::-;101557:317;101483:398;101394:487;;;:::o;96133:308::-;96233:1;96217:18;;:4;:18;;;96213:88;;96286:1;96259:30;;;;;;;;;;;:::i;:::-;;;;;;;;96213:88;96329:1;96315:16;;:2;:16;;;96311:88;;96384:1;96355:32;;;;;;;;;;;:::i;:::-;;;;;;;;96311:88;96409:24;96417:4;96423:2;96427:5;96409:7;:24::i;:::-;96133:308;;;:::o;112322:111::-;112375:7;112402:23;:21;:23::i;:::-;112395:30;;112322:111;:::o;60011:174::-;60069:30;60146:21;60136:31;;60011:174;:::o;91711:149::-;58153:20;:18;:20::i;:::-;91814:38:::1;91837:5;91844:7;91814:22;:38::i;:::-;91711:149:::0;;:::o;73609:129::-;58153:20;:18;:20::i;:::-;73692:38:::1;73717:12;73692:24;:38::i;:::-;73609:129:::0;:::o;118576:127::-;58153:20;:18;:20::i;:::-;118661:34:::1;118685:4;118661:34;;;;;;;;;;;;;;;;::::0;:23:::1;:34::i;:::-;118576:127:::0;:::o;104716:68::-;58153:20;:18;:20::i;:::-;104716:68::o;98317:213::-;98407:1;98388:21;;:7;:21;;;98384:93;;98462:1;98433:32;;;;;;;;;;;:::i;:::-;;;;;;;;98384:93;98487:35;98503:1;98507:7;98516:5;98487:7;:35::i;:::-;98317:213;;:::o;130029:343::-;130157:21;130181:30;130203:7;130181:21;:30::i;:::-;130157:54;;130242:7;130226:13;:23;130222:65;;;130258:29;;;;;;;;;;;;;;130222:65;130298:34;130315:7;130324;130298:16;:34::i;:::-;130343:21;130349:5;130356:7;130343:5;:21::i;:::-;130146:226;130029:343;;;:::o;106384:319::-;106475:6;106458:23;;106466:4;106458:23;;;:121;;;;106573:6;106537:42;;:32;:30;:32::i;:::-;:42;;;;106458:121;106440:256;;;106655:29;;;;;;;;;;;;;;106440:256;106384:319::o;130402:100::-;74111:13;:11;:13::i;:::-;130402:100;:::o;107877:548::-;107995:17;107977:50;;;:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;107973:445;;108388:17;108346:60;;;;;;;;;;;:::i;:::-;;;;;;;;107973:445;77076:66;108080:32;;108072:4;:40;108068:122;;108169:4;108140:34;;;;;;;;;;;:::i;:::-;;;;;;;;108068:122;108204:54;108234:17;108253:4;108204:29;:54::i;:::-;108030:240;107877:548;;:::o;106826:218::-;106910:6;106893:23;;106901:4;106893:23;;;106889:148;;106996:29;;;;;;;;;;;;;;106889:148;106826:218::o;128533:735::-;128711:14;128747:13;128738:22;;128785:9;128775:6;:19;128771:490;128811:13;128771:490;128872:15;120315:6;128846:10;:22;;;;:::i;:::-;:41;128842:419;;128913:9;128904:18;;128842:419;;;128969:15;120315:6;128944:10;:22;;;;:::i;:::-;:40;128940:321;;;129001:19;129041:10;129023:15;:28;;;;:::i;:::-;129001:50;;129066:24;129117:14;129103:11;:28;;;;:::i;:::-;129093:6;:39;;;;:::i;:::-;129066:66;;129175:9;129156:16;:28;:93;;129233:16;129156:93;;;129204:9;129156:93;129147:102;;128986:275;;128940:321;128842:419;128533:735;;;;;;;:::o;74450:166::-;74521:12;:10;:12::i;:::-;74510:23;;:7;:5;:7::i;:::-;:23;;;74506:103;;74584:12;:10;:12::i;:::-;74557:40;;;;;;;;;;;:::i;:::-;;;;;;;;74506:103;74450:166::o;88890:226::-;88973:29;89005:25;:23;:25::i;:::-;88973:57;;89048:1;:15;;;89041:22;;;;;;;;;;;89074:34;89099:8;89074:24;:34::i;:::-;88962:154;88890:226;:::o;67623:167::-;67683:7;67703:23;67729:19;:17;:19::i;:::-;67703:45;;67766:1;:9;;:16;67776:5;67766:16;;;;;;;;;;;;;;;;67759:23;;;67623:167;;;:::o;110992:160::-;111043:23;111113:21;111103:31;;110992:160;:::o;114673:158::-;114727:13;114753:23;114779:19;:17;:19::i;:::-;114753:45;;114816:1;:7;;114809:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;114673:158;:::o;115066:164::-;115123:13;115149:23;115175:19;:17;:19::i;:::-;115149:45;;115212:1;:10;;115205:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;115066:164;:::o;72933:163::-;72985:24;73056:22;73046:32;;72933:163;:::o;129477:343::-;129605:21;129629:30;129651:7;129629:21;:30::i;:::-;129605:54;;129690:7;129674:13;:23;129670:65;;;129706:29;;;;;;;;;;;;;;129670:65;129746:34;129763:7;129772;129746:16;:34::i;:::-;129791:21;129797:5;129804:7;129791:5;:21::i;:::-;129594:226;129477:343;;;:::o;125977:582::-;126058:17;126078:7;:16;126086:7;126078:16;;;;;;;;;;;;;;;:29;;:38;;;126058:58;;126127:21;126151:30;126173:7;126151:21;:30::i;:::-;126127:54;;126233:6;126192:7;:16;126200:7;126192:16;;;;;;;;;;;;;;;:29;;:38;;:47;;;;126297:109;126337:6;126358:9;126382:13;126297:25;:109::i;:::-;126252:7;:16;126260:7;126252:16;;;;;;;;;;;;;;;:29;;:42;;:154;;;;120315:6;126465;:18;;;;:::i;:::-;126419:7;:16;126427:7;126419:16;;;;;;;;;;;;;;;:29;;:43;;:64;;;;126536:15;126494:7;:16;126502:7;126494:16;;;;;;;;;;;;;;;:29;;:39;;:57;;;;126047:512;;125977:582;;:::o;126825:::-;126906:17;126926:7;:16;126934:7;126926:16;;;;;;;;;;;;;;;:29;;:38;;;126906:58;;126975:21;126999:30;127021:7;126999:21;:30::i;:::-;126975:54;;127081:6;127040:7;:16;127048:7;127040:16;;;;;;;;;;;;;;;:29;;:38;;:47;;;;127145:109;127185:6;127206:9;127230:13;127145:25;:109::i;:::-;127100:7;:16;127108:7;127100:16;;;;;;;;;;;;;;;:29;;:42;;:154;;;;120315:6;127313;:18;;;;:::i;:::-;127267:7;:16;127275:7;127267:16;;;;;;;;;;;;;;;:29;;:43;;:64;;;;127384:15;127342:7;:16;127350:7;127342:16;;;;;;;;;;;;;;;:29;;:39;;:57;;;;126895:512;;126825:582;;:::o;67911:460::-;67971:7;67991:23;68017:19;:17;:19::i;:::-;67991:45;;68334:1;:9;;:16;68344:5;68334:16;;;;;;;;;;;;;;;;:18;;;;;;;;;;;;68327:25;;;67911:460;;;:::o;113276:178::-;113353:7;113380:66;113413:20;:18;:20::i;:::-;113435:10;113380:32;:66::i;:::-;113373:73;;113276:178;;;:::o;33223:264::-;33308:7;33329:17;33348:18;33368:16;33388:25;33399:4;33405:1;33408;33411;33388:10;:25::i;:::-;33328:85;;;;;;33424:28;33436:5;33443:8;33424:11;:28::i;:::-;33470:9;33463:16;;;;;33223:264;;;;;;:::o;87570:178::-;87627:29;87703:27;87693:37;;87570:178;:::o;100603:499::-;100712:22;100737:18;:16;:18::i;:::-;100712:43;;100787:1;100770:19;;:5;:19;;;100766:91;;100842:1;100813:32;;;;;;;;;;;:::i;:::-;;;;;;;;100766:91;100890:1;100871:21;;:7;:21;;;100867:92;;100944:1;100916:31;;;;;;;;;;;:::i;:::-;;;;;;;;100867:92;101001:5;100969:1;:13;;:20;100983:5;100969:20;;;;;;;;;;;;;;;:29;100990:7;100969:29;;;;;;;;;;;;;;;:37;;;;101021:9;101017:78;;;101068:7;101052:31;;101061:5;101052:31;;;101077:5;101052:31;;;;;;:::i;:::-;;;;;;;;101017:78;100701:401;100603:499;;;;:::o;96765:1199::-;96851:22;96876:18;:16;:18::i;:::-;96851:43;;96925:1;96909:18;;:4;:18;;;96905:558;;97065:5;97047:1;:14;;;:23;;;;;;;:::i;:::-;;;;;;;;96905:558;;;97103:19;97125:1;:11;;:17;97137:4;97125:17;;;;;;;;;;;;;;;;97103:39;;97175:5;97161:11;:19;97157:117;;;97233:4;97239:11;97252:5;97208:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;97157:117;97431:5;97417:11;:19;97397:1;:11;;:17;97409:4;97397:17;;;;;;;;;;;;;;;:39;;;;97088:375;96905:558;97493:1;97479:16;;:2;:16;;;97475:439;;97663:5;97645:1;:14;;;:23;;;;;;;;;;;97475:439;;;97882:5;97863:1;:11;;:15;97875:2;97863:15;;;;;;;;;;;;;;;;:24;;;;;;;;;;;97475:439;97946:2;97931:25;;97940:4;97931:25;;;97950:5;97931:25;;;;;;:::i;:::-;;;;;;;;96840:1124;96765:1199;;;:::o;112441:193::-;112496:7;110329:95;112555:17;:15;:17::i;:::-;112574:20;:18;:20::i;:::-;112596:13;112619:4;112533:92;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;112523:103;;;;;;112516:110;;112441:193;:::o;58313:145::-;58381:17;:15;:17::i;:::-;58376:75;;58422:17;;;;;;;;;;;;;;58376:75;58313:145::o;91868:220::-;58153:20;:18;:20::i;:::-;91981:22:::1;92006:18;:16;:18::i;:::-;91981:43;;92045:5;92035:1;:7;;:15;;;;;;:::i;:::-;;92073:7;92061:1;:9;;:19;;;;;;:::i;:::-;;91970:118;91868:220:::0;;:::o;73746:240::-;58153:20;:18;:20::i;:::-;73867:1:::1;73843:26;;:12;:26;;::::0;73839:97:::1;;73921:1;73893:31;;;;;;;;;;;:::i;:::-;;;;;;;;73839:97;73946:32;73965:12;73946:18;:32::i;:::-;73746:240:::0;:::o;111893:338::-;58153:20;:18;:20::i;:::-;112006:23:::1;112032:19;:17;:19::i;:::-;112006:45;;112072:4;112062:1;:7;;:14;;;;;;:::i;:::-;;112100:7;112087:1;:10;;:20;;;;;;:::i;:::-;;112191:1;112175:17:::0;::::1;:1;:13;;:17;;;;112222:1;112203:20:::0;::::1;:1;:16;;:20;;;;111995:236;111893:338:::0;;:::o;124945:289::-;125025:21;125049:30;125071:7;125049:21;:30::i;:::-;125025:54;;125132:15;125090:7;:16;125098:7;125090:16;;;;;;;;;;;;;;;:29;;:39;;:57;;;;125219:7;125203:13;:23;;;;:::i;:::-;125158:7;:16;125166:7;125158:16;;;;;;;;;;;;;;;:29;;:42;;:68;;;;125014:220;124945:289;;:::o;77731:140::-;77783:7;77810:47;77076:66;77837:19;;77810:26;:47::i;:::-;:53;;;;;;;;;;;;77803:60;;77731:140;:::o;78574:344::-;78666:37;78685:17;78666:18;:37::i;:::-;78728:17;78719:27;;;;;;;;;;;;78777:1;78763:4;:11;:15;78759:152;;;78795:53;78824:17;78843:4;78795:28;:53::i;:::-;;78759:152;;;78881:18;:16;:18::i;:::-;78759:152;78574:344;;:::o;75598:253::-;75672:24;75699:20;:18;:20::i;:::-;75672:47;;75730:16;75749:1;:8;;;;;;;;;;;;75730:27;;75779:8;75768:1;:8;;;:19;;;;;;;;;;;;;;;;;;75834:8;75803:40;;75824:8;75803:40;;;;;;;;;;;;75661:190;;75598:253;:::o;67236:160::-;67287:23;67357:21;67347:31;;67236:160;:::o;125422:289::-;125502:21;125526:30;125548:7;125526:21;:30::i;:::-;125502:54;;125609:15;125567:7;:16;125575:7;125567:16;;;;;;;;;;;;;;;:29;;:39;;:57;;;;125696:7;125680:13;:23;;;;:::i;:::-;125635:7;:16;125643:7;125635:16;;;;;;;;;;;;;;;:29;;:42;;:68;;;;125491:220;125422:289;;:::o;98858:211::-;98948:1;98929:21;;:7;:21;;;98925:91;;99001:1;98974:30;;;;;;;;;;;:::i;:::-;;;;;;;;98925:91;99026:35;99034:7;99051:1;99055:5;99026:7;:35::i;:::-;98858:211;;:::o;127660:564::-;127810:24;127847:19;127895:6;127883:9;:18;127879:338;;;127944:6;127932:9;:18;;;;:::i;:::-;127918:32;;128000:11;127984:13;:27;:95;;128078:1;127984:95;;;128047:11;128031:13;:27;;;;:::i;:::-;127984:95;127965:114;;127879:338;;;128135:9;128126:6;:18;;;;:::i;:::-;128112:32;;128194:11;128178:13;:27;;;;:::i;:::-;128159:46;;127879:338;127836:388;127660:564;;;;;:::o;86038:410::-;86131:14;86243:4;86237:11;86274:10;86269:3;86262:23;86322:15;86315:4;86310:3;86306:14;86299:39;86375:10;86368:4;86363:3;86359:14;86352:34;86425:4;86420:3;86410:20;86400:30;;86211:230;86038:410;;;;:::o;31528:1556::-;31659:7;31668:12;31682:7;32602:66;32597:1;32589:10;;:79;32585:166;;;32701:1;32705:30;32737:1;32685:54;;;;;;;;32585:166;32848:14;32865:24;32875:4;32881:1;32884;32887;32865:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32848:41;;32922:1;32904:20;;:6;:20;;;32900:115;;32957:1;32961:29;33000:1;32992:10;;32941:62;;;;;;;;;32900:115;33035:6;33043:20;33073:1;33065:10;;33027:49;;;;;;;31528:1556;;;;;;;;;:::o;33625:542::-;33721:20;33712:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;33708:452;33758:7;33708:452;33819:29;33810:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;33806:354;;33872:23;;;;;;;;;;;;;;33806:354;33926:35;33917:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;33913:247;;34021:8;34013:17;;33985:46;;;;;;;;;;;:::i;:::-;;;;;;;;33913:247;34062:30;34053:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;34049:111;;34139:8;34116:32;;;;;;;;;;;:::i;:::-;;;;;;;;34049:111;33625:542;;;:::o;115452:702::-;115502:7;115522:23;115548:19;:17;:19::i;:::-;115522:45;;115578:18;115599:13;:11;:13::i;:::-;115578:34;;115648:1;115633:4;115627:18;:22;115623:524;;;115689:4;115673:22;;;;;;115666:29;;;;;;115623:524;115953:18;115974:1;:13;;;115953:34;;116020:1;116006:15;;:10;:15;116002:134;;116049:10;116042:17;;;;;;;116002:134;116107:13;116100:20;;;;;115452:702;;:::o;116382:738::-;116435:7;116455:23;116481:19;:17;:19::i;:::-;116455:45;;116511:21;116535:16;:14;:16::i;:::-;116511:40;;116590:1;116572:7;116566:21;:25;116562:551;;;116631:7;116615:25;;;;;;116608:32;;;;;;116562:551;116907:21;116931:1;:16;;;116907:40;;116983:1;116966:18;;:13;:18;116962:140;;117012:13;117005:20;;;;;;;116962:140;117073:13;117066:20;;;;;116382:738;;:::o;59753:122::-;59803:4;59827:26;:24;:26::i;:::-;:40;;;;;;;;;;;;59820:47;;59753:122;:::o;23930:195::-;23991:21;24103:4;24093:14;;23930:195;;;:::o;77967:286::-;78078:1;78045:17;:29;;;:34;78041:121;;78132:17;78103:47;;;;;;;;;;;:::i;:::-;;;;;;;;78041:121;78228:17;78172:47;77076:66;78199:19;;78172:26;:47::i;:::-;:53;;;:73;;;;;;;;;;;;;;;;;;77967:286;:::o;19970:256::-;20053:12;20079;20093:23;20120:6;:19;;20140:4;20120:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20078:67;;;;20163:55;20190:6;20198:7;20207:10;20163:26;:55::i;:::-;20156:62;;;;19970:256;;;;:::o;82498:126::-;82561:1;82549:9;:13;82545:72;;;82586:19;;;;;;;;;;;;;;82545:72;82498:126::o;20499:597::-;20647:12;20677:7;20672:417;;20701:19;20709:10;20701:7;:19::i;:::-;20672:417;;;20950:1;20929:10;:17;:22;:49;;;;;20977:1;20955:6;:18;;;:23;20929:49;20925:121;;;21023:6;21006:24;;;;;;;;;;;:::i;:::-;;;;;;;;20925:121;21067:10;21060:17;;;;20672:417;20499:597;;;;;;:::o;21649:528::-;21802:1;21782:10;:17;:21;21778:392;;;22014:10;22008:17;22071:15;22058:10;22054:2;22050:19;22043:44;21778:392;22141:17;;;;;;;;;;;;;;7:99:1;59:6;93:5;87:12;77:22;;7:99;;;:::o;112:169::-;196:11;230:6;225:3;218:19;270:4;265:3;261:14;246:29;;112:169;;;;:::o;287:246::-;368:1;378:113;392:6;389:1;386:13;378:113;;;477:1;472:3;468:11;462:18;458:1;453:3;449:11;442:39;414:2;411:1;407:10;402:15;;378:113;;;525:1;516:6;511:3;507:16;500:27;349:184;287:246;;;:::o;539:102::-;580:6;631:2;627:7;622:2;615:5;611:14;607:28;597:38;;539:102;;;:::o;647:377::-;735:3;763:39;796:5;763:39;:::i;:::-;818:71;882:6;877:3;818:71;:::i;:::-;811:78;;898:65;956:6;951:3;944:4;937:5;933:16;898:65;:::i;:::-;988:29;1010:6;988:29;:::i;:::-;983:3;979:39;972:46;;739:285;647:377;;;;:::o;1030:313::-;1143:4;1181:2;1170:9;1166:18;1158:26;;1230:9;1224:4;1220:20;1216:1;1205:9;1201:17;1194:47;1258:78;1331:4;1322:6;1258:78;:::i;:::-;1250:86;;1030:313;;;;:::o;1349:75::-;1382:6;1415:2;1409:9;1399:19;;1349:75;:::o;1430:117::-;1539:1;1536;1529:12;1553:117;1662:1;1659;1652:12;1676:126;1713:7;1753:42;1746:5;1742:54;1731:65;;1676:126;;;:::o;1808:96::-;1845:7;1874:24;1892:5;1874:24;:::i;:::-;1863:35;;1808:96;;;:::o;1910:122::-;1983:24;2001:5;1983:24;:::i;:::-;1976:5;1973:35;1963:63;;2022:1;2019;2012:12;1963:63;1910:122;:::o;2038:139::-;2084:5;2122:6;2109:20;2100:29;;2138:33;2165:5;2138:33;:::i;:::-;2038:139;;;;:::o;2183:77::-;2220:7;2249:5;2238:16;;2183:77;;;:::o;2266:122::-;2339:24;2357:5;2339:24;:::i;:::-;2332:5;2329:35;2319:63;;2378:1;2375;2368:12;2319:63;2266:122;:::o;2394:139::-;2440:5;2478:6;2465:20;2456:29;;2494:33;2521:5;2494:33;:::i;:::-;2394:139;;;;:::o;2539:474::-;2607:6;2615;2664:2;2652:9;2643:7;2639:23;2635:32;2632:119;;;2670:79;;:::i;:::-;2632:119;2790:1;2815:53;2860:7;2851:6;2840:9;2836:22;2815:53;:::i;:::-;2805:63;;2761:117;2917:2;2943:53;2988:7;2979:6;2968:9;2964:22;2943:53;:::i;:::-;2933:63;;2888:118;2539:474;;;;;:::o;3019:90::-;3053:7;3096:5;3089:13;3082:21;3071:32;;3019:90;;;:::o;3115:109::-;3196:21;3211:5;3196:21;:::i;:::-;3191:3;3184:34;3115:109;;:::o;3230:210::-;3317:4;3355:2;3344:9;3340:18;3332:26;;3368:65;3430:1;3419:9;3415:17;3406:6;3368:65;:::i;:::-;3230:210;;;;:::o;3446:329::-;3505:6;3554:2;3542:9;3533:7;3529:23;3525:32;3522:119;;;3560:79;;:::i;:::-;3522:119;3680:1;3705:53;3750:7;3741:6;3730:9;3726:22;3705:53;:::i;:::-;3695:63;;3651:117;3446:329;;;;:::o;3781:118::-;3868:24;3886:5;3868:24;:::i;:::-;3863:3;3856:37;3781:118;;:::o;3905:222::-;3998:4;4036:2;4025:9;4021:18;4013:26;;4049:71;4117:1;4106:9;4102:17;4093:6;4049:71;:::i;:::-;3905:222;;;;:::o;4133:619::-;4210:6;4218;4226;4275:2;4263:9;4254:7;4250:23;4246:32;4243:119;;;4281:79;;:::i;:::-;4243:119;4401:1;4426:53;4471:7;4462:6;4451:9;4447:22;4426:53;:::i;:::-;4416:63;;4372:117;4528:2;4554:53;4599:7;4590:6;4579:9;4575:22;4554:53;:::i;:::-;4544:63;;4499:118;4656:2;4682:53;4727:7;4718:6;4707:9;4703:22;4682:53;:::i;:::-;4672:63;;4627:118;4133:619;;;;;:::o;4758:86::-;4793:7;4833:4;4826:5;4822:16;4811:27;;4758:86;;;:::o;4850:112::-;4933:22;4949:5;4933:22;:::i;:::-;4928:3;4921:35;4850:112;;:::o;4968:214::-;5057:4;5095:2;5084:9;5080:18;5072:26;;5108:67;5172:1;5161:9;5157:17;5148:6;5108:67;:::i;:::-;4968:214;;;;:::o;5188:77::-;5225:7;5254:5;5243:16;;5188:77;;;:::o;5271:118::-;5358:24;5376:5;5358:24;:::i;:::-;5353:3;5346:37;5271:118;;:::o;5395:222::-;5488:4;5526:2;5515:9;5511:18;5503:26;;5539:71;5607:1;5596:9;5592:17;5583:6;5539:71;:::i;:::-;5395:222;;;;:::o;5623:116::-;5693:21;5708:5;5693:21;:::i;:::-;5686:5;5683:32;5673:60;;5729:1;5726;5719:12;5673:60;5623:116;:::o;5745:133::-;5788:5;5826:6;5813:20;5804:29;;5842:30;5866:5;5842:30;:::i;:::-;5745:133;;;;:::o;5884:468::-;5949:6;5957;6006:2;5994:9;5985:7;5981:23;5977:32;5974:119;;;6012:79;;:::i;:::-;5974:119;6132:1;6157:53;6202:7;6193:6;6182:9;6178:22;6157:53;:::i;:::-;6147:63;;6103:117;6259:2;6285:50;6327:7;6318:6;6307:9;6303:22;6285:50;:::i;:::-;6275:60;;6230:115;5884:468;;;;;:::o;6358:117::-;6467:1;6464;6457:12;6481:117;6590:1;6587;6580:12;6604:180;6652:77;6649:1;6642:88;6749:4;6746:1;6739:15;6773:4;6770:1;6763:15;6790:281;6873:27;6895:4;6873:27;:::i;:::-;6865:6;6861:40;7003:6;6991:10;6988:22;6967:18;6955:10;6952:34;6949:62;6946:88;;;7014:18;;:::i;:::-;6946:88;7054:10;7050:2;7043:22;6833:238;6790:281;;:::o;7077:129::-;7111:6;7138:20;;:::i;:::-;7128:30;;7167:33;7195:4;7187:6;7167:33;:::i;:::-;7077:129;;;:::o;7212:307::-;7273:4;7363:18;7355:6;7352:30;7349:56;;;7385:18;;:::i;:::-;7349:56;7423:29;7445:6;7423:29;:::i;:::-;7415:37;;7507:4;7501;7497:15;7489:23;;7212:307;;;:::o;7525:146::-;7622:6;7617:3;7612;7599:30;7663:1;7654:6;7649:3;7645:16;7638:27;7525:146;;;:::o;7677:423::-;7754:5;7779:65;7795:48;7836:6;7795:48;:::i;:::-;7779:65;:::i;:::-;7770:74;;7867:6;7860:5;7853:21;7905:4;7898:5;7894:16;7943:3;7934:6;7929:3;7925:16;7922:25;7919:112;;;7950:79;;:::i;:::-;7919:112;8040:54;8087:6;8082:3;8077;8040:54;:::i;:::-;7760:340;7677:423;;;;;:::o;8119:338::-;8174:5;8223:3;8216:4;8208:6;8204:17;8200:27;8190:122;;8231:79;;:::i;:::-;8190:122;8348:6;8335:20;8373:78;8447:3;8439:6;8432:4;8424:6;8420:17;8373:78;:::i;:::-;8364:87;;8180:277;8119:338;;;;:::o;8463:652::-;8540:6;8548;8597:2;8585:9;8576:7;8572:23;8568:32;8565:119;;;8603:79;;:::i;:::-;8565:119;8723:1;8748:53;8793:7;8784:6;8773:9;8769:22;8748:53;:::i;:::-;8738:63;;8694:117;8878:2;8867:9;8863:18;8850:32;8909:18;8901:6;8898:30;8895:117;;;8931:79;;:::i;:::-;8895:117;9036:62;9090:7;9081:6;9070:9;9066:22;9036:62;:::i;:::-;9026:72;;8821:287;8463:652;;;;;:::o;9121:149::-;9157:7;9197:66;9190:5;9186:78;9175:89;;9121:149;;;:::o;9276:115::-;9361:23;9378:5;9361:23;:::i;:::-;9356:3;9349:36;9276:115;;:::o;9397:118::-;9484:24;9502:5;9484:24;:::i;:::-;9479:3;9472:37;9397:118;;:::o;9521:114::-;9588:6;9622:5;9616:12;9606:22;;9521:114;;;:::o;9641:184::-;9740:11;9774:6;9769:3;9762:19;9814:4;9809:3;9805:14;9790:29;;9641:184;;;;:::o;9831:132::-;9898:4;9921:3;9913:11;;9951:4;9946:3;9942:14;9934:22;;9831:132;;;:::o;9969:108::-;10046:24;10064:5;10046:24;:::i;:::-;10041:3;10034:37;9969:108;;:::o;10083:179::-;10152:10;10173:46;10215:3;10207:6;10173:46;:::i;:::-;10251:4;10246:3;10242:14;10228:28;;10083:179;;;;:::o;10268:113::-;10338:4;10370;10365:3;10361:14;10353:22;;10268:113;;;:::o;10417:732::-;10536:3;10565:54;10613:5;10565:54;:::i;:::-;10635:86;10714:6;10709:3;10635:86;:::i;:::-;10628:93;;10745:56;10795:5;10745:56;:::i;:::-;10824:7;10855:1;10840:284;10865:6;10862:1;10859:13;10840:284;;;10941:6;10935:13;10968:63;11027:3;11012:13;10968:63;:::i;:::-;10961:70;;11054:60;11107:6;11054:60;:::i;:::-;11044:70;;10900:224;10887:1;10884;10880:9;10875:14;;10840:284;;;10844:14;11140:3;11133:10;;10541:608;;;10417:732;;;;:::o;11155:1215::-;11504:4;11542:3;11531:9;11527:19;11519:27;;11556:69;11622:1;11611:9;11607:17;11598:6;11556:69;:::i;:::-;11672:9;11666:4;11662:20;11657:2;11646:9;11642:18;11635:48;11700:78;11773:4;11764:6;11700:78;:::i;:::-;11692:86;;11825:9;11819:4;11815:20;11810:2;11799:9;11795:18;11788:48;11853:78;11926:4;11917:6;11853:78;:::i;:::-;11845:86;;11941:72;12009:2;11998:9;11994:18;11985:6;11941:72;:::i;:::-;12023:73;12091:3;12080:9;12076:19;12067:6;12023:73;:::i;:::-;12106;12174:3;12163:9;12159:19;12150:6;12106:73;:::i;:::-;12227:9;12221:4;12217:20;12211:3;12200:9;12196:19;12189:49;12255:108;12358:4;12349:6;12255:108;:::i;:::-;12247:116;;11155:1215;;;;;;;;;;:::o;12376:222::-;12469:4;12507:2;12496:9;12492:18;12484:26;;12520:71;12588:1;12577:9;12573:17;12564:6;12520:71;:::i;:::-;12376:222;;;;:::o;12604:619::-;12681:6;12689;12697;12746:2;12734:9;12725:7;12721:23;12717:32;12714:119;;;12752:79;;:::i;:::-;12714:119;12872:1;12897:53;12942:7;12933:6;12922:9;12918:22;12897:53;:::i;:::-;12887:63;;12843:117;12999:2;13025:53;13070:7;13061:6;13050:9;13046:22;13025:53;:::i;:::-;13015:63;;12970:118;13127:2;13153:53;13198:7;13189:6;13178:9;13174:22;13153:53;:::i;:::-;13143:63;;13098:118;12604:619;;;;;:::o;13303:899::-;13468:4;13463:3;13459:14;13560:4;13553:5;13549:16;13543:23;13579:63;13636:4;13631:3;13627:14;13613:12;13579:63;:::i;:::-;13483:169;13743:4;13736:5;13732:16;13726:23;13762:63;13819:4;13814:3;13810:14;13796:12;13762:63;:::i;:::-;13662:173;13921:4;13914:5;13910:16;13904:23;13940:63;13997:4;13992:3;13988:14;13974:12;13940:63;:::i;:::-;13845:168;14103:4;14096:5;14092:16;14086:23;14122:63;14179:4;14174:3;14170:14;14156:12;14122:63;:::i;:::-;14023:172;13437:765;13303:899;;:::o;14208:606::-;14465:4;14503:3;14492:9;14488:19;14480:27;;14517:139;14653:1;14642:9;14638:17;14629:6;14517:139;:::i;:::-;14666:141;14802:3;14791:9;14787:19;14778:6;14666:141;:::i;:::-;14208:606;;;;;:::o;14820:118::-;14891:22;14907:5;14891:22;:::i;:::-;14884:5;14881:33;14871:61;;14928:1;14925;14918:12;14871:61;14820:118;:::o;14944:135::-;14988:5;15026:6;15013:20;15004:29;;15042:31;15067:5;15042:31;:::i;:::-;14944:135;;;;:::o;15085:122::-;15158:24;15176:5;15158:24;:::i;:::-;15151:5;15148:35;15138:63;;15197:1;15194;15187:12;15138:63;15085:122;:::o;15213:139::-;15259:5;15297:6;15284:20;15275:29;;15313:33;15340:5;15313:33;:::i;:::-;15213:139;;;;:::o;15358:1199::-;15469:6;15477;15485;15493;15501;15509;15517;15566:3;15554:9;15545:7;15541:23;15537:33;15534:120;;;15573:79;;:::i;:::-;15534:120;15693:1;15718:53;15763:7;15754:6;15743:9;15739:22;15718:53;:::i;:::-;15708:63;;15664:117;15820:2;15846:53;15891:7;15882:6;15871:9;15867:22;15846:53;:::i;:::-;15836:63;;15791:118;15948:2;15974:53;16019:7;16010:6;15999:9;15995:22;15974:53;:::i;:::-;15964:63;;15919:118;16076:2;16102:53;16147:7;16138:6;16127:9;16123:22;16102:53;:::i;:::-;16092:63;;16047:118;16204:3;16231:51;16274:7;16265:6;16254:9;16250:22;16231:51;:::i;:::-;16221:61;;16175:117;16331:3;16358:53;16403:7;16394:6;16383:9;16379:22;16358:53;:::i;:::-;16348:63;;16302:119;16460:3;16487:53;16532:7;16523:6;16512:9;16508:22;16487:53;:::i;:::-;16477:63;;16431:119;15358:1199;;;;;;;;;;:::o;16563:474::-;16631:6;16639;16688:2;16676:9;16667:7;16663:23;16659:32;16656:119;;;16694:79;;:::i;:::-;16656:119;16814:1;16839:53;16884:7;16875:6;16864:9;16860:22;16839:53;:::i;:::-;16829:63;;16785:117;16941:2;16967:53;17012:7;17003:6;16992:9;16988:22;16967:53;:::i;:::-;16957:63;;16912:118;16563:474;;;;;:::o;17043:180::-;17091:77;17088:1;17081:88;17188:4;17185:1;17178:15;17212:4;17209:1;17202:15;17229:320;17273:6;17310:1;17304:4;17300:12;17290:22;;17357:1;17351:4;17347:12;17378:18;17368:81;;17434:4;17426:6;17422:17;17412:27;;17368:81;17496:2;17488:6;17485:14;17465:18;17462:38;17459:84;;17515:18;;:::i;:::-;17459:84;17280:269;17229:320;;;:::o;17555:180::-;17603:77;17600:1;17593:88;17700:4;17697:1;17690:15;17724:4;17721:1;17714:15;17741:102;17783:8;17830:5;17827:1;17823:13;17802:34;;17741:102;;;:::o;17849:848::-;17910:5;17917:4;17941:6;17932:15;;17965:5;17956:14;;17979:712;18000:1;17990:8;17987:15;17979:712;;;18095:4;18090:3;18086:14;18080:4;18077:24;18074:50;;;18104:18;;:::i;:::-;18074:50;18154:1;18144:8;18140:16;18137:451;;;18569:4;18562:5;18558:16;18549:25;;18137:451;18619:4;18613;18609:15;18601:23;;18649:32;18672:8;18649:32;:::i;:::-;18637:44;;17979:712;;;17849:848;;;;;;;:::o;18703:1073::-;18757:5;18948:8;18938:40;;18969:1;18960:10;;18971:5;;18938:40;18997:4;18987:36;;19014:1;19005:10;;19016:5;;18987:36;19083:4;19131:1;19126:27;;;;19167:1;19162:191;;;;19076:277;;19126:27;19144:1;19135:10;;19146:5;;;19162:191;19207:3;19197:8;19194:17;19191:43;;;19214:18;;:::i;:::-;19191:43;19263:8;19260:1;19256:16;19247:25;;19298:3;19291:5;19288:14;19285:40;;;19305:18;;:::i;:::-;19285:40;19338:5;;;19076:277;;19462:2;19452:8;19449:16;19443:3;19437:4;19434:13;19430:36;19412:2;19402:8;19399:16;19394:2;19388:4;19385:12;19381:35;19365:111;19362:246;;;19518:8;19512:4;19508:19;19499:28;;19553:3;19546:5;19543:14;19540:40;;;19560:18;;:::i;:::-;19540:40;19593:5;;19362:246;19633:42;19671:3;19661:8;19655:4;19652:1;19633:42;:::i;:::-;19618:57;;;;19707:4;19702:3;19698:14;19691:5;19688:25;19685:51;;;19716:18;;:::i;:::-;19685:51;19765:4;19758:5;19754:16;19745:25;;18703:1073;;;;;;:::o;19782:281::-;19840:5;19864:23;19882:4;19864:23;:::i;:::-;19856:31;;19908:25;19924:8;19908:25;:::i;:::-;19896:37;;19952:104;19989:66;19979:8;19973:4;19952:104;:::i;:::-;19943:113;;19782:281;;;;:::o;20069:410::-;20109:7;20132:20;20150:1;20132:20;:::i;:::-;20127:25;;20166:20;20184:1;20166:20;:::i;:::-;20161:25;;20221:1;20218;20214:9;20243:30;20261:11;20243:30;:::i;:::-;20232:41;;20422:1;20413:7;20409:15;20406:1;20403:22;20383:1;20376:9;20356:83;20333:139;;20452:18;;:::i;:::-;20333:139;20117:362;20069:410;;;;:::o;20485:85::-;20530:7;20559:5;20548:16;;20485:85;;;:::o;20576:101::-;20612:7;20652:18;20645:5;20641:30;20630:41;;20576:101;;;:::o;20683:60::-;20711:3;20732:5;20725:12;;20683:60;;;:::o;20749:156::-;20806:9;20839:60;20856:42;20865:32;20891:5;20865:32;:::i;:::-;20856:42;:::i;:::-;20839:60;:::i;:::-;20826:73;;20749:156;;;:::o;20911:145::-;21005:44;21043:5;21005:44;:::i;:::-;21000:3;20993:57;20911:145;;:::o;21062:236::-;21162:4;21200:2;21189:9;21185:18;21177:26;;21213:78;21288:1;21277:9;21273:17;21264:6;21213:78;:::i;:::-;21062:236;;;;:::o;21304:223::-;21444:34;21440:1;21432:6;21428:14;21421:58;21513:6;21508:2;21500:6;21496:15;21489:31;21304:223;:::o;21533:366::-;21675:3;21696:67;21760:2;21755:3;21696:67;:::i;:::-;21689:74;;21772:93;21861:3;21772:93;:::i;:::-;21890:2;21885:3;21881:12;21874:19;;21533:366;;;:::o;21905:419::-;22071:4;22109:2;22098:9;22094:18;22086:26;;22158:9;22152:4;22148:20;22144:1;22133:9;22129:17;22122:47;22186:131;22312:4;22186:131;:::i;:::-;22178:139;;21905:419;;;:::o;22330:171::-;22470:23;22466:1;22458:6;22454:14;22447:47;22330:171;:::o;22507:366::-;22649:3;22670:67;22734:2;22729:3;22670:67;:::i;:::-;22663:74;;22746:93;22835:3;22746:93;:::i;:::-;22864:2;22859:3;22855:12;22848:19;;22507:366;;;:::o;22879:419::-;23045:4;23083:2;23072:9;23068:18;23060:26;;23132:9;23126:4;23122:20;23118:1;23107:9;23103:17;23096:47;23160:131;23286:4;23160:131;:::i;:::-;23152:139;;22879:419;;;:::o;23304:180::-;23352:77;23349:1;23342:88;23449:4;23446:1;23439:15;23473:4;23470:1;23463:15;23490:185;23530:1;23547:20;23565:1;23547:20;:::i;:::-;23542:25;;23581:20;23599:1;23581:20;:::i;:::-;23576:25;;23620:1;23610:35;;23625:18;;:::i;:::-;23610:35;23667:1;23664;23660:9;23655:14;;23490:185;;;;:::o;23681:332::-;23802:4;23840:2;23829:9;23825:18;23817:26;;23853:71;23921:1;23910:9;23906:17;23897:6;23853:71;:::i;:::-;23934:72;24002:2;23991:9;23987:18;23978:6;23934:72;:::i;:::-;23681:332;;;;;:::o;24019:775::-;24252:4;24290:3;24279:9;24275:19;24267:27;;24304:71;24372:1;24361:9;24357:17;24348:6;24304:71;:::i;:::-;24385:72;24453:2;24442:9;24438:18;24429:6;24385:72;:::i;:::-;24467;24535:2;24524:9;24520:18;24511:6;24467:72;:::i;:::-;24549;24617:2;24606:9;24602:18;24593:6;24549:72;:::i;:::-;24631:73;24699:3;24688:9;24684:19;24675:6;24631:73;:::i;:::-;24714;24782:3;24771:9;24767:19;24758:6;24714:73;:::i;:::-;24019:775;;;;;;;;;:::o;24800:332::-;24921:4;24959:2;24948:9;24944:18;24936:26;;24972:71;25040:1;25029:9;25025:17;25016:6;24972:71;:::i;:::-;25053:72;25121:2;25110:9;25106:18;25097:6;25053:72;:::i;:::-;24800:332;;;;;:::o;25138:442::-;25287:4;25325:2;25314:9;25310:18;25302:26;;25338:71;25406:1;25395:9;25391:17;25382:6;25338:71;:::i;:::-;25419:72;25487:2;25476:9;25472:18;25463:6;25419:72;:::i;:::-;25501;25569:2;25558:9;25554:18;25545:6;25501:72;:::i;:::-;25138:442;;;;;;:::o;25586:143::-;25643:5;25674:6;25668:13;25659:22;;25690:33;25717:5;25690:33;:::i;:::-;25586:143;;;;:::o;25735:351::-;25805:6;25854:2;25842:9;25833:7;25829:23;25825:32;25822:119;;;25860:79;;:::i;:::-;25822:119;25980:1;26005:64;26061:7;26052:6;26041:9;26037:22;26005:64;:::i;:::-;25995:74;;25951:128;25735:351;;;;:::o;26092:191::-;26132:3;26151:20;26169:1;26151:20;:::i;:::-;26146:25;;26185:20;26203:1;26185:20;:::i;:::-;26180:25;;26228:1;26225;26221:9;26214:16;;26249:3;26246:1;26243:10;26240:36;;;26256:18;;:::i;:::-;26240:36;26092:191;;;;:::o;26289:194::-;26329:4;26349:20;26367:1;26349:20;:::i;:::-;26344:25;;26383:20;26401:1;26383:20;:::i;:::-;26378:25;;26427:1;26424;26420:9;26412:17;;26451:1;26445:4;26442:11;26439:37;;;26456:18;;:::i;:::-;26439:37;26289:194;;;;:::o;26489:664::-;26694:4;26732:3;26721:9;26717:19;26709:27;;26746:71;26814:1;26803:9;26799:17;26790:6;26746:71;:::i;:::-;26827:72;26895:2;26884:9;26880:18;26871:6;26827:72;:::i;:::-;26909;26977:2;26966:9;26962:18;26953:6;26909:72;:::i;:::-;26991;27059:2;27048:9;27044:18;27035:6;26991:72;:::i;:::-;27073:73;27141:3;27130:9;27126:19;27117:6;27073:73;:::i;:::-;26489:664;;;;;;;;:::o;27159:141::-;27208:4;27231:3;27223:11;;27254:3;27251:1;27244:14;27288:4;27285:1;27275:18;27267:26;;27159:141;;;:::o;27306:93::-;27343:6;27390:2;27385;27378:5;27374:14;27370:23;27360:33;;27306:93;;;:::o;27405:107::-;27449:8;27499:5;27493:4;27489:16;27468:37;;27405:107;;;;:::o;27518:393::-;27587:6;27637:1;27625:10;27621:18;27660:97;27690:66;27679:9;27660:97;:::i;:::-;27778:39;27808:8;27797:9;27778:39;:::i;:::-;27766:51;;27850:4;27846:9;27839:5;27835:21;27826:30;;27899:4;27889:8;27885:19;27878:5;27875:30;27865:40;;27594:317;;27518:393;;;;;:::o;27917:142::-;27967:9;28000:53;28018:34;28027:24;28045:5;28027:24;:::i;:::-;28018:34;:::i;:::-;28000:53;:::i;:::-;27987:66;;27917:142;;;:::o;28065:75::-;28108:3;28129:5;28122:12;;28065:75;;;:::o;28146:269::-;28256:39;28287:7;28256:39;:::i;:::-;28317:91;28366:41;28390:16;28366:41;:::i;:::-;28358:6;28351:4;28345:11;28317:91;:::i;:::-;28311:4;28304:105;28222:193;28146:269;;;:::o;28421:73::-;28466:3;28421:73;:::o;28500:189::-;28577:32;;:::i;:::-;28618:65;28676:6;28668;28662:4;28618:65;:::i;:::-;28553:136;28500:189;;:::o;28695:186::-;28755:120;28772:3;28765:5;28762:14;28755:120;;;28826:39;28863:1;28856:5;28826:39;:::i;:::-;28799:1;28792:5;28788:13;28779:22;;28755:120;;;28695:186;;:::o;28887:543::-;28988:2;28983:3;28980:11;28977:446;;;29022:38;29054:5;29022:38;:::i;:::-;29106:29;29124:10;29106:29;:::i;:::-;29096:8;29092:44;29289:2;29277:10;29274:18;29271:49;;;29310:8;29295:23;;29271:49;29333:80;29389:22;29407:3;29389:22;:::i;:::-;29379:8;29375:37;29362:11;29333:80;:::i;:::-;28992:431;;28977:446;28887:543;;;:::o;29436:117::-;29490:8;29540:5;29534:4;29530:16;29509:37;;29436:117;;;;:::o;29559:169::-;29603:6;29636:51;29684:1;29680:6;29672:5;29669:1;29665:13;29636:51;:::i;:::-;29632:56;29717:4;29711;29707:15;29697:25;;29610:118;29559:169;;;;:::o;29733:295::-;29809:4;29955:29;29980:3;29974:4;29955:29;:::i;:::-;29947:37;;30017:3;30014:1;30010:11;30004:4;30001:21;29993:29;;29733:295;;;;:::o;30033:1395::-;30150:37;30183:3;30150:37;:::i;:::-;30252:18;30244:6;30241:30;30238:56;;;30274:18;;:::i;:::-;30238:56;30318:38;30350:4;30344:11;30318:38;:::i;:::-;30403:67;30463:6;30455;30449:4;30403:67;:::i;:::-;30497:1;30521:4;30508:17;;30553:2;30545:6;30542:14;30570:1;30565:618;;;;31227:1;31244:6;31241:77;;;31293:9;31288:3;31284:19;31278:26;31269:35;;31241:77;31344:67;31404:6;31397:5;31344:67;:::i;:::-;31338:4;31331:81;31200:222;30535:887;;30565:618;30617:4;30613:9;30605:6;30601:22;30651:37;30683:4;30651:37;:::i;:::-;30710:1;30724:208;30738:7;30735:1;30732:14;30724:208;;;30817:9;30812:3;30808:19;30802:26;30794:6;30787:42;30868:1;30860:6;30856:14;30846:24;;30915:2;30904:9;30900:18;30887:31;;30761:4;30758:1;30754:12;30749:17;;30724:208;;;30960:6;30951:7;30948:19;30945:179;;;31018:9;31013:3;31009:19;31003:26;31061:48;31103:4;31095:6;31091:17;31080:9;31061:48;:::i;:::-;31053:6;31046:64;30968:156;30945:179;31170:1;31166;31158:6;31154:14;31150:22;31144:4;31137:36;30572:611;;;30535:887;;30125:1303;;;30033:1395;;:::o;31434:545::-;31607:4;31645:3;31634:9;31630:19;31622:27;;31659:71;31727:1;31716:9;31712:17;31703:6;31659:71;:::i;:::-;31740:68;31804:2;31793:9;31789:18;31780:6;31740:68;:::i;:::-;31818:72;31886:2;31875:9;31871:18;31862:6;31818:72;:::i;:::-;31900;31968:2;31957:9;31953:18;31944:6;31900:72;:::i;:::-;31434:545;;;;;;;:::o;31985:180::-;32033:77;32030:1;32023:88;32130:4;32127:1;32120:15;32154:4;32151:1;32144:15;32171:98;32222:6;32256:5;32250:12;32240:22;;32171:98;;;:::o;32275:147::-;32376:11;32413:3;32398:18;;32275:147;;;;:::o;32428:386::-;32532:3;32560:38;32592:5;32560:38;:::i;:::-;32614:88;32695:6;32690:3;32614:88;:::i;:::-;32607:95;;32711:65;32769:6;32764:3;32757:4;32750:5;32746:16;32711:65;:::i;:::-;32801:6;32796:3;32792:16;32785:23;;32536:278;32428:386;;;;:::o;32820:271::-;32950:3;32972:93;33061:3;33052:6;32972:93;:::i;:::-;32965:100;;33082:3;33075:10;;32820:271;;;;:::o
Swarm Source
ipfs://0935dde0b8eed7acd071d68af03f7276dbc7b66eb2cc826938fba17e4e76a20c
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.