ETH Price: $1,999.81 (+3.24%)
Gas: 0.04 Gwei

Contract

0xAC74F987d8C7583473fB4cB50E85f1EEe1e81677
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Transfer Ownersh...165408112023-02-02 11:26:591131 days ago1675337219IN
0xAC74F987...Ee1e81677
0 ETH0.0007166715.53050238
Claim Ownership164914442023-01-26 13:59:471138 days ago1674741587IN
0xAC74F987...Ee1e81677
0 ETH0.0005692220

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60806040164914362023-01-26 13:58:111138 days ago1674741491  Contract Creation0 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SmartController

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion, Apache-2.0 license

Contract Source Code (Solidity Multiple files format)

File 1 of 31: SmartController.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

import "./SmartTokenLib.sol";
import "./MintableController.sol";
import "./IValidator.sol";

/**
 * @title SmartController
 * @dev This contract adds "smart" functionality which is required from a regulatory perspective.
 */
contract SmartController is MintableController {

    using SmartTokenLib for SmartTokenLib.SmartStorage;

    SmartTokenLib.SmartStorage internal smartToken;

    bytes3 public ticker;
    uint constant public INITIAL_SUPPLY = 0;

    /**
     * @dev Contract constructor.
     * @param storage_ Address of the token storage for the controller.
     * @param validator Address of validator.
     * @param ticker_ 3 letter currency ticker.
     * @param frontend_ Address of the authorized frontend.
     */
    constructor(address storage_, address validator, bytes3 ticker_, address frontend_)
        MintableController(storage_, INITIAL_SUPPLY, frontend_)
    {
        require(validator != address(0x0), "validator cannot be the null address");
        smartToken.setValidator(validator);
        ticker = ticker_;
    }

    /**
     * @dev Sets a new validator.
     * @param validator Address of validator.
     */
    function setValidator(address validator) external onlySystemAccounts {
        smartToken.setValidator(validator);
    }

    /**
     * @dev Recovers tokens from an address and reissues them to another address.
     * In case a user loses its private key the tokens can be recovered by burning
     * the tokens from that address and reissuing to a new address.
     * To recover tokens the contract owner needs to provide a signature
     * proving that the token owner has authorized the owner to do so.
     * @param caller Address of the caller passed through the frontend.
     * @param from Address to burn tokens from.
     * @param to Address to mint tokens to.
     * @param h Hash which the token owner signed.
     * @param v Signature component.
     * @param r Signature component.
     * @param s Sigature component.
     * @return Amount recovered.
     */
    function recover_withCaller(address caller, address from, address to, bytes32 h, uint8 v, bytes32 r, bytes32 s)
        external
        guarded(caller)
        onlySystemAccount(caller)
        returns (uint)
    {
        avoidBlackholes(to);
        return SmartTokenLib.recover(token, from, to, h, v, r, s);
    }

    /**
     * @dev Transfers tokens [ERC20].
     * The caller, to address and amount are validated before executing method.
     * Prior to transfering tokens the validator needs to approve.
     * @notice Overrides method in a parent.
     * @param caller Address of the caller passed through the frontend.
     * @param to Recipient address.
     * @param amount Number of tokens to transfer.
     */
    function transfer_withCaller(address caller, address to, uint amount)
        public
        override
        guarded(caller)
        whenNotPaused
        returns (bool)
    {
        require(smartToken.validate(caller, to, amount), "transfer request not valid");
        return super.transfer_withCaller(caller, to, amount);
    }

    /**
     * @dev Transfers tokens from a specific address [ERC20].
     * The address owner has to approve the spender beforehand.
     * The from address, to address and amount are validated before executing method.
     * @notice Overrides method in a parent.
     * Prior to transfering tokens the validator needs to approve.
     * @param caller Address of the caller passed through the frontend.
     * @param from Address to debet the tokens from.
     * @param to Recipient address.
     * @param amount Number of tokens to transfer.
     */
    function transferFrom_withCaller(address caller, address from, address to, uint amount)
        public
        override
        guarded(caller)
        whenNotPaused
        returns (bool)
    {
        require(smartToken.validate(from, to, amount), "transferFrom request not valid");
        return super.transferFrom_withCaller(caller, from, to, amount);
    }

    /**
     * @dev Transfers tokens and subsequently calls a method on the recipient [ERC677].
     * If the recipient is a non-contract address this method behaves just like transfer.
     * The caller, to address and amount are validated before executing method.
     * @notice Overrides method in a parent.
     * @param caller Address of the caller passed through the frontend.
     * @param to Recipient address.
     * @param amount Number of tokens to transfer.
     * @param data Additional data passed to the recipient's tokenFallback method.
     */
    function transferAndCall_withCaller(
        address caller,
        address to,
        uint256 amount,
        bytes calldata data
    )
        public
        override
        guarded(caller)
        whenNotPaused
        returns (bool)
    {
        require(smartToken.validate(caller, to, amount), "transferAndCall request not valid");
        return super.transferAndCall_withCaller(caller, to, amount, data);
    }

    /**
     * @dev Gets the current validator.
     * @return Address of validator.
     */
    function getValidator() external view returns (address) {
        return smartToken.getValidator();
    }

}

File 2 of 31: Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 3 of 31: CanReclaimToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./Ownable.sol";
import "./ERC20Basic.sol";
import "./SafeERC20.sol";

/**
 * @title Contracts that should be able to recover tokens
 * @author SylTi
 * @dev This allow a contract to recover any ERC20 token received in a contract by transferring the balance to the contract owner.
 * This will prevent any accidental loss of tokens.
 */
contract CanReclaimToken is Ownable {
  using SafeERC20 for ERC20Basic;

  /**
   * @dev Reclaim all ERC20Basic compatible tokens
   * @param _token ERC20Basic The address of the token contract
   */
  function reclaimToken(ERC20Basic _token) external onlyOwner {
    uint256 balance = _token.balanceOf(address(this));
    _token.safeTransfer(owner, balance);
  }

}

File 4 of 31: Claimable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./Ownable.sol";

/**
 * @title Claimable
 * @dev Extension for the Ownable contract, where the ownership needs to be claimed.
 * This allows the new owner to accept the transfer.
 */
abstract contract Claimable is Ownable {
  address public pendingOwner;

  /**
   * @dev Modifier throws if called by any account other than the pendingOwner.
   */
  modifier onlyPendingOwner() {
    require(msg.sender == pendingOwner);
    _;
  }

  /**
   * @dev Allows the current owner to set the pendingOwner address.
   * @param newOwner The address to transfer ownership to.
   */
  function transferOwnership(address newOwner) public virtual override onlyOwner {
    pendingOwner = newOwner;
  }

  /**
   * @dev Allows the pendingOwner address to finalize the transfer.
   */
  function claimOwnership() public onlyPendingOwner {
    emit OwnershipTransferred(owner, pendingOwner);
    owner = pendingOwner;
    pendingOwner = address(0);
  }
}

File 5 of 31: Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 6 of 31: ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "./Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        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.
            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 if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 7 of 31: ERC20Basic.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;


/**
 * @title ERC20Basic
 * @dev Simpler version of ERC20 interface
 * See https://github.com/ethereum/EIPs/issues/179
 */
abstract contract ERC20Basic {
  function totalSupply() public virtual view returns (uint256);
  function balanceOf(address _who) public virtual view returns (uint256);
  function transfer(address _to, uint256 _value) public virtual returns (bool);
  event Transfer(address indexed from, address indexed to, uint256 value);
}

File 8 of 31: ERC20Lib.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

import "./SafeMath.sol";
import "./TokenStorage.sol";

/**
 * @title ERC20Lib
 * @dev Standard ERC20 token functionality.
 * https://github.com/ethereum/EIPs/issues/20
 */
library ERC20Lib {

    using SafeMath for uint;

    /**
     * @dev Transfers tokens [ERC20].
     * @param db Token storage to operate on.
     * @param caller Address of the caller passed through the frontend.
     * @param to Recipient address.
     * @param amount Number of tokens to transfer.
     */
    function transfer(TokenStorage db, address caller, address to, uint amount)
        external
        returns (bool success)
    {
        db.subBalance(caller, amount);
        db.addBalance(to, amount);
        return true;
    }

    /**
     * @dev Transfers tokens from a specific address [ERC20].
     * The address owner has to approve the spender beforehand.
     * @param db Token storage to operate on.
     * @param caller Address of the caller passed through the frontend.
     * @param from Address to debet the tokens from.
     * @param to Recipient address.
     * @param amount Number of tokens to transfer.
     */
    function transferFrom(
        TokenStorage db,
        address caller,
        address from,
        address to,
        uint amount
    )
        external
        returns (bool success)
    {
        uint allowance_ = db.getAllowed(from, caller);
        db.subBalance(from, amount);
        db.addBalance(to, amount);
        db.setAllowed(from, caller, allowance_.sub(amount));
        return true;
    }

    /**
     * @dev Approves a spender [ERC20].
     * Note that using the approve/transferFrom presents a possible
     * security vulnerability described in:
     * https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/edit#heading=h.quou09mcbpzw
     * Use transferAndCall to mitigate.
     * @param db Token storage to operate on.
     * @param caller Address of the caller passed through the frontend.
     * @param spender The address of the future spender.
     * @param amount The allowance of the spender.
     */
    function approve(TokenStorage db, address caller, address spender, uint amount)
        public
        returns (bool success)
    {
        db.setAllowed(caller, spender, amount);
        return true;
    }

    /**
     * @dev Returns the number tokens associated with an address.
     * @param db Token storage to operate on.
     * @param who Address to lookup.
     * @return balance Balance of address.
     */
    function balanceOf(TokenStorage db, address who)
        external
        view
        returns (uint balance)
    {
        return db.getBalance(who);
    }

    /**
     * @dev Returns the allowance for a spender
     * @param db Token storage to operate on.
     * @param owner The address of the owner of the tokens.
     * @param spender The address of the spender.
     * @return remaining Number of tokens the spender is allowed to spend.
     */
    function allowance(TokenStorage db, address owner, address spender)
        external
        view
        returns (uint remaining)
    {
        return db.getAllowed(owner, spender);
    }

}

File 9 of 31: ERC677Lib.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

import "./Address.sol";
import "./IERC677Recipient.sol";
import "./TokenStorage.sol";
import "./ERC20Lib.sol";

/**
 * @title ERC677
 * @dev ERC677 token functionality.
 * https://github.com/ethereum/EIPs/issues/677
 */
library ERC677Lib {

    using ERC20Lib for TokenStorage;
    using Address for address;

    /**
     * @dev Transfers tokens and subsequently calls a method on the recipient [ERC677].
     * If the recipient is a non-contract address this method behaves just like transfer.
     * @notice db.transfer either returns true or reverts.
     * @param db Token storage to operate on.
     * @param caller Address of the caller passed through the frontend.
     * @param to Recipient address.
     * @param amount Number of tokens to transfer.
     * @param data Additional data passed to the recipient's tokenFallback method.
     */
    function transferAndCall(
        TokenStorage db,
        address caller,
        address to,
        uint256 amount,
        bytes calldata data
    )
        external
        returns (bool)
    {
        require(
            db.transfer(caller, to, amount), 
            "unable to transfer"
        );
        if (to.isContract()) {
            IERC677Recipient recipient = IERC677Recipient(to);
            require(
                recipient.onTokenTransfer(caller, amount, data),
                "token handler returns false"
            );
        }
        return true;
    }

}

File 10 of 31: HasNoContracts.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./Ownable.sol";

/**
 * @title Contracts that should not own Contracts
 * @author Remco Bloemen <remco@2π.com>
 * @dev Should contracts (anything Ownable) end up being owned by this contract, it allows the owner
 * of this contract to reclaim ownership of the contracts.
 */
contract HasNoContracts is Ownable {

  /**
   * @dev Reclaim ownership of Ownable contracts
   * @param _contractAddr The address of the Ownable to be reclaimed.
   */
  function reclaimContract(address _contractAddr) external onlyOwner {
    Ownable contractInst = Ownable(_contractAddr);
    contractInst.transferOwnership(owner);
  }
}

File 11 of 31: HasNoEther.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

import "./Ownable.sol";

/**
 * @title Contracts that should not own Ether
 * @author Remco Bloemen <remco@2π.com>
 * @dev This tries to block incoming ether to prevent accidental loss of Ether. Should Ether end up
 * in the contract, it will allow the owner to reclaim this Ether.
 * @notice Ether can still be sent to this contract by:
 * calling functions labeled `payable`
 * `selfdestruct(contract_address)`
 * mining directly to the contract address
 */
contract HasNoEther is Ownable {

  /**
  * @dev Constructor that rejects incoming Ether
  * The `payable` flag is added so we can access `msg.value` without compiler warning. If we
  * leave out payable, then Solidity will allow inheriting contracts to implement a payable
  * constructor. By doing it this way we prevent a payable constructor from working. Alternatively
  * we could use assembly to access msg.value.
  */
  constructor() payable {
    require(msg.value == 0);
  }

  /**
   * @dev Disallows direct send by setting a default function without the `payable` flag.
   */
  fallback() external {
  }

  /**
   * @dev Transfer all Ether held by the contract to the owner.
   */
  function reclaimEther() external onlyOwner {
    payable(owner).transfer(address(this).balance);
  }
}

File 12 of 31: HasNoTokens.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./CanReclaimToken.sol";

/**
 * @title Contracts that should not own Tokens
 * @author Remco Bloemen <remco@2π.com>
 * @dev This blocks incoming ERC223 tokens to prevent accidental loss of tokens.
 * Should tokens (any ERC20Basic compatible) end up in the contract, it allows the
 * owner to reclaim the tokens.
 */
contract HasNoTokens is CanReclaimToken {

 /**
  * @dev Reject all ERC223 compatible tokens
  * @param _from address The address that is transferring the tokens
  * @param _value uint256 the amount of the specified token
  * @param _data Bytes The data passed from the caller.
  */
  function tokenFallback(
    address _from,
    uint256 _value,
    bytes calldata _data
  )
    external
    pure
  {
    _from;
    _value;
    _data;
    revert();
  }

}

File 13 of 31: IERC1271.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC1271 standard signature validation method for
 * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
 *
 * _Available since v4.1._
 */
interface IERC1271 {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param hash      Hash of the data to be signed
     * @param signature Signature byte array associated with _data
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

File 14 of 31: IERC20.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see `ERC20Detailed`.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a `Transfer` event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through `transferFrom`. This is
     * zero by default.
     *
     * This value changes when `approve` or `transferFrom` are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * > Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an `Approval` event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a `Transfer` event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @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);
}

File 15 of 31: IERC677Recipient.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

/**
 * @title IERC677Recipient
 * @dev Contracts implementing this interface can participate in [ERC677].
 */
interface IERC677Recipient {

    /**
     * @dev Receives notification from [ERC677] transferAndCall.
     * @param from Sender address.
     * @param amount Number of tokens.
     * @param data Additional data.
     */
    function onTokenTransfer(address from, uint256 amount, bytes calldata data) external returns (bool);

}

File 16 of 31: IValidator.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

/**
 * @title IValidator
 * @dev Contracts implementing this interface validate token transfers.
 */
interface IValidator {

    /**
     * @dev Emitted when a validator makes a decision.
     * @param from Sender address.
     * @param to Recipient address.
     * @param amount Number of tokens.
     * @param valid True if transfer approved, false if rejected.
     */
    event Decision(address indexed from, address indexed to, uint amount, bool valid);

    /**
     * @dev Validates token transfer.
     * If the sender is on the blacklist the transfer is denied.
     * @param from Sender address.
     * @param to Recipient address.
     * @param amount Number of tokens.
     */
    function validate(address from, address to, uint amount) external returns (bool valid);

}

File 17 of 31: MintableController.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

import "./StandardController.sol";
import "./MintableTokenLib.sol";
import "./SystemRole.sol";

/**
* @title MintableController
* @dev This contracts implements functionality allowing for minting and burning of tokens.
*/
contract MintableController is SystemRole, StandardController {

  using MintableTokenLib for TokenStorage;

  /**
   * @dev Contract constructor.
   * @param storage_ Address of the token storage for the controller.
   * @param initialSupply The amount of tokens to mint upon creation.
   * @param frontend_ Address of the authorized frontend.
   */
  constructor(address storage_, uint initialSupply, address frontend_)
    StandardController(storage_, initialSupply, frontend_)
    { }

  /**
   * @dev Assigns the system role to an account.
   */
  function addSystemAccount(address account) public override onlyOwner {
    super.addSystemAccount(account);
  }

  /**
   * @dev Removes the system role from an account.
   */
  function removeSystemAccount(address account) public override onlyOwner {
    super.removeSystemAccount(account);
  }

  /**
   * @dev Mints new tokens.
   * @param caller Address of the caller passed through the frontend.
   * @param to Address to credit the tokens.
   * @param amount Number of tokens to mint.
   */
  function mintTo_withCaller(address caller, address to, uint amount)
    public
    guarded(caller)
    onlySystemAccount(caller)
    returns (bool)
  {
    avoidBlackholes(to);
    return token.mint(to, amount);
  }

  /**
   * @dev Burns tokens from token owner.
   * This removes the burned tokens from circulation.
   * @param caller Address of the caller passed through the frontend.
   * @param from Address of the token owner.
   * @param amount Number of tokens to burn.
   * @param h Hash which the token owner signed.
   * @param v Signature component.
   * @param r Signature component.
   * @param s Sigature component.
   */
  function burnFrom_withCaller(address caller, address from, uint amount, bytes32 h, uint8 v, bytes32 r, bytes32 s)
    public
    guarded(caller)
    onlySystemAccount(caller)
    returns (bool)
  {
    return token.burn(from, amount, h, v, r, s);
  }

  /**
   * @dev Burns tokens from token owner.
   * This removes the burned tokens from circulation.
   * @param from Address of the token owner.
   * @param amount Number of tokens to burn.
   */
  function burnFrom(address from, uint amount)
    public
    guarded(msg.sender)
    onlySystemAccount(msg.sender)
    returns (bool)
  {
    return token.burn(from, amount);
  }

}

File 18 of 31: MintableTokenLib.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

import "./SafeMath.sol";
import "./SignatureChecker.sol";
import "./ERC20Lib.sol";
import "./TokenStorage.sol";

/**
 * @title Mintable token
 * @dev Simple ERC20 Token example, with mintable token creation
 * @dev Issue: * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/120
 * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
 */

library MintableTokenLib {

  using SafeMath for uint;
  using SignatureChecker for address;

    /**
     * @dev Mints new tokens.
     * @param db Token storage to operate on.
     * @param to The address that will recieve the minted tokens.
     * @param amount The amount of tokens to mint.
     */
    function mint(
        TokenStorage db,
        address to,
        uint amount
    )
        external
        returns (bool)
    {
        db.addBalance(to, amount);
        return true;
    }

    /**
     * @dev Burns tokens.
     * @param db Token storage to operate on.
     * @param from The address holding tokens.
     * @param amount The amount of tokens to burn.
     */
    function burn(
        TokenStorage db,
        address from,
        uint amount
    )
        public
        returns (bool)
    {
        db.subBalance(from, amount);
        return true;
    }

    /**
     * @dev Burns tokens from a specific address.
     * To burn the tokens the caller needs to provide a signature
     * proving that the caller is authorized by the token owner to do so.
     * @param db Token storage to operate on.
     * @param from The address holding tokens.
     * @param amount The amount of tokens to burn.
     * @param h Hash which the token owner signed.
     * @param v Signature component.
     * @param r Signature component.
     * @param s Sigature component.
     */
    function burn(
        TokenStorage db,
        address from,
        uint amount,
        bytes32 h,
        uint8 v,
        bytes32 r,
        bytes32 s
    )
        external
        returns (bool)
    {
      bytes memory signature;
      if (r != bytes32(0) || s != bytes32(0)) {
        signature = bytes(abi.encodePacked(r,s,v));
      }
      require(
          from.isValidSignatureNow(h, signature),
          "signature/hash does not match"
        );
        return burn(db, from, amount);
    }

}

File 19 of 31: NoOwner.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./HasNoEther.sol";
import "./HasNoTokens.sol";
import "./HasNoContracts.sol";

/**
 * @title Base contract for contracts that should not own things.
 * @author Remco Bloemen <remco@2π.com>
 * @dev Solves a class of errors where a contract accidentally becomes owner of Ether, Tokens or
 * Owned contracts. See respective base contracts for details.
 */
contract NoOwner is HasNoEther, HasNoTokens, HasNoContracts {
}

File 20 of 31: Ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address public owner;

  event OwnershipRenounced(address indexed previousOwner);
  event OwnershipTransferred(
    address indexed previousOwner,
    address indexed newOwner
  );

  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  constructor(){
    owner = msg.sender;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  /**
   * @dev Allows the current owner to relinquish control of the contract.
   * @notice Renouncing to ownership will leave the contract without an owner.
   * It will not be possible to call the functions with the `onlyOwner`
   * modifier anymore.
   */
  function renounceOwnership() public onlyOwner {
    emit OwnershipRenounced(owner);
    owner = address(0);
  }

  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function transferOwnership(address _newOwner) public virtual onlyOwner {
    _transferOwnership(_newOwner);
  }

  /**
   * @dev Transfers control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function _transferOwnership(address _newOwner) internal {
    require(_newOwner != address(0));
    emit OwnershipTransferred(owner, _newOwner);
    owner = _newOwner;
  }
}

File 21 of 31: Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)

pragma solidity ^0.8.0;

import "./Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 22 of 31: Roles.sol
/* SPDX-License-Identifier: MIT */
pragma solidity 0.8.11;

/**
 * @title Roles
 * @author Francisco Giordano (@frangio)
 * @dev Library for managing addresses assigned to a Role.
 * See RBAC.sol for example usage.
 */
library Roles {
  struct Role {
    mapping (address => bool) bearer;
  }

  /**
   * @dev give an address access to this role
   */
  function add(Role storage _role, address _addr)
    internal
  {
    _role.bearer[_addr] = true;
  }

  /**
   * @dev remove an address' access to this role
   */
  function remove(Role storage _role, address _addr)
    internal
  {
    _role.bearer[_addr] = false;
  }

  /**
   * @dev check if an address has this role
   * // reverts
   */
  function check(Role storage _role, address _addr)
    internal
    view
  {
    require(has(_role, _addr));
  }

  /**
   * @dev check if an address has this role
   * @return bool
   */
  function has(Role storage _role, address _addr)
    internal
    view
    returns (bool)
  {
    return _role.bearer[_addr];
  }
}

File 23 of 31: SafeERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./ERC20Basic.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure.
 * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
  function safeTransfer(
    ERC20Basic _token,
    address _to,
    uint256 _value
  )
    internal
  {
    require(_token.transfer(_to, _value));
  }
}

File 24 of 31: SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 25 of 31: SignatureChecker.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/SignatureChecker.sol)

pragma solidity ^0.8.0;

import "./ECDSA.sol";
import "./Address.sol";
import "./IERC1271.sol";

/**
 * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
 * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
 * Argent and Gnosis Safe.
 *
 * _Available since v4.1._
 */
library SignatureChecker {
    /**
     * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
     * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
     *
     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
     * change through time. It could return true at block N and false at block N+1 (or the opposite).
     */
    function isValidSignatureNow(
        address signer,
        bytes32 hash,
        bytes memory signature
    ) internal view returns (bool) {
        (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
        if (error == ECDSA.RecoverError.NoError && recovered == signer) {
            return true;
        }

        (bool success, bytes memory result) = signer.staticcall(
            abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
        );
        return (success && result.length == 32 && abi.decode(result, (bytes4)) == IERC1271.isValidSignature.selector);
    }
}

File 26 of 31: SmartTokenLib.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

import "./ERC20Lib.sol";
import "./MintableTokenLib.sol";
import "./IValidator.sol";
import "./SignatureChecker.sol";

/**
 * @title SmartTokenLib
 * @dev This library provides functionality which is required from a regulatory perspective.
 */
library SmartTokenLib {

    using ERC20Lib for TokenStorage;
    using MintableTokenLib for TokenStorage;
    using SignatureChecker for address;

    struct SmartStorage {
        IValidator validator;
    }

    /**
     * @dev Emitted when the contract owner recovers tokens.
     * @param from Sender address.
     * @param to Recipient address.
     * @param amount Number of tokens.
     */
    event Recovered(address indexed from, address indexed to, uint amount);

    /**
     * @dev Emitted when updating the validator.
     * @param old Address of the old validator.
     * @param current Address of the new validator.
     */
    event Validator(address indexed old, address indexed current);

    /**
     * @dev Sets a new validator.
     * @param self Smart storage to operate on.
     * @param validator Address of validator.
     */
    function setValidator(SmartStorage storage self, address validator)
        external
    {
      emit Validator(address(self.validator), validator);
        self.validator = IValidator(validator);
    }


    /**
     * @dev Approves or rejects a transfer request.
     * The request is forwarded to a validator which implements
     * the actual business logic.
     * @param self Smart storage to operate on.
     * @param from Sender address.
     * @param to Recipient address.
     * @param amount Number of tokens.
     */
    function validate(SmartStorage storage self, address from, address to, uint amount)
        external
        returns (bool valid)
    {
        return self.validator.validate(from, to, amount);
    }

    /**
     * @dev Recovers tokens from an address and reissues them to another address.
     * In case a user loses its private key the tokens can be recovered by burning
     * the tokens from that address and reissuing to a new address.
     * To recover tokens the contract owner needs to provide a signature
     * proving that the token owner has authorized the owner to do so.
     * @param from Address to burn tokens from.
     * @param to Address to mint tokens to.
     * @param h Hash which the token owner signed.
     * @param v Signature component.
     * @param r Signature component.
     * @param s Sigature component.
     * @return Amount recovered.
     */
    function recover(
        TokenStorage token,
        address from,
        address to,
        bytes32 h,
        uint8 v,
        bytes32 r,
        bytes32 s
    )
        external
        returns (uint)
    {
      bytes memory signature;
      if (r != bytes32(0) || s != bytes32(0)) {
        signature = bytes(abi.encodePacked(r,s,v));
      }
      require(
          from.isValidSignatureNow(h, signature),
          "signature/hash does not recover from address"
        );
        uint amount = token.balanceOf(from);
        token.burn(from, amount);
        token.mint(to, amount);
        emit Recovered(from, to, amount);
        return amount;
    }

    /**
     * @dev Gets the current validator.
     * @param self Smart storage to operate on.
     * @return Address of validator.
     */
    function getValidator(SmartStorage storage self)
        external
        view
        returns (address)
    {
        return address(self.validator);
    }

}

File 27 of 31: StandardController.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

import "./Claimable.sol";
import "./Pausable.sol";

import "./TokenStorage.sol";
import "./IERC20.sol";
import "./ERC20Lib.sol";
import "./ERC677Lib.sol";

/**
 * @title StandardController
 * @dev This is the base contract which delegates token methods [ERC20 and ERC677]
 * to their respective library implementations.
 * The controller is primarily intended to be interacted with via a token frontend.
 */
contract StandardController is Pausable, Claimable {

  using ERC20Lib for TokenStorage;
  using ERC677Lib for TokenStorage;

  TokenStorage internal token;
  address internal frontend;
  mapping(address => bool) internal bridgeFrontends;

  string public name;
  string public symbol;
  uint public decimals = 18;

  /**
   * @dev Emitted when updating the frontend.
   * @param old Address of the old frontend.
   * @param current Address of the new frontend.
   */
  event Frontend(address indexed old, address indexed current);

  /**
   * @dev Emitted when updating the Bridge frontend.
   * @param frontend Address of the new Bridge frontend.
   * @param title String of the frontend name.
   */
  event BridgeFrontend(address indexed frontend, string indexed title);

  /**
   * @dev Emitted when updating the storage.
   * @param old Address of the old storage.
   * @param current Address of the new storage.
   */
  event Storage(address indexed old, address indexed current);

  /**
   * @dev Modifier which prevents the function from being called by unauthorized parties.
   * The caller must either be the sender or the function must be
   * called via the frontend, otherwise the call is reverted.
   * @param caller The address of the passed-in caller. Used to preserve the original caller.
   */
  modifier guarded(address caller) {
    require(
            msg.sender == caller || isFrontend(msg.sender),
            "either caller must be sender or calling via frontend"
            );
    _;
  }

  /**
   * @dev Contract constructor.
   * @param storage_ Address of the token storage for the controller.
   * @param initialSupply The amount of tokens to mint upon creation.
   * @param frontend_ Address of the authorized frontend.
   */
  constructor(address storage_, uint initialSupply, address frontend_) {
    require(
            storage_ == address(0x0) || initialSupply == 0,
            "either a token storage must be initialized or no initial supply"
            );
    if (storage_ == address(0x0)) {
      token = new TokenStorage();
      token.addBalance(msg.sender, initialSupply);
    } else {
      token = TokenStorage(storage_);
    }
    frontend = frontend_;
  }

  /**
   * @dev Prevents tokens to be sent to well known blackholes by throwing on known blackholes.
   * @param to The address of the intended recipient.
   */
  function avoidBlackholes(address to) internal view {
    require(to != address(0x0), "must not send to 0x0");
    require(to != address(this), "must not send to controller");
    require(to != address(token), "must not send to token storage");
    require(to != frontend, "must not send to frontend");
    require(isFrontend(to) == false, "must not send to bridgeFrontends");
  }

  /**
   * @dev Returns the current frontend.
   * @return Address of the frontend.
   */
  function getFrontend() external view returns (address) {
    return frontend;
  }

  /**
   * @dev Returns the current storage.
   * @return Address of the storage.
   */
  function getStorage() external view returns (address) {
    return address(token);
  }

  /**
   * @dev Sets a new frontend.
   * @param frontend_ Address of the new frontend.
   */
  function setFrontend(address frontend_) public onlyOwner {
    emit Frontend(frontend, frontend_);
    frontend = frontend_;
  }

  /**
   * @dev Set a new bridge frontend.
   * @param frontend_ Address of the new bridge frontend.
   * @param title Keccack256 hash of the frontend title.
   */
  function setBridgeFrontend(address frontend_, string calldata title) public onlyOwner {
    emit BridgeFrontend(frontend_, title);
    bridgeFrontends[frontend_] = true;
  }

  /**
   * @dev Checks wether an address is a frontend.
   * @param frontend_ Address of the frontend candidate.
   */
  function isFrontend(address frontend_) public view returns (bool) {
    return (frontend_ == frontend) || bridgeFrontends[frontend_];
  }

  /**
   * @dev Sets a new storage.
   * @param storage_ Address of the new storage.
   */
  function setStorage(address storage_) external onlyOwner {
    emit Storage(address(token), storage_);
    token = TokenStorage(storage_);
  }

  /**
   * @dev Transfers the ownership of the storage.
   * @param newOwner Address of the new storage owner.
   */
  function transferStorageOwnership(address newOwner) public onlyOwner {
    token.transferOwnership(newOwner);
  }

  /**
   * @dev Claims the ownership of the storage.
   */
  function claimStorageOwnership() public onlyOwner {
    token.claimOwnership();
  }

  /**
   * @dev Transfers tokens [ERC20].
   * @param caller Address of the caller passed through the frontend.
   * @param to Recipient address.
   * @param amount Number of tokens to transfer.
   */
  function transfer_withCaller(address caller, address to, uint amount)
    public
    virtual
    guarded(caller)
    whenNotPaused
    returns (bool ok)
  {
    avoidBlackholes(to);
    return token.transfer(caller, to, amount);
  }

  /**
   * @dev Transfers tokens from a specific address [ERC20].
   * The address owner has to approve the spender beforehand.
   * @param caller Address of the caller passed through the frontend.
   * @param from Address to debet the tokens from.
   * @param to Recipient address.
   * @param amount Number of tokens to transfer.
   */
  function transferFrom_withCaller(address caller, address from, address to, uint amount)
    public
    virtual
    guarded(caller)
    whenNotPaused
    returns (bool ok)
  {
    avoidBlackholes(to);
    return token.transferFrom(caller, from, to, amount);
  }

  /**
   * @dev Approves a spender [ERC20].
   * Note that using the approve/transferFrom presents a possible
   * security vulnerability described in:
   * https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/edit#heading=h.quou09mcbpzw
   * Use transferAndCall to mitigate.
   * @param caller Address of the caller passed through the frontend.
   * @param spender The address of the future spender.
   * @param amount The allowance of the spender.
   */
  function approve_withCaller(address caller, address spender, uint amount)
    public
    guarded(caller)
    whenNotPaused
    returns (bool ok)
  {
    return token.approve(caller, spender, amount);
  }

  /**
   * @dev Transfers tokens and subsequently calls a method on the recipient [ERC677].
   * If the recipient is a non-contract address this method behaves just like transfer.
   * @param caller Address of the caller passed through the frontend.
   * @param to Recipient address.
   * @param amount Number of tokens to transfer.
   * @param data Additional data passed to the recipient's tokenFallback method.
   */
  function transferAndCall_withCaller(
                                      address caller,
                                      address to,
                                      uint256 amount,
                                      bytes calldata data
                                      )
    public
    virtual
    guarded(caller)
    whenNotPaused
    returns (bool ok)
  {
    avoidBlackholes(to);
    return token.transferAndCall(caller, to, amount, data);
  }

  /**
   * @dev Returns the total supply.
   * @return Number of tokens.
   */
  function totalSupply() external view returns (uint) {
    return token.getSupply();
  }

  /**
   * @dev Returns the number tokens associated with an address.
   * @param who Address to lookup.
   * @return Balance of address.
   */
  function balanceOf(address who) external view returns (uint) {
    return token.getBalance(who);
  }

  /**
   * @dev Returns the allowance for a spender
   * @param owner The address of the owner of the tokens.
   * @param spender The address of the spender.
   * @return Number of tokens the spender is allowed to spend.
   */
  function allowance(address owner, address spender) external view returns (uint) {
    return token.allowance(owner, spender);
  }

  /**
   * @dev Pause the function protected by Pausable modifier.
   */
  function pause() public onlyOwner
  {
    _pause();
  }

  /**
   * @dev Unpause the function protected by Pausable modifier.
   */
  function unpause() public onlyOwner
  {
    _unpause();
  }
}

File 28 of 31: Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 29 of 31: SystemRole.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.8.11;

import "./Roles.sol";

/**
 * @title SystemRole
 * @dev SystemRole accounts have been approved to perform operational actions (e.g. mint and burn).
 * @notice addSystemAccount and removeSystemAccount are unprotected by default, i.e. anyone can call them.
 * @notice Contracts inheriting SystemRole *should* authorize the caller by overriding them.
 * @notice The contract is an abstract contract.
 */
abstract contract SystemRole {

  using Roles for Roles.Role;
  Roles.Role private systemAccounts;

    /**
     * @dev Emitted when system account is added.
     * @param account is a new system account.
     */
    event SystemAccountAdded(address indexed account);

    /**
     * @dev Emitted when system account is removed.
     * @param account is the old system account.
     */
    event SystemAccountRemoved(address indexed account);

    /**
     * @dev Modifier which prevents non-system accounts from calling protected functions.
     */
    modifier onlySystemAccounts() {
        require(isSystemAccount(msg.sender));
        _;
    }

    /**
     * @dev Modifier which prevents non-system accounts from being passed to the guard.
     * @param account The account to check.
     */
    modifier onlySystemAccount(address account) {
        require(
            isSystemAccount(account),
            "must be a system account"
        );
        _;
    }

    /**
     * @dev Checks whether an address is a system account.
     * @param account the address to check.
     * @return true if system account.
     */
    function isSystemAccount(address account) public view returns (bool) {
        return systemAccounts.has(account);
    }

    /**
     * @dev Assigns the system role to an account.
     * @notice This method is unprotected and should be authorized in the child contract.
     */
    function addSystemAccount(address account) public virtual {
        systemAccounts.add(account);
        emit SystemAccountAdded(account);
    }

    /**
     * @dev Removes the system role from an account.
     * @notice This method is unprotected and should be authorized in the child contract.
     */
    function removeSystemAccount(address account) public virtual {
        systemAccounts.remove(account);
        emit SystemAccountRemoved(account);
    }

}

File 30 of 31: TokenStorage.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

import "./Claimable.sol";
import "./CanReclaimToken.sol";
import "./NoOwner.sol";
import "./TokenStorageLib.sol";

/**
 * @title TokenStorage
 * @dev External storage for tokens.
 * The storage is implemented in a separate contract to maintain state
 * between token upgrades.
 */
contract TokenStorage is Claimable, CanReclaimToken, NoOwner {

    using TokenStorageLib for TokenStorageLib.TokenStorage;

    TokenStorageLib.TokenStorage internal tokenStorage;

    /**
     * @dev Increases balance of an address.
     * @param to Address to increase.
     * @param amount Number of units to add.
     */
    function addBalance(address to, uint amount) external onlyOwner {
        tokenStorage.addBalance(to, amount);
    }

    /**
     * @dev Decreases balance of an address.
     * @param from Address to decrease.
     * @param amount Number of units to subtract.
     */
    function subBalance(address from, uint amount) external onlyOwner {
        tokenStorage.subBalance(from, amount);
    }

    /**
     * @dev Sets the allowance for a spender.
     * @param owner Address of the owner of the tokens to spend.
     * @param spender Address of the spender.
     * @param amount Qunatity of allowance.
     */
    function setAllowed(address owner, address spender, uint amount) external onlyOwner {
        tokenStorage.setAllowed(owner, spender, amount);
    }

    /**
     * @dev Returns the supply of tokens.
     * @return Total supply.
     */
    function getSupply() external view returns (uint) {
        return tokenStorage.getSupply();
    }

    /**
     * @dev Returns the balance of an address.
     * @param who Address to lookup.
     * @return Number of units.
     */
    function getBalance(address who) external view returns (uint) {
        return tokenStorage.getBalance(who);
    }

    /**
     * @dev Returns the allowance for a spender.
     * @param owner Address of the owner of the tokens to spend.
     * @param spender Address of the spender.
     * @return Number of units.
     */
    function getAllowed(address owner, address spender)
        external
        view
        returns (uint)
    {
        return tokenStorage.getAllowed(owner, spender);
    }

    /**
     * @dev Explicit override of transferOwnership from Claimable and Ownable
     * @param newOwner Address to transfer ownership to.
     */
    function transferOwnership(address newOwner) public override(Claimable, Ownable){
      Claimable.transferOwnership(newOwner);
    }
}

File 31 of 31: TokenStorageLib.sol
/* SPDX-License-Identifier: apache-2.0 */
/**
 * Copyright 2022 Monerium ehf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity 0.8.11;

import "./SafeMath.sol";

/*
 * @title TokenStorageLib
 * @dev Implementation of an[external storage for tokens.
 */
library TokenStorageLib {

    using SafeMath for uint;

    struct TokenStorage {
        mapping (address => uint) balances;
        mapping (address => mapping (address => uint)) allowed;
        uint totalSupply;
    }

    /**
     * @dev Increases balance of an address.
     * @param self Token storage to operate on.
     * @param to Address to increase.
     * @param amount Number of units to add.
     */
    function addBalance(TokenStorage storage self, address to, uint amount)
        external
    {
        self.totalSupply = self.totalSupply.add(amount);
        self.balances[to] = self.balances[to].add(amount);
    }

    /**
     * @dev Decreases balance of an address.
     * @param self Token storage to operate on.
     * @param from Address to decrease.
     * @param amount Number of units to subtract.
     */
    function subBalance(TokenStorage storage self, address from, uint amount)
        external
    {
        self.totalSupply = self.totalSupply.sub(amount);
        self.balances[from] = self.balances[from].sub(amount);
    }

    /**
     * @dev Sets the allowance for a spender.
     * @param self Token storage to operate on.
     * @param owner Address of the owner of the tokens to spend.
     * @param spender Address of the spender.
     * @param amount Qunatity of allowance.
     */
    function setAllowed(TokenStorage storage self, address owner, address spender, uint amount)
        external
    {
        self.allowed[owner][spender] = amount;
    }

    /**
     * @dev Returns the supply of tokens.
     * @param self Token storage to operate on.
     * @return Total supply.
     */
    function getSupply(TokenStorage storage self)
        external
        view
        returns (uint)
    {
        return self.totalSupply;
    }

    /**
     * @dev Returns the balance of an address.
     * @param self Token storage to operate on.
     * @param who Address to lookup.
     * @return Number of units.
     */
    function getBalance(TokenStorage storage self, address who)
        external
        view
        returns (uint)
    {
        return self.balances[who];
    }

    /**
     * @dev Returns the allowance for a spender.
     * @param self Token storage to operate on.
     * @param owner Address of the owner of the tokens to spend.
     * @param spender Address of the spender.
     * @return Number of units.
     */
    function getAllowed(TokenStorage storage self, address owner, address spender)
        external
        view
        returns (uint)
    {
        return self.allowed[owner][spender];
    }

}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"storage_","type":"address"},{"internalType":"address","name":"validator","type":"address"},{"internalType":"bytes3","name":"ticker_","type":"bytes3"},{"internalType":"address","name":"frontend_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"frontend","type":"address"},{"indexed":true,"internalType":"string","name":"title","type":"string"}],"name":"BridgeFrontend","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"old","type":"address"},{"indexed":true,"internalType":"address","name":"current","type":"address"}],"name":"Frontend","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"old","type":"address"},{"indexed":true,"internalType":"address","name":"current","type":"address"}],"name":"Storage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"SystemAccountAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"SystemAccountRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"INITIAL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addSystemAccount","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":"caller","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve_withCaller","outputs":[{"internalType":"bool","name":"ok","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"h","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"burnFrom_withCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimStorageOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFrontend","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getValidator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"frontend_","type":"address"}],"name":"isFrontend","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isSystemAccount","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintTo_withCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes32","name":"h","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"recover_withCaller","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeSystemAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"frontend_","type":"address"},{"internalType":"string","name":"title","type":"string"}],"name":"setBridgeFrontend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"frontend_","type":"address"}],"name":"setFrontend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"storage_","type":"address"}],"name":"setStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"validator","type":"address"}],"name":"setValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ticker","outputs":[{"internalType":"bytes3","name":"","type":"bytes3"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"transferAndCall_withCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom_withCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferStorageOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer_withCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405260126008553480156200001657600080fd5b50604051620035bd380380620035bd8339810160408190526200003991620002f7565b600180546001600160a81b0319166101003302179055836000828282826001600160a01b03831615806200006b575081155b620000e35760405162461bcd60e51b815260206004820152603f60248201527f656974686572206120746f6b656e2073746f72616765206d757374206265206960448201527f6e697469616c697a6564206f72206e6f20696e697469616c20737570706c790060648201526084015b60405180910390fd5b6001600160a01b0383166200019a576040516200010090620002cc565b604051809103906000f0801580156200011d573d6000803e3d6000fd5b50600380546001600160a01b0319166001600160a01b039290921691821790556040516310f29c1d60e11b8152336004820152602481018490526321e5383a90604401600060405180830381600087803b1580156200017b57600080fd5b505af115801562000190573d6000803e3d6000fd5b50505050620001b6565b600380546001600160a01b0319166001600160a01b0385161790555b600480546001600160a01b0319166001600160a01b039283161790558816151594506200023793505050505760405162461bcd60e51b8152602060048201526024808201527f76616c696461746f722063616e6e6f7420626520746865206e756c6c206164646044820152637265737360e01b6064820152608401620000da565b60405163ad41534960e01b8152600960048201526001600160a01b0384166024820152732ecb7d02c0bfd824d88f47e26602a6ae861482429063ad4153499060440160006040518083038186803b1580156200029257600080fd5b505af4158015620002a7573d6000803e3d6000fd5b5050600a805462ffffff191660e89590951c9490941790935550620003639350505050565b610b5c8062002a6183390190565b80516001600160a01b0381168114620002f257600080fd5b919050565b600080600080608085870312156200030e57600080fd5b6200031985620002da565b93506200032960208601620002da565b60408601519093506001600160e81b0319811681146200034857600080fd5b91506200035860608601620002da565b905092959194509250565b6126ee80620003736000396000f3fe608060405234801561001057600080fd5b50600436106102765760003560e01c8063715018a6116101605780639e7f43ca116100d8578063e30c39781161008c578063ebbc3d4611610071578063ebbc3d46146104f3578063ee0b544514610506578063f2fde38b1461051957600080fd5b8063e30c3978146104cd578063e974fee9146104e057600080fd5b8063b516af70116100bd578063b516af701461049f578063dd62ed3e146104a7578063e174fd94146104ba57600080fd5b80639e7f43ca14610479578063a84c56d01461048c57600080fd5b80638ba47bdd1161012f5780638fb81d98116101145780638fb81d981461044b5780639137c1a71461045e57806395d89b411461047157600080fd5b80638ba47bdd146103f55780638da5cb5b1461043357600080fd5b8063715018a6146103bf578063774d5409146103c757806379cc6790146103da5780638456cb59146103ed57600080fd5b8063326ecb05116101f35780634e71e0c8116101c25780635c975abb116101a75780635c975abb1461038e57806369569a511461039957806370a08231146103ac57600080fd5b80634e71e0c8146103735780634eb007541461037b57600080fd5b8063326ecb05146103345780633408f73a146103475780633cd1570f146103585780633f4ba83a1461036b57600080fd5b806318160ddd1161024a5780632ff2e9dc1161022f5780632ff2e9dc14610310578063313ce56714610318578063322ec0fb1461032157600080fd5b806318160ddd146102d757806325ec2eb0146102ed57600080fd5b80623074ff1461027b57806306fdde03146102a55780631195e07e146102ba5780631327d3d8146102c2575b600080fd5b6004546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b6102ad61052c565b60405161029c9190612231565b6102886105ba565b6102d56102d036600461229b565b61064f565b005b6102df6106ef565b60405190815260200161029c565b6103006102fb36600461229b565b610776565b604051901515815260200161029c565b6102df600081565b6102df60085481565b61030061032f3660046122b8565b6107b3565b61030061034236600461229b565b610950565b6003546001600160a01b0316610288565b6102df61036636600461230f565b610971565b6102d5610b2c565b6102d5610b52565b610300610389366004612386565b610bfa565b60015460ff16610300565b6102d56103a736600461229b565b610d9d565b6102df6103ba36600461229b565b610e22565b6102d5610eaa565b6103006103d53660046122b8565b610f22565b6103006103e83660046123d8565b6110a9565b6102d5611186565b600a546104029060e81b81565b6040517fffffff0000000000000000000000000000000000000000000000000000000000909116815260200161029c565b6001546102889061010090046001600160a01b031681565b6102d561045936600461244d565b6111aa565b6102d561046c36600461229b565b611237565b6102ad6112bc565b6103006104873660046124a2565b6112c9565b6102d561049a36600461229b565b6114b2565b6102d56114da565b6102df6104b5366004612515565b611560565b6103006104c83660046122b8565b611613565b600254610288906001600160a01b031681565b6103006104ee36600461254e565b6117c9565b6102d561050136600461229b565b611980565b6102d561051436600461229b565b6119a5565b6102d561052736600461229b565b611a35565b600680546105399061259f565b80601f01602080910402602001604051908101604052809291908181526020018280546105659061259f565b80156105b25780601f10610587576101008083540402835291602001916105b2565b820191906000526020600020905b81548152906001019060200180831161059557829003601f168201915b505050505081565b6040517f6271970c00000000000000000000000000000000000000000000000000000000815260096004820152600090732ecb7d02c0bfd824d88f47e26602a6ae8614824290636271970c90602401602060405180830381865af4158015610626573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a91906125f3565b905090565b61065833610950565b61066157600080fd5b6040517fad415349000000000000000000000000000000000000000000000000000000008152600960048201526001600160a01b0382166024820152732ecb7d02c0bfd824d88f47e26602a6ae861482429063ad4153499060440160006040518083038186803b1580156106d457600080fd5b505af41580156106e8573d6000803e3d6000fd5b5050505050565b600354604080517f6c9c2faf00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691636c9c2faf9160048083019260209291908290030181865afa158015610752573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a9190612610565b6004546000906001600160a01b03838116911614806107ad57506001600160a01b03821660009081526005602052604090205460ff165b92915050565b600083336001600160a01b03821614806107d157506107d133610776565b61083f5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b60648201526084015b60405180910390fd5b8461084981610950565b6108955760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b61089e85611a80565b6003546040517fb0c29c740000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015290861660248201526044810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063b0c29c7490606401602060405180830381865af4158015610922573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109469190612629565b9695505050505050565b6001600160a01b03811660009081526020819052604081205460ff166107ad565b600087336001600160a01b038216148061098f575061098f33610776565b6109f85760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b88610a0281610950565b610a4e5760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b610a5788611a80565b6003546040517f8f7227340000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528a8216602482015290891660448201526064810188905260ff8716608482015260a4810186905260c48101859052732ecb7d02c0bfd824d88f47e26602a6ae8614824290638f7227349060e401602060405180830381865af4158015610afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1e9190612610565b9a9950505050505050505050565b60015461010090046001600160a01b03163314610b4857600080fd5b610b50611c41565b565b6002546001600160a01b03163314610b6957600080fd5b6002546001546040516001600160a01b0392831692610100909204909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600280546001805474ffffffffffffffffffffffffffffffffffffffff0019166101006001600160a01b0384160217905573ffffffffffffffffffffffffffffffffffffffff19169055565b600087336001600160a01b0382161480610c185750610c1833610776565b610c815760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b88610c8b81610950565b610cd75760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b6003546040517f799639d40000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152908a166024820152604481018990526064810188905260ff8716608482015260a4810186905260c4810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063799639d49060e401602060405180830381865af4158015610d79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1e9190612629565b60015461010090046001600160a01b03163314610db957600080fd5b6004546040516001600160a01b038084169216907fcb01f884fc4203d4c1643cb0e126faeb397682c122ca8c0433776d42cdc0060a90600090a36004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6003546040517ff8b2cb4f0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063f8b2cb4f90602401602060405180830381865afa158015610e86573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ad9190612610565b60015461010090046001600160a01b03163314610ec657600080fd5b6001546040516101009091046001600160a01b0316907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26001805474ffffffffffffffffffffffffffffffffffffffff0019169055565b600083336001600160a01b0382161480610f405750610f4033610776565b610fa95760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff1615610fef5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6003546040517f365feff10000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152868216602482015290851660448201526064810184905273b912a741f60779390d789c3c5f78131b999493b59063365feff1906084015b602060405180830381865af415801561107c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a09190612629565b95945050505050565b600033336110b681610950565b6111025760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b6003546040517fa6c9ac280000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015290861660248201526044810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063a6c9ac2890606401602060405180830381865af415801561107c573d6000803e3d6000fd5b60015461010090046001600160a01b031633146111a257600080fd5b610b50611cdd565b60015461010090046001600160a01b031633146111c657600080fd5b81816040516111d692919061264b565b604051908190038120906001600160a01b038516907fec75908259de4d038ff5f2b6b99e3725bc21871f4d2a44adeff9bb814afbc9f790600090a350506001600160a01b03166000908152600560205260409020805460ff19166001179055565b60015461010090046001600160a01b0316331461125357600080fd5b6003546040516001600160a01b038084169216907fdaaa9d417a3107fd3d9db02eba3eeafbae2b8af16ee08c534f5bc449054c1c4c90600090a36003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600780546105399061259f565b600085336001600160a01b03821614806112e757506112e733610776565b6113505760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156113965760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380891660248301528716604482015260648101869052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af4158015611404573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114289190612629565b61149a5760405162461bcd60e51b815260206004820152602160248201527f7472616e73666572416e6443616c6c2072657175657374206e6f742076616c6960448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610836565b6114a78787878787611d56565b979650505050505050565b60015461010090046001600160a01b031633146114ce57600080fd5b6114d781611ed2565b50565b60015461010090046001600160a01b031633146114f657600080fd5b600360009054906101000a90046001600160a01b03166001600160a01b0316634e71e0c86040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561154657600080fd5b505af115801561155a573d6000803e3d6000fd5b50505050565b6003546040517f1045d7ce0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528382166024820152908216604482015260009073b912a741f60779390d789c3c5f78131b999493b590631045d7ce90606401602060405180830381865af41580156115e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160c9190612610565b9392505050565b600083336001600160a01b0382161480611631575061163133610776565b61169a5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156116e05760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380871660248301528516604482015260648101849052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af415801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190612629565b6117be5760405162461bcd60e51b815260206004820152601a60248201527f7472616e736665722072657175657374206e6f742076616c69640000000000006044820152606401610836565b6110a0858585611f34565b600084336001600160a01b03821614806117e757506117e733610776565b6118505760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156118965760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380871660248301528516604482015260648101849052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af4158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190612629565b6119745760405162461bcd60e51b815260206004820152601e60248201527f7472616e7366657246726f6d2072657175657374206e6f742076616c696400006044820152606401610836565b6109468686868661207e565b60015461010090046001600160a01b0316331461199c57600080fd5b6114d7816121e8565b60015461010090046001600160a01b031633146119c157600080fd5b6003546040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301529091169063f2fde38b90602401600060405180830381600087803b158015611a2157600080fd5b505af11580156106e8573d6000803e3d6000fd5b60015461010090046001600160a01b03163314611a5157600080fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6001600160a01b038116611ad65760405162461bcd60e51b815260206004820152601460248201527f6d757374206e6f742073656e6420746f203078300000000000000000000000006044820152606401610836565b6001600160a01b038116301415611b2f5760405162461bcd60e51b815260206004820152601b60248201527f6d757374206e6f742073656e6420746f20636f6e74726f6c6c657200000000006044820152606401610836565b6003546001600160a01b0382811691161415611b8d5760405162461bcd60e51b815260206004820152601e60248201527f6d757374206e6f742073656e6420746f20746f6b656e2073746f7261676500006044820152606401610836565b6004546001600160a01b0382811691161415611beb5760405162461bcd60e51b815260206004820152601960248201527f6d757374206e6f742073656e6420746f2066726f6e74656e64000000000000006044820152606401610836565b611bf481610776565b156114d75760405162461bcd60e51b815260206004820181905260248201527f6d757374206e6f742073656e6420746f2062726964676546726f6e74656e64736044820152606401610836565b60015460ff16611c935760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610836565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60015460ff1615611d235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833611cc0565b600085336001600160a01b0382161480611d745750611d7433610776565b611ddd5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff1615611e235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b611e2c86611a80565b6003546040517f1eb8bccb00000000000000000000000000000000000000000000000000000000815273f6d4568574c1de8f1eb002f58d1e5ecdf652b1d091631eb8bccb91611e91916001600160a01b0316908b908b908b908b908b9060040161265b565b602060405180830381865af4158015611eae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a79190612629565b611efd6000826001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6040516001600160a01b038216907fdfb5b1167ef9eadf5cac67570f1a2971a6f6175303b9d4166a65a11d0a294e3490600090a250565b600083336001600160a01b0382161480611f525750611f5233610776565b611fbb5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156120015760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b61200a84611a80565b6003546040517f44ded8ba0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152868216602482015290851660448201526064810184905273b912a741f60779390d789c3c5f78131b999493b5906344ded8ba9060840161105f565b600084336001600160a01b038216148061209c575061209c33610776565b6121055760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff161561214b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b61215484611a80565b6003546040517ff3a0ddf90000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528782166024820152868216604482015290851660648201526084810184905273b912a741f60779390d789c3c5f78131b999493b59063f3a0ddf99060a401602060405180830381865af4158015610922573d6000803e3d6000fd5b6001600160a01b038116600081815260208190526040808220805460ff19169055517f21bfb3de07221bc6197a8c23f7a059308b7a741f259cf4ef3b519cde0fde7ac39190a250565b600060208083528351808285015260005b8181101561225e57858101830151858201604001528201612242565b81811115612270576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b03811681146114d757600080fd5b6000602082840312156122ad57600080fd5b813561160c81612286565b6000806000606084860312156122cd57600080fd5b83356122d881612286565b925060208401356122e881612286565b929592945050506040919091013590565b803560ff8116811461230a57600080fd5b919050565b600080600080600080600060e0888a03121561232a57600080fd5b873561233581612286565b9650602088013561234581612286565b9550604088013561235581612286565b94506060880135935061236a608089016122f9565b925060a0880135915060c0880135905092959891949750929550565b600080600080600080600060e0888a0312156123a157600080fd5b87356123ac81612286565b965060208801356123bc81612286565b9550604088013594506060880135935061236a608089016122f9565b600080604083850312156123eb57600080fd5b82356123f681612286565b946020939093013593505050565b60008083601f84011261241657600080fd5b50813567ffffffffffffffff81111561242e57600080fd5b60208301915083602082850101111561244657600080fd5b9250929050565b60008060006040848603121561246257600080fd5b833561246d81612286565b9250602084013567ffffffffffffffff81111561248957600080fd5b61249586828701612404565b9497909650939450505050565b6000806000806000608086880312156124ba57600080fd5b85356124c581612286565b945060208601356124d581612286565b935060408601359250606086013567ffffffffffffffff8111156124f857600080fd5b61250488828901612404565b969995985093965092949392505050565b6000806040838503121561252857600080fd5b823561253381612286565b9150602083013561254381612286565b809150509250929050565b6000806000806080858703121561256457600080fd5b843561256f81612286565b9350602085013561257f81612286565b9250604085013561258f81612286565b9396929550929360600135925050565b600181811c908216806125b357607f821691505b602082108114156125ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561260557600080fd5b815161160c81612286565b60006020828403121561262257600080fd5b5051919050565b60006020828403121561263b57600080fd5b8151801515811461160c57600080fd5b8183823760009101908152919050565b60006001600160a01b038089168352808816602084015280871660408401525084606083015260a060808301528260a0830152828460c0840137600060c0848401015260c0601f19601f850116830101905097965050505050505056fea2646970667358221220589a221d8b174737710c755745052e2f1667b39f8d95fad86ef93c86334ff97964736f6c634300080b0033608060405234801561001057600080fd5b50600080546001600160a01b03191633179055341561002e57600080fd5b610b1f8061003d6000396000f3fe608060405234801561001057600080fd5b50600436106100ec5760003560e01c80638da5cb5b11610091578063cf8eeb7e11610063578063cf8eeb7e146101be578063e30c3978146101d1578063f2fde38b146101e4578063f8b2cb4f146101f757005b80638da5cb5b146101655780639f727c2714610190578063c0ee0b8a14610198578063c7c7e9ea146101ab57005b806333dd1b8a116100ca57806333dd1b8a146101275780634e71e0c81461013a5780636c9c2faf14610142578063715018a61461015d57005b806317ffc320146100ee57806321e5383a146101015780632aed7f3f14610114575b005b6100ec6100fc366004610962565b61020a565b6100ec61010f36600461097f565b6102c6565b6100ec610122366004610962565b610374565b6100ec6101353660046109ab565b610400565b6100ec6104b6565b61014a61053e565b6040519081526020015b60405180910390f35b6100ec6105d3565b600054610178906001600160a01b031681565b6040516001600160a01b039091168152602001610154565b6100ec61063f565b6100ec6101a63660046109ec565b600080fd5b61014a6101b9366004610a75565b610693565b6100ec6101cc36600461097f565b610741565b600154610178906001600160a01b031681565b6100ec6101f2366004610962565b6107bf565b61014a610205366004610962565b6107c8565b6000546001600160a01b0316331461022157600080fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610281573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a59190610aae565b6000549091506102c2906001600160a01b0384811691168361086d565b5050565b6000546001600160a01b031633146102dd57600080fd5b6040517f7aeb0ed5000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b03831660248201526044810182905273e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c90637aeb0ed5906064015b60006040518083038186803b15801561035857600080fd5b505af415801561036c573d6000803e3d6000fd5b505050505050565b6000546001600160a01b0316331461038b57600080fd5b6000546040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152829182169063f2fde38b90602401600060405180830381600087803b1580156103ec57600080fd5b505af115801561036c573d6000803e3d6000fd5b6000546001600160a01b0316331461041757600080fd5b6040517f5599b4b7000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b038085166024830152831660448201526064810182905273e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c90635599b4b79060840160006040518083038186803b15801561049957600080fd5b505af41580156104ad573d6000803e3d6000fd5b50505050505050565b6001546001600160a01b031633146104cd57600080fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600180546000805473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b03841617909155169055565b6040517f072f9a500000000000000000000000000000000000000000000000000000000081526002600482015260009073e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c9063072f9a5090602401602060405180830381865af41580156105aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ce9190610aae565b905090565b6000546001600160a01b031633146105ea57600080fd5b600080546040516001600160a01b03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b6000546001600160a01b0316331461065657600080fd5b600080546040516001600160a01b03909116914780156108fc02929091818181858888f19350505050158015610690573d6000803e3d6000fd5b50565b6040517f9daeae1e000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b0380841660248301528216604482015260009073e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c90639daeae1e90606401602060405180830381865af4158015610716573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073a9190610aae565b9392505050565b6000546001600160a01b0316331461075857600080fd5b6040517fd9c7339e000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b03831660248201526044810182905273e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c9063d9c7339e90606401610340565b61069081610907565b6040517fb0aacf24000000000000000000000000000000000000000000000000000000008152600260048201526001600160a01b038216602482015260009073e0912ea0fe61ba97ad4f45a92b34e34643bbbb0c9063b0aacf2490604401602060405180830381865af4158015610843573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108679190610aae565b92915050565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af11580156108d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f99190610ac7565b61090257600080fd5b505050565b6000546001600160a01b0316331461091e57600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6001600160a01b038116811461069057600080fd5b60006020828403121561097457600080fd5b813561073a8161094d565b6000806040838503121561099257600080fd5b823561099d8161094d565b946020939093013593505050565b6000806000606084860312156109c057600080fd5b83356109cb8161094d565b925060208401356109db8161094d565b929592945050506040919091013590565b60008060008060608587031215610a0257600080fd5b8435610a0d8161094d565b935060208501359250604085013567ffffffffffffffff80821115610a3157600080fd5b818701915087601f830112610a4557600080fd5b813581811115610a5457600080fd5b886020828501011115610a6657600080fd5b95989497505060200194505050565b60008060408385031215610a8857600080fd5b8235610a938161094d565b91506020830135610aa38161094d565b809150509250929050565b600060208284031215610ac057600080fd5b5051919050565b600060208284031215610ad957600080fd5b8151801515811461073a57600080fdfea2646970667358221220f0093be45eefa3b445c0e69fc35c23602399ad72137343475b219857f044da1564736f6c634300080b003300000000000000000000000057f1b40baf4d5708a15fea71e06841897cd2d262000000000000000000000000774681a648125d46f35017cf6cec43a41857254e45555200000000000000000000000000000000000000000000000000000000000000000000000000000000003231cb76718cdef2155fc47b5286d82e6eda273f

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102765760003560e01c8063715018a6116101605780639e7f43ca116100d8578063e30c39781161008c578063ebbc3d4611610071578063ebbc3d46146104f3578063ee0b544514610506578063f2fde38b1461051957600080fd5b8063e30c3978146104cd578063e974fee9146104e057600080fd5b8063b516af70116100bd578063b516af701461049f578063dd62ed3e146104a7578063e174fd94146104ba57600080fd5b80639e7f43ca14610479578063a84c56d01461048c57600080fd5b80638ba47bdd1161012f5780638fb81d98116101145780638fb81d981461044b5780639137c1a71461045e57806395d89b411461047157600080fd5b80638ba47bdd146103f55780638da5cb5b1461043357600080fd5b8063715018a6146103bf578063774d5409146103c757806379cc6790146103da5780638456cb59146103ed57600080fd5b8063326ecb05116101f35780634e71e0c8116101c25780635c975abb116101a75780635c975abb1461038e57806369569a511461039957806370a08231146103ac57600080fd5b80634e71e0c8146103735780634eb007541461037b57600080fd5b8063326ecb05146103345780633408f73a146103475780633cd1570f146103585780633f4ba83a1461036b57600080fd5b806318160ddd1161024a5780632ff2e9dc1161022f5780632ff2e9dc14610310578063313ce56714610318578063322ec0fb1461032157600080fd5b806318160ddd146102d757806325ec2eb0146102ed57600080fd5b80623074ff1461027b57806306fdde03146102a55780631195e07e146102ba5780631327d3d8146102c2575b600080fd5b6004546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b6102ad61052c565b60405161029c9190612231565b6102886105ba565b6102d56102d036600461229b565b61064f565b005b6102df6106ef565b60405190815260200161029c565b6103006102fb36600461229b565b610776565b604051901515815260200161029c565b6102df600081565b6102df60085481565b61030061032f3660046122b8565b6107b3565b61030061034236600461229b565b610950565b6003546001600160a01b0316610288565b6102df61036636600461230f565b610971565b6102d5610b2c565b6102d5610b52565b610300610389366004612386565b610bfa565b60015460ff16610300565b6102d56103a736600461229b565b610d9d565b6102df6103ba36600461229b565b610e22565b6102d5610eaa565b6103006103d53660046122b8565b610f22565b6103006103e83660046123d8565b6110a9565b6102d5611186565b600a546104029060e81b81565b6040517fffffff0000000000000000000000000000000000000000000000000000000000909116815260200161029c565b6001546102889061010090046001600160a01b031681565b6102d561045936600461244d565b6111aa565b6102d561046c36600461229b565b611237565b6102ad6112bc565b6103006104873660046124a2565b6112c9565b6102d561049a36600461229b565b6114b2565b6102d56114da565b6102df6104b5366004612515565b611560565b6103006104c83660046122b8565b611613565b600254610288906001600160a01b031681565b6103006104ee36600461254e565b6117c9565b6102d561050136600461229b565b611980565b6102d561051436600461229b565b6119a5565b6102d561052736600461229b565b611a35565b600680546105399061259f565b80601f01602080910402602001604051908101604052809291908181526020018280546105659061259f565b80156105b25780601f10610587576101008083540402835291602001916105b2565b820191906000526020600020905b81548152906001019060200180831161059557829003601f168201915b505050505081565b6040517f6271970c00000000000000000000000000000000000000000000000000000000815260096004820152600090732ecb7d02c0bfd824d88f47e26602a6ae8614824290636271970c90602401602060405180830381865af4158015610626573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a91906125f3565b905090565b61065833610950565b61066157600080fd5b6040517fad415349000000000000000000000000000000000000000000000000000000008152600960048201526001600160a01b0382166024820152732ecb7d02c0bfd824d88f47e26602a6ae861482429063ad4153499060440160006040518083038186803b1580156106d457600080fd5b505af41580156106e8573d6000803e3d6000fd5b5050505050565b600354604080517f6c9c2faf00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691636c9c2faf9160048083019260209291908290030181865afa158015610752573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a9190612610565b6004546000906001600160a01b03838116911614806107ad57506001600160a01b03821660009081526005602052604090205460ff165b92915050565b600083336001600160a01b03821614806107d157506107d133610776565b61083f5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b60648201526084015b60405180910390fd5b8461084981610950565b6108955760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b61089e85611a80565b6003546040517fb0c29c740000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015290861660248201526044810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063b0c29c7490606401602060405180830381865af4158015610922573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109469190612629565b9695505050505050565b6001600160a01b03811660009081526020819052604081205460ff166107ad565b600087336001600160a01b038216148061098f575061098f33610776565b6109f85760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b88610a0281610950565b610a4e5760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b610a5788611a80565b6003546040517f8f7227340000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528a8216602482015290891660448201526064810188905260ff8716608482015260a4810186905260c48101859052732ecb7d02c0bfd824d88f47e26602a6ae8614824290638f7227349060e401602060405180830381865af4158015610afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1e9190612610565b9a9950505050505050505050565b60015461010090046001600160a01b03163314610b4857600080fd5b610b50611c41565b565b6002546001600160a01b03163314610b6957600080fd5b6002546001546040516001600160a01b0392831692610100909204909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600280546001805474ffffffffffffffffffffffffffffffffffffffff0019166101006001600160a01b0384160217905573ffffffffffffffffffffffffffffffffffffffff19169055565b600087336001600160a01b0382161480610c185750610c1833610776565b610c815760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b88610c8b81610950565b610cd75760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b6003546040517f799639d40000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152908a166024820152604481018990526064810188905260ff8716608482015260a4810186905260c4810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063799639d49060e401602060405180830381865af4158015610d79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1e9190612629565b60015461010090046001600160a01b03163314610db957600080fd5b6004546040516001600160a01b038084169216907fcb01f884fc4203d4c1643cb0e126faeb397682c122ca8c0433776d42cdc0060a90600090a36004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6003546040517ff8b2cb4f0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063f8b2cb4f90602401602060405180830381865afa158015610e86573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ad9190612610565b60015461010090046001600160a01b03163314610ec657600080fd5b6001546040516101009091046001600160a01b0316907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26001805474ffffffffffffffffffffffffffffffffffffffff0019169055565b600083336001600160a01b0382161480610f405750610f4033610776565b610fa95760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff1615610fef5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6003546040517f365feff10000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152868216602482015290851660448201526064810184905273b912a741f60779390d789c3c5f78131b999493b59063365feff1906084015b602060405180830381865af415801561107c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a09190612629565b95945050505050565b600033336110b681610950565b6111025760405162461bcd60e51b815260206004820152601860248201527f6d75737420626520612073797374656d206163636f756e7400000000000000006044820152606401610836565b6003546040517fa6c9ac280000000000000000000000000000000000000000000000000000000081526001600160a01b03918216600482015290861660248201526044810185905273b93a7f29e11f86469ea8d0e086c9993cdc148faa9063a6c9ac2890606401602060405180830381865af415801561107c573d6000803e3d6000fd5b60015461010090046001600160a01b031633146111a257600080fd5b610b50611cdd565b60015461010090046001600160a01b031633146111c657600080fd5b81816040516111d692919061264b565b604051908190038120906001600160a01b038516907fec75908259de4d038ff5f2b6b99e3725bc21871f4d2a44adeff9bb814afbc9f790600090a350506001600160a01b03166000908152600560205260409020805460ff19166001179055565b60015461010090046001600160a01b0316331461125357600080fd5b6003546040516001600160a01b038084169216907fdaaa9d417a3107fd3d9db02eba3eeafbae2b8af16ee08c534f5bc449054c1c4c90600090a36003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600780546105399061259f565b600085336001600160a01b03821614806112e757506112e733610776565b6113505760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156113965760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380891660248301528716604482015260648101869052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af4158015611404573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114289190612629565b61149a5760405162461bcd60e51b815260206004820152602160248201527f7472616e73666572416e6443616c6c2072657175657374206e6f742076616c6960448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610836565b6114a78787878787611d56565b979650505050505050565b60015461010090046001600160a01b031633146114ce57600080fd5b6114d781611ed2565b50565b60015461010090046001600160a01b031633146114f657600080fd5b600360009054906101000a90046001600160a01b03166001600160a01b0316634e71e0c86040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561154657600080fd5b505af115801561155a573d6000803e3d6000fd5b50505050565b6003546040517f1045d7ce0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528382166024820152908216604482015260009073b912a741f60779390d789c3c5f78131b999493b590631045d7ce90606401602060405180830381865af41580156115e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160c9190612610565b9392505050565b600083336001600160a01b0382161480611631575061163133610776565b61169a5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156116e05760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380871660248301528516604482015260648101849052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af415801561174e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117729190612629565b6117be5760405162461bcd60e51b815260206004820152601a60248201527f7472616e736665722072657175657374206e6f742076616c69640000000000006044820152606401610836565b6110a0858585611f34565b600084336001600160a01b03821614806117e757506117e733610776565b6118505760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156118965760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6040516332c5a6eb60e01b8152600960048201526001600160a01b0380871660248301528516604482015260648101849052732ecb7d02c0bfd824d88f47e26602a6ae86148242906332c5a6eb90608401602060405180830381865af4158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190612629565b6119745760405162461bcd60e51b815260206004820152601e60248201527f7472616e7366657246726f6d2072657175657374206e6f742076616c696400006044820152606401610836565b6109468686868661207e565b60015461010090046001600160a01b0316331461199c57600080fd5b6114d7816121e8565b60015461010090046001600160a01b031633146119c157600080fd5b6003546040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301529091169063f2fde38b90602401600060405180830381600087803b158015611a2157600080fd5b505af11580156106e8573d6000803e3d6000fd5b60015461010090046001600160a01b03163314611a5157600080fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6001600160a01b038116611ad65760405162461bcd60e51b815260206004820152601460248201527f6d757374206e6f742073656e6420746f203078300000000000000000000000006044820152606401610836565b6001600160a01b038116301415611b2f5760405162461bcd60e51b815260206004820152601b60248201527f6d757374206e6f742073656e6420746f20636f6e74726f6c6c657200000000006044820152606401610836565b6003546001600160a01b0382811691161415611b8d5760405162461bcd60e51b815260206004820152601e60248201527f6d757374206e6f742073656e6420746f20746f6b656e2073746f7261676500006044820152606401610836565b6004546001600160a01b0382811691161415611beb5760405162461bcd60e51b815260206004820152601960248201527f6d757374206e6f742073656e6420746f2066726f6e74656e64000000000000006044820152606401610836565b611bf481610776565b156114d75760405162461bcd60e51b815260206004820181905260248201527f6d757374206e6f742073656e6420746f2062726964676546726f6e74656e64736044820152606401610836565b60015460ff16611c935760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610836565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60015460ff1615611d235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833611cc0565b600085336001600160a01b0382161480611d745750611d7433610776565b611ddd5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff1615611e235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b611e2c86611a80565b6003546040517f1eb8bccb00000000000000000000000000000000000000000000000000000000815273f6d4568574c1de8f1eb002f58d1e5ecdf652b1d091631eb8bccb91611e91916001600160a01b0316908b908b908b908b908b9060040161265b565b602060405180830381865af4158015611eae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a79190612629565b611efd6000826001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6040516001600160a01b038216907fdfb5b1167ef9eadf5cac67570f1a2971a6f6175303b9d4166a65a11d0a294e3490600090a250565b600083336001600160a01b0382161480611f525750611f5233610776565b611fbb5760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff16156120015760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b61200a84611a80565b6003546040517f44ded8ba0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152868216602482015290851660448201526064810184905273b912a741f60779390d789c3c5f78131b999493b5906344ded8ba9060840161105f565b600084336001600160a01b038216148061209c575061209c33610776565b6121055760405162461bcd60e51b815260206004820152603460248201527f6569746865722063616c6c6572206d7573742062652073656e646572206f722060448201527318d85b1b1a5b99c81d9a5848199c9bdb9d195b9960621b6064820152608401610836565b60015460ff161561214b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610836565b61215484611a80565b6003546040517ff3a0ddf90000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201528782166024820152868216604482015290851660648201526084810184905273b912a741f60779390d789c3c5f78131b999493b59063f3a0ddf99060a401602060405180830381865af4158015610922573d6000803e3d6000fd5b6001600160a01b038116600081815260208190526040808220805460ff19169055517f21bfb3de07221bc6197a8c23f7a059308b7a741f259cf4ef3b519cde0fde7ac39190a250565b600060208083528351808285015260005b8181101561225e57858101830151858201604001528201612242565b81811115612270576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b03811681146114d757600080fd5b6000602082840312156122ad57600080fd5b813561160c81612286565b6000806000606084860312156122cd57600080fd5b83356122d881612286565b925060208401356122e881612286565b929592945050506040919091013590565b803560ff8116811461230a57600080fd5b919050565b600080600080600080600060e0888a03121561232a57600080fd5b873561233581612286565b9650602088013561234581612286565b9550604088013561235581612286565b94506060880135935061236a608089016122f9565b925060a0880135915060c0880135905092959891949750929550565b600080600080600080600060e0888a0312156123a157600080fd5b87356123ac81612286565b965060208801356123bc81612286565b9550604088013594506060880135935061236a608089016122f9565b600080604083850312156123eb57600080fd5b82356123f681612286565b946020939093013593505050565b60008083601f84011261241657600080fd5b50813567ffffffffffffffff81111561242e57600080fd5b60208301915083602082850101111561244657600080fd5b9250929050565b60008060006040848603121561246257600080fd5b833561246d81612286565b9250602084013567ffffffffffffffff81111561248957600080fd5b61249586828701612404565b9497909650939450505050565b6000806000806000608086880312156124ba57600080fd5b85356124c581612286565b945060208601356124d581612286565b935060408601359250606086013567ffffffffffffffff8111156124f857600080fd5b61250488828901612404565b969995985093965092949392505050565b6000806040838503121561252857600080fd5b823561253381612286565b9150602083013561254381612286565b809150509250929050565b6000806000806080858703121561256457600080fd5b843561256f81612286565b9350602085013561257f81612286565b9250604085013561258f81612286565b9396929550929360600135925050565b600181811c908216806125b357607f821691505b602082108114156125ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561260557600080fd5b815161160c81612286565b60006020828403121561262257600080fd5b5051919050565b60006020828403121561263b57600080fd5b8151801515811461160c57600080fd5b8183823760009101908152919050565b60006001600160a01b038089168352808816602084015280871660408401525084606083015260a060808301528260a0830152828460c0840137600060c0848401015260c0601f19601f850116830101905097965050505050505056fea2646970667358221220589a221d8b174737710c755745052e2f1667b39f8d95fad86ef93c86334ff97964736f6c634300080b0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000057f1b40baf4d5708a15fea71e06841897cd2d262000000000000000000000000774681a648125d46f35017cf6cec43a41857254e45555200000000000000000000000000000000000000000000000000000000000000000000000000000000003231cb76718cdef2155fc47b5286d82e6eda273f

-----Decoded View---------------
Arg [0] : storage_ (address): 0x57f1B40BaF4D5708a15fEa71e06841897cd2d262
Arg [1] : validator (address): 0x774681A648125D46f35017cF6CEC43A41857254e
Arg [2] : ticker_ (bytes3): 0x455552
Arg [3] : frontend_ (address): 0x3231Cb76718CDeF2155FC47b5286d82e6eDA273f

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000057f1b40baf4d5708a15fea71e06841897cd2d262
Arg [1] : 000000000000000000000000774681a648125d46f35017cf6cec43a41857254e
Arg [2] : 4555520000000000000000000000000000000000000000000000000000000000
Arg [3] : 0000000000000000000000003231cb76718cdef2155fc47b5286d82e6eda273f


Deployed Bytecode Sourcemap

891:4979:24:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3916:81:26;3984:8;;-1:-1:-1;;;;;3984:8:26;3916:81;;;-1:-1:-1;;;;;178:55:31;;;160:74;;148:2;133:18;3916:81:26;;;;;;;;1316:18;;;:::i;:::-;;;;;;;:::i;5762:105:24:-;;;:::i;1818:120::-;;;;;;:::i;:::-;;:::i;:::-;;8323:87:26;;;:::i;:::-;;;1404:25:31;;;1392:2;1377:18;8323:87:26;1258:177:31;4865:137:26;;;;;;:::i;:::-;;:::i;:::-;;;1605:14:31;;1598:22;1580:41;;1568:2;1553:18;4865:137:26;1440:187:31;1081:39:24;;1119:1;1081:39;;1362:25:26;;;;;;1940:215:15;;;;;;:::i;:::-;;:::i;2201:120:28:-;;;;;;:::i;:::-;;:::i;4089:86:26:-;4164:5;;-1:-1:-1;;;;;4164:5:26;4089:86;;2695:317:24;;;;;;:::i;:::-;;:::i;9229:59:26:-;;;:::i;836:164:2:-;;;:::i;2579:250:15:-;;;;;;:::i;:::-;;:::i;1091:84:19:-;1161:7;;;;1091:84;;4273:128:26;;;;;;:::i;:::-;;:::i;8558:100::-;;;;;;:::i;:::-;;:::i;1022:111:18:-;;;:::i;7145:203:26:-;;;;;;:::i;:::-;;:::i;3030:177:15:-;;;;;;:::i;:::-;;:::i;9095:55:26:-;;;:::i;1055:20:24:-;;;;;;;;;;;;4299:66:31;4287:79;;;4269:98;;4257:2;4242:18;1055:20:24;4125:248:31;269:20:18;;;;;;;;-1:-1:-1;;;;;269:20:18;;;4569:173:26;;;;;;:::i;:::-;;:::i;5097:142::-;;;;;;:::i;:::-;;:::i;1338:20::-;;;:::i;5242:421:24:-;;;;;;:::i;:::-;;:::i;1441:111:15:-;;;;;;:::i;:::-;;:::i;5536:83:26:-;;;:::i;8889:129::-;;;;;;:::i;:::-;;:::i;3423:332:24:-;;;;;;:::i;:::-;;:::i;291:27:2:-;;;;;-1:-1:-1;;;;;291:27:2;;;4313:362:24;;;;;;:::i;:::-;;:::i;1619:117:15:-;;;;;;:::i;:::-;;:::i;5360:113:26:-;;;;;;:::i;:::-;;:::i;639::2:-;;;;;;:::i;:::-;;:::i;1316:18:26:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5762:105:24:-;5835:25;;;;;:10;:25;;;1404::31;5809:7:24;;5835:23;;;;1377:18:31;;5835:25:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5828:32;;5762:105;:::o;1818:120::-;1670:27:28;1686:10;1670:15;:27::i;:::-;1662:36;;;;;;1897:34:24::1;::::0;;;;:10:::1;:34;::::0;::::1;8170:25:31::0;-1:-1:-1;;;;;8231:55:31;;8211:18;;;8204:83;1897:23:24::1;::::0;::::1;::::0;8143:18:31;;1897:34:24::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;1818:120:::0;:::o;8323:87:26:-;8388:5;;:17;;;;;;;;8369:4;;-1:-1:-1;;;;;8388:5:26;;:15;;:17;;;;;;;;;;;;;;:5;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;4865:137::-;4958:8;;4925:4;;-1:-1:-1;;;;;4945:21:26;;;4958:8;;4945:21;;4944:53;;-1:-1:-1;;;;;;4971:26:26;;;;;;:15;:26;;;;;;;;4944:53;4937:60;4865:137;-1:-1:-1;;4865:137:26:o;1940:215:15:-;2082:4;2031:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;;;;;;;;;2061:6:15::1;1945:24:28;1961:7;1945:15;:24::i;:::-;1924:95;;;::::0;-1:-1:-1;;;1924:95:28;;9110:2:31;1924:95:28::1;::::0;::::1;9092:21:31::0;9149:2;9129:18;;;9122:30;9188:26;9168:18;;;9161:54;9232:18;;1924:95:28::1;8908:348:31::0;1924:95:28::1;2096:19:15::2;2112:2;2096:15;:19::i;:::-;2128:5;::::0;:22:::2;::::0;;;;-1:-1:-1;;;;;2128:5:15;;::::2;:22;::::0;::::2;9553:34:31::0;9623:15;;;9603:18;;;9596:43;9655:18;;;9648:34;;;2128:10:15::2;::::0;::::2;::::0;9465:18:31;;2128:22:15::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2121:29:::0;1940:215;-1:-1:-1;;;;;;1940:215:15:o;2201:120:28:-;-1:-1:-1;;;;;992:19:20;;2264:4:28;992:19:20;;;;;;;;;;;;;2287:27:28;888:128:20;2695:317:24;2899:4;2840:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;2874:6:24::1;1945:24:28;1961:7;1945:15;:24::i;:::-;1924:95;;;::::0;-1:-1:-1;;;1924:95:28;;9110:2:31;1924:95:28::1;::::0;::::1;9092:21:31::0;9149:2;9129:18;;;9122:30;9188:26;9168:18;;;9161:54;9232:18;;1924:95:28::1;8908:348:31::0;1924:95:28::1;2919:19:24::2;2935:2;2919:15;:19::i;:::-;2977:5;::::0;2955:50:::2;::::0;;;;-1:-1:-1;;;;;2977:5:24;;::::2;2955:50;::::0;::::2;10376:34:31::0;10446:15;;;10426:18;;;10419:43;10498:15;;;10478:18;;;10471:43;10530:18;;;10523:34;;;10606:4;10594:17;;10573:19;;;10566:46;10628:19;;;10621:35;;;10672:19;;;10665:35;;;2955:13:24::2;::::0;:21:::2;::::0;10287:19:31;;2955:50:24::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2948:57:::0;2695:317;-1:-1:-1;;;;;;;;;;2695:317:24:o;9229:59:26:-;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;9273:10:26::1;:8;:10::i;:::-;9229:59::o:0;836:164:2:-;471:12;;-1:-1:-1;;;;;471:12:2;457:10;:26;449:35;;;;;;925:12:::1;::::0;;918:5;897:41:::1;::::0;-1:-1:-1;;;;;925:12:2;;::::1;::::0;::::1;918:5:::0;;::::1;::::0;;::::1;::::0;897:41:::1;::::0;925:12:::1;::::0;897:41:::1;952:12;::::0;;;944:20;;-1:-1:-1;;944:20:2::1;952:12;-1:-1:-1::0;;;;;952:12:2;::::1;944:20;;::::0;;-1:-1:-1;;970:25:2::1;::::0;;836:164::o;2579:250:15:-;2767:4;2716:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;2746:6:15::1;1945:24:28;1961:7;1945:15;:24::i;:::-;1924:95;;;::::0;-1:-1:-1;;;1924:95:28;;9110:2:31;1924:95:28::1;::::0;::::1;9092:21:31::0;9149:2;9129:18;;;9122:30;9188:26;9168:18;;;9161:54;9232:18;;1924:95:28::1;8908:348:31::0;1924:95:28::1;2788:5:15::2;::::0;:36:::2;::::0;;;;-1:-1:-1;;;;;2788:5:15;;::::2;:36;::::0;::::2;11112:34:31::0;11182:15;;;11162:18;;;11155:43;11214:18;;;11207:34;;;11257:18;;;11250:34;;;11333:4;11321:17;;11300:19;;;11293:46;11355:19;;;11348:35;;;11399:19;;;11392:35;;;2788:10:15::2;::::0;::::2;::::0;11023:19:31;;2788:36:15::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;4273:128:26:-:0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;4350:8:26::1;::::0;4341:29:::1;::::0;-1:-1:-1;;;;;4341:29:26;;::::1;::::0;4350:8:::1;::::0;4341:29:::1;::::0;4350:8:::1;::::0;4341:29:::1;4376:8;:20:::0;;-1:-1:-1;;4376:20:26::1;-1:-1:-1::0;;;;;4376:20:26;;;::::1;::::0;;;::::1;::::0;;4273:128::o;8558:100::-;8632:5;;:21;;;;;-1:-1:-1;;;;;178:55:31;;;8632:21:26;;;160:74:31;8613:4:26;;8632:5;;:16;;133:18:31;;8632:21:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;1022:111:18:-;740:5;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;1098:5:::1;::::0;1079:25:::1;::::0;1098:5:::1;::::0;;::::1;-1:-1:-1::0;;;;;1098:5:18::1;::::0;1079:25:::1;::::0;;;::::1;1110:5;:18:::0;;-1:-1:-1;;1110:18:18::1;::::0;;1022:111::o;7145:203:26:-;7281:7;7242:6;2448:10;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;7305:5:26::2;::::0;:38:::2;::::0;;;;-1:-1:-1;;;;;7305:5:26;;::::2;:38;::::0;::::2;12104:34:31::0;12174:15;;;12154:18;;;12147:43;12226:15;;;12206:18;;;12199:43;12258:18;;;12251:34;;;7305:13:26::2;::::0;::::2;::::0;12015:19:31;;7305:38:26::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7298:45:::0;7145:203;-1:-1:-1;;;;;7145:203:26:o;3030:177:15:-;3157:4;3098:10;3132::::1;1945:24:28;1961:7;1945:15;:24::i;:::-;1924:95;;;::::0;-1:-1:-1;;;1924:95:28;;9110:2:31;1924:95:28::1;::::0;::::1;9092:21:31::0;9149:2;9129:18;;;9122:30;9188:26;9168:18;;;9161:54;9232:18;;1924:95:28::1;8908:348:31::0;1924:95:28::1;3178:5:15::2;::::0;:24:::2;::::0;;;;-1:-1:-1;;;;;3178:5:15;;::::2;:24;::::0;::::2;9553:34:31::0;9623:15;;;9603:18;;;9596:43;9655:18;;;9648:34;;;3178:10:15::2;::::0;::::2;::::0;9465:18:31;;3178:24:15::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;9095:55:26::0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;9137:8:26::1;:6;:8::i;4569:173::-:0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;4692:5:26::1;;4666:32;;;;;;;:::i;:::-;;::::0;;;;::::1;::::0;;;-1:-1:-1;;;;;4666:32:26;::::1;::::0;::::1;::::0;;;::::1;-1:-1:-1::0;;;;;;;4704:26:26::1;;::::0;;;:15:::1;:26;::::0;;;;:33;;-1:-1:-1;;4704:33:26::1;4733:4;4704:33;::::0;;4569:173::o;5097:142::-;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;5181:5:26::1;::::0;5165:33:::1;::::0;-1:-1:-1;;;;;5165:33:26;;::::1;::::0;5181:5:::1;::::0;5165:33:::1;::::0;5181:5:::1;::::0;5165:33:::1;5204:5;:30:::0;;-1:-1:-1;;5204:30:26::1;-1:-1:-1::0;;;;;5204:30:26;;;::::1;::::0;;;::::1;::::0;;5097:142::o;1338:20::-;;;;;;;:::i;5242:421:24:-;5476:4;5429:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;5504:39:24::2;::::0;-1:-1:-1;;;5504:39:24;;:10:::2;:39;::::0;::::2;12844:25:31::0;-1:-1:-1;;;;;12966:15:31;;;12946:18;;;12939:43;13018:15;;12998:18;;;12991:43;13050:18;;;13043:34;;;5504:19:24::2;::::0;::::2;::::0;12816::31;;5504:39:24::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5496:85;;;::::0;-1:-1:-1;;;5496:85:24;;13290:2:31;5496:85:24::2;::::0;::::2;13272:21:31::0;13329:2;13309:18;;;13302:30;13368:34;13348:18;;;13341:62;13439:3;13419:18;;;13412:31;13460:19;;5496:85:24::2;13088:397:31::0;5496:85:24::2;5598:58;5631:6;5639:2;5643:6;5651:4;;5598:32;:58::i;:::-;5591:65:::0;5242:421;-1:-1:-1;;;;;;;5242:421:24:o;1441:111:15:-;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;1516:31:15::1;1539:7;1516:22;:31::i;:::-;1441:111:::0;:::o;5536:83:26:-;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;5592:5:26::1;;;;;;;;;-1:-1:-1::0;;;;;5592:5:26::1;-1:-1:-1::0;;;;;5592:20:26::1;;:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;5536:83::o:0;8889:129::-;8982:5;;:31;;;;;-1:-1:-1;;;;;8982:5:26;;;:31;;;13782:34:31;13852:15;;;13832:18;;;13825:43;13904:15;;;13884:18;;;13877:43;8963:4:26;;8982:15;;;;13694:18:31;;8982:31:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8975:38;8889:129;-1:-1:-1;;;8889:129:26:o;3423:332:24:-;3588:4;3541:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;3616:39:24::2;::::0;-1:-1:-1;;;3616:39:24;;:10:::2;:39;::::0;::::2;12844:25:31::0;-1:-1:-1;;;;;12966:15:31;;;12946:18;;;12939:43;13018:15;;12998:18;;;12991:43;13050:18;;;13043:34;;;3616:19:24::2;::::0;::::2;::::0;12816::31;;3616:39:24::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3608:78;;;::::0;-1:-1:-1;;;3608:78:24;;14133:2:31;3608:78:24::2;::::0;::::2;14115:21:31::0;14172:2;14152:18;;;14145:30;14211:28;14191:18;;;14184:56;14257:18;;3608:78:24::2;13931:350:31::0;3608:78:24::2;3703:45;3729:6;3737:2;3741:6;3703:25;:45::i;4313:362::-:0;4496:4;4449:6;2448:10:26;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;4524:37:24::2;::::0;-1:-1:-1;;;4524:37:24;;:10:::2;:37;::::0;::::2;12844:25:31::0;-1:-1:-1;;;;;12966:15:31;;;12946:18;;;12939:43;13018:15;;12998:18;;;12991:43;13050:18;;;13043:34;;;4524:19:24::2;::::0;::::2;::::0;12816::31;;4524:37:24::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4516:80;;;::::0;-1:-1:-1;;;4516:80:24;;14488:2:31;4516:80:24::2;::::0;::::2;14470:21:31::0;14527:2;14507:18;;;14500:30;14566:32;14546:18;;;14539:60;14616:18;;4516:80:24::2;14286:354:31::0;4516:80:24::2;4613:55;4643:6;4651:4;4657:2;4661:6;4613:29;:55::i;1619:117:15:-:0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;1697:34:15::1;1723:7;1697:25;:34::i;5360:113:26:-:0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;5435:5:26::1;::::0;:33:::1;::::0;;;;-1:-1:-1;;;;;178:55:31;;;5435:33:26::1;::::0;::::1;160:74:31::0;5435:5:26;;::::1;::::0;:23:::1;::::0;133:18:31;;5435:33:26::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;639:113:2::0;740:5:18;;;;;-1:-1:-1;;;;;740:5:18;726:10;:19;718:28;;;;;;724:12:2::1;:23:::0;;-1:-1:-1;;724:23:2::1;-1:-1:-1::0;;;;;724:23:2;;;::::1;::::0;;;::::1;::::0;;639:113::o;3443:379:26:-;-1:-1:-1;;;;;3508:18:26;;3500:51;;;;-1:-1:-1;;;3500:51:26;;14847:2:31;3500:51:26;;;14829:21:31;14886:2;14866:18;;;14859:30;14925:22;14905:18;;;14898:50;14965:18;;3500:51:26;14645:344:31;3500:51:26;-1:-1:-1;;;;;3565:19:26;;3579:4;3565:19;;3557:59;;;;-1:-1:-1;;;3557:59:26;;15196:2:31;3557:59:26;;;15178:21:31;15235:2;15215:18;;;15208:30;15274:29;15254:18;;;15247:57;15321:18;;3557:59:26;14994:351:31;3557:59:26;3644:5;;-1:-1:-1;;;;;3630:20:26;;;3644:5;;3630:20;;3622:63;;;;-1:-1:-1;;;3622:63:26;;15552:2:31;3622:63:26;;;15534:21:31;15591:2;15571:18;;;15564:30;15630:32;15610:18;;;15603:60;15680:18;;3622:63:26;15350:354:31;3622:63:26;3705:8;;-1:-1:-1;;;;;3699:14:26;;;3705:8;;3699:14;;3691:52;;;;-1:-1:-1;;;3691:52:26;;15911:2:31;3691:52:26;;;15893:21:31;15950:2;15930:18;;;15923:30;15989:27;15969:18;;;15962:55;16034:18;;3691:52:26;15709:349:31;3691:52:26;3757:14;3768:2;3757:10;:14::i;:::-;:23;3749:68;;;;-1:-1:-1;;;3749:68:26;;16265:2:31;3749:68:26;;;16247:21:31;;;16284:18;;;16277:30;16343:34;16323:18;;;16316:62;16395:18;;3749:68:26;16063:356:31;2103:117:19;1161:7;;;;1662:41;;;;-1:-1:-1;;;1662:41:19;;16626:2:31;1662:41:19;;;16608:21:31;16665:2;16645:18;;;16638:30;16704:22;16684:18;;;16677:50;16744:18;;1662:41:19;16424:344:31;1662:41:19;2161:7:::1;:15:::0;;-1:-1:-1;;2161:15:19::1;::::0;;2191:22:::1;719:10:3::0;2200:12:19::1;2191:22;::::0;-1:-1:-1;;;;;178:55:31;;;160:74;;148:2;133:18;2191:22:19::1;;;;;;;2103:117::o:0;1856:115::-;1161:7;;;;1404:9;1396:38;;;;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19;;;11622:21:31;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19;11438:340:31;1396:38:19;1925:4:::1;1915:14:::0;;-1:-1:-1;;1915:14:19::1;::::0;::::1;::::0;;1944:20:::1;719:10:3::0;1951:12:19::1;640:96:3::0;7772:468:26;8139:7;8100:6;2448:10;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;8156:19:26::2;8172:2;8156:15;:19::i;:::-;8188:5;::::0;:47:::2;::::0;;;;:21:::2;::::0;::::2;::::0;:47:::2;::::0;-1:-1:-1;;;;;8188:5:26::2;::::0;8210:6;;8218:2;;8222:6;;8230:4;;;;8188:47:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;2484:144:28:-:0;2552:27;:14;2571:7;-1:-1:-1;;;;;423:19:20;:12;:19;;;;;;;;;;;:26;;-1:-1:-1;;423:26:20;445:4;423:26;;;354:100;2552:27:28;2594;;-1:-1:-1;;;;;2594:27:28;;;;;;;;2484:144;:::o;5824:232:26:-;5968:7;5929:6;2448:10;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;5985:19:26::2;6001:2;5985:15;:19::i;:::-;6017:5;::::0;:34:::2;::::0;;;;-1:-1:-1;;;;;6017:5:26;;::::2;:34;::::0;::::2;12104::31::0;12174:15;;;12154:18;;;12147:43;12226:15;;;12206:18;;;12199:43;12258:18;;;12251:34;;;6017:14:26::2;::::0;::::2;::::0;12015:19:31;;6017:34:26::2;11783:508:31::0;6398:260:26;6560:7;6521:6;2448:10;-1:-1:-1;;;;;2448:20:26;;;;:46;;;2472:22;2483:10;2472;:22::i;:::-;2427:149;;;;-1:-1:-1;;;2427:149:26;;8689:2:31;2427:149:26;;;8671:21:31;8728:2;8708:18;;;8701:30;8767:34;8747:18;;;8740:62;-1:-1:-1;;;8818:18:31;;;8811:50;8878:19;;2427:149:26;8487:416:31;2427:149:26;1161:7:19;;;;1404:9:::1;1396:38;;;::::0;-1:-1:-1;;;1396:38:19;;11640:2:31;1396:38:19::1;::::0;::::1;11622:21:31::0;11679:2;11659:18;;;11652:30;-1:-1:-1;;;11698:18:31;;;11691:46;11754:18;;1396:38:19::1;11438:340:31::0;1396:38:19::1;6577:19:26::2;6593:2;6577:15;:19::i;:::-;6609:5;::::0;:44:::2;::::0;;;;-1:-1:-1;;;;;6609:5:26;;::::2;:44;::::0;::::2;17922:34:31::0;17992:15;;;17972:18;;;17965:43;18044:15;;;18024:18;;;18017:43;18096:15;;;18076:18;;;18069:43;18128:19;;;18121:35;;;6609:18:26::2;::::0;::::2;::::0;17833:19:31;;6609:44:26::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;2793:152:28::0;-1:-1:-1;;;;;591:19:20;;2864:14:28;591:19:20;;;;;;;;;;;:27;;-1:-1:-1;;591:27:20;;;2909:29:28;;;2864:14;2909:29;2793:152;:::o;245:597:31:-;357:4;386:2;415;404:9;397:21;447:6;441:13;490:6;485:2;474:9;470:18;463:34;515:1;525:140;539:6;536:1;533:13;525:140;;;634:14;;;630:23;;624:30;600:17;;;619:2;596:26;589:66;554:10;;525:140;;;683:6;680:1;677:13;674:91;;;753:1;748:2;739:6;728:9;724:22;720:31;713:42;674:91;-1:-1:-1;826:2:31;805:15;-1:-1:-1;;801:29:31;786:45;;;;833:2;782:54;;245:597;-1:-1:-1;;;245:597:31:o;847:154::-;-1:-1:-1;;;;;926:5:31;922:54;915:5;912:65;902:93;;991:1;988;981:12;1006:247;1065:6;1118:2;1106:9;1097:7;1093:23;1089:32;1086:52;;;1134:1;1131;1124:12;1086:52;1173:9;1160:23;1192:31;1217:5;1192:31;:::i;1632:456::-;1709:6;1717;1725;1778:2;1766:9;1757:7;1753:23;1749:32;1746:52;;;1794:1;1791;1784:12;1746:52;1833:9;1820:23;1852:31;1877:5;1852:31;:::i;:::-;1902:5;-1:-1:-1;1959:2:31;1944:18;;1931:32;1972:33;1931:32;1972:33;:::i;:::-;1632:456;;2024:7;;-1:-1:-1;;;2078:2:31;2063:18;;;;2050:32;;1632:456::o;2093:156::-;2159:20;;2219:4;2208:16;;2198:27;;2188:55;;2239:1;2236;2229:12;2188:55;2093:156;;;:::o;2254:807::-;2365:6;2373;2381;2389;2397;2405;2413;2466:3;2454:9;2445:7;2441:23;2437:33;2434:53;;;2483:1;2480;2473:12;2434:53;2522:9;2509:23;2541:31;2566:5;2541:31;:::i;:::-;2591:5;-1:-1:-1;2648:2:31;2633:18;;2620:32;2661:33;2620:32;2661:33;:::i;:::-;2713:7;-1:-1:-1;2772:2:31;2757:18;;2744:32;2785:33;2744:32;2785:33;:::i;:::-;2837:7;-1:-1:-1;2891:2:31;2876:18;;2863:32;;-1:-1:-1;2914:37:31;2946:3;2931:19;;2914:37;:::i;:::-;2904:47;;2998:3;2987:9;2983:19;2970:33;2960:43;;3050:3;3039:9;3035:19;3022:33;3012:43;;2254:807;;;;;;;;;;:::o;3066:734::-;3177:6;3185;3193;3201;3209;3217;3225;3278:3;3266:9;3257:7;3253:23;3249:33;3246:53;;;3295:1;3292;3285:12;3246:53;3334:9;3321:23;3353:31;3378:5;3353:31;:::i;:::-;3403:5;-1:-1:-1;3460:2:31;3445:18;;3432:32;3473:33;3432:32;3473:33;:::i;:::-;3525:7;-1:-1:-1;3579:2:31;3564:18;;3551:32;;-1:-1:-1;3630:2:31;3615:18;;3602:32;;-1:-1:-1;3653:37:31;3685:3;3670:19;;3653:37;:::i;3805:315::-;3873:6;3881;3934:2;3922:9;3913:7;3909:23;3905:32;3902:52;;;3950:1;3947;3940:12;3902:52;3989:9;3976:23;4008:31;4033:5;4008:31;:::i;:::-;4058:5;4110:2;4095:18;;;;4082:32;;-1:-1:-1;;;3805:315:31:o;4378:348::-;4430:8;4440:6;4494:3;4487:4;4479:6;4475:17;4471:27;4461:55;;4512:1;4509;4502:12;4461:55;-1:-1:-1;4535:20:31;;4578:18;4567:30;;4564:50;;;4610:1;4607;4600:12;4564:50;4647:4;4639:6;4635:17;4623:29;;4699:3;4692:4;4683:6;4675;4671:19;4667:30;4664:39;4661:59;;;4716:1;4713;4706:12;4661:59;4378:348;;;;;:::o;4731:546::-;4811:6;4819;4827;4880:2;4868:9;4859:7;4855:23;4851:32;4848:52;;;4896:1;4893;4886:12;4848:52;4935:9;4922:23;4954:31;4979:5;4954:31;:::i;:::-;5004:5;-1:-1:-1;5060:2:31;5045:18;;5032:32;5087:18;5076:30;;5073:50;;;5119:1;5116;5109:12;5073:50;5158:59;5209:7;5200:6;5189:9;5185:22;5158:59;:::i;:::-;4731:546;;5236:8;;-1:-1:-1;5132:85:31;;-1:-1:-1;;;;4731:546:31:o;5282:755::-;5379:6;5387;5395;5403;5411;5464:3;5452:9;5443:7;5439:23;5435:33;5432:53;;;5481:1;5478;5471:12;5432:53;5520:9;5507:23;5539:31;5564:5;5539:31;:::i;:::-;5589:5;-1:-1:-1;5646:2:31;5631:18;;5618:32;5659:33;5618:32;5659:33;:::i;:::-;5711:7;-1:-1:-1;5765:2:31;5750:18;;5737:32;;-1:-1:-1;5820:2:31;5805:18;;5792:32;5847:18;5836:30;;5833:50;;;5879:1;5876;5869:12;5833:50;5918:59;5969:7;5960:6;5949:9;5945:22;5918:59;:::i;:::-;5282:755;;;;-1:-1:-1;5282:755:31;;-1:-1:-1;5996:8:31;;5892:85;5282:755;-1:-1:-1;;;5282:755:31:o;6042:388::-;6110:6;6118;6171:2;6159:9;6150:7;6146:23;6142:32;6139:52;;;6187:1;6184;6177:12;6139:52;6226:9;6213:23;6245:31;6270:5;6245:31;:::i;:::-;6295:5;-1:-1:-1;6352:2:31;6337:18;;6324:32;6365:33;6324:32;6365:33;:::i;:::-;6417:7;6407:17;;;6042:388;;;;;:::o;6435:598::-;6521:6;6529;6537;6545;6598:3;6586:9;6577:7;6573:23;6569:33;6566:53;;;6615:1;6612;6605:12;6566:53;6654:9;6641:23;6673:31;6698:5;6673:31;:::i;:::-;6723:5;-1:-1:-1;6780:2:31;6765:18;;6752:32;6793:33;6752:32;6793:33;:::i;:::-;6845:7;-1:-1:-1;6904:2:31;6889:18;;6876:32;6917:33;6876:32;6917:33;:::i;:::-;6435:598;;;;-1:-1:-1;6969:7:31;;7023:2;7008:18;6995:32;;-1:-1:-1;;6435:598:31:o;7038:437::-;7117:1;7113:12;;;;7160;;;7181:61;;7235:4;7227:6;7223:17;7213:27;;7181:61;7288:2;7280:6;7277:14;7257:18;7254:38;7251:218;;;7325:77;7322:1;7315:88;7426:4;7423:1;7416:15;7454:4;7451:1;7444:15;7251:218;;7038:437;;;:::o;7701:251::-;7771:6;7824:2;7812:9;7803:7;7799:23;7795:32;7792:52;;;7840:1;7837;7830:12;7792:52;7872:9;7866:16;7891:31;7916:5;7891:31;:::i;8298:184::-;8368:6;8421:2;8409:9;8400:7;8396:23;8392:32;8389:52;;;8437:1;8434;8427:12;8389:52;-1:-1:-1;8460:16:31;;8298:184;-1:-1:-1;8298:184:31:o;9693:277::-;9760:6;9813:2;9801:9;9792:7;9788:23;9784:32;9781:52;;;9829:1;9826;9819:12;9781:52;9861:9;9855:16;9914:5;9907:13;9900:21;9893:5;9890:32;9880:60;;9936:1;9933;9926:12;12296:273;12481:6;12473;12468:3;12455:33;12437:3;12507:16;;12532:13;;;12507:16;12296:273;-1:-1:-1;12296:273:31:o;16773:795::-;17034:4;-1:-1:-1;;;;;17144:2:31;17136:6;17132:15;17121:9;17114:34;17196:2;17188:6;17184:15;17179:2;17168:9;17164:18;17157:43;17248:2;17240:6;17236:15;17231:2;17220:9;17216:18;17209:43;;17288:6;17283:2;17272:9;17268:18;17261:34;17332:3;17326;17315:9;17311:19;17304:32;17373:6;17367:3;17356:9;17352:19;17345:35;17431:6;17423;17417:3;17406:9;17402:19;17389:49;17488:1;17482:3;17473:6;17462:9;17458:22;17454:32;17447:43;17558:3;17551:2;17547:7;17542:2;17534:6;17530:15;17526:29;17515:9;17511:45;17507:55;17499:63;;16773:795;;;;;;;;;:::o

Swarm Source

ipfs://f0093be45eefa3b445c0e69fc35c23602399ad72137343475b219857f044da15

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.