Overview
Max Total Supply
78,542,226.735366648590475194 FRAX
Holders
7,985 (0.00%)
Market
Price
$0.9956 @ 0.000249 frxETH (-0.03%)
Onchain Market Cap
$78,196,202.22
Circulating Supply Market Cap
$646,572,303.53
Other Info
Token Contract (WITH 18 Decimals)
Balance
1.638694637054901406 FRAXValue
$1.63 ( ~0.000407783034027927 frxETH) [0.0000%]Loading...
Loading
Loading...
Loading
Loading...
Loading
Contract Source Code Verified (Genesis Bytecode Match Only)
Contract Name:
Frax
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; import { ERC20PermitPermissionedOptiMintable } from "./ERC20PermitPermissionedOptiMintable.sol"; contract Frax is ERC20PermitPermissionedOptiMintable { /// @param _creator_address The contract creator /// @param _timelock_address The timelock /// @param _bridge Address of the L2 standard bridge /// @param _remoteToken Address of the corresponding L1 token constructor( address _creator_address, address _timelock_address, address _bridge, address _remoteToken ) ERC20PermitPermissionedOptiMintable(_creator_address, _timelock_address, _bridge, _remoteToken, "Frax", "FRAX") {} }
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import { IERC20 } from "@openzeppelin-5/contracts/token/ERC20/IERC20.sol"; import { ERC20Permit, ERC20 } from "@openzeppelin-5/contracts/token/ERC20/extensions/ERC20Permit.sol"; import { ERC20Burnable } from "@openzeppelin-5/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { IERC165 } from "@openzeppelin-5/contracts/utils/introspection/IERC165.sol"; import { ILegacyMintableERC20, IOptimismMintableERC20 } from "@eth-optimism/contracts-bedrock/src/universal/IOptimismMintableERC20.sol"; import { ISemver } from "@eth-optimism/contracts-bedrock/src/universal/ISemver.sol"; import { OwnedV2 } from "./OwnedV2.sol"; /// @title Parent contract for frxETH.sol, but also CrossChainCanonicalV2 /** * @notice Combines Openzeppelin's ERC20Permit and ERC20Burnable with Synthetix's Owned and Optimism's OptimismMintableERC20. * Also includes a list of authorized minters */ /// @dev ERC20PermitPermissionedOptiMintable adheres to EIP-712/EIP-2612 and can use permits contract ERC20PermitPermissionedOptiMintable is ERC20Permit, ERC20Burnable, OwnedV2, IOptimismMintableERC20, ILegacyMintableERC20, ISemver { /// @custom:semver 1.0.0 string public constant version = "1.0.0"; /// @notice The timelock address address public timelock_address; /// @notice Address of the L2 StandardBridge on this network. address public immutable BRIDGE; /// @notice Address of the corresponding version of this token on the remote chain. address public immutable REMOTE_TOKEN; /// @notice Array of the non-bridge minters address[] public minters_array; /// @notice Mapping of the non-bridge minters /// @dev Mapping is used for faster verification mapping(address => bool) public minters; /* ========== CONSTRUCTOR ========== */ /// @custom:semver 1.0.0 /// @param _creator_address The contract creator /// @param _timelock_address The timelock /// @param _bridge Address of the L2 standard bridge /// @param _remoteToken Address of the corresponding L1 token /// @param _name ERC20 name /// @param _symbol ERC20 symbol constructor( address _creator_address, address _timelock_address, address _bridge, address _remoteToken, string memory _name, string memory _symbol ) ERC20(_name, _symbol) ERC20Permit(_name) OwnedV2(_creator_address) { REMOTE_TOKEN = _remoteToken; BRIDGE = _bridge; timelock_address = _timelock_address; } /* ========== MODIFIERS ========== */ /// @notice A modifier that only allows the contract owner or the timelock to call modifier onlyByOwnGov() { require(msg.sender == timelock_address || msg.sender == owner, "Not owner or timelock"); _; } /// @notice A modifier that only allows a non-bridge minter to call modifier onlyMinters() { require(minters[msg.sender] == true, "Only minters"); _; } /// @notice A modifier that only allows the bridge to call modifier onlyBridge() { require(msg.sender == BRIDGE, "OptimismMintableERC20: only bridge can mint and burn"); _; } /* ========== LEGACY VIEWS ========== */ /// @custom:legacy /// @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward. /// @return address The L1 remote token address function l1Token() public view returns (address) { return REMOTE_TOKEN; } /// @custom:legacy /// @notice Legacy getter for the bridge. Use BRIDGE going forward. /// @return address The bridge address function l2Bridge() public view returns (address) { return BRIDGE; } /// @custom:legacy /// @notice Legacy getter for REMOTE_TOKEN /// @return address The L1 remote token address function remoteToken() public view returns (address) { return REMOTE_TOKEN; } /// @custom:legacy /// @notice Legacy getter for BRIDGE /// @return address The bridge address function bridge() public view returns (address) { return BRIDGE; } /// @notice ERC165 interface check function. /// @param _interfaceId Interface ID to check. /// @return Whether or not the interface is supported by this contract. function supportsInterface(bytes4 _interfaceId) external pure virtual returns (bool) { bytes4 iface1 = type(IERC165).interfaceId; // Interface corresponding to the legacy L2StandardERC20. bytes4 iface2 = type(ILegacyMintableERC20).interfaceId; // Interface corresponding to the updated OptimismMintableERC20 (this contract). bytes4 iface3 = type(IOptimismMintableERC20).interfaceId; return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3; } /* ========== RESTRICTED FUNCTIONS [BRIDGE] ========== */ /// @notice Allows the StandardBridge on this network to mint tokens. /// @param _to Address to mint tokens to. /// @param _amount Amount of tokens to mint. function mint( address _to, uint256 _amount ) external virtual override(IOptimismMintableERC20, ILegacyMintableERC20) onlyBridge { _mint(_to, _amount); emit Mint(_to, _amount); } /// @notice Allows the StandardBridge on this network to burn tokens. /// @param _from Address to burn tokens from. /// @param _amount Amount of tokens to burn. function burn( address _from, uint256 _amount ) external virtual override(IOptimismMintableERC20, ILegacyMintableERC20) onlyBridge { _burn(_from, _amount); emit Burn(_from, _amount); } /* ========== RESTRICTED FUNCTIONS [NON-BRIDGE MINTERS] ========== */ /// @notice Used by non-bridge minters to burn tokens /// @param b_address Address of the account to burn from /// @param b_amount Amount of tokens to burn function minter_burn_from(address b_address, uint256 b_amount) public onlyMinters { super.burnFrom(b_address, b_amount); emit TokenMinterBurned(b_address, msg.sender, b_amount); } /// @notice Used by non-bridge minters to mint new tokens /// @param m_address Address of the account to mint to /// @param m_amount Amount of tokens to mint function minter_mint(address m_address, uint256 m_amount) public onlyMinters { super._mint(m_address, m_amount); emit TokenMinterMinted(msg.sender, m_address, m_amount); } /// @notice Adds a non-bridge minter /// @param minter_address Address of minter to add function addMinter(address minter_address) public onlyByOwnGov { require(minter_address != address(0), "Zero address detected"); require(minters[minter_address] == false, "Address already exists"); minters[minter_address] = true; minters_array.push(minter_address); emit MinterAdded(minter_address); } /// @notice Removes a non-bridge minter /// @param minter_address Address of minter to remove function removeMinter(address minter_address) public onlyByOwnGov { require(minter_address != address(0), "Zero address detected"); require(minters[minter_address] == true, "Address nonexistant"); // Delete from the mapping delete minters[minter_address]; // 'Delete' from the array by setting the address to 0x0 for (uint256 i = 0; i < minters_array.length; i++) { if (minters_array[i] == minter_address) { minters_array[i] = address(0); // This will leave a null in the array and keep the indices the same break; } } emit MinterRemoved(minter_address); } /* ========== RESTRICTED FUNCTIONS [ADMIN-RELATED] ========== */ /// @notice Sets the timelock address /// @param _timelock_address Address of the timelock function setTimelock(address _timelock_address) public onlyByOwnGov { require(_timelock_address != address(0), "Zero address detected"); timelock_address = _timelock_address; emit TimelockChanged(_timelock_address); } /* ========== EVENTS ========== */ /// @notice Emitted whenever the bridge burns tokens from an account /// @param account Address of the account tokens are being burned from /// @param amount Amount of tokens burned event Burn(address indexed account, uint256 amount); /// @notice Emitted whenever the bridge mints tokens to an account /// @param account Address of the account tokens are being minted for /// @param amount Amount of tokens minted. event Mint(address indexed account, uint256 amount); /// @notice Emitted when a non-bridge minter is added /// @param minter_address Address of the new minter event MinterAdded(address minter_address); /// @notice Emitted when a non-bridge minter is removed /// @param minter_address Address of the removed minter event MinterRemoved(address minter_address); /// @notice Emitted when the timelock address changes /// @param timelock_address Address of the removed timelock event TimelockChanged(address timelock_address); /// @notice Emitted when a non-bridge minter burns tokens /// @param from The account whose tokens are burned /// @param to The minter doing the burning /// @param amount Amount of tokens burned event TokenMinterBurned(address indexed from, address indexed to, uint256 amount); /// @notice Emitted when a non-bridge minter mints tokens /// @param from The minter doing the minting /// @param to The account that gets the newly minted tokens /// @param amount Amount of tokens minted event TokenMinterMinted(address indexed from, address indexed to, uint256 amount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Permit.sol) pragma solidity ^0.8.20; import {IERC20Permit} from "./IERC20Permit.sol"; import {ERC20} from "../ERC20.sol"; import {ECDSA} from "../../../utils/cryptography/ECDSA.sol"; import {EIP712} from "../../../utils/cryptography/EIP712.sol"; import {Nonces} from "../../../utils/Nonces.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 ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces { 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. */ constructor(string memory name) EIP712(name, "1") {} /** * @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, Nonces) 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(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol) pragma solidity ^0.8.20; import {ERC20} from "../ERC20.sol"; import {Context} from "../../../utils/Context.sol"; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys a `value` amount of tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 value) public virtual { _burn(_msgSender(), value); } /** * @dev Destroys a `value` amount of tokens from `account`, deducting from * the caller's allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `value`. */ function burnFrom(address account, uint256 value) public virtual { _spendAllowance(account, _msgSender(), value); _burn(account, value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /// @title IOptimismMintableERC20 /// @notice This interface is available on the OptimismMintableERC20 contract. /// We declare it as a separate interface so that it can be used in /// custom implementations of OptimismMintableERC20. interface IOptimismMintableERC20 is IERC165 { function remoteToken() external view returns (address); function bridge() external returns (address); function mint(address _to, uint256 _amount) external; function burn(address _from, uint256 _amount) external; } /// @custom:legacy /// @title ILegacyMintableERC20 /// @notice This interface was available on the legacy L2StandardERC20 contract. /// It remains available on the OptimismMintableERC20 contract for /// backwards compatibility. interface ILegacyMintableERC20 is IERC165 { function l1Token() external view returns (address); function mint(address _to, uint256 _amount) external; function burn(address _from, uint256 _amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title ISemver /// @notice ISemver is a simple contract for ensuring that contracts are /// versioned using semantic versioning. interface ISemver { /// @notice Getter for the semantic version of the contract. This is not /// meant to be used onchain but instead meant to be used by offchain /// tooling. /// @return Semver contract version as a string. function version() external view returns (string memory); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.4; // https://docs.synthetix.io/contracts/Owned contract OwnedV2 { error OwnerCannotBeZero(); error InvalidOwnershipAcceptance(); error OnlyOwner(); address public owner; address public nominatedOwner; constructor(address _owner) { // require(_owner != address(0), "Owner address cannot be 0"); if (_owner == address(0)) revert OwnerCannotBeZero(); owner = _owner; emit OwnerChanged(address(0), _owner); } function nominateNewOwner(address _owner) external onlyOwner { nominatedOwner = _owner; emit OwnerNominated(_owner); } function acceptOwnership() external { // require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership"); if (msg.sender != nominatedOwner) revert InvalidOwnershipAcceptance(); emit OwnerChanged(owner, nominatedOwner); owner = nominatedOwner; nominatedOwner = address(0); } modifier onlyOwner() { // require(msg.sender == owner, "Only the contract owner may perform this action"); if (msg.sender != owner) revert OnlyOwner(); _; } event OwnerNominated(address newOwner); event OwnerChanged(address oldOwner, address newOwner); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @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); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.20; import {MessageHashUtils} from "./MessageHashUtils.sol"; import {ShortStrings, ShortString} from "../ShortStrings.sol"; import {IERC5267} from "../../interfaces/IERC5267.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. * * @custom:oz-upgrades-unsafe-allow state-variable-immutable */ abstract contract EIP712 is IERC5267 { using ShortStrings for *; bytes32 private constant TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; address private immutable _cachedThis; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; ShortString private immutable _name; ShortString private immutable _version; string private _nameFallback; string private _versionFallback; /** * @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]. */ constructor(string memory name, string memory version) { _name = name.toShortStringWithFallback(_nameFallback); _version = version.toShortStringWithFallback(_versionFallback); _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); _cachedThis = address(this); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _cachedThis && block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, 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 ) { return ( hex"0f", // 01111 _EIP712Name(), _EIP712Version(), block.chainid, address(this), bytes32(0), new uint256[](0) ); } /** * @dev The name parameter for the EIP712 domain. * * NOTE: By default this function reads _name which is an immutable value. * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). */ // solhint-disable-next-line func-name-mixedcase function _EIP712Name() internal view returns (string memory) { return _name.toStringWithFallback(_nameFallback); } /** * @dev The version parameter for the EIP712 domain. * * NOTE: By default this function reads _version which is an immutable value. * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). */ // solhint-disable-next-line func-name-mixedcase function _EIP712Version() internal view returns (string memory) { return _version.toStringWithFallback(_versionFallback); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol) pragma solidity ^0.8.20; /** * @dev Provides tracking nonces for addresses. Nonces will only increment. */ abstract contract Nonces { /** * @dev The nonce used for an `account` is not the expected current nonce. */ error InvalidAccountNonce(address account, uint256 currentNonce); mapping(address account => uint256) private _nonces; /** * @dev Returns the next unused nonce for an address. */ function nonces(address owner) public view virtual returns (uint256) { return _nonces[owner]; } /** * @dev Consumes a nonce. * * Returns the current value and increments nonce. */ function _useNonce(address owner) internal virtual returns (uint256) { // 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); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "../Strings.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) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol) pragma solidity ^0.8.20; import {StorageSlot} from "./StorageSlot.sol"; // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | // | length | 0x BB | type ShortString is bytes32; /** * @dev This library provides functions to convert short memory strings * into a `ShortString` type that can be used as an immutable variable. * * Strings of arbitrary length can be optimized using this library if * they are short enough (up to 31 bytes) by packing them with their * length (1 byte) in a single EVM word (32 bytes). Additionally, a * fallback mechanism can be used for every other case. * * Usage example: * * ```solidity * contract Named { * using ShortStrings for *; * * ShortString private immutable _name; * string private _nameFallback; * * constructor(string memory contractName) { * _name = contractName.toShortStringWithFallback(_nameFallback); * } * * function name() external view returns (string memory) { * return _name.toStringWithFallback(_nameFallback); * } * } * ``` */ library ShortStrings { // Used as an identifier for strings longer than 31 bytes. bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; error StringTooLong(string str); error InvalidShortString(); /** * @dev Encode a string of at most 31 chars into a `ShortString`. * * This will trigger a `StringTooLong` error is the input string is too long. */ function toShortString(string memory str) internal pure returns (ShortString) { bytes memory bstr = bytes(str); if (bstr.length > 31) { revert StringTooLong(str); } return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); } /** * @dev Decode a `ShortString` back to a "normal" string. */ function toString(ShortString sstr) internal pure returns (string memory) { uint256 len = byteLength(sstr); // using `new string(len)` would work locally but is not memory safe. string memory str = new string(32); /// @solidity memory-safe-assembly assembly { mstore(str, len) mstore(add(str, 0x20), sstr) } return str; } /** * @dev Return the length of a `ShortString`. */ function byteLength(ShortString sstr) internal pure returns (uint256) { uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; if (result > 31) { revert InvalidShortString(); } return result; } /** * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. */ function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { if (bytes(value).length < 32) { return toShortString(value); } else { StorageSlot.getStringSlot(store).value = value; return ShortString.wrap(FALLBACK_SENTINEL); } } /** * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. */ function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { return toString(value); } else { return store; } } /** * @dev Return the length of a string that was encoded to `ShortString` or written to storage using * {setWithFallback}. * * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. */ function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { return byteLength(value); } else { return bytes(store).length; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.20; 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 ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @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 } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
{ "remappings": [ "frax-std/=lib/frax-standard-solidity/src/", "@eth-optimism/=lib/optimism/packages/", "lib/optimism/packages/contracts-bedrock:src/=lib/optimism/packages/contracts-bedrock/src/", "@openzeppelin-4/=node_modules/@openzeppelin-4/", "@openzeppelin-5/=node_modules/@openzeppelin-5/", "@openzeppelin/=node_modules/@openzeppelin/", "@rari-capital/=node_modules/@rari-capital/", "clones-with-immutable-args/=lib/optimism/packages/contracts-bedrock/lib/clones-with-immutable-args/src/", "ds-test/=lib/frax-standard-solidity/lib/forge-std/lib/ds-test/src/", "forge-std/=lib/frax-standard-solidity/lib/forge-std/src/", "frax-standard-solidity/=lib/frax-standard-solidity/src/", "kontrol-cheatcodes/=lib/optimism/packages/contracts-bedrock/lib/kontrol-cheatcodes/src/", "lib-keccak/=lib/optimism/packages/contracts-bedrock/lib/lib-keccak/contracts/", "openzeppelin-contracts-upgradeable/=lib/optimism/packages/contracts-bedrock/lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/optimism/packages/contracts-bedrock/lib/openzeppelin-contracts/", "optimism/=lib/optimism/", "safe-contracts/=lib/optimism/packages/contracts-bedrock/lib/safe-contracts/contracts/", "solady/=lib/optimism/packages/contracts-bedrock/lib/solady/", "solidity-bytes-utils/=lib/frax-standard-solidity/lib/solidity-bytes-utils/", "solmate/=lib/optimism/packages/contracts-bedrock/lib/solmate/src/" ], "optimizer": { "enabled": false, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": false }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_creator_address","type":"address"},{"internalType":"address","name":"_timelock_address","type":"address"},{"internalType":"address","name":"_bridge","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"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":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidOwnershipAcceptance","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"OwnerCannotBeZero","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","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":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter_address","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter_address","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"timelock_address","type":"address"}],"name":"TimelockChanged","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":"amount","type":"uint256"}],"name":"TokenMinterBurned","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":"amount","type":"uint256"}],"name":"TokenMinterMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BRIDGE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REMOTE_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter_address","type":"address"}],"name":"addMinter","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":[],"name":"bridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","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":[],"name":"l1Token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2Bridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"b_address","type":"address"},{"internalType":"uint256","name":"b_amount","type":"uint256"}],"name":"minter_burn_from","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"m_address","type":"address"},{"internalType":"uint256","name":"m_amount","type":"uint256"}],"name":"minter_mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minters","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"minters_array","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"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":[{"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":"remoteToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter_address","type":"address"}],"name":"removeMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_timelock_address","type":"address"}],"name":"setTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelock_address","outputs":[{"internalType":"address","name":"","type":"address"}],"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":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50600436106102275760003560e01c806379cc679011610130578063bdacb303116100b8578063dc6663c71161007c578063dc6663c714610646578063dd62ed3e14610664578063e78cea9214610694578063ee9a31a2146106b2578063f46eccc4146106d057610227565b8063bdacb303146105a2578063c01e1bd6146105be578063d505accf146105dc578063d6c0b2c4146105f8578063d73ced041461061657610227565b806395d89b41116100ff57806395d89b41146104fe578063983b2d561461051c5780639dc29fac14610538578063a9059cbb14610554578063ae1f6aaf1461058457610227565b806379cc6790146104705780637ecebe001461048c57806384b0196e146104bc5780638da5cb5b146104e057610227565b80633644e515116101b357806354fd4d501161018257806354fd4d50146103e05780636a257ebc146103fe57806370a082311461041a5780637941bc891461044a57806379ba50971461046657610227565b80633644e5151461036c57806340c10f191461038a57806342966c68146103a657806353a47bb7146103c257610227565b80631627540c116101fa5780631627540c146102c857806318160ddd146102e457806323b872dd146103025780633092afd514610332578063313ce5671461034e57610227565b806301ffc9a71461022c578063033964be1461025c57806306fdde031461027a578063095ea7b314610298575b600080fd5b61024660048036038101906102419190612b5b565b610700565b6040516102539190612ba3565b60405180910390f35b61026461084b565b6040516102719190612bff565b60405180910390f35b61028261086f565b60405161028f9190612caa565b60405180910390f35b6102b260048036038101906102ad9190612d2e565b610901565b6040516102bf9190612ba3565b60405180910390f35b6102e260048036038101906102dd9190612d6e565b610924565b005b6102ec610a26565b6040516102f99190612daa565b60405180910390f35b61031c60048036038101906103179190612dc5565b610a30565b6040516103299190612ba3565b60405180910390f35b61034c60048036038101906103479190612d6e565b610a5f565b005b610356610dc4565b6040516103639190612e34565b60405180910390f35b610374610dcd565b6040516103819190612e68565b60405180910390f35b6103a4600480360381019061039f9190612d2e565b610ddc565b005b6103c060048036038101906103bb9190612e83565b610ec6565b005b6103ca610eda565b6040516103d79190612bff565b60405180910390f35b6103e8610f00565b6040516103f59190612caa565b60405180910390f35b61041860048036038101906104139190612d2e565b610f39565b005b610434600480360381019061042f9190612d6e565b61103f565b6040516104419190612daa565b60405180910390f35b610464600480360381019061045f9190612d2e565b611087565b005b61046e61118d565b005b61048a60048036038101906104859190612d2e565b611338565b005b6104a660048036038101906104a19190612d6e565b611358565b6040516104b39190612daa565b60405180910390f35b6104c461136a565b6040516104d79796959493929190612fa9565b60405180910390f35b6104e8611414565b6040516104f59190612bff565b60405180910390f35b61050661143a565b6040516105139190612caa565b60405180910390f35b61053660048036038101906105319190612d6e565b6114cc565b005b610552600480360381019061054d9190612d2e565b6117ab565b005b61056e60048036038101906105699190612d2e565b611895565b60405161057b9190612ba3565b60405180910390f35b61058c6118b8565b6040516105999190612bff565b60405180910390f35b6105bc60048036038101906105b79190612d6e565b6118e0565b005b6105c6611ab2565b6040516105d39190612bff565b60405180910390f35b6105f660048036038101906105f19190613085565b611ada565b005b610600611c22565b60405161060d9190612bff565b60405180910390f35b610630600480360381019061062b9190612e83565b611c4a565b60405161063d9190612bff565b60405180910390f35b61064e611c89565b60405161065b9190612bff565b60405180910390f35b61067e60048036038101906106799190613127565b611caf565b60405161068b9190612daa565b60405180910390f35b61069c611d36565b6040516106a99190612bff565b60405180910390f35b6106ba611d5e565b6040516106c79190612bff565b60405180910390f35b6106ea60048036038101906106e59190612d6e565b611d82565b6040516106f79190612ba3565b60405180910390f35b6000807f01ffc9a700000000000000000000000000000000000000000000000000000000905060007f1d1d8b6300000000000000000000000000000000000000000000000000000000905060007fec4fc8e3000000000000000000000000000000000000000000000000000000009050827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107f95750817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806108415750807bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9350505050919050565b7f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e81565b60606003805461087e90613196565b80601f01602080910402602001604051908101604052809291908181526020018280546108aa90613196565b80156108f75780601f106108cc576101008083540402835291602001916108f7565b820191906000526020600020905b8154815290600101906020018083116108da57829003601f168201915b5050505050905090565b60008061090c611da2565b9050610919818585611daa565b600191505092915050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109ab576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2281604051610a1b9190612bff565b60405180910390a150565b6000600254905090565b600080610a3b611da2565b9050610a48858285611dbc565b610a53858585611e50565b60019150509392505050565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610b085750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b610b47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3e90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bad9061327f565b60405180910390fd5b60011515600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610c49576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c40906132eb565b60405180910390fd5b600c60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff021916905560005b600b80549050811015610d89578173ffffffffffffffffffffffffffffffffffffffff16600b8281548110610cd357610cd261330b565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610d7c576000600b8281548110610d2f57610d2e61330b565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610d89565b8080600101915050610c9b565b507fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669281604051610db99190612bff565b60405180910390a150565b60006012905090565b6000610dd7611f44565b905090565b7f000000000000000000000000420000000000000000000000000000000000001073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e61906133ac565b60405180910390fd5b610e748282611ffb565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688582604051610eba9190612daa565b60405180910390a25050565b610ed7610ed1611da2565b8261207d565b50565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60011515600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610fcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc390613418565b60405180910390fd5b610fd68282611ffb565b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe0dcb47e0eb67e20e87f3e34aab31c669ecec7466e8b7fb329d586dadebac6b6836040516110339190612daa565b60405180910390a35050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60011515600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151461111a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111190613418565b60405180910390fd5b6111248282611338565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fdc7fd22bc401e7c6b9be2c2736286a2a42ea0c6307bc97ff0fb12bd0abd2c747836040516111819190612daa565b60405180910390a35050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611214576040517fd74b334e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611289929190613438565b60405180910390a1600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b61134a82611344611da2565b83611dbc565b611354828261207d565b5050565b6000611363826120ff565b9050919050565b60006060806000806000606061137e612148565b611386612183565b46306000801b600067ffffffffffffffff8111156113a7576113a6613461565b5b6040519080825280602002602001820160405280156113d55781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606004805461144990613196565b80601f016020809104026020016040519081016040528092919081815260200182805461147590613196565b80156114c25780601f10611497576101008083540402835291602001916114c2565b820191906000526020600020905b8154815290600101906020018083116114a557829003601f168201915b5050505050905090565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806115755750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6115b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ab90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611623576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161a9061327f565b60405180910390fd5b60001515600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515146116b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ad906134dc565b60405180910390fd5b6001600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600b819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6816040516117a09190612bff565b60405180910390a150565b7f000000000000000000000000420000000000000000000000000000000000001073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611839576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611830906133ac565b60405180910390fd5b611843828261207d565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516118899190612daa565b60405180910390a25050565b6000806118a0611da2565b90506118ad818585611e50565b600191505092915050565b60007f0000000000000000000000004200000000000000000000000000000000000010905090565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806119895750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6119c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119bf90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a2e9061327f565b60405180910390fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff02fdf7b40fb25784d39342249bbb15cee2bc0288f75ded1cf8ad2e63d4d91aa81604051611aa79190612bff565b60405180910390a150565b60007f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e905090565b83421115611b1f57836040517f62791302000000000000000000000000000000000000000000000000000000008152600401611b169190612daa565b60405180910390fd5b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888611b4e8c6121be565b89604051602001611b64969594939291906134fc565b6040516020818303038152906040528051906020012090506000611b8782612215565b90506000611b978287878761222f565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611c0b57808a6040517f4b800e46000000000000000000000000000000000000000000000000000000008152600401611c02929190613438565b60405180910390fd5b611c168a8a8a611daa565b50505050505050505050565b60007f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e905090565b600b8181548110611c5a57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60007f0000000000000000000000004200000000000000000000000000000000000010905090565b7f000000000000000000000000420000000000000000000000000000000000001081565b600c6020528060005260406000206000915054906101000a900460ff1681565b600033905090565b611db7838383600161225f565b505050565b6000611dc88484611caf565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611e4a5781811015611e3a578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401611e319392919061355d565b60405180910390fd5b611e498484848403600061225f565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611ec25760006040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611eb99190612bff565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611f345760006040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611f2b9190612bff565b60405180910390fd5b611f3f838383612436565b505050565b60007f0000000000000000000000008c5d64d10394cfa070066e70ec19e67398b4dabe73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611fc057507f00000000000000000000000000000000000000000000000000000000000000fc46145b15611fed577f0b181ca4e35f62a48be63938a0439676660a67f2d7b67d3269bc90a9cf49d8fa9050611ff8565b611ff561265b565b90505b90565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361206d5760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016120649190612bff565b60405180910390fd5b61207960008383612436565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036120ef5760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016120e69190612bff565b60405180910390fd5b6120fb82600083612436565b5050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606061217e60057f46726178000000000000000000000000000000000000000000000000000000046126f190919063ffffffff16565b905090565b60606121b960067f31000000000000000000000000000000000000000000000000000000000000016126f190919063ffffffff16565b905090565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600101919050559050919050565b6000612228612222611f44565b836127a1565b9050919050565b600080600080612241888888886127e2565b92509250925061225182826128d6565b829350505050949350505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122d15760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016122c89190612bff565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036123435760006040517f94280d6200000000000000000000000000000000000000000000000000000000815260040161233a9190612bff565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508015612430578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516124279190612daa565b60405180910390a35b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361248857806002600082825461247c91906135c3565b9250508190555061255b565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612514578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161250b9392919061355d565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036125a457806002600082825403925050819055506125f1565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161264e9190612daa565b60405180910390a3505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7ffd2be0deba5de05ced723e61a8dd6da10b7aa70a18a5a2a8108522a800c42a7a7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc646306040516020016126d69594939291906135f7565b60405160208183030381529060405280519060200120905090565b606060ff60001b831461270e5761270783612a3a565b905061279b565b81805461271a90613196565b80601f016020809104026020016040519081016040528092919081815260200182805461274690613196565b80156127935780601f1061276857610100808354040283529160200191612793565b820191906000526020600020905b81548152906001019060200180831161277657829003601f168201915b505050505090505b92915050565b60006040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60008060007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08460001c11156128225760006003859250925092506128cc565b600060018888888860405160008152602001604052604051612847949392919061364a565b6020604051602081039080840390855afa158015612869573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036128bd57600060016000801b935093509350506128cc565b8060008060001b935093509350505b9450945094915050565b600060038111156128ea576128e961368f565b5b8260038111156128fd576128fc61368f565b5b0315612a3657600160038111156129175761291661368f565b5b82600381111561292a5761292961368f565b5b03612961576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260038111156129755761297461368f565b5b8260038111156129885761298761368f565b5b036129cd578060001c6040517ffce698f70000000000000000000000000000000000000000000000000000000081526004016129c49190612daa565b60405180910390fd5b6003808111156129e0576129df61368f565b5b8260038111156129f3576129f261368f565b5b03612a3557806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612a2c9190612e68565b60405180910390fd5b5b5050565b60606000612a4783612aae565b90506000602067ffffffffffffffff811115612a6657612a65613461565b5b6040519080825280601f01601f191660200182016040528015612a985781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b60008060ff8360001c169050601f811115612af5576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612b3881612b03565b8114612b4357600080fd5b50565b600081359050612b5581612b2f565b92915050565b600060208284031215612b7157612b70612afe565b5b6000612b7f84828501612b46565b91505092915050565b60008115159050919050565b612b9d81612b88565b82525050565b6000602082019050612bb86000830184612b94565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612be982612bbe565b9050919050565b612bf981612bde565b82525050565b6000602082019050612c146000830184612bf0565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612c54578082015181840152602081019050612c39565b60008484015250505050565b6000601f19601f8301169050919050565b6000612c7c82612c1a565b612c868185612c25565b9350612c96818560208601612c36565b612c9f81612c60565b840191505092915050565b60006020820190508181036000830152612cc48184612c71565b905092915050565b612cd581612bde565b8114612ce057600080fd5b50565b600081359050612cf281612ccc565b92915050565b6000819050919050565b612d0b81612cf8565b8114612d1657600080fd5b50565b600081359050612d2881612d02565b92915050565b60008060408385031215612d4557612d44612afe565b5b6000612d5385828601612ce3565b9250506020612d6485828601612d19565b9150509250929050565b600060208284031215612d8457612d83612afe565b5b6000612d9284828501612ce3565b91505092915050565b612da481612cf8565b82525050565b6000602082019050612dbf6000830184612d9b565b92915050565b600080600060608486031215612dde57612ddd612afe565b5b6000612dec86828701612ce3565b9350506020612dfd86828701612ce3565b9250506040612e0e86828701612d19565b9150509250925092565b600060ff82169050919050565b612e2e81612e18565b82525050565b6000602082019050612e496000830184612e25565b92915050565b6000819050919050565b612e6281612e4f565b82525050565b6000602082019050612e7d6000830184612e59565b92915050565b600060208284031215612e9957612e98612afe565b5b6000612ea784828501612d19565b91505092915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b612ee581612eb0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612f2081612cf8565b82525050565b6000612f328383612f17565b60208301905092915050565b6000602082019050919050565b6000612f5682612eeb565b612f608185612ef6565b9350612f6b83612f07565b8060005b83811015612f9c578151612f838882612f26565b9750612f8e83612f3e565b925050600181019050612f6f565b5085935050505092915050565b600060e082019050612fbe600083018a612edc565b8181036020830152612fd08189612c71565b90508181036040830152612fe48188612c71565b9050612ff36060830187612d9b565b6130006080830186612bf0565b61300d60a0830185612e59565b81810360c083015261301f8184612f4b565b905098975050505050505050565b61303681612e18565b811461304157600080fd5b50565b6000813590506130538161302d565b92915050565b61306281612e4f565b811461306d57600080fd5b50565b60008135905061307f81613059565b92915050565b600080600080600080600060e0888a0312156130a4576130a3612afe565b5b60006130b28a828b01612ce3565b97505060206130c38a828b01612ce3565b96505060406130d48a828b01612d19565b95505060606130e58a828b01612d19565b94505060806130f68a828b01613044565b93505060a06131078a828b01613070565b92505060c06131188a828b01613070565b91505092959891949750929550565b6000806040838503121561313e5761313d612afe565b5b600061314c85828601612ce3565b925050602061315d85828601612ce3565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806131ae57607f821691505b6020821081036131c1576131c0613167565b5b50919050565b7f4e6f74206f776e6572206f722074696d656c6f636b0000000000000000000000600082015250565b60006131fd601583612c25565b9150613208826131c7565b602082019050919050565b6000602082019050818103600083015261322c816131f0565b9050919050565b7f5a65726f20616464726573732064657465637465640000000000000000000000600082015250565b6000613269601583612c25565b915061327482613233565b602082019050919050565b600060208201905081810360008301526132988161325c565b9050919050565b7f41646472657373206e6f6e6578697374616e7400000000000000000000000000600082015250565b60006132d5601383612c25565b91506132e08261329f565b602082019050919050565b60006020820190508181036000830152613304816132c8565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460008201527f67652063616e206d696e7420616e64206275726e000000000000000000000000602082015250565b6000613396603483612c25565b91506133a18261333a565b604082019050919050565b600060208201905081810360008301526133c581613389565b9050919050565b7f4f6e6c79206d696e746572730000000000000000000000000000000000000000600082015250565b6000613402600c83612c25565b915061340d826133cc565b602082019050919050565b60006020820190508181036000830152613431816133f5565b9050919050565b600060408201905061344d6000830185612bf0565b61345a6020830184612bf0565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4164647265737320616c72656164792065786973747300000000000000000000600082015250565b60006134c6601683612c25565b91506134d182613490565b602082019050919050565b600060208201905081810360008301526134f5816134b9565b9050919050565b600060c0820190506135116000830189612e59565b61351e6020830188612bf0565b61352b6040830187612bf0565b6135386060830186612d9b565b6135456080830185612d9b565b61355260a0830184612d9b565b979650505050505050565b60006060820190506135726000830186612bf0565b61357f6020830185612d9b565b61358c6040830184612d9b565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006135ce82612cf8565b91506135d983612cf8565b92508282019050808211156135f1576135f0613594565b5b92915050565b600060a08201905061360c6000830188612e59565b6136196020830187612e59565b6136266040830186612e59565b6136336060830185612d9b565b6136406080830184612bf0565b9695505050505050565b600060808201905061365f6000830187612e59565b61366c6020830186612e25565b6136796040830185612e59565b6136866060830184612e59565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102275760003560e01c806379cc679011610130578063bdacb303116100b8578063dc6663c71161007c578063dc6663c714610646578063dd62ed3e14610664578063e78cea9214610694578063ee9a31a2146106b2578063f46eccc4146106d057610227565b8063bdacb303146105a2578063c01e1bd6146105be578063d505accf146105dc578063d6c0b2c4146105f8578063d73ced041461061657610227565b806395d89b41116100ff57806395d89b41146104fe578063983b2d561461051c5780639dc29fac14610538578063a9059cbb14610554578063ae1f6aaf1461058457610227565b806379cc6790146104705780637ecebe001461048c57806384b0196e146104bc5780638da5cb5b146104e057610227565b80633644e515116101b357806354fd4d501161018257806354fd4d50146103e05780636a257ebc146103fe57806370a082311461041a5780637941bc891461044a57806379ba50971461046657610227565b80633644e5151461036c57806340c10f191461038a57806342966c68146103a657806353a47bb7146103c257610227565b80631627540c116101fa5780631627540c146102c857806318160ddd146102e457806323b872dd146103025780633092afd514610332578063313ce5671461034e57610227565b806301ffc9a71461022c578063033964be1461025c57806306fdde031461027a578063095ea7b314610298575b600080fd5b61024660048036038101906102419190612b5b565b610700565b6040516102539190612ba3565b60405180910390f35b61026461084b565b6040516102719190612bff565b60405180910390f35b61028261086f565b60405161028f9190612caa565b60405180910390f35b6102b260048036038101906102ad9190612d2e565b610901565b6040516102bf9190612ba3565b60405180910390f35b6102e260048036038101906102dd9190612d6e565b610924565b005b6102ec610a26565b6040516102f99190612daa565b60405180910390f35b61031c60048036038101906103179190612dc5565b610a30565b6040516103299190612ba3565b60405180910390f35b61034c60048036038101906103479190612d6e565b610a5f565b005b610356610dc4565b6040516103639190612e34565b60405180910390f35b610374610dcd565b6040516103819190612e68565b60405180910390f35b6103a4600480360381019061039f9190612d2e565b610ddc565b005b6103c060048036038101906103bb9190612e83565b610ec6565b005b6103ca610eda565b6040516103d79190612bff565b60405180910390f35b6103e8610f00565b6040516103f59190612caa565b60405180910390f35b61041860048036038101906104139190612d2e565b610f39565b005b610434600480360381019061042f9190612d6e565b61103f565b6040516104419190612daa565b60405180910390f35b610464600480360381019061045f9190612d2e565b611087565b005b61046e61118d565b005b61048a60048036038101906104859190612d2e565b611338565b005b6104a660048036038101906104a19190612d6e565b611358565b6040516104b39190612daa565b60405180910390f35b6104c461136a565b6040516104d79796959493929190612fa9565b60405180910390f35b6104e8611414565b6040516104f59190612bff565b60405180910390f35b61050661143a565b6040516105139190612caa565b60405180910390f35b61053660048036038101906105319190612d6e565b6114cc565b005b610552600480360381019061054d9190612d2e565b6117ab565b005b61056e60048036038101906105699190612d2e565b611895565b60405161057b9190612ba3565b60405180910390f35b61058c6118b8565b6040516105999190612bff565b60405180910390f35b6105bc60048036038101906105b79190612d6e565b6118e0565b005b6105c6611ab2565b6040516105d39190612bff565b60405180910390f35b6105f660048036038101906105f19190613085565b611ada565b005b610600611c22565b60405161060d9190612bff565b60405180910390f35b610630600480360381019061062b9190612e83565b611c4a565b60405161063d9190612bff565b60405180910390f35b61064e611c89565b60405161065b9190612bff565b60405180910390f35b61067e60048036038101906106799190613127565b611caf565b60405161068b9190612daa565b60405180910390f35b61069c611d36565b6040516106a99190612bff565b60405180910390f35b6106ba611d5e565b6040516106c79190612bff565b60405180910390f35b6106ea60048036038101906106e59190612d6e565b611d82565b6040516106f79190612ba3565b60405180910390f35b6000807f01ffc9a700000000000000000000000000000000000000000000000000000000905060007f1d1d8b6300000000000000000000000000000000000000000000000000000000905060007fec4fc8e3000000000000000000000000000000000000000000000000000000009050827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107f95750817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806108415750807bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9350505050919050565b7f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e81565b60606003805461087e90613196565b80601f01602080910402602001604051908101604052809291908181526020018280546108aa90613196565b80156108f75780601f106108cc576101008083540402835291602001916108f7565b820191906000526020600020905b8154815290600101906020018083116108da57829003601f168201915b5050505050905090565b60008061090c611da2565b9050610919818585611daa565b600191505092915050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109ab576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2281604051610a1b9190612bff565b60405180910390a150565b6000600254905090565b600080610a3b611da2565b9050610a48858285611dbc565b610a53858585611e50565b60019150509392505050565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610b085750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b610b47576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3e90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bad9061327f565b60405180910390fd5b60011515600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610c49576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c40906132eb565b60405180910390fd5b600c60008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff021916905560005b600b80549050811015610d89578173ffffffffffffffffffffffffffffffffffffffff16600b8281548110610cd357610cd261330b565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603610d7c576000600b8281548110610d2f57610d2e61330b565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610d89565b8080600101915050610c9b565b507fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669281604051610db99190612bff565b60405180910390a150565b60006012905090565b6000610dd7611f44565b905090565b7f000000000000000000000000420000000000000000000000000000000000001073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e61906133ac565b60405180910390fd5b610e748282611ffb565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688582604051610eba9190612daa565b60405180910390a25050565b610ed7610ed1611da2565b8261207d565b50565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60011515600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610fcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc390613418565b60405180910390fd5b610fd68282611ffb565b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe0dcb47e0eb67e20e87f3e34aab31c669ecec7466e8b7fb329d586dadebac6b6836040516110339190612daa565b60405180910390a35050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60011515600c60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151461111a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161111190613418565b60405180910390fd5b6111248282611338565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fdc7fd22bc401e7c6b9be2c2736286a2a42ea0c6307bc97ff0fb12bd0abd2c747836040516111819190612daa565b60405180910390a35050565b600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611214576040517fd74b334e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611289929190613438565b60405180910390a1600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b61134a82611344611da2565b83611dbc565b611354828261207d565b5050565b6000611363826120ff565b9050919050565b60006060806000806000606061137e612148565b611386612183565b46306000801b600067ffffffffffffffff8111156113a7576113a6613461565b5b6040519080825280602002602001820160405280156113d55781602001602082028036833780820191505090505b507f0f00000000000000000000000000000000000000000000000000000000000000959493929190965096509650965096509650965090919293949596565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606004805461144990613196565b80601f016020809104026020016040519081016040528092919081815260200182805461147590613196565b80156114c25780601f10611497576101008083540402835291602001916114c2565b820191906000526020600020905b8154815290600101906020018083116114a557829003601f168201915b5050505050905090565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806115755750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6115b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ab90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611623576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161a9061327f565b60405180910390fd5b60001515600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515146116b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ad906134dc565b60405180910390fd5b6001600c60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600b819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6816040516117a09190612bff565b60405180910390a150565b7f000000000000000000000000420000000000000000000000000000000000001073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611839576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611830906133ac565b60405180910390fd5b611843828261207d565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516118899190612daa565b60405180910390a25050565b6000806118a0611da2565b90506118ad818585611e50565b600191505092915050565b60007f0000000000000000000000004200000000000000000000000000000000000010905090565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806119895750600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6119c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119bf90613213565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611a37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a2e9061327f565b60405180910390fd5b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff02fdf7b40fb25784d39342249bbb15cee2bc0288f75ded1cf8ad2e63d4d91aa81604051611aa79190612bff565b60405180910390a150565b60007f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e905090565b83421115611b1f57836040517f62791302000000000000000000000000000000000000000000000000000000008152600401611b169190612daa565b60405180910390fd5b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9888888611b4e8c6121be565b89604051602001611b64969594939291906134fc565b6040516020818303038152906040528051906020012090506000611b8782612215565b90506000611b978287878761222f565b90508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611c0b57808a6040517f4b800e46000000000000000000000000000000000000000000000000000000008152600401611c02929190613438565b60405180910390fd5b611c168a8a8a611daa565b50505050505050505050565b60007f000000000000000000000000853d955acef822db058eb8505911ed77f175b99e905090565b600b8181548110611c5a57600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b60007f0000000000000000000000004200000000000000000000000000000000000010905090565b7f000000000000000000000000420000000000000000000000000000000000001081565b600c6020528060005260406000206000915054906101000a900460ff1681565b600033905090565b611db7838383600161225f565b505050565b6000611dc88484611caf565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611e4a5781811015611e3a578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401611e319392919061355d565b60405180910390fd5b611e498484848403600061225f565b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611ec25760006040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401611eb99190612bff565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611f345760006040517fec442f05000000000000000000000000000000000000000000000000000000008152600401611f2b9190612bff565b60405180910390fd5b611f3f838383612436565b505050565b60007f0000000000000000000000008c5d64d10394cfa070066e70ec19e67398b4dabe73ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16148015611fc057507f00000000000000000000000000000000000000000000000000000000000000fc46145b15611fed577f0b181ca4e35f62a48be63938a0439676660a67f2d7b67d3269bc90a9cf49d8fa9050611ff8565b611ff561265b565b90505b90565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361206d5760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016120649190612bff565b60405180910390fd5b61207960008383612436565b5050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036120ef5760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016120e69190612bff565b60405180910390fd5b6120fb82600083612436565b5050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606061217e60057f46726178000000000000000000000000000000000000000000000000000000046126f190919063ffffffff16565b905090565b60606121b960067f31000000000000000000000000000000000000000000000000000000000000016126f190919063ffffffff16565b905090565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600101919050559050919050565b6000612228612222611f44565b836127a1565b9050919050565b600080600080612241888888886127e2565b92509250925061225182826128d6565b829350505050949350505050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036122d15760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016122c89190612bff565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036123435760006040517f94280d6200000000000000000000000000000000000000000000000000000000815260040161233a9190612bff565b60405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508015612430578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516124279190612daa565b60405180910390a35b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361248857806002600082825461247c91906135c3565b9250508190555061255b565b60008060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905081811015612514578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161250b9392919061355d565b60405180910390fd5b8181036000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036125a457806002600082825403925050819055506125f1565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161264e9190612daa565b60405180910390a3505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7ffd2be0deba5de05ced723e61a8dd6da10b7aa70a18a5a2a8108522a800c42a7a7fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc646306040516020016126d69594939291906135f7565b60405160208183030381529060405280519060200120905090565b606060ff60001b831461270e5761270783612a3a565b905061279b565b81805461271a90613196565b80601f016020809104026020016040519081016040528092919081815260200182805461274690613196565b80156127935780601f1061276857610100808354040283529160200191612793565b820191906000526020600020905b81548152906001019060200180831161277657829003601f168201915b505050505090505b92915050565b60006040517f190100000000000000000000000000000000000000000000000000000000000081528360028201528260228201526042812091505092915050565b60008060007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08460001c11156128225760006003859250925092506128cc565b600060018888888860405160008152602001604052604051612847949392919061364a565b6020604051602081039080840390855afa158015612869573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036128bd57600060016000801b935093509350506128cc565b8060008060001b935093509350505b9450945094915050565b600060038111156128ea576128e961368f565b5b8260038111156128fd576128fc61368f565b5b0315612a3657600160038111156129175761291661368f565b5b82600381111561292a5761292961368f565b5b03612961576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260038111156129755761297461368f565b5b8260038111156129885761298761368f565b5b036129cd578060001c6040517ffce698f70000000000000000000000000000000000000000000000000000000081526004016129c49190612daa565b60405180910390fd5b6003808111156129e0576129df61368f565b5b8260038111156129f3576129f261368f565b5b03612a3557806040517fd78bce0c000000000000000000000000000000000000000000000000000000008152600401612a2c9190612e68565b60405180910390fd5b5b5050565b60606000612a4783612aae565b90506000602067ffffffffffffffff811115612a6657612a65613461565b5b6040519080825280601f01601f191660200182016040528015612a985781602001600182028036833780820191505090505b5090508181528360208201528092505050919050565b60008060ff8360001c169050601f811115612af5576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80915050919050565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612b3881612b03565b8114612b4357600080fd5b50565b600081359050612b5581612b2f565b92915050565b600060208284031215612b7157612b70612afe565b5b6000612b7f84828501612b46565b91505092915050565b60008115159050919050565b612b9d81612b88565b82525050565b6000602082019050612bb86000830184612b94565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612be982612bbe565b9050919050565b612bf981612bde565b82525050565b6000602082019050612c146000830184612bf0565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612c54578082015181840152602081019050612c39565b60008484015250505050565b6000601f19601f8301169050919050565b6000612c7c82612c1a565b612c868185612c25565b9350612c96818560208601612c36565b612c9f81612c60565b840191505092915050565b60006020820190508181036000830152612cc48184612c71565b905092915050565b612cd581612bde565b8114612ce057600080fd5b50565b600081359050612cf281612ccc565b92915050565b6000819050919050565b612d0b81612cf8565b8114612d1657600080fd5b50565b600081359050612d2881612d02565b92915050565b60008060408385031215612d4557612d44612afe565b5b6000612d5385828601612ce3565b9250506020612d6485828601612d19565b9150509250929050565b600060208284031215612d8457612d83612afe565b5b6000612d9284828501612ce3565b91505092915050565b612da481612cf8565b82525050565b6000602082019050612dbf6000830184612d9b565b92915050565b600080600060608486031215612dde57612ddd612afe565b5b6000612dec86828701612ce3565b9350506020612dfd86828701612ce3565b9250506040612e0e86828701612d19565b9150509250925092565b600060ff82169050919050565b612e2e81612e18565b82525050565b6000602082019050612e496000830184612e25565b92915050565b6000819050919050565b612e6281612e4f565b82525050565b6000602082019050612e7d6000830184612e59565b92915050565b600060208284031215612e9957612e98612afe565b5b6000612ea784828501612d19565b91505092915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b612ee581612eb0565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b612f2081612cf8565b82525050565b6000612f328383612f17565b60208301905092915050565b6000602082019050919050565b6000612f5682612eeb565b612f608185612ef6565b9350612f6b83612f07565b8060005b83811015612f9c578151612f838882612f26565b9750612f8e83612f3e565b925050600181019050612f6f565b5085935050505092915050565b600060e082019050612fbe600083018a612edc565b8181036020830152612fd08189612c71565b90508181036040830152612fe48188612c71565b9050612ff36060830187612d9b565b6130006080830186612bf0565b61300d60a0830185612e59565b81810360c083015261301f8184612f4b565b905098975050505050505050565b61303681612e18565b811461304157600080fd5b50565b6000813590506130538161302d565b92915050565b61306281612e4f565b811461306d57600080fd5b50565b60008135905061307f81613059565b92915050565b600080600080600080600060e0888a0312156130a4576130a3612afe565b5b60006130b28a828b01612ce3565b97505060206130c38a828b01612ce3565b96505060406130d48a828b01612d19565b95505060606130e58a828b01612d19565b94505060806130f68a828b01613044565b93505060a06131078a828b01613070565b92505060c06131188a828b01613070565b91505092959891949750929550565b6000806040838503121561313e5761313d612afe565b5b600061314c85828601612ce3565b925050602061315d85828601612ce3565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806131ae57607f821691505b6020821081036131c1576131c0613167565b5b50919050565b7f4e6f74206f776e6572206f722074696d656c6f636b0000000000000000000000600082015250565b60006131fd601583612c25565b9150613208826131c7565b602082019050919050565b6000602082019050818103600083015261322c816131f0565b9050919050565b7f5a65726f20616464726573732064657465637465640000000000000000000000600082015250565b6000613269601583612c25565b915061327482613233565b602082019050919050565b600060208201905081810360008301526132988161325c565b9050919050565b7f41646472657373206e6f6e6578697374616e7400000000000000000000000000600082015250565b60006132d5601383612c25565b91506132e08261329f565b602082019050919050565b60006020820190508181036000830152613304816132c8565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460008201527f67652063616e206d696e7420616e64206275726e000000000000000000000000602082015250565b6000613396603483612c25565b91506133a18261333a565b604082019050919050565b600060208201905081810360008301526133c581613389565b9050919050565b7f4f6e6c79206d696e746572730000000000000000000000000000000000000000600082015250565b6000613402600c83612c25565b915061340d826133cc565b602082019050919050565b60006020820190508181036000830152613431816133f5565b9050919050565b600060408201905061344d6000830185612bf0565b61345a6020830184612bf0565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4164647265737320616c72656164792065786973747300000000000000000000600082015250565b60006134c6601683612c25565b91506134d182613490565b602082019050919050565b600060208201905081810360008301526134f5816134b9565b9050919050565b600060c0820190506135116000830189612e59565b61351e6020830188612bf0565b61352b6040830187612bf0565b6135386060830186612d9b565b6135456080830185612d9b565b61355260a0830184612d9b565b979650505050505050565b60006060820190506135726000830186612bf0565b61357f6020830185612d9b565b61358c6040830184612d9b565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006135ce82612cf8565b91506135d983612cf8565b92508282019050808211156135f1576135f0613594565b5b92915050565b600060a08201905061360c6000830188612e59565b6136196020830187612e59565b6136266040830186612e59565b6136336060830185612d9b565b6136406080830184612bf0565b9695505050505050565b600060808201905061365f6000830187612e59565b61366c6020830186612e25565b6136796040830185612e59565b6136866060830184612e59565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd
Deployed Bytecode Sourcemap
169:539:23:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4357:519:22;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1560:37;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2074:89:4;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4293:186;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;541:138:24;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3144:97:4;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5039:244;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7113:683:22;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3002:82:4;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2656:112:7;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5118:218:22;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;618:87:6;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;260:29:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1246:40:22;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6365:191;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3299:116:4;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5990:199:22;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;685:348:24;;;:::i;:::-;;1021:158:6;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;2406:143:7;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;5144:557:16;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;234:20:24;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2276:93:4;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6658:347:22;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5517:224;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3610:178:4;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3687:80:22;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7971:245;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3458:85;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1680:672:7;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3895:89:22;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1652:30;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1330:31;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3846:140:4;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4097:78:22;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1434:31;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1792:39;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4357:519;4436:4;4452:13;4468:25;4452:41;;4569:13;4585:38;4569:54;;4722:13;4738:40;4722:56;;4811:6;4795:22;;;:12;:22;;;;:48;;;;4837:6;4821:22;;;:12;:22;;;;4795:48;:74;;;;4863:6;4847:22;;;:12;:22;;;;4795:74;4788:81;;;;;4357:519;;;:::o;1560:37::-;;;:::o;2074:89:4:-;2119:13;2151:5;2144:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2074:89;:::o;4293:186::-;4366:4;4382:13;4398:12;:10;:12::i;:::-;4382:28;;4420:31;4429:5;4436:7;4445:5;4420:8;:31::i;:::-;4468:4;4461:11;;;4293:186;;;;:::o;541:138:24:-;1180:5;;;;;;;;;;;1166:19;;:10;:19;;;1162:43;;1194:11;;;;;;;;;;;;;;1162:43;629:6:::1;612:14;;:23;;;;;;;;;;;;;;;;;;650:22;665:6;650:22;;;;;;:::i;:::-;;;;;;;;541:138:::0;:::o;3144:97:4:-;3196:7;3222:12;;3215:19;;3144:97;:::o;5039:244::-;5126:4;5142:15;5160:12;:10;:12::i;:::-;5142:30;;5182:37;5198:4;5204:7;5213:5;5182:15;:37::i;:::-;5229:26;5239:4;5245:2;5249:5;5229:9;:26::i;:::-;5272:4;5265:11;;;5039:244;;;;;:::o;7113:683:22:-;2779:16;;;;;;;;;;;2765:30;;:10;:30;;;:53;;;;2813:5;;;;;;;;;;;2799:19;;:10;:19;;;2765:53;2757:87;;;;;;;;;;;;:::i;:::-;;;;;;;;;7223:1:::1;7197:28;;:14;:28;;::::0;7189:62:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;7296:4;7269:31;;:7;:23;7277:14;7269:23;;;;;;;;;;;;;;;;;;;;;;;;;:31;;;7261:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;7377:7;:23;7385:14;7377:23;;;;;;;;;;;;;;;;7370:30;;;;;;;;;;;7481:9;7476:269;7500:13;:20;;;;7496:1;:24;7476:269;;;7565:14;7545:34;;:13;7559:1;7545:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:34;;::::0;7541:194:::1;;7626:1;7599:13;7613:1;7599:16;;;;;;;;:::i;:::-;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;7715:5;;7541:194;7522:3;;;;;;;7476:269;;;;7760:29;7774:14;7760:29;;;;;;:::i;:::-;;;;;;;;7113:683:::0;:::o;3002:82:4:-;3051:5;3075:2;3068:9;;3002:82;:::o;2656:112:7:-;2715:7;2741:20;:18;:20::i;:::-;2734:27;;2656:112;:::o;5118:218:22:-;3166:6;3152:20;;:10;:20;;;3144:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;5277:19:::1;5283:3;5288:7;5277:5;:19::i;:::-;5316:3;5311:18;;;5321:7;5311:18;;;;;;:::i;:::-;;;;;;;;5118:218:::0;;:::o;618:87:6:-;672:26;678:12;:10;:12::i;:::-;692:5;672;:26::i;:::-;618:87;:::o;260:29:24:-;;;;;;;;;;;;;:::o;1246:40:22:-;;;;;;;;;;;;;;;;;;;:::o;6365:191::-;3004:4;2981:27;;:7;:19;2989:10;2981:19;;;;;;;;;;;;;;;;;;;;;;;;;:27;;;2973:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;6452:32:::1;6464:9;6475:8;6452:11;:32::i;:::-;6529:9;6499:50;;6517:10;6499:50;;;6540:8;6499:50;;;;;;:::i;:::-;;;;;;;;6365:191:::0;;:::o;3299:116:4:-;3364:7;3390:9;:18;3400:7;3390:18;;;;;;;;;;;;;;;;3383:25;;3299:116;;;:::o;5990:199:22:-;3004:4;2981:27;;:7;:19;2989:10;2981:19;;;;;;;;;;;;;;;;;;;;;;;;;:27;;;2973:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;6082:35:::1;6097:9;6108:8;6082:14;:35::i;:::-;6161:10;6132:50;;6150:9;6132:50;;;6173:8;6132:50;;;;;;:::i;:::-;;;;;;;;5990:199:::0;;:::o;685:348:24:-;856:14;;;;;;;;;;;842:28;;:10;:28;;;838:69;;879:28;;;;;;;;;;;;;;838:69;922:35;935:5;;;;;;;;;;;942:14;;;;;;;;;;;922:35;;;;;;;:::i;:::-;;;;;;;;975:14;;;;;;;;;;;967:5;;:22;;;;;;;;;;;;;;;;;;1024:1;999:14;;:27;;;;;;;;;;;;;;;;;;685:348::o;1021:158:6:-;1096:45;1112:7;1121:12;:10;:12::i;:::-;1135:5;1096:15;:45::i;:::-;1151:21;1157:7;1166:5;1151;:21::i;:::-;1021:158;;:::o;2406:143:7:-;2497:7;2523:19;2536:5;2523:12;:19::i;:::-;2516:26;;2406:143;;;:::o;5144:557:16:-;5242:13;5269:18;5301:21;5336:15;5365:25;5404:12;5430:27;5533:13;:11;:13::i;:::-;5560:16;:14;:16::i;:::-;5590:13;5625:4;5652:1;5644:10;;5682:1;5668:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5482:212;;;;;;;;;;;;;;;;;;;;;5144:557;;;;;;;:::o;234:20:24:-;;;;;;;;;;;;;:::o;2276:93:4:-;2323:13;2355:7;2348:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2276:93;:::o;6658:347:22:-;2779:16;;;;;;;;;;;2765:30;;:10;:30;;;:53;;;;2813:5;;;;;;;;;;;2799:19;;:10;:19;;;2765:53;2757:87;;;;;;;;;;;;:::i;:::-;;;;;;;;;6765:1:::1;6739:28;;:14;:28;;::::0;6731:62:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;6839:5;6812:32;;:7;:23;6820:14;6812:23;;;;;;;;;;;;;;;;;;;;;;;;;:32;;;6804:67;;;;;;;;;;;;:::i;:::-;;;;;;;;;6907:4;6881:7;:23;6889:14;6881:23;;;;;;;;;;;;;;;;:30;;;;;;;;;;;;;;;;;;6921:13;6940:14;6921:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6971:27;6983:14;6971:27;;;;;;:::i;:::-;;;;;;;;6658:347:::0;:::o;5517:224::-;3166:6;3152:20;;:10;:20;;;3144:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;5678:21:::1;5684:5;5691:7;5678:5;:21::i;:::-;5719:5;5714:20;;;5726:7;5714:20;;;;;;:::i;:::-;;;;;;;;5517:224:::0;;:::o;3610:178:4:-;3679:4;3695:13;3711:12;:10;:12::i;:::-;3695:28;;3733:27;3743:5;3750:2;3754:5;3733:9;:27::i;:::-;3777:4;3770:11;;;3610:178;;;;:::o;3687:80:22:-;3728:7;3754:6;3747:13;;3687:80;:::o;7971:245::-;2779:16;;;;;;;;;;;2765:30;;:10;:30;;;:53;;;;2813:5;;;;;;;;;;;2799:19;;:10;:19;;;2765:53;2757:87;;;;;;;;;;;;:::i;:::-;;;;;;;;;8086:1:::1;8057:31;;:17;:31;;::::0;8049:65:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;8143:17;8124:16;;:36;;;;;;;;;;;;;;;;;;8175:34;8191:17;8175:34;;;;;;:::i;:::-;;;;;;;;7971:245:::0;:::o;3458:85::-;3498:7;3524:12;3517:19;;3458:85;:::o;1680:672:7:-;1901:8;1883:15;:26;1879:97;;;1956:8;1932:33;;;;;;;;;;;:::i;:::-;;;;;;;;1879:97;1986:18;1022:95;2045:5;2052:7;2061:5;2068:16;2078:5;2068:9;:16::i;:::-;2086:8;2017:78;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2007:89;;;;;;1986:110;;2107:12;2122:28;2139:10;2122:16;:28::i;:::-;2107:43;;2161:14;2178:28;2192:4;2198:1;2201;2204;2178:13;:28::i;:::-;2161:45;;2230:5;2220:15;;:6;:15;;;2216:88;;2279:6;2287:5;2258:35;;;;;;;;;;;;:::i;:::-;;;;;;;;2216:88;2314:31;2323:5;2330:7;2339:5;2314:8;:31::i;:::-;1869:483;;;1680:672;;;;;;;:::o;3895:89:22:-;3939:7;3965:12;3958:19;;3895:89;:::o;1652:30::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1330:31::-;;;;;;;;;;;;;:::o;3846:140:4:-;3926:7;3952:11;:18;3964:5;3952:18;;;;;;;;;;;;;;;:27;3971:7;3952:27;;;;;;;;;;;;;;;;3945:34;;3846:140;;;;:::o;4097:78:22:-;4136:7;4162:6;4155:13;;4097:78;:::o;1434:31::-;;;:::o;1792:39::-;;;;;;;;;;;;;;;;;;;;;;:::o;656:96:10:-;709:7;735:10;728:17;;656:96;:::o;8989:128:4:-;9073:37;9082:5;9089:7;9098:5;9105:4;9073:8;:37::i;:::-;8989:128;;;:::o;10663:477::-;10762:24;10789:25;10799:5;10806:7;10789:9;:25::i;:::-;10762:52;;10848:17;10828:16;:37;10824:310;;10904:5;10885:16;:24;10881:130;;;10963:7;10972:16;10990:5;10936:60;;;;;;;;;;;;;:::i;:::-;;;;;;;;10881:130;11052:57;11061:5;11068:7;11096:5;11077:16;:24;11103:5;11052:8;:57::i;:::-;10824:310;10752:388;10663:477;;;:::o;5656:300::-;5755:1;5739:18;;:4;:18;;;5735:86;;5807:1;5780:30;;;;;;;;;;;:::i;:::-;;;;;;;;5735:86;5848:1;5834:16;;:2;:16;;;5830:86;;5902:1;5873:32;;;;;;;;;;;:::i;:::-;;;;;;;;5830:86;5925:24;5933:4;5939:2;5943:5;5925:7;:24::i;:::-;5656:300;;;:::o;3845:262:16:-;3898:7;3938:11;3921:28;;3929:4;3921:28;;;:63;;;;;3970:14;3953:13;:31;3921:63;3917:184;;;4007:22;4000:29;;;;3917:184;4067:23;:21;:23::i;:::-;4060:30;;3845:262;;:::o;7721:208:4:-;7810:1;7791:21;;:7;:21;;;7787:91;;7864:1;7835:32;;;;;;;;;;;:::i;:::-;;;;;;;;7787:91;7887:35;7903:1;7907:7;7916:5;7887:7;:35::i;:::-;7721:208;;:::o;8247:206::-;8336:1;8317:21;;:7;:21;;;8313:89;;8388:1;8361:30;;;;;;;;;;;:::i;:::-;;;;;;;;8313:89;8411:35;8419:7;8436:1;8440:5;8411:7;:35::i;:::-;8247:206;;:::o;538:107:11:-;598:7;624;:14;632:5;624:14;;;;;;;;;;;;;;;;617:21;;538:107;;;:::o;6021:126:16:-;6067:13;6099:41;6126:13;6099:5;:26;;:41;;;;:::i;:::-;6092:48;;6021:126;:::o;6473:135::-;6522:13;6554:47;6584:16;6554:8;:29;;:47;;;;:::i;:::-;6547:54;;6473:135;:::o;759:395:11:-;819:7;1121;:14;1129:5;1121:14;;;;;;;;;;;;;;;;:16;;;;;;;;;;;;1114:23;;759:395;;;:::o;4917:176:16:-;4994:7;5020:66;5053:20;:18;:20::i;:::-;5075:10;5020:32;:66::i;:::-;5013:73;;4917:176;;;:::o;6803:260:15:-;6888:7;6908:17;6927:18;6947:16;6967:25;6978:4;6984:1;6987;6990;6967:10;:25::i;:::-;6907:85;;;;;;7002:28;7014:5;7021:8;7002:11;:28::i;:::-;7047:9;7040:16;;;;;6803:260;;;;;;:::o;9949:432:4:-;10078:1;10061:19;;:5;:19;;;10057:89;;10132:1;10103:32;;;;;;;;;;;:::i;:::-;;;;;;;;10057:89;10178:1;10159:21;;:7;:21;;;10155:90;;10231:1;10203:31;;;;;;;;;;;:::i;:::-;;;;;;;;10155:90;10284:5;10254:11;:18;10266:5;10254:18;;;;;;;;;;;;;;;:27;10273:7;10254:27;;;;;;;;;;;;;;;:35;;;;10303:9;10299:76;;;10349:7;10333:31;;10342:5;10333:31;;;10358:5;10333:31;;;;;;:::i;:::-;;;;;;;;10299:76;9949:432;;;;:::o;6271:1107::-;6376:1;6360:18;;:4;:18;;;6356:540;;6512:5;6496:12;;:21;;;;;;;:::i;:::-;;;;;;;;6356:540;;;6548:19;6570:9;:15;6580:4;6570:15;;;;;;;;;;;;;;;;6548:37;;6617:5;6603:11;:19;6599:115;;;6674:4;6680:11;6693:5;6649:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;6599:115;6866:5;6852:11;:19;6834:9;:15;6844:4;6834:15;;;;;;;;;;;;;;;:37;;;;6534:362;6356:540;6924:1;6910:16;;:2;:16;;;6906:425;;7089:5;7073:12;;:21;;;;;;;;;;;6906:425;;;7301:5;7284:9;:13;7294:2;7284:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;6906:425;7361:2;7346:25;;7355:4;7346:25;;;7365:5;7346:25;;;;;;:::i;:::-;;;;;;;;6271:1107;;;:::o;4113:179:16:-;4168:7;2079:95;4226:11;4239:14;4255:13;4278:4;4204:80;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;4194:91;;;;;;4187:98;;4113:179;:::o;3385:267:12:-;3479:13;1390:66;3537:17;;3527:5;3508:46;3504:142;;3577:15;3586:5;3577:8;:15::i;:::-;3570:22;;;;3504:142;3630:5;3623:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3385:267;;;;;:::o;3353:401:17:-;3446:14;3555:4;3549:11;3585:10;3580:3;3573:23;3632:15;3625:4;3620:3;3616:14;3609:39;3684:10;3677:4;3672:3;3668:14;3661:34;3733:4;3728:3;3718:20;3708:30;;3524:224;3353:401;;;;:::o;5140:1530:15:-;5266:7;5275:12;5289:7;6199:66;6194:1;6186:10;;:79;6182:164;;;6297:1;6301:30;6333:1;6281:54;;;;;;;;6182:164;6440:14;6457:24;6467:4;6473:1;6476;6479;6457:24;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6440:41;;6513:1;6495:20;;:6;:20;;;6491:113;;6547:1;6551:29;6590:1;6582:10;;6531:62;;;;;;;;;6491:113;6622:6;6630:20;6660:1;6652:10;;6614:49;;;;;;;5140:1530;;;;;;;;;:::o;7196:532::-;7291:20;7282:29;;;;;;;;:::i;:::-;;:5;:29;;;;;;;;:::i;:::-;;;7278:444;7327:7;7278:444;7387:29;7378:38;;;;;;;;:::i;:::-;;:5;:38;;;;;;;;:::i;:::-;;;7374:348;;7439:23;;;;;;;;;;;;;;7374:348;7492:35;7483:44;;;;;;;;:::i;:::-;;:5;:44;;;;;;;;:::i;:::-;;;7479:243;;7586:8;7578:17;;7550:46;;;;;;;;;;;:::i;:::-;;;;;;;;7479:243;7626:30;7617:39;;;;;;;;:::i;:::-;;:5;:39;;;;;;;;:::i;:::-;;;7613:109;;7702:8;7679:32;;;;;;;;;;;:::i;:::-;;;;;;;;7613:109;7196:532;;;:::o;2078:405:12:-;2137:13;2162:11;2176:16;2187:4;2176:10;:16::i;:::-;2162:30;;2280:17;2311:2;2300:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2280:34;;2402:3;2397;2390:16;2442:4;2435;2430:3;2426:14;2419:28;2473:3;2466:10;;;;2078:405;;;:::o;2555:245::-;2616:7;2635:14;2688:4;2679;2652:33;;:40;2635:57;;2715:2;2706:6;:11;2702:69;;;2740:20;;;;;;;;;;;;;;2702:69;2787:6;2780:13;;;2555:245;;;:::o;88:117:25:-;197:1;194;187:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:126::-;1555:7;1595:42;1588:5;1584:54;1573:65;;1518:126;;;:::o;1650:96::-;1687:7;1716:24;1734:5;1716:24;:::i;:::-;1705:35;;1650:96;;;:::o;1752:118::-;1839:24;1857:5;1839:24;:::i;:::-;1834:3;1827:37;1752:118;;:::o;1876:222::-;1969:4;2007:2;1996:9;1992:18;1984:26;;2020:71;2088:1;2077:9;2073:17;2064:6;2020:71;:::i;:::-;1876:222;;;;:::o;2104:99::-;2156:6;2190:5;2184:12;2174:22;;2104:99;;;:::o;2209:169::-;2293:11;2327:6;2322:3;2315:19;2367:4;2362:3;2358:14;2343:29;;2209:169;;;;:::o;2384:246::-;2465:1;2475:113;2489:6;2486:1;2483:13;2475:113;;;2574:1;2569:3;2565:11;2559:18;2555:1;2550:3;2546:11;2539:39;2511:2;2508:1;2504:10;2499:15;;2475:113;;;2622:1;2613:6;2608:3;2604:16;2597:27;2446:184;2384:246;;;:::o;2636:102::-;2677:6;2728:2;2724:7;2719:2;2712:5;2708:14;2704:28;2694:38;;2636:102;;;:::o;2744:377::-;2832:3;2860:39;2893:5;2860:39;:::i;:::-;2915:71;2979:6;2974:3;2915:71;:::i;:::-;2908:78;;2995:65;3053:6;3048:3;3041:4;3034:5;3030:16;2995:65;:::i;:::-;3085:29;3107:6;3085:29;:::i;:::-;3080:3;3076:39;3069:46;;2836:285;2744:377;;;;:::o;3127:313::-;3240:4;3278:2;3267:9;3263:18;3255:26;;3327:9;3321:4;3317:20;3313:1;3302:9;3298:17;3291:47;3355:78;3428:4;3419:6;3355:78;:::i;:::-;3347:86;;3127:313;;;;:::o;3446:122::-;3519:24;3537:5;3519:24;:::i;:::-;3512:5;3509:35;3499:63;;3558:1;3555;3548:12;3499:63;3446:122;:::o;3574:139::-;3620:5;3658:6;3645:20;3636:29;;3674:33;3701:5;3674:33;:::i;:::-;3574:139;;;;:::o;3719:77::-;3756:7;3785:5;3774:16;;3719:77;;;:::o;3802:122::-;3875:24;3893:5;3875:24;:::i;:::-;3868:5;3865:35;3855:63;;3914:1;3911;3904:12;3855:63;3802:122;:::o;3930:139::-;3976:5;4014:6;4001:20;3992:29;;4030:33;4057:5;4030:33;:::i;:::-;3930:139;;;;:::o;4075:474::-;4143:6;4151;4200:2;4188:9;4179:7;4175:23;4171:32;4168:119;;;4206:79;;:::i;:::-;4168:119;4326:1;4351:53;4396:7;4387:6;4376:9;4372:22;4351:53;:::i;:::-;4341:63;;4297:117;4453:2;4479:53;4524:7;4515:6;4504:9;4500:22;4479:53;:::i;:::-;4469:63;;4424:118;4075:474;;;;;:::o;4555:329::-;4614:6;4663:2;4651:9;4642:7;4638:23;4634:32;4631:119;;;4669:79;;:::i;:::-;4631:119;4789:1;4814:53;4859:7;4850:6;4839:9;4835:22;4814:53;:::i;:::-;4804:63;;4760:117;4555:329;;;;:::o;4890:118::-;4977:24;4995:5;4977:24;:::i;:::-;4972:3;4965:37;4890:118;;:::o;5014:222::-;5107:4;5145:2;5134:9;5130:18;5122:26;;5158:71;5226:1;5215:9;5211:17;5202:6;5158:71;:::i;:::-;5014:222;;;;:::o;5242:619::-;5319:6;5327;5335;5384:2;5372:9;5363:7;5359:23;5355:32;5352:119;;;5390:79;;:::i;:::-;5352:119;5510:1;5535:53;5580:7;5571:6;5560:9;5556:22;5535:53;:::i;:::-;5525:63;;5481:117;5637:2;5663:53;5708:7;5699:6;5688:9;5684:22;5663:53;:::i;:::-;5653:63;;5608:118;5765:2;5791:53;5836:7;5827:6;5816:9;5812:22;5791:53;:::i;:::-;5781:63;;5736:118;5242:619;;;;;:::o;5867:86::-;5902:7;5942:4;5935:5;5931:16;5920:27;;5867:86;;;:::o;5959:112::-;6042:22;6058:5;6042:22;:::i;:::-;6037:3;6030:35;5959:112;;:::o;6077:214::-;6166:4;6204:2;6193:9;6189:18;6181:26;;6217:67;6281:1;6270:9;6266:17;6257:6;6217:67;:::i;:::-;6077:214;;;;:::o;6297:77::-;6334:7;6363:5;6352:16;;6297:77;;;:::o;6380:118::-;6467:24;6485:5;6467:24;:::i;:::-;6462:3;6455:37;6380:118;;:::o;6504:222::-;6597:4;6635:2;6624:9;6620:18;6612:26;;6648:71;6716:1;6705:9;6701:17;6692:6;6648:71;:::i;:::-;6504:222;;;;:::o;6732:329::-;6791:6;6840:2;6828:9;6819:7;6815:23;6811:32;6808:119;;;6846:79;;:::i;:::-;6808:119;6966:1;6991:53;7036:7;7027:6;7016:9;7012:22;6991:53;:::i;:::-;6981:63;;6937:117;6732:329;;;;:::o;7067:149::-;7103:7;7143:66;7136:5;7132:78;7121:89;;7067:149;;;:::o;7222:115::-;7307:23;7324:5;7307:23;:::i;:::-;7302:3;7295:36;7222:115;;:::o;7343:114::-;7410:6;7444:5;7438:12;7428:22;;7343:114;;;:::o;7463:184::-;7562:11;7596:6;7591:3;7584:19;7636:4;7631:3;7627:14;7612:29;;7463:184;;;;:::o;7653:132::-;7720:4;7743:3;7735:11;;7773:4;7768:3;7764:14;7756:22;;7653:132;;;:::o;7791:108::-;7868:24;7886:5;7868:24;:::i;:::-;7863:3;7856:37;7791:108;;:::o;7905:179::-;7974:10;7995:46;8037:3;8029:6;7995:46;:::i;:::-;8073:4;8068:3;8064:14;8050:28;;7905:179;;;;:::o;8090:113::-;8160:4;8192;8187:3;8183:14;8175:22;;8090:113;;;:::o;8239:732::-;8358:3;8387:54;8435:5;8387:54;:::i;:::-;8457:86;8536:6;8531:3;8457:86;:::i;:::-;8450:93;;8567:56;8617:5;8567:56;:::i;:::-;8646:7;8677:1;8662:284;8687:6;8684:1;8681:13;8662:284;;;8763:6;8757:13;8790:63;8849:3;8834:13;8790:63;:::i;:::-;8783:70;;8876:60;8929:6;8876:60;:::i;:::-;8866:70;;8722:224;8709:1;8706;8702:9;8697:14;;8662:284;;;8666:14;8962:3;8955:10;;8363:608;;;8239:732;;;;:::o;8977:1215::-;9326:4;9364:3;9353:9;9349:19;9341:27;;9378:69;9444:1;9433:9;9429:17;9420:6;9378:69;:::i;:::-;9494:9;9488:4;9484:20;9479:2;9468:9;9464:18;9457:48;9522:78;9595:4;9586:6;9522:78;:::i;:::-;9514:86;;9647:9;9641:4;9637:20;9632:2;9621:9;9617:18;9610:48;9675:78;9748:4;9739:6;9675:78;:::i;:::-;9667:86;;9763:72;9831:2;9820:9;9816:18;9807:6;9763:72;:::i;:::-;9845:73;9913:3;9902:9;9898:19;9889:6;9845:73;:::i;:::-;9928;9996:3;9985:9;9981:19;9972:6;9928:73;:::i;:::-;10049:9;10043:4;10039:20;10033:3;10022:9;10018:19;10011:49;10077:108;10180:4;10171:6;10077:108;:::i;:::-;10069:116;;8977:1215;;;;;;;;;;:::o;10198:118::-;10269:22;10285:5;10269:22;:::i;:::-;10262:5;10259:33;10249:61;;10306:1;10303;10296:12;10249:61;10198:118;:::o;10322:135::-;10366:5;10404:6;10391:20;10382:29;;10420:31;10445:5;10420:31;:::i;:::-;10322:135;;;;:::o;10463:122::-;10536:24;10554:5;10536:24;:::i;:::-;10529:5;10526:35;10516:63;;10575:1;10572;10565:12;10516:63;10463:122;:::o;10591:139::-;10637:5;10675:6;10662:20;10653:29;;10691:33;10718:5;10691:33;:::i;:::-;10591:139;;;;:::o;10736:1199::-;10847:6;10855;10863;10871;10879;10887;10895;10944:3;10932:9;10923:7;10919:23;10915:33;10912:120;;;10951:79;;:::i;:::-;10912:120;11071:1;11096:53;11141:7;11132:6;11121:9;11117:22;11096:53;:::i;:::-;11086:63;;11042:117;11198:2;11224:53;11269:7;11260:6;11249:9;11245:22;11224:53;:::i;:::-;11214:63;;11169:118;11326:2;11352:53;11397:7;11388:6;11377:9;11373:22;11352:53;:::i;:::-;11342:63;;11297:118;11454:2;11480:53;11525:7;11516:6;11505:9;11501:22;11480:53;:::i;:::-;11470:63;;11425:118;11582:3;11609:51;11652:7;11643:6;11632:9;11628:22;11609:51;:::i;:::-;11599:61;;11553:117;11709:3;11736:53;11781:7;11772:6;11761:9;11757:22;11736:53;:::i;:::-;11726:63;;11680:119;11838:3;11865:53;11910:7;11901:6;11890:9;11886:22;11865:53;:::i;:::-;11855:63;;11809:119;10736:1199;;;;;;;;;;:::o;11941:474::-;12009:6;12017;12066:2;12054:9;12045:7;12041:23;12037:32;12034:119;;;12072:79;;:::i;:::-;12034:119;12192:1;12217:53;12262:7;12253:6;12242:9;12238:22;12217:53;:::i;:::-;12207:63;;12163:117;12319:2;12345:53;12390:7;12381:6;12370:9;12366:22;12345:53;:::i;:::-;12335:63;;12290:118;11941:474;;;;;:::o;12421:180::-;12469:77;12466:1;12459:88;12566:4;12563:1;12556:15;12590:4;12587:1;12580:15;12607:320;12651:6;12688:1;12682:4;12678:12;12668:22;;12735:1;12729:4;12725:12;12756:18;12746:81;;12812:4;12804:6;12800:17;12790:27;;12746:81;12874:2;12866:6;12863:14;12843:18;12840:38;12837:84;;12893:18;;:::i;:::-;12837:84;12658:269;12607:320;;;:::o;12933:171::-;13073:23;13069:1;13061:6;13057:14;13050:47;12933:171;:::o;13110:366::-;13252:3;13273:67;13337:2;13332:3;13273:67;:::i;:::-;13266:74;;13349:93;13438:3;13349:93;:::i;:::-;13467:2;13462:3;13458:12;13451:19;;13110:366;;;:::o;13482:419::-;13648:4;13686:2;13675:9;13671:18;13663:26;;13735:9;13729:4;13725:20;13721:1;13710:9;13706:17;13699:47;13763:131;13889:4;13763:131;:::i;:::-;13755:139;;13482:419;;;:::o;13907:171::-;14047:23;14043:1;14035:6;14031:14;14024:47;13907:171;:::o;14084:366::-;14226:3;14247:67;14311:2;14306:3;14247:67;:::i;:::-;14240:74;;14323:93;14412:3;14323:93;:::i;:::-;14441:2;14436:3;14432:12;14425:19;;14084:366;;;:::o;14456:419::-;14622:4;14660:2;14649:9;14645:18;14637:26;;14709:9;14703:4;14699:20;14695:1;14684:9;14680:17;14673:47;14737:131;14863:4;14737:131;:::i;:::-;14729:139;;14456:419;;;:::o;14881:169::-;15021:21;15017:1;15009:6;15005:14;14998:45;14881:169;:::o;15056:366::-;15198:3;15219:67;15283:2;15278:3;15219:67;:::i;:::-;15212:74;;15295:93;15384:3;15295:93;:::i;:::-;15413:2;15408:3;15404:12;15397:19;;15056:366;;;:::o;15428:419::-;15594:4;15632:2;15621:9;15617:18;15609:26;;15681:9;15675:4;15671:20;15667:1;15656:9;15652:17;15645:47;15709:131;15835:4;15709:131;:::i;:::-;15701:139;;15428:419;;;:::o;15853:180::-;15901:77;15898:1;15891:88;15998:4;15995:1;15988:15;16022:4;16019:1;16012:15;16039:239;16179:34;16175:1;16167:6;16163:14;16156:58;16248:22;16243:2;16235:6;16231:15;16224:47;16039:239;:::o;16284:366::-;16426:3;16447:67;16511:2;16506:3;16447:67;:::i;:::-;16440:74;;16523:93;16612:3;16523:93;:::i;:::-;16641:2;16636:3;16632:12;16625:19;;16284:366;;;:::o;16656:419::-;16822:4;16860:2;16849:9;16845:18;16837:26;;16909:9;16903:4;16899:20;16895:1;16884:9;16880:17;16873:47;16937:131;17063:4;16937:131;:::i;:::-;16929:139;;16656:419;;;:::o;17081:162::-;17221:14;17217:1;17209:6;17205:14;17198:38;17081:162;:::o;17249:366::-;17391:3;17412:67;17476:2;17471:3;17412:67;:::i;:::-;17405:74;;17488:93;17577:3;17488:93;:::i;:::-;17606:2;17601:3;17597:12;17590:19;;17249:366;;;:::o;17621:419::-;17787:4;17825:2;17814:9;17810:18;17802:26;;17874:9;17868:4;17864:20;17860:1;17849:9;17845:17;17838:47;17902:131;18028:4;17902:131;:::i;:::-;17894:139;;17621:419;;;:::o;18046:332::-;18167:4;18205:2;18194:9;18190:18;18182:26;;18218:71;18286:1;18275:9;18271:17;18262:6;18218:71;:::i;:::-;18299:72;18367:2;18356:9;18352:18;18343:6;18299:72;:::i;:::-;18046:332;;;;;:::o;18384:180::-;18432:77;18429:1;18422:88;18529:4;18526:1;18519:15;18553:4;18550:1;18543:15;18570:172;18710:24;18706:1;18698:6;18694:14;18687:48;18570:172;:::o;18748:366::-;18890:3;18911:67;18975:2;18970:3;18911:67;:::i;:::-;18904:74;;18987:93;19076:3;18987:93;:::i;:::-;19105:2;19100:3;19096:12;19089:19;;18748:366;;;:::o;19120:419::-;19286:4;19324:2;19313:9;19309:18;19301:26;;19373:9;19367:4;19363:20;19359:1;19348:9;19344:17;19337:47;19401:131;19527:4;19401:131;:::i;:::-;19393:139;;19120:419;;;:::o;19545:775::-;19778:4;19816:3;19805:9;19801:19;19793:27;;19830:71;19898:1;19887:9;19883:17;19874:6;19830:71;:::i;:::-;19911:72;19979:2;19968:9;19964:18;19955:6;19911:72;:::i;:::-;19993;20061:2;20050:9;20046:18;20037:6;19993:72;:::i;:::-;20075;20143:2;20132:9;20128:18;20119:6;20075:72;:::i;:::-;20157:73;20225:3;20214:9;20210:19;20201:6;20157:73;:::i;:::-;20240;20308:3;20297:9;20293:19;20284:6;20240:73;:::i;:::-;19545:775;;;;;;;;;:::o;20326:442::-;20475:4;20513:2;20502:9;20498:18;20490:26;;20526:71;20594:1;20583:9;20579:17;20570:6;20526:71;:::i;:::-;20607:72;20675:2;20664:9;20660:18;20651:6;20607:72;:::i;:::-;20689;20757:2;20746:9;20742:18;20733:6;20689:72;:::i;:::-;20326:442;;;;;;:::o;20774:180::-;20822:77;20819:1;20812:88;20919:4;20916:1;20909:15;20943:4;20940:1;20933:15;20960:191;21000:3;21019:20;21037:1;21019:20;:::i;:::-;21014:25;;21053:20;21071:1;21053:20;:::i;:::-;21048:25;;21096:1;21093;21089:9;21082:16;;21117:3;21114:1;21111:10;21108:36;;;21124:18;;:::i;:::-;21108:36;20960:191;;;;:::o;21157:664::-;21362:4;21400:3;21389:9;21385:19;21377:27;;21414:71;21482:1;21471:9;21467:17;21458:6;21414:71;:::i;:::-;21495:72;21563:2;21552:9;21548:18;21539:6;21495:72;:::i;:::-;21577;21645:2;21634:9;21630:18;21621:6;21577:72;:::i;:::-;21659;21727:2;21716:9;21712:18;21703:6;21659:72;:::i;:::-;21741:73;21809:3;21798:9;21794:19;21785:6;21741:73;:::i;:::-;21157:664;;;;;;;;:::o;21827:545::-;22000:4;22038:3;22027:9;22023:19;22015:27;;22052:71;22120:1;22109:9;22105:17;22096:6;22052:71;:::i;:::-;22133:68;22197:2;22186:9;22182:18;22173:6;22133:68;:::i;:::-;22211:72;22279:2;22268:9;22264:18;22255:6;22211:72;:::i;:::-;22293;22361:2;22350:9;22346:18;22337:6;22293:72;:::i;:::-;21827:545;;;;;;;:::o;22378:180::-;22426:77;22423:1;22416:88;22523:4;22520:1;22513:15;22547:4;22544:1;22537:15
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.