{
  "address": "0x8F8Cc42B52D4a10A82fdb4B73FCABB0d05128fCb",
  "abi": [
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "previousOwner",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "OwnershipTransferred",
      "type": "event"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "user",
          "type": "address"
        }
      ],
      "name": "aggregateEligibleStakes",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "totalEligibleAmount",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "owner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "renounceOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract DataStakingDynamicNative[]",
          "name": "_stakingContracts",
          "type": "address[]"
        }
      ],
      "name": "setStakingContracts",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "name": "stakingContracts",
      "outputs": [
        {
          "internalType": "contract DataStakingDynamicNative",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "stakingContractsLength",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "transferOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0xcfece451afef414e27fdb393bf8d25cf38598d11ca910b80913612f3768d9aa1",
  "receipt": {
    "to": null,
    "from": "0x84a74cC52048dd8421Df4a9EB139D91bb7744b4E",
    "contractAddress": "0x8F8Cc42B52D4a10A82fdb4B73FCABB0d05128fCb",
    "transactionIndex": 0,
    "gasUsed": "647969",
    "logsBloom": "0x00000000000000000080000000000000000000000000100000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000100000000000000000000000000000000000000000000000000",
    "blockHash": "0x19d031140cbb5a601d94849284d77c5d41fe09c0c64304f0de8de0c7b64db046",
    "transactionHash": "0xcfece451afef414e27fdb393bf8d25cf38598d11ca910b80913612f3768d9aa1",
    "logs": [
      {
        "transactionIndex": 0,
        "blockNumber": 30880,
        "transactionHash": "0xcfece451afef414e27fdb393bf8d25cf38598d11ca910b80913612f3768d9aa1",
        "address": "0x8F8Cc42B52D4a10A82fdb4B73FCABB0d05128fCb",
        "topics": [
          "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0x00000000000000000000000084a74cc52048dd8421df4a9eb139d91bb7744b4e"
        ],
        "data": "0x",
        "logIndex": 0,
        "blockHash": "0x19d031140cbb5a601d94849284d77c5d41fe09c0c64304f0de8de0c7b64db046"
      }
    ],
    "blockNumber": 30880,
    "cumulativeGasUsed": "647969",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "numDeployments": 1,
  "solcInputHash": "3e956c308bcbfe4c2f3d376546d0e4f2",
  "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"aggregateEligibleStakes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"totalEligibleAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract DataStakingDynamicNative[]\",\"name\":\"_stakingContracts\",\"type\":\"address[]\"}],\"name\":\"setStakingContracts\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"stakingContracts\",\"outputs\":[{\"internalType\":\"contract DataStakingDynamicNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakingContractsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"aggregateEligibleStakes(address)\":{\"details\":\"Aggregates the eligible stake amounts for a user across multiple DataStakingDynamicNative contracts.\",\"params\":{\"user\":\"The address of the user.\"},\"returns\":{\"totalEligibleAmount\":\"The total sum of eligible stake amounts for the user across all pools.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setStakingContracts(address[])\":{\"details\":\"Sets the array of DataStakingDynamicNative contract addresses.\",\"params\":{\"_stakingContracts\":\"An array of DataStakingDynamicNative contract addresses.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ProxyViewAggregator.sol\":\"ProxyViewAggregator\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"details\":{\"constantOptimizer\":true,\"cse\":true,\"deduplicate\":true,\"inliner\":true,\"jumpdestRemover\":true,\"orderLiterals\":true,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false},\"runs\":1},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IAccessControl.sol\\\";\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```solidity\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```solidity\\n * function foo() public {\\n *     require(hasRole(MY_ROLE, msg.sender));\\n *     ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\\n * to enforce additional security measures for this role.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n    struct RoleData {\\n        mapping(address => bool) members;\\n        bytes32 adminRole;\\n    }\\n\\n    mapping(bytes32 => RoleData) private _roles;\\n\\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n    /**\\n     * @dev Modifier that checks that an account has a specific role. Reverts\\n     * with a standardized message including the required role.\\n     *\\n     * The format of the revert reason is given by the following regular expression:\\n     *\\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n     *\\n     * _Available since v4.1._\\n     */\\n    modifier onlyRole(bytes32 role) {\\n        _checkRole(role);\\n        _;\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n    }\\n\\n    /**\\n     * @dev Returns `true` if `account` has been granted `role`.\\n     */\\n    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\\n        return _roles[role].members[account];\\n    }\\n\\n    /**\\n     * @dev Revert with a standard message if `_msgSender()` is missing `role`.\\n     * Overriding this function changes the behavior of the {onlyRole} modifier.\\n     *\\n     * Format of the revert message is described in {_checkRole}.\\n     *\\n     * _Available since v4.6._\\n     */\\n    function _checkRole(bytes32 role) internal view virtual {\\n        _checkRole(role, _msgSender());\\n    }\\n\\n    /**\\n     * @dev Revert with a standard message if `account` is missing `role`.\\n     *\\n     * The format of the revert reason is given by the following regular expression:\\n     *\\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n     */\\n    function _checkRole(bytes32 role, address account) internal view virtual {\\n        if (!hasRole(role, account)) {\\n            revert(\\n                string(\\n                    abi.encodePacked(\\n                        \\\"AccessControl: account \\\",\\n                        Strings.toHexString(account),\\n                        \\\" is missing role \\\",\\n                        Strings.toHexString(uint256(role), 32)\\n                    )\\n                )\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\\n     * {revokeRole}.\\n     *\\n     * To change a role's admin, use {_setRoleAdmin}.\\n     */\\n    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\\n        return _roles[role].adminRole;\\n    }\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     *\\n     * May emit a {RoleGranted} event.\\n     */\\n    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n        _grantRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Revokes `role` from `account`.\\n     *\\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     *\\n     * May emit a {RoleRevoked} event.\\n     */\\n    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n        _revokeRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Revokes `role` from the calling account.\\n     *\\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n     * purpose is to provide a mechanism for accounts to lose their privileges\\n     * if they are compromised (such as when a trusted device is misplaced).\\n     *\\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must be `account`.\\n     *\\n     * May emit a {RoleRevoked} event.\\n     */\\n    function renounceRole(bytes32 role, address account) public virtual override {\\n        require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n        _revokeRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\\n     * event. Note that unlike {grantRole}, this function doesn't perform any\\n     * checks on the calling account.\\n     *\\n     * May emit a {RoleGranted} event.\\n     *\\n     * [WARNING]\\n     * ====\\n     * This function should only be called from the constructor when setting\\n     * up the initial roles for the system.\\n     *\\n     * Using this function in any other way is effectively circumventing the admin\\n     * system imposed by {AccessControl}.\\n     * ====\\n     *\\n     * NOTE: This function is deprecated in favor of {_grantRole}.\\n     */\\n    function _setupRole(bytes32 role, address account) internal virtual {\\n        _grantRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Sets `adminRole` as ``role``'s admin role.\\n     *\\n     * Emits a {RoleAdminChanged} event.\\n     */\\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n        bytes32 previousAdminRole = getRoleAdmin(role);\\n        _roles[role].adminRole = adminRole;\\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\\n    }\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * Internal function without access restriction.\\n     *\\n     * May emit a {RoleGranted} event.\\n     */\\n    function _grantRole(bytes32 role, address account) internal virtual {\\n        if (!hasRole(role, account)) {\\n            _roles[role].members[account] = true;\\n            emit RoleGranted(role, account, _msgSender());\\n        }\\n    }\\n\\n    /**\\n     * @dev Revokes `role` from `account`.\\n     *\\n     * Internal function without access restriction.\\n     *\\n     * May emit a {RoleRevoked} event.\\n     */\\n    function _revokeRole(bytes32 role, address account) internal virtual {\\n        if (hasRole(role, account)) {\\n            _roles[role].members[account] = false;\\n            emit RoleRevoked(role, account, _msgSender());\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x0dd6e52cb394d7f5abe5dca2d4908a6be40417914720932de757de34a99ab87f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n    /**\\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n     *\\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n     * {RoleAdminChanged} not being emitted signaling this.\\n     *\\n     * _Available since v3.1._\\n     */\\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n    /**\\n     * @dev Emitted when `account` is granted `role`.\\n     *\\n     * `sender` is the account that originated the contract call, an admin role\\n     * bearer except when using {AccessControl-_setupRole}.\\n     */\\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n    /**\\n     * @dev Emitted when `account` is revoked `role`.\\n     *\\n     * `sender` is the account that originated the contract call:\\n     *   - if using `revokeRole`, it is the admin role bearer\\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n     */\\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n    /**\\n     * @dev Returns `true` if `account` has been granted `role`.\\n     */\\n    function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n    /**\\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\\n     * {revokeRole}.\\n     *\\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n     */\\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     */\\n    function grantRole(bytes32 role, address account) external;\\n\\n    /**\\n     * @dev Revokes `role` from `account`.\\n     *\\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     */\\n    function revokeRole(bytes32 role, address account) external;\\n\\n    /**\\n     * @dev Revokes `role` from the calling account.\\n     *\\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n     * purpose is to provide a mechanism for accounts to lose their privileges\\n     * if they are compromised (such as when a trusted device is misplaced).\\n     *\\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must be `account`.\\n     */\\n    function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n    address private _owner;\\n\\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n    /**\\n     * @dev Initializes the contract setting the deployer as the initial owner.\\n     */\\n    constructor() {\\n        _transferOwnership(_msgSender());\\n    }\\n\\n    /**\\n     * @dev Throws if called by any account other than the owner.\\n     */\\n    modifier onlyOwner() {\\n        _checkOwner();\\n        _;\\n    }\\n\\n    /**\\n     * @dev Returns the address of the current owner.\\n     */\\n    function owner() public view virtual returns (address) {\\n        return _owner;\\n    }\\n\\n    /**\\n     * @dev Throws if the sender is not the owner.\\n     */\\n    function _checkOwner() internal view virtual {\\n        require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n    }\\n\\n    /**\\n     * @dev Leaves the contract without owner. It will not be possible to call\\n     * `onlyOwner` functions. Can only be called by the current owner.\\n     *\\n     * NOTE: Renouncing ownership will leave the contract without an owner,\\n     * thereby disabling any functionality that is only available to the owner.\\n     */\\n    function renounceOwnership() public virtual onlyOwner {\\n        _transferOwnership(address(0));\\n    }\\n\\n    /**\\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n     * Can only be called by the current owner.\\n     */\\n    function transferOwnership(address newOwner) public virtual onlyOwner {\\n        require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n        _transferOwnership(newOwner);\\n    }\\n\\n    /**\\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n     * Internal function without access restriction.\\n     */\\n    function _transferOwnership(address newOwner) internal virtual {\\n        address oldOwner = _owner;\\n        _owner = newOwner;\\n        emit OwnershipTransferred(oldOwner, newOwner);\\n    }\\n}\\n\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/ERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n    using Address for address;\\n\\n    // Mapping from token ID to account balances\\n    mapping(uint256 => mapping(address => uint256)) private _balances;\\n\\n    // Mapping from account to operator approvals\\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n    // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n    string private _uri;\\n\\n    /**\\n     * @dev See {_setURI}.\\n     */\\n    constructor(string memory uri_) {\\n        _setURI(uri_);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n        return\\n            interfaceId == type(IERC1155).interfaceId ||\\n            interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n            super.supportsInterface(interfaceId);\\n    }\\n\\n    /**\\n     * @dev See {IERC1155MetadataURI-uri}.\\n     *\\n     * This implementation returns the same URI for *all* token types. It relies\\n     * on the token type ID substitution mechanism\\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n     *\\n     * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n     * actual token type ID.\\n     */\\n    function uri(uint256) public view virtual override returns (string memory) {\\n        return _uri;\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-balanceOf}.\\n     *\\n     * Requirements:\\n     *\\n     * - `account` cannot be the zero address.\\n     */\\n    function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n        require(account != address(0), \\\"ERC1155: address zero is not a valid owner\\\");\\n        return _balances[id][account];\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-balanceOfBatch}.\\n     *\\n     * Requirements:\\n     *\\n     * - `accounts` and `ids` must have the same length.\\n     */\\n    function balanceOfBatch(\\n        address[] memory accounts,\\n        uint256[] memory ids\\n    ) public view virtual override returns (uint256[] memory) {\\n        require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n        uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n        for (uint256 i = 0; i < accounts.length; ++i) {\\n            batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n        }\\n\\n        return batchBalances;\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        _setApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[account][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(\\n        address from,\\n        address to,\\n        uint256 id,\\n        uint256 amount,\\n        bytes memory data\\n    ) public virtual override {\\n        require(\\n            from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n            \\\"ERC1155: caller is not token owner or approved\\\"\\n        );\\n        _safeTransferFrom(from, to, id, amount, data);\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-safeBatchTransferFrom}.\\n     */\\n    function safeBatchTransferFrom(\\n        address from,\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) public virtual override {\\n        require(\\n            from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n            \\\"ERC1155: caller is not token owner or approved\\\"\\n        );\\n        _safeBatchTransferFrom(from, to, ids, amounts, data);\\n    }\\n\\n    /**\\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n     *\\n     * Emits a {TransferSingle} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n     * acceptance magic value.\\n     */\\n    function _safeTransferFrom(\\n        address from,\\n        address to,\\n        uint256 id,\\n        uint256 amount,\\n        bytes memory data\\n    ) internal virtual {\\n        require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n        address operator = _msgSender();\\n        uint256[] memory ids = _asSingletonArray(id);\\n        uint256[] memory amounts = _asSingletonArray(amount);\\n\\n        _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n        uint256 fromBalance = _balances[id][from];\\n        require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n        unchecked {\\n            _balances[id][from] = fromBalance - amount;\\n        }\\n        _balances[id][to] += amount;\\n\\n        emit TransferSingle(operator, from, to, id, amount);\\n\\n        _afterTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n    }\\n\\n    /**\\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\\n     *\\n     * Emits a {TransferBatch} event.\\n     *\\n     * Requirements:\\n     *\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n     * acceptance magic value.\\n     */\\n    function _safeBatchTransferFrom(\\n        address from,\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) internal virtual {\\n        require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n        require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n        address operator = _msgSender();\\n\\n        _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n        for (uint256 i = 0; i < ids.length; ++i) {\\n            uint256 id = ids[i];\\n            uint256 amount = amounts[i];\\n\\n            uint256 fromBalance = _balances[id][from];\\n            require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n            unchecked {\\n                _balances[id][from] = fromBalance - amount;\\n            }\\n            _balances[id][to] += amount;\\n        }\\n\\n        emit TransferBatch(operator, from, to, ids, amounts);\\n\\n        _afterTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n        _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n    }\\n\\n    /**\\n     * @dev Sets a new URI for all token types, by relying on the token type ID\\n     * substitution mechanism\\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n     *\\n     * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n     * URI or any of the amounts in the JSON file at said URI will be replaced by\\n     * clients with the token type ID.\\n     *\\n     * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n     * interpreted by clients as\\n     * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n     * for token type ID 0x4cce0.\\n     *\\n     * See {uri}.\\n     *\\n     * Because these URIs cannot be meaningfully represented by the {URI} event,\\n     * this function emits no events.\\n     */\\n    function _setURI(string memory newuri) internal virtual {\\n        _uri = newuri;\\n    }\\n\\n    /**\\n     * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\\n     *\\n     * Emits a {TransferSingle} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n     * acceptance magic value.\\n     */\\n    function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal virtual {\\n        require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n        address operator = _msgSender();\\n        uint256[] memory ids = _asSingletonArray(id);\\n        uint256[] memory amounts = _asSingletonArray(amount);\\n\\n        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n        _balances[id][to] += amount;\\n        emit TransferSingle(operator, address(0), to, id, amount);\\n\\n        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n        _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\\n    }\\n\\n    /**\\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n     *\\n     * Emits a {TransferBatch} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `ids` and `amounts` must have the same length.\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n     * acceptance magic value.\\n     */\\n    function _mintBatch(\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) internal virtual {\\n        require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n        require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n        address operator = _msgSender();\\n\\n        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n        for (uint256 i = 0; i < ids.length; i++) {\\n            _balances[ids[i]][to] += amounts[i];\\n        }\\n\\n        emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n        _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n    }\\n\\n    /**\\n     * @dev Destroys `amount` tokens of token type `id` from `from`\\n     *\\n     * Emits a {TransferSingle} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `from` must have at least `amount` tokens of token type `id`.\\n     */\\n    function _burn(address from, uint256 id, uint256 amount) internal virtual {\\n        require(from != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n        address operator = _msgSender();\\n        uint256[] memory ids = _asSingletonArray(id);\\n        uint256[] memory amounts = _asSingletonArray(amount);\\n\\n        _beforeTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n\\n        uint256 fromBalance = _balances[id][from];\\n        require(fromBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n        unchecked {\\n            _balances[id][from] = fromBalance - amount;\\n        }\\n\\n        emit TransferSingle(operator, from, address(0), id, amount);\\n\\n        _afterTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n     *\\n     * Emits a {TransferBatch} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `ids` and `amounts` must have the same length.\\n     */\\n    function _burnBatch(address from, uint256[] memory ids, uint256[] memory amounts) internal virtual {\\n        require(from != address(0), \\\"ERC1155: burn from the zero address\\\");\\n        require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n        address operator = _msgSender();\\n\\n        _beforeTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n\\n        for (uint256 i = 0; i < ids.length; i++) {\\n            uint256 id = ids[i];\\n            uint256 amount = amounts[i];\\n\\n            uint256 fromBalance = _balances[id][from];\\n            require(fromBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n            unchecked {\\n                _balances[id][from] = fromBalance - amount;\\n            }\\n        }\\n\\n        emit TransferBatch(operator, from, address(0), ids, amounts);\\n\\n        _afterTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Approve `operator` to operate on all of `owner` tokens\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n        require(owner != operator, \\\"ERC1155: setting approval status for self\\\");\\n        _operatorApprovals[owner][operator] = approved;\\n        emit ApprovalForAll(owner, operator, approved);\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning, as well as batched variants.\\n     *\\n     * The same hook is called on both single and batched variants. For single\\n     * transfers, the length of the `ids` and `amounts` arrays will be 1.\\n     *\\n     * Calling conditions (for each `id` and `amount` pair):\\n     *\\n     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n     * of token type `id` will be  transferred to `to`.\\n     * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n     * for `to`.\\n     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n     * will be burned.\\n     * - `from` and `to` are never both zero.\\n     * - `ids` and `amounts` have the same, non-zero length.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(\\n        address operator,\\n        address from,\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) internal virtual {}\\n\\n    /**\\n     * @dev Hook that is called after any token transfer. This includes minting\\n     * and burning, as well as batched variants.\\n     *\\n     * The same hook is called on both single and batched variants. For single\\n     * transfers, the length of the `id` and `amount` arrays will be 1.\\n     *\\n     * Calling conditions (for each `id` and `amount` pair):\\n     *\\n     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n     * of token type `id` will be  transferred to `to`.\\n     * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n     * for `to`.\\n     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n     * will be burned.\\n     * - `from` and `to` are never both zero.\\n     * - `ids` and `amounts` have the same, non-zero length.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _afterTokenTransfer(\\n        address operator,\\n        address from,\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) internal virtual {}\\n\\n    function _doSafeTransferAcceptanceCheck(\\n        address operator,\\n        address from,\\n        address to,\\n        uint256 id,\\n        uint256 amount,\\n        bytes memory data\\n    ) private {\\n        if (to.isContract()) {\\n            try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n                if (response != IERC1155Receiver.onERC1155Received.selector) {\\n                    revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n                }\\n            } catch Error(string memory reason) {\\n                revert(reason);\\n            } catch {\\n                revert(\\\"ERC1155: transfer to non-ERC1155Receiver implementer\\\");\\n            }\\n        }\\n    }\\n\\n    function _doSafeBatchTransferAcceptanceCheck(\\n        address operator,\\n        address from,\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) private {\\n        if (to.isContract()) {\\n            try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\\n                bytes4 response\\n            ) {\\n                if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\\n                    revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n                }\\n            } catch Error(string memory reason) {\\n                revert(reason);\\n            } catch {\\n                revert(\\\"ERC1155: transfer to non-ERC1155Receiver implementer\\\");\\n            }\\n        }\\n    }\\n\\n    function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n        uint256[] memory array = new uint256[](1);\\n        array[0] = element;\\n\\n        return array;\\n    }\\n}\\n\",\"keccak256\":\"0x81149353c99ccf8ff18af7701bc3f38665c7a97e344cdc0d27f927f03d22af0e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n    /**\\n     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n     */\\n    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n    /**\\n     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n     * transfers.\\n     */\\n    event TransferBatch(\\n        address indexed operator,\\n        address indexed from,\\n        address indexed to,\\n        uint256[] ids,\\n        uint256[] values\\n    );\\n\\n    /**\\n     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n     * `approved`.\\n     */\\n    event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n     *\\n     * If an {URI} event was emitted for `id`, the standard\\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n     * returned by {IERC1155MetadataURI-uri}.\\n     */\\n    event URI(string value, uint256 indexed id);\\n\\n    /**\\n     * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n     *\\n     * Requirements:\\n     *\\n     * - `account` cannot be the zero address.\\n     */\\n    function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n    /**\\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n     *\\n     * Requirements:\\n     *\\n     * - `accounts` and `ids` must have the same length.\\n     */\\n    function balanceOfBatch(\\n        address[] calldata accounts,\\n        uint256[] calldata ids\\n    ) external view returns (uint256[] memory);\\n\\n    /**\\n     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `operator` cannot be the caller.\\n     */\\n    function setApprovalForAll(address operator, bool approved) external;\\n\\n    /**\\n     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n     *\\n     * See {setApprovalForAll}.\\n     */\\n    function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n    /**\\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n     *\\n     * Emits a {TransferSingle} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n     * acceptance magic value.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n    /**\\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n     *\\n     * Emits a {TransferBatch} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `ids` and `amounts` must have the same length.\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n     * acceptance magic value.\\n     */\\n    function safeBatchTransferFrom(\\n        address from,\\n        address to,\\n        uint256[] calldata ids,\\n        uint256[] calldata amounts,\\n        bytes calldata data\\n    ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n    /**\\n     * @dev Handles the receipt of a single ERC1155 token type. This function is\\n     * called at the end of a `safeTransferFrom` after the balance has been updated.\\n     *\\n     * NOTE: To accept the transfer, this must return\\n     * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n     * (i.e. 0xf23a6e61, or its own function selector).\\n     *\\n     * @param operator The address which initiated the transfer (i.e. msg.sender)\\n     * @param from The address which previously owned the token\\n     * @param id The ID of the token being transferred\\n     * @param value The amount of tokens being transferred\\n     * @param data Additional data with no specified format\\n     * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n     */\\n    function onERC1155Received(\\n        address operator,\\n        address from,\\n        uint256 id,\\n        uint256 value,\\n        bytes calldata data\\n    ) external returns (bytes4);\\n\\n    /**\\n     * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n     * is called at the end of a `safeBatchTransferFrom` after the balances have\\n     * been updated.\\n     *\\n     * NOTE: To accept the transfer(s), this must return\\n     * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n     * (i.e. 0xbc197c81, or its own function selector).\\n     *\\n     * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n     * @param from The address which previously owned the token\\n     * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n     * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n     * @param data Additional data with no specified format\\n     * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n     */\\n    function onERC1155BatchReceived(\\n        address operator,\\n        address from,\\n        uint256[] calldata ids,\\n        uint256[] calldata values,\\n        bytes calldata data\\n    ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n    /**\\n     * @dev Returns the URI for token type `id`.\\n     *\\n     * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n     * clients with the actual token type ID.\\n     */\\n    function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xa66d18b9a85458d28fc3304717964502ae36f7f8a2ff35bc83f6f85d74b03574\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `to`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address to, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `from` to `to` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     *\\n     * Furthermore, `isContract` will also return true if the target contract within\\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n     * which only has an effect at the end of a transaction.\\n     * ====\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n     *\\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n     * constructor.\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize/address.code.length, which returns 0\\n        // for contracts in construction, since the code is only stored at the end\\n        // of the constructor execution.\\n\\n        return account.code.length > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain `call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(\\n        address target,\\n        bytes memory data,\\n        uint256 value,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal view returns (bytes memory) {\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n     *\\n     * _Available since v4.8._\\n     */\\n    function verifyCallResultFromTarget(\\n        address target,\\n        bool success,\\n        bytes memory returndata,\\n        string memory errorMessage\\n    ) internal view returns (bytes memory) {\\n        if (success) {\\n            if (returndata.length == 0) {\\n                // only check isContract if the call was successful and the return data is empty\\n                // otherwise we already know that it was a contract\\n                require(isContract(target), \\\"Address: call to non-contract\\\");\\n            }\\n            return returndata;\\n        } else {\\n            _revert(returndata, errorMessage);\\n        }\\n    }\\n\\n    /**\\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n     * revert reason or using the provided one.\\n     *\\n     * _Available since v4.3._\\n     */\\n    function verifyCallResult(\\n        bool success,\\n        bytes memory returndata,\\n        string memory errorMessage\\n    ) internal pure returns (bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            _revert(returndata, errorMessage);\\n        }\\n    }\\n\\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n        // Look for revert reason and bubble it up if present\\n        if (returndata.length > 0) {\\n            // The easiest way to bubble the revert reason is using memory via assembly\\n            /// @solidity memory-safe-assembly\\n            assembly {\\n                let returndata_size := mload(returndata)\\n                revert(add(32, returndata), returndata_size)\\n            }\\n        } else {\\n            revert(errorMessage);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n    function _msgSender() internal view virtual returns (address) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes calldata) {\\n        return msg.data;\\n    }\\n\\n    function _contextSuffixLength() internal view virtual returns (uint256) {\\n        return 0;\\n    }\\n}\\n\",\"keccak256\":\"0xa92e4fa126feb6907daa0513ddd816b2eb91f30a808de54f63c17d0e162c3439\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n    uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n     */\\n    function toString(uint256 value) internal pure returns (string memory) {\\n        unchecked {\\n            uint256 length = Math.log10(value) + 1;\\n            string memory buffer = new string(length);\\n            uint256 ptr;\\n            /// @solidity memory-safe-assembly\\n            assembly {\\n                ptr := add(buffer, add(32, length))\\n            }\\n            while (true) {\\n                ptr--;\\n                /// @solidity memory-safe-assembly\\n                assembly {\\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n                }\\n                value /= 10;\\n                if (value == 0) break;\\n            }\\n            return buffer;\\n        }\\n    }\\n\\n    /**\\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n     */\\n    function toString(int256 value) internal pure returns (string memory) {\\n        return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n    }\\n\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n     */\\n    function toHexString(uint256 value) internal pure returns (string memory) {\\n        unchecked {\\n            return toHexString(value, Math.log256(value) + 1);\\n        }\\n    }\\n\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n     */\\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n        bytes memory buffer = new bytes(2 * length + 2);\\n        buffer[0] = \\\"0\\\";\\n        buffer[1] = \\\"x\\\";\\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\\n            buffer[i] = _SYMBOLS[value & 0xf];\\n            value >>= 4;\\n        }\\n        require(value == 0, \\\"Strings: hex length insufficient\\\");\\n        return string(buffer);\\n    }\\n\\n    /**\\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n     */\\n    function toHexString(address addr) internal pure returns (string memory) {\\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n    }\\n\\n    /**\\n     * @dev Returns true if the two strings are equal.\\n     */\\n    function equal(string memory a, string memory b) internal pure returns (bool) {\\n        return keccak256(bytes(a)) == keccak256(bytes(b));\\n    }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return interfaceId == type(IERC165).interfaceId;\\n    }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n    enum Rounding {\\n        Down, // Toward negative infinity\\n        Up, // Toward infinity\\n        Zero // Toward zero\\n    }\\n\\n    /**\\n     * @dev Returns the largest of two numbers.\\n     */\\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a > b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the smallest of two numbers.\\n     */\\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a < b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the average of two numbers. The result is rounded towards\\n     * zero.\\n     */\\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // (a + b) / 2 can overflow.\\n        return (a & b) + (a ^ b) / 2;\\n    }\\n\\n    /**\\n     * @dev Returns the ceiling of the division of two numbers.\\n     *\\n     * This differs from standard division with `/` in that it rounds up instead\\n     * of rounding down.\\n     */\\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // (a + b - 1) / b can overflow on addition, so we distribute.\\n        return a == 0 ? 0 : (a - 1) / b + 1;\\n    }\\n\\n    /**\\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n     * with further edits by Uniswap Labs also under MIT license.\\n     */\\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n        unchecked {\\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n            // variables such that product = prod1 * 2^256 + prod0.\\n            uint256 prod0; // Least significant 256 bits of the product\\n            uint256 prod1; // Most significant 256 bits of the product\\n            assembly {\\n                let mm := mulmod(x, y, not(0))\\n                prod0 := mul(x, y)\\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n            }\\n\\n            // Handle non-overflow cases, 256 by 256 division.\\n            if (prod1 == 0) {\\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n                // The surrounding unchecked block does not change this fact.\\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n                return prod0 / denominator;\\n            }\\n\\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n            require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n            ///////////////////////////////////////////////\\n            // 512 by 256 division.\\n            ///////////////////////////////////////////////\\n\\n            // Make division exact by subtracting the remainder from [prod1 prod0].\\n            uint256 remainder;\\n            assembly {\\n                // Compute remainder using mulmod.\\n                remainder := mulmod(x, y, denominator)\\n\\n                // Subtract 256 bit number from 512 bit number.\\n                prod1 := sub(prod1, gt(remainder, prod0))\\n                prod0 := sub(prod0, remainder)\\n            }\\n\\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n            // See https://cs.stackexchange.com/q/138556/92363.\\n\\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\\n            uint256 twos = denominator & (~denominator + 1);\\n            assembly {\\n                // Divide denominator by twos.\\n                denominator := div(denominator, twos)\\n\\n                // Divide [prod1 prod0] by twos.\\n                prod0 := div(prod0, twos)\\n\\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n                twos := add(div(sub(0, twos), twos), 1)\\n            }\\n\\n            // Shift in bits from prod1 into prod0.\\n            prod0 |= prod1 * twos;\\n\\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n            // four bits. That is, denominator * inv = 1 mod 2^4.\\n            uint256 inverse = (3 * denominator) ^ 2;\\n\\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n            // in modular arithmetic, doubling the correct bits in each step.\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n            // is no longer required.\\n            result = prod0 * inverse;\\n            return result;\\n        }\\n    }\\n\\n    /**\\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n     */\\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n        uint256 result = mulDiv(x, y, denominator);\\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n            result += 1;\\n        }\\n        return result;\\n    }\\n\\n    /**\\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n     *\\n     * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n     */\\n    function sqrt(uint256 a) internal pure returns (uint256) {\\n        if (a == 0) {\\n            return 0;\\n        }\\n\\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n        //\\n        // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n        //\\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n        // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n        // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n        //\\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n        uint256 result = 1 << (log2(a) >> 1);\\n\\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n        // into the expected uint128 result.\\n        unchecked {\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            return min(result, a / result);\\n        }\\n    }\\n\\n    /**\\n     * @notice Calculates sqrt(a), following the selected rounding direction.\\n     */\\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n        unchecked {\\n            uint256 result = sqrt(a);\\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n        }\\n    }\\n\\n    /**\\n     * @dev Return the log in base 2, rounded down, of a positive value.\\n     * Returns 0 if given 0.\\n     */\\n    function log2(uint256 value) internal pure returns (uint256) {\\n        uint256 result = 0;\\n        unchecked {\\n            if (value >> 128 > 0) {\\n                value >>= 128;\\n                result += 128;\\n            }\\n            if (value >> 64 > 0) {\\n                value >>= 64;\\n                result += 64;\\n            }\\n            if (value >> 32 > 0) {\\n                value >>= 32;\\n                result += 32;\\n            }\\n            if (value >> 16 > 0) {\\n                value >>= 16;\\n                result += 16;\\n            }\\n            if (value >> 8 > 0) {\\n                value >>= 8;\\n                result += 8;\\n            }\\n            if (value >> 4 > 0) {\\n                value >>= 4;\\n                result += 4;\\n            }\\n            if (value >> 2 > 0) {\\n                value >>= 2;\\n                result += 2;\\n            }\\n            if (value >> 1 > 0) {\\n                result += 1;\\n            }\\n        }\\n        return result;\\n    }\\n\\n    /**\\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n     * Returns 0 if given 0.\\n     */\\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n        unchecked {\\n            uint256 result = log2(value);\\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n        }\\n    }\\n\\n    /**\\n     * @dev Return the log in base 10, rounded down, of a positive value.\\n     * Returns 0 if given 0.\\n     */\\n    function log10(uint256 value) internal pure returns (uint256) {\\n        uint256 result = 0;\\n        unchecked {\\n            if (value >= 10 ** 64) {\\n                value /= 10 ** 64;\\n                result += 64;\\n            }\\n            if (value >= 10 ** 32) {\\n                value /= 10 ** 32;\\n                result += 32;\\n            }\\n            if (value >= 10 ** 16) {\\n                value /= 10 ** 16;\\n                result += 16;\\n            }\\n            if (value >= 10 ** 8) {\\n                value /= 10 ** 8;\\n                result += 8;\\n            }\\n            if (value >= 10 ** 4) {\\n                value /= 10 ** 4;\\n                result += 4;\\n            }\\n            if (value >= 10 ** 2) {\\n                value /= 10 ** 2;\\n                result += 2;\\n            }\\n            if (value >= 10 ** 1) {\\n                result += 1;\\n            }\\n        }\\n        return result;\\n    }\\n\\n    /**\\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n     * Returns 0 if given 0.\\n     */\\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n        unchecked {\\n            uint256 result = log10(value);\\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n        }\\n    }\\n\\n    /**\\n     * @dev Return the log in base 256, rounded down, of a positive value.\\n     * Returns 0 if given 0.\\n     *\\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n     */\\n    function log256(uint256 value) internal pure returns (uint256) {\\n        uint256 result = 0;\\n        unchecked {\\n            if (value >> 128 > 0) {\\n                value >>= 128;\\n                result += 16;\\n            }\\n            if (value >> 64 > 0) {\\n                value >>= 64;\\n                result += 8;\\n            }\\n            if (value >> 32 > 0) {\\n                value >>= 32;\\n                result += 4;\\n            }\\n            if (value >> 16 > 0) {\\n                value >>= 16;\\n                result += 2;\\n            }\\n            if (value >> 8 > 0) {\\n                result += 1;\\n            }\\n        }\\n        return result;\\n    }\\n\\n    /**\\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n     * Returns 0 if given 0.\\n     */\\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n        unchecked {\\n            uint256 result = log256(value);\\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// CAUTION\\n// This version of SafeMath should only be used with Solidity 0.8 or later,\\n// because it relies on the compiler's built in overflow checks.\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations.\\n *\\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\\n * now has built in overflow checking.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        unchecked {\\n            uint256 c = a + b;\\n            if (c < a) return (false, 0);\\n            return (true, c);\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        unchecked {\\n            if (b > a) return (false, 0);\\n            return (true, a - b);\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        unchecked {\\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n            // benefit is lost if 'b' is also tested.\\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n            if (a == 0) return (true, 0);\\n            uint256 c = a * b;\\n            if (c / a != b) return (false, 0);\\n            return (true, c);\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        unchecked {\\n            if (b == 0) return (false, 0);\\n            return (true, a / b);\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n        unchecked {\\n            if (b == 0) return (false, 0);\\n            return (true, a % b);\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a + b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a - b;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a * b;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a / b;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a % b;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {trySub}.\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        unchecked {\\n            require(b <= a, errorMessage);\\n            return a - b;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        unchecked {\\n            require(b > 0, errorMessage);\\n            return a / b;\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * reverting with custom message when dividing by zero.\\n     *\\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\\n     * message unnecessarily. For custom revert reasons use {tryMod}.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     *\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        unchecked {\\n            require(b > 0, errorMessage);\\n            return a % b;\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x58b21219689909c4f8339af00813760337f7e2e7f169a97fe49e2896dcfb3b9a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n    /**\\n     * @dev Returns the largest of two signed numbers.\\n     */\\n    function max(int256 a, int256 b) internal pure returns (int256) {\\n        return a > b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the smallest of two signed numbers.\\n     */\\n    function min(int256 a, int256 b) internal pure returns (int256) {\\n        return a < b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the average of two signed numbers without overflow.\\n     * The result is rounded towards zero.\\n     */\\n    function average(int256 a, int256 b) internal pure returns (int256) {\\n        // Formula from the book \\\"Hacker's Delight\\\"\\n        int256 x = (a & b) + ((a ^ b) >> 1);\\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\\n    }\\n\\n    /**\\n     * @dev Returns the absolute unsigned value of a signed value.\\n     */\\n    function abs(int256 n) internal pure returns (uint256) {\\n        unchecked {\\n            // must be unchecked in order to support `n = type(int256).min`\\n            return uint256(n >= 0 ? n : -n);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"contracts/DataPointsMulti.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport \\\"./lib/base64.sol\\\";\\n\\n/**\\n * @title DataPointsMulti\\n * @dev This contract extends ERC1155 to create a multi-token contract, named DataPointsMulti, intended to represent accumulated data points\\n * within the Masa Network. Each token ID represents a different data type, and it features minting and burning capabilities, with distinct roles\\n * for each action, as well as an admin role for role management. The tokens are non-transferable, meaning they cannot be transferred between\\n * addresses once minted, making them purely a representation of earned points rather than a tradable asset.\\n *\\n * The contract utilizes OpenZeppelin's ERC1155 for the multi-token standard and AccessControl for role-based access control, respectively.\\n * It also implements the ERC1155 URI mechanism to provide on-chain metadata for each token type.\\n */\\ncontract DataPointsMulti is ERC1155, AccessControl {\\n    using Strings for uint256;\\n\\n    // Role definitions for role-based access control\\n    bytes32 public constant MINTER_ROLE = keccak256(\\\"MINTER_ROLE\\\");\\n    bytes32 public constant ADMIN_ROLE = keccak256(\\\"ADMIN_ROLE\\\");\\n    bytes32 public constant UPDATER_ROLE = keccak256(\\\"UPDATER_ROLE\\\");\\n\\n    // Struct for storing token metadata.\\n    struct TokenMetadata {\\n        string name;\\n        string image;\\n        string description;\\n    }\\n\\n    // Define a new struct that includes the token ID and its metadata\\n    struct TokenIdMetadata {\\n        uint256 tokenId;\\n        TokenMetadata metadata;\\n    }\\n\\n    // Struct to hold token balance information.\\n    struct TokenBalance {\\n        string tokenName;\\n        uint256 balance;\\n    }\\n\\n    // Mapping from token ID to its metadata.\\n    mapping(uint256 => TokenMetadata) public tokenMetadata;\\n\\n    // Mapping from address and token ID to an array of UUIDs.\\n    mapping(address => mapping(uint256 => uint256[])) public accountTokenUUIDs;\\n\\n    // Counter for the total number of token types.\\n    uint256 public tokenTypeCount;\\n\\n    // Array of valid token IDs.\\n    uint256[] public validTokenIds;\\n\\n    // Base URI for constructing token URIs.\\n    string public baseURI;\\n\\n    // Events for logging actions on the contract.\\n    event BaseURISet(string newBaseURI);\\n    event TokenMinted(\\n        address account,\\n        uint256 id,\\n        uint256 amount,\\n        uint256 uuid\\n    );\\n    event TokenBatchMinted(\\n        address account,\\n        uint256[] ids,\\n        uint256[] amounts,\\n        uint256[] uuid\\n    );\\n    event TokenBurned(address account, uint256 id, uint256 amount);\\n    event TokenBatchBurned(address account, uint256[] ids, uint256[] amounts);\\n    event TokenNameSet(uint256 id, string name);\\n    event RoleSetup(bytes32 role, address account);\\n\\n    /**\\n     * @dev Initializes the contract by setting a base URI and configuring roles.\\n     * @param baseUriInput The initial base URI for token metadata.\\n     */\\n    constructor(string memory baseUriInput) ERC1155(\\\"\\\") {\\n        baseURI = baseUriInput;\\n\\n        // Grant roles to the contract deployer\\n        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\\n        _setupRole(ADMIN_ROLE, msg.sender);\\n        _setupRole(MINTER_ROLE, msg.sender);\\n        _setupRole(UPDATER_ROLE, msg.sender);\\n\\n        // Configure role hierarchies\\n        _setRoleAdmin(MINTER_ROLE, ADMIN_ROLE);\\n        _setRoleAdmin(UPDATER_ROLE, ADMIN_ROLE);\\n    }\\n\\n    /**\\n     * @dev Updates the base URI used for token metadata. Can only be called by an admin.\\n     * @param newBaseURI The new base URI to set.\\n     */\\n    function setBaseURI(string memory newBaseURI) public onlyRole(ADMIN_ROLE) {\\n        require(\\n            bytes(newBaseURI).length > 0,\\n            \\\"DataPointsMulti: Base URI cannot be empty\\\"\\n        );\\n        baseURI = newBaseURI;\\n        emit BaseURISet(newBaseURI);\\n    }\\n\\n    /**\\n     * @dev Sets the metadata for a token ID. Can only be called by an admin.\\n     * @param tokenId The token ID to set metadata for.\\n     * @param name The name for the token.\\n     * @param image The image URL for the token.\\n     * @param description The description for the token.\\n     */\\n    function setTokenMetadata(\\n        uint256 tokenId,\\n        string memory name,\\n        string memory image,\\n        string memory description\\n    ) public onlyRole(ADMIN_ROLE) {\\n        require(\\n            bytes(name).length > 0,\\n            \\\"DataPointsMulti: Token name cannot be empty\\\"\\n        );\\n        require(\\n            bytes(image).length > 0,\\n            \\\"DataPointsMulti: Token image cannot be empty\\\"\\n        );\\n        require(\\n            bytes(description).length > 0,\\n            \\\"DataPointsMulti: Token description cannot be empty\\\"\\n        );\\n\\n        tokenMetadata[tokenId] = TokenMetadata(name, image, description);\\n    }\\n\\n    /**\\n     * @dev Generates a URI for a given token ID. The URI is a data URI with a JSON-formatted metadata blob.\\n     * This includes the name, description, and image for the token.\\n     * @param tokenId The token ID to generate a URI for.\\n     * @return The URI string for the given token ID's metadata.\\n     */\\n    function uri(uint256 tokenId) public view override returns (string memory) {\\n        require(\\n            bytes(tokenMetadata[tokenId].name).length > 0,\\n            \\\"DataPointsMulti: Token ID does not exist\\\"\\n        );\\n\\n        // Create a JSON blob with the metadata\\n        string memory json = string(\\n            abi.encodePacked(\\n                '{\\\"name\\\": \\\"',\\n                tokenMetadata[tokenId].name,\\n                '\\\", \\\"description\\\": \\\"',\\n                tokenMetadata[tokenId].description,\\n                '\\\", \\\"image\\\": \\\"',\\n                tokenMetadata[tokenId].image,\\n                '\\\"}'\\n            )\\n        );\\n\\n        // Encode the JSON blob as Base64\\n        string memory encodedJson = Base64.encode(bytes(json));\\n\\n        // Return the encoded data as the URI\\n        return\\n            string(\\n                abi.encodePacked(\\\"data:application/json;base64,\\\", encodedJson)\\n            );\\n    }\\n\\n    /**\\n     * @dev Mint batch of tokens of different types to specified addresses, each with a unique numeric UUID.\\n     * @param toAddresses An array of addresses to mint tokens to.\\n     * @param ids An array of token types to mint.\\n     * @param uuids An array of numeric UUIDs for each token being minted.\\n     */\\n\\n    function batchMint(\\n        address[] memory toAddresses,\\n        uint256[] memory ids,\\n        uint256[] memory uuids\\n    ) public onlyRole(MINTER_ROLE) {\\n        require(\\n            toAddresses.length == ids.length && ids.length == uuids.length,\\n            \\\"Must provide equal numbers of addresses, ids, and UUIDs\\\"\\n        );\\n\\n        for (uint256 i = 0; i < toAddresses.length; i++) {\\n            require(isTokenIdValid(ids[i]), \\\"Invalid token ID\\\");\\n            require(uuids[i] != 0, \\\"UUID cannot be zero\\\");\\n            require(\\n                toAddresses[i] != address(0),\\n                \\\"Cannot mint to the zero address\\\"\\n            );\\n\\n            // Update the state variable before the external call\\n            accountTokenUUIDs[toAddresses[i]][ids[i]].push(uuids[i]);\\n\\n            // External call to mint the token\\n            _mint(toAddresses[i], ids[i], 1, \\\"0x00\\\");\\n\\n            emit TokenMinted(toAddresses[i], ids[i], 1, uuids[i]);\\n        }\\n    }\\n\\n    function isTokenIdValid(uint256 tokenId) public view returns (bool) {\\n        // Example validation logic to check if the token ID has been initialized\\n        // This could be checking against a list of validTokenIds or other criteria\\n        // indicating the token ID has been properly set up.\\n        for (uint256 i = 0; i < validTokenIds.length; i++) {\\n            if (validTokenIds[i] == tokenId) {\\n                return true;\\n            }\\n        }\\n        return false;\\n    }\\n\\n    /**\\n     * @dev Sets the name for a given token ID.\\n     * @param id The token ID.\\n     * @param name The name to assign to the token ID.\\n     * Requires that the caller has the UPDATER_ROLE.\\n     */\\n    function setTokenName(\\n        uint256 id,\\n        string memory name\\n    ) public onlyRole(UPDATER_ROLE) {\\n        require(\\n            bytes(name).length > 0,\\n            \\\"DataPointsMulti: Token name cannot be empty\\\"\\n        );\\n\\n        // Check if the token already has metadata set\\n        bool isNewToken = bytes(tokenMetadata[id].name).length == 0;\\n\\n        // Update the token name within the token metadata\\n        tokenMetadata[id].name = name;\\n\\n        // If this is a new token type, add the token ID to the list and increment the token type counter\\n        if (isNewToken) {\\n            validTokenIds.push(id);\\n            tokenTypeCount++;\\n        }\\n\\n        emit TokenNameSet(id, name);\\n    }\\n\\n    /**\\n     * @dev Retrieves the name of a given token ID.\\n     * @param id The token ID.\\n     * @return The name of the token ID.\\n     */\\n    function getTokenName(uint256 id) public view returns (string memory) {\\n        require(\\n            bytes(tokenMetadata[id].name).length != 0,\\n            \\\"DataPointsMulti: Token ID does not exist\\\"\\n        );\\n        return tokenMetadata[id].name;\\n    }\\n\\n    /**\\n     * @dev Grant or revoke role permissions dynamically.\\n     * @param role The role identifier.\\n     * @param account The address to grant or revoke the role from.\\n     */\\n    function setupRole(bytes32 role, address account) public {\\n        require(\\n            hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n            \\\"Caller is not an admin\\\"\\n        );\\n        _setupRole(role, account);\\n        emit RoleSetup(role, account);\\n    }\\n\\n    /**\\n     * @dev Prevents token transfers by overriding `safeTransferFrom` and `safeBatchTransferFrom`.\\n     */\\n    function safeTransferFrom(\\n        address,\\n        address,\\n        uint256,\\n        uint256,\\n        bytes memory\\n    ) public pure override {\\n        require(false, \\\"DataPointsMulti: transfer not allowed\\\");\\n    }\\n\\n    function safeBatchTransferFrom(\\n        address,\\n        address,\\n        uint256[] memory,\\n        uint256[] memory,\\n        bytes memory\\n    ) public pure override {\\n        require(false, \\\"DataPointsMulti: batch transfer not allowed\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     */\\n    function supportsInterface(\\n        bytes4 interfaceId\\n    ) public view virtual override(ERC1155, AccessControl) returns (bool) {\\n        return super.supportsInterface(interfaceId);\\n    }\\n\\n    /**\\n     * @dev Retrieves user balances for all token types.\\n     * @param user The address of the user to query balances for.\\n     * @return An array of TokenBalance structs containing token names and balances.\\n     */\\n    function getUserBalances(\\n        address user\\n    ) public view returns (TokenBalance[] memory) {\\n        uint256 length = validTokenIds.length; // Cache the length of the array\\n        TokenBalance[] memory balances = new TokenBalance[](length);\\n\\n        for (uint256 i = 0; i < validTokenIds.length; i++) {\\n            uint256 tokenId = validTokenIds[i];\\n            balances[i].tokenName = tokenMetadata[tokenId].name;\\n            balances[i].balance = balanceOf(user, tokenId);\\n        }\\n\\n        return balances;\\n    }\\n\\n    /**\\n     * @dev Retrieves the UUIDs for a specific token ID associated with an account.\\n     * @param account The address of the user to query UUIDs for.\\n     * @param id The token ID to query UUIDs for.\\n     * @return An array of UUIDs for the specified token ID associated with the account.\\n     */\\n    function getAccountTokenUUIDs(\\n        address account,\\n        uint256 id\\n    ) public view returns (uint256[] memory) {\\n        return accountTokenUUIDs[account][id];\\n    }\\n\\n    /**\\n     * @dev Public getter to access the array of valid token IDs.\\n     * @return An array of valid token IDs.\\n     */\\n    function getValidTokenIds() public view returns (uint256[] memory) {\\n        return validTokenIds;\\n    }\\n\\n    /**\\n     * @dev Returns an array of structs containing token IDs and their corresponding metadata.\\n     * @return An array of TokenIdMetadata structs.\\n     */\\n    function getAllTokenIdMetadata()\\n        public\\n        view\\n        returns (TokenIdMetadata[] memory)\\n    {\\n        TokenIdMetadata[] memory allTokenIdMetadata = new TokenIdMetadata[](\\n            validTokenIds.length\\n        );\\n        for (uint256 i = 0; i < validTokenIds.length; i++) {\\n            allTokenIdMetadata[i].tokenId = validTokenIds[i];\\n            allTokenIdMetadata[i].metadata = tokenMetadata[validTokenIds[i]];\\n        }\\n        return allTokenIdMetadata;\\n    }\\n}\\n\",\"keccak256\":\"0x49073e359c10f550ae8c51c0b7c862d4f7cda878a38ee35b871dbd8447d3ac27\",\"license\":\"MIT\"},\"contracts/DataStakingDynamicNative.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"./DataPointsMulti.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/**\\n * @title DataStakingDynamicNative\\n * @dev This contract enables users to stake their non-transferable tokens, represented by DataPointsMulti.sol,\\n * and earn rewards based on the staked amount for a specific duration. Each token ID is associated with a unique reward rate, and rewards\\n * are distributed in the form of the native currency (e.g., ETH) after the staking period ends.\\n *\\n * Inherits from DataPointsMulti for token balance interactions. Rewards are managed directly with the native currency of the blockchain,\\n * allowing users to claim their earnings in ETH or the native currency of the network where the contract is deployed.\\n *\\n * @notice Ensure that the DataPointsMulti contract is deployed and its address is known before deploying this contract.\\n * The contract should be funded with enough native currency to cover the reward payouts.\\n */\\ncontract DataStakingDynamicNative is Ownable {\\n    using SafeMath for uint256;\\n\\n    // Name of the Data Staking Pool\\n    string public name;\\n\\n    // Reference to the DataPointsMulti contract for staking operations.\\n    DataPointsMulti public dataPointsMulti;\\n\\n    // Struct to hold staking information for a particular token ID.\\n    struct StakeInfo {\\n        uint256 amountStaked; // Total amount of tokens staked for this ID.\\n        uint256 rewardPerToken; // Reward per token for this ID.\\n        uint256 maxStakeLimit; // Maximum limit of tokens that can be staked.\\n    }\\n\\n    // Struct to hold details of a staking transaction\\n    struct StakingTransaction {\\n        uint256 tokenId;\\n        uint256 amount;\\n        uint256 rewardPerToken;\\n        uint256 timestamp;\\n    }\\n\\n    // Struct to hold details of a claim transaction\\n    struct ClaimTransaction {\\n        uint256 totalRewardsClaimed;\\n        uint256 timestamp;\\n    }\\n\\n    // Struct to hold eligible staking amount details\\n    struct EligibleStakeAmount {\\n        uint256 tokenId;\\n        uint256 amount;\\n    }\\n\\n    // Mapping from user address to an array of their staking transactions\\n    mapping(address => StakingTransaction[]) public userStakingTransactions;\\n\\n    // Mapping from user address to an array of their claimed transactions\\n    mapping(address => ClaimTransaction) public userClaimTransactions;\\n\\n    // Mapping from token ID to its staking information.\\n    mapping(uint256 => StakeInfo) public stakeInfos;\\n\\n    // Nested mapping to track the staked amount by user and token ID.\\n    mapping(address => mapping(uint256 => uint256)) public userStakes;\\n\\n    // Mapping from address to its staked status.\\n    mapping(address => bool) private hasStaked;\\n\\n    // State variable to track number of stakers in pool.\\n    address[] private stakers;\\n\\n    // State variable to track the total rewards available for distribution.\\n    uint256 public totalRewardsPool;\\n\\n    // Array to keep track of all tokenIds with staking parameters\\n    uint256[] public stakingTokenIds;\\n\\n    // State variable to track the timestamp when the total rewards pool becomes full\\n    uint256 public rewardsPoolFullTimestamp;\\n\\n    // State variable to track the amount of rewards that have been reserved but not yet claimed.\\n    uint256 public totalReservedRewards;\\n\\n    // Duration of the staking period in seconds.\\n    uint256 public duration;\\n\\n    // Start time of staking.\\n    uint256 public startTime;\\n\\n    // Royalty fee info\\n    uint256 public royaltyFeePercentage; // Represented as a whole number, e.g., 1 for 1%\\n\\n    // Royalty fee info\\n    address public royaltyRecipient;\\n\\n    // Staking period initialized tracking\\n    bool public stakingPeriodInitialized = false;\\n\\n    // Event emitted when tokens are staked.\\n    event Staked(\\n        address indexed user,\\n        uint256 tokenId,\\n        uint256 amount,\\n        uint256 startTime,\\n        uint256 duration\\n    );\\n\\n    // Event emitted when rewards are claimed.\\n    event RewardsClaimed(address indexed user, uint256 tokenId, uint256 reward);\\n\\n    // Event emitted when rewards are deposited into the contract\\n    event RewardsDeposited(\\n        address indexed depositor,\\n        uint256 amount,\\n        uint256 newTotalRewardsPool\\n    );\\n\\n    // Event emitted when unclaimed rewards are withdrawn from the contract\\n    event UnclaimedRewardsWithdrawn(address indexed owner, uint256 amount);\\n\\n    /**\\n     * @dev Constructor to initialize the DataStaking contract.\\n     * @param _name Name of the Data Staking Pool.\\n     * @param _dataPointsMulti Address of the DataPointsMulti contract.\\n     */\\n    constructor(\\n        string memory _name,\\n        DataPointsMulti _dataPointsMulti\\n    ) Ownable() {\\n        name = _name;\\n        dataPointsMulti = _dataPointsMulti;\\n    }\\n\\n    // Function to receive Ether. msg.data must be empty\\n    receive() external payable {\\n        // Emit an event or handle received Ether\\n        emit RewardsDeposited(\\n            msg.sender,\\n            msg.value,\\n            totalRewardsPool.add(msg.value)\\n        );\\n        totalRewardsPool = totalRewardsPool.add(msg.value);\\n    }\\n\\n    /**\\n     * @dev Sets the staking duration and start time for the contract.\\n     * @param _duration The duration of the staking period in seconds.\\n     * @param _startTime The start time for staking to begin.\\n     */\\n    function setStakingTimeframe(\\n        uint256 _duration,\\n        uint256 _startTime\\n    ) public onlyOwner {\\n        require(\\n            !stakingPeriodInitialized,\\n            \\\"Staking timeframe cannot be changed after initialization.\\\"\\n        );\\n        duration = _duration;\\n        startTime = _startTime;\\n        stakingPeriodInitialized = true;\\n    }\\n\\n    /**\\n     * @dev Sets the reward per token, duration, and max stake limit for a specific token ID.\\n     * @param tokenId The token ID for which to set the staking parameters.\\n     * @param rewardPerToken The reward per token to set for the token ID.\\n     * @param maxStakeLimit The maximum amount of tokens that can be staked for the token ID.\\n     */\\n    function setStakingParameters(\\n        uint256 tokenId,\\n        uint256 rewardPerToken,\\n        uint256 maxStakeLimit\\n    ) public onlyOwner {\\n        require(\\n            stakeInfos[tokenId].amountStaked == 0,\\n            \\\"Token already initialized with staked amounts\\\"\\n        );\\n        require(\\n            dataPointsMulti.isTokenIdValid(tokenId),\\n            \\\"Token ID is not valid\\\"\\n        );\\n        require(\\n            !stakingPeriodInitialized,\\n            \\\"Staking parameters cannot be changed after initialization.\\\"\\n        );\\n\\n        // Set the staking parameters\\n        stakeInfos[tokenId] = StakeInfo({\\n            amountStaked: 0, // Initialize to zero\\n            rewardPerToken: rewardPerToken,\\n            maxStakeLimit: maxStakeLimit\\n        });\\n\\n        // Check if tokenId is already in stakingTokenIds array to avoid duplicates\\n        bool exists = false;\\n        for (uint256 i = 0; i < stakingTokenIds.length; i++) {\\n            if (stakingTokenIds[i] == tokenId) {\\n                exists = true;\\n                break;\\n            }\\n        }\\n        if (!exists) {\\n            stakingTokenIds.push(tokenId);\\n        }\\n    }\\n\\n    /**\\n     * @dev Allows users to stake all their tokens for which staking parameters have been set.\\n     * This function iterates over the array of token IDs that have staking parameters defined.\\n     * For each token ID, it checks the user's balance and stakes up to the maximum stake limit,\\n     * or the user's balance, whichever is lower. It calculates the potential reward and ensures\\n     * that staking does not exceed the total available reward pool. The function updates the user's\\n     * staked amount and the total staked amount for each token ID. It emits a Staked event for each\\n     * staking action performed.\\n     */\\n    function stakeAll() public {\\n        bool isStakingPeriodOver = isStakingPoolFilledOrExpired();\\n        require(!isStakingPeriodOver, \\\"Staking period has not ended yet\\\");\\n\\n        uint256 remainingRewardsPool = totalRewardsPool.sub(\\n            totalReservedRewards\\n        );\\n        require(\\n            remainingRewardsPool > 0,\\n            \\\"Insufficient rewards available in the pool.\\\"\\n        );\\n\\n        uint256 minRewardPerToken = getMinRewardPerToken(); // Get the smallest rewardPerToken\\n\\n        bool hasStakableTokens = false;\\n\\n        for (uint256 i = 0; i < stakingTokenIds.length; i++) {\\n            uint256 tokenId = stakingTokenIds[i];\\n            uint256 userBalance = dataPointsMulti.balanceOf(\\n                msg.sender,\\n                tokenId\\n            );\\n            uint256 previousTotalStaked = userStakes[msg.sender][tokenId];\\n            StakeInfo memory stakeInfo = stakeInfos[tokenId];\\n\\n            if (userBalance == 0 || duration == 0) {\\n                continue;\\n            }\\n            if (userBalance <= previousTotalStaked) {\\n                continue;\\n            }\\n\\n            hasStakableTokens = true;\\n\\n            uint256 remainingUserStakeCapacity = stakeInfo.maxStakeLimit.sub(\\n                previousTotalStaked\\n            );\\n            uint256 maxStakeableBasedOnRewards = remainingRewardsPool.div(\\n                stakeInfo.rewardPerToken\\n            );\\n            uint256 actualMaxStakeable = Math.min(\\n                remainingUserStakeCapacity,\\n                maxStakeableBasedOnRewards\\n            );\\n\\n            uint256 actualStakeableAmount = Math.min(\\n                userBalance.sub(previousTotalStaked),\\n                actualMaxStakeable\\n            );\\n\\n            uint256 actualPotentialReward = actualStakeableAmount.mul(\\n                stakeInfo.rewardPerToken\\n            );\\n            if (actualPotentialReward > remainingRewardsPool) {\\n                actualStakeableAmount = remainingRewardsPool.div(\\n                    stakeInfo.rewardPerToken\\n                );\\n                actualPotentialReward = actualStakeableAmount.mul(\\n                    stakeInfo.rewardPerToken\\n                );\\n            }\\n\\n            remainingRewardsPool = remainingRewardsPool.sub(\\n                actualPotentialReward\\n            );\\n\\n            // Calculate the stake difference for the transaction record\\n            uint256 stakeDifference = actualStakeableAmount;\\n\\n            // Update the user's total staked amount for the tokenId\\n            userStakes[msg.sender][tokenId] = previousTotalStaked.add(\\n                actualStakeableAmount\\n            );\\n\\n            // Update the stake info and total reserved rewards\\n            stakeInfo.amountStaked = stakeInfo.amountStaked.add(\\n                actualStakeableAmount\\n            );\\n            totalReservedRewards = totalReservedRewards.add(\\n                actualPotentialReward\\n            );\\n\\n            if (stakeDifference > 0) {\\n                userStakingTransactions[msg.sender].push(\\n                    StakingTransaction({\\n                        tokenId: tokenId,\\n                        amount: stakeDifference,\\n                        rewardPerToken: stakeInfo.rewardPerToken,\\n                        timestamp: block.timestamp\\n                    })\\n                );\\n                // Emit an event that tokens have been staked\\n                emit Staked(\\n                    msg.sender,\\n                    tokenId,\\n                    actualStakeableAmount,\\n                    startTime,\\n                    duration\\n                );\\n            }\\n        }\\n\\n        // Track unique staker\\n        if (hasStakableTokens && !hasStaked[msg.sender]) {\\n            stakers.push(msg.sender);\\n            hasStaked[msg.sender] = true;\\n        }\\n\\n        require(\\n            hasStakableTokens,\\n            \\\"No stakable tokens found or staking period has ended.\\\"\\n        );\\n\\n        // Adjust the condition to check if the remaining rewards pool is less than the smallest rewardPerToken\\n        if (\\n            remainingRewardsPool > 0 &&\\n            remainingRewardsPool < minRewardPerToken &&\\n            rewardsPoolFullTimestamp == 0\\n        ) {\\n            rewardsPoolFullTimestamp = block.timestamp;\\n        }\\n    }\\n\\n    /**\\n     * @dev Allows users to claim rewards for all their staked tokens after their respective staking periods end.\\n     */\\n    function claimAllRewards() public {\\n        bool isStakingPeriodOver = isStakingPoolFilledOrExpired();\\n        require(isStakingPeriodOver, \\\"Staking period has not ended yet\\\");\\n        uint256 totalReward = 0;\\n\\n        // First pass: Calculate the total reward without making state changes\\n        for (uint256 i = 0; i < stakingTokenIds.length; i++) {\\n            uint256 tokenId = stakingTokenIds[i];\\n            StakeInfo memory stakeInfo = stakeInfos[tokenId];\\n\\n            uint256 stakedAmount = userStakes[msg.sender][tokenId];\\n            if (stakedAmount > 0) {\\n                uint256 reward = stakedAmount.mul(stakeInfo.rewardPerToken);\\n                totalReward = totalReward.add(reward);\\n            }\\n        }\\n\\n        // Check if there are any rewards to claim\\n        require(totalReward > 0, \\\"No rewards to claim\\\");\\n\\n        // Ensure there are enough reserved rewards to cover the claim\\n        require(\\n            totalReward <= totalReservedRewards,\\n            \\\"Insufficient reserved rewards\\\"\\n        );\\n\\n        // Subtract the claimed rewards from the total rewards pool\\n        totalRewardsPool = totalRewardsPool.sub(totalReward); // Update totalRewardsPool to reflect the claimed rewards\\n\\n        // Second pass: Reset stakes and emit events\\n        for (uint256 i = 0; i < stakingTokenIds.length; i++) {\\n            uint256 tokenId = stakingTokenIds[i];\\n            StakeInfo storage stakeInfo = stakeInfos[tokenId];\\n\\n            uint256 stakedAmount = userStakes[msg.sender][tokenId];\\n            if (stakedAmount > 0) {\\n                // Reset the user's staked amount for the tokenId to zero\\n                userStakes[msg.sender][tokenId] = 0;\\n\\n                // Emit an event for the reward claim\\n                emit RewardsClaimed(\\n                    msg.sender,\\n                    tokenId,\\n                    stakedAmount.mul(stakeInfo.rewardPerToken)\\n                );\\n            }\\n        }\\n\\n        // Initialize rewardAfterRoyalty with the totalReward\\n        uint256 rewardAfterRoyalty = totalReward;\\n        uint256 royaltyFee = 0;\\n\\n        // Calculate the royalty fee only if the royaltyFeePercentage is greater than 0\\n        if (royaltyFeePercentage > 0) {\\n            royaltyFee = totalReward.mul(royaltyFeePercentage).div(100);\\n            rewardAfterRoyalty = totalReward.sub(royaltyFee);\\n        }\\n\\n        // Update the claim transaction with the reward after potential royalty\\n        ClaimTransaction memory newClaimTransaction = ClaimTransaction({\\n            totalRewardsClaimed: rewardAfterRoyalty,\\n            timestamp: block.timestamp\\n        });\\n\\n        userClaimTransactions[msg.sender] = newClaimTransaction;\\n\\n        // Subtract the total reward from the total reserved rewards\\n        totalReservedRewards = totalReservedRewards.sub(totalReward);\\n\\n        // Transfer the royalty fee to the royalty recipient if there is a fee\\n        if (royaltyFee > 0) {\\n            (bool royaltySuccess, ) = royaltyRecipient.call{value: royaltyFee}(\\n                \\\"\\\"\\n            );\\n            require(royaltySuccess, \\\"Failed to transfer royalty fee\\\");\\n        }\\n\\n        // Transfer the reward after royalty to the user, reverting on failure\\n        (bool rewardSuccess, ) = msg.sender.call{value: rewardAfterRoyalty}(\\\"\\\");\\n        require(rewardSuccess, \\\"Failed to transfer rewards\\\");\\n    }\\n\\n    /**\\n     * @dev Allows the contract owner to withdraw unclaimed rewards after the staking period has ended.\\n     * This function is designed to recover funds that were not distributed because users did not claim their rewards.\\n     * It can only be called by the owner of the contract and only after the staking period has concluded,\\n     * as determined by the `startTime` and `duration` parameters. The amount withdrawn is the difference\\n     * between the total rewards pool and the total reserved rewards, which represents the unclaimed rewards.\\n     * It is crucial to ensure that all users have had a sufficient opportunity to claim their rewards\\n     * before this function is called to maintain trust and integrity in the staking process.\\n     * @notice This function will revert if the staking period has not ended or if there are no unclaimed rewards.\\n     */\\n    function withdrawUnclaimedRewards() public onlyOwner {\\n        bool isStakingPeriodOver = isStakingPoolFilledOrExpired();\\n        require(isStakingPeriodOver, \\\"Staking period has not ended yet\\\");\\n        require(\\n            totalReservedRewards < totalRewardsPool,\\n            \\\"No unclaimed rewards available\\\"\\n        );\\n\\n        uint256 unclaimedRewards = totalRewardsPool.sub(totalReservedRewards);\\n        // Ensure there are unclaimed rewards to withdraw\\n        require(unclaimedRewards > 0, \\\"No unclaimed rewards to withdraw\\\");\\n\\n        // Update the total rewards pool\\n        totalRewardsPool = totalRewardsPool.sub(unclaimedRewards);\\n\\n        // Transfer the unclaimed rewards to the owner\\n        (bool success, ) = owner().call{value: unclaimedRewards}(\\\"\\\");\\n        require(success, \\\"Failed to withdraw unclaimed rewards\\\");\\n\\n        // Emit the event after a successful withdrawal\\n        emit UnclaimedRewardsWithdrawn(owner(), unclaimedRewards);\\n    }\\n\\n    /**\\n     * @dev Sets the royalty fee and royalty recipient.\\n     * Can only be called by the contract owner.\\n     * @param _royaltyFeePercentage The new royalty fee percentage.\\n     *  @param _royaltyRecipient The new royalty recipient address.\\n     */\\n    function setRoyaltyFeePercentageAndRecipient(\\n        uint256 _royaltyFeePercentage,\\n        address _royaltyRecipient\\n    ) public onlyOwner {\\n        require(\\n            _royaltyRecipient != address(0),\\n            \\\"Royalty recipient cannot be the zero address\\\"\\n        );\\n        royaltyFeePercentage = _royaltyFeePercentage;\\n        royaltyRecipient = _royaltyRecipient;\\n    }\\n\\n    /**\\n     * @dev Returns the remaining amount of ETH in the contract.\\n     * @return The amount of ETH left for rewards.\\n     */\\n    function getRemainingRewards() public view returns (uint256) {\\n        return address(this).balance;\\n    }\\n\\n    /**\\n     * @dev Calculates the maximum amount a user can stake for each tokenId based on the current staking parameters.\\n     * It takes into account the user's balance, the maxStakeLimit for each tokenId, and the remaining rewards in the pool.\\n     * The function ensures that the user does not exceed the maximum staking capacity for any tokenId and that the\\n     * total potential rewards do not surpass the available rewards in the pool. The function returns an array of structs,\\n     * each containing a tokenId and the corresponding amount that the user is eligible to stake.\\n     * @param user The address of the user for whom to calculate the available staking amounts.\\n     * @return eligibleStakes An array of structs, each containing a tokenId and the corresponding eligible staking amount.\\n     */\\n    function getEligibleStakingAmounts(\\n        address user\\n    ) public view returns (EligibleStakeAmount[] memory eligibleStakes) {\\n        eligibleStakes = new EligibleStakeAmount[](stakingTokenIds.length);\\n\\n        // Check if the staking pool is expired or full\\n        bool poolIsExpiredOrFull = block.timestamp > startTime.add(duration) ||\\n            totalReservedRewards >= totalRewardsPool;\\n\\n        if (poolIsExpiredOrFull) {\\n            for (uint256 i = 0; i < stakingTokenIds.length; i++) {\\n                eligibleStakes[i] = EligibleStakeAmount({\\n                    tokenId: stakingTokenIds[i],\\n                    amount: 0\\n                });\\n            }\\n            return eligibleStakes;\\n        }\\n\\n        uint256 remainingUnreservedRewards = totalRewardsPool.sub(\\n            totalReservedRewards\\n        );\\n\\n        for (uint256 i = 0; i < stakingTokenIds.length; i++) {\\n            uint256 tokenId = stakingTokenIds[i];\\n            StakeInfo memory stakeInfo = stakeInfos[tokenId];\\n\\n            uint256 userBalance = dataPointsMulti.balanceOf(user, tokenId);\\n            uint256 userStakedAmount = userStakes[user][tokenId];\\n\\n            // Calculate the remaining staking capacity for this user for this tokenId\\n            uint256 remainingUserStakeCapacity = stakeInfo.maxStakeLimit >\\n                userStakedAmount\\n                ? stakeInfo.maxStakeLimit.sub(userStakedAmount)\\n                : 0;\\n\\n            // Calculate the maximum stakeable amount based on the remaining rewards in the pool\\n            uint256 maxStakeableBasedOnRemainingRewards = remainingUnreservedRewards\\n                    .div(stakeInfo.rewardPerToken);\\n\\n            // The actual maximum stakeable amount is the minimum of the remainingUserStakeCapacity and maxStakeableBasedOnRemainingRewards\\n            uint256 actualMaxStakeable = Math.min(\\n                remainingUserStakeCapacity,\\n                maxStakeableBasedOnRemainingRewards\\n            );\\n\\n            // Determine the maximum additional amount the user can stake\\n            uint256 maxAdditionalStake = Math.min(\\n                userBalance.sub(userStakedAmount),\\n                actualMaxStakeable\\n            );\\n\\n            // Calculate the potential reward for the maxAdditionalStake\\n            uint256 potentialReward = maxAdditionalStake.mul(\\n                stakeInfo.rewardPerToken\\n            );\\n\\n            // If the potential reward exceeds the remaining unreserved rewards, adjust the maxAdditionalStake\\n            if (potentialReward > remainingUnreservedRewards) {\\n                maxAdditionalStake = remainingUnreservedRewards.div(\\n                    stakeInfo.rewardPerToken\\n                );\\n                potentialReward = maxAdditionalStake.mul(\\n                    stakeInfo.rewardPerToken\\n                ); // Recalculate potential reward after adjustment\\n            }\\n\\n            // Set the available staking amount for this tokenId\\n            eligibleStakes[i] = EligibleStakeAmount({\\n                tokenId: tokenId,\\n                amount: maxAdditionalStake\\n            });\\n\\n            // Subtract the potential reward from the remaining unreserved rewards for subsequent iterations\\n            remainingUnreservedRewards = remainingUnreservedRewards.sub(\\n                potentialReward\\n            );\\n        }\\n\\n        return eligibleStakes;\\n    }\\n\\n    /**\\n     * @dev Checks if the staking pool is full based on the total reserved rewards or if the staking period has expired.\\n     * The staking pool is considered full if the total reserved rewards equal the total rewards pool initially set.\\n     * The staking period is considered expired if the current block timestamp is greater than or equal to\\n     * the sum of the `startTime` and `duration`.\\n     * @return True if the staking pool is full based on the total reserved rewards or the staking period has expired, false otherwise.\\n     */\\n    function isStakingPoolFilledOrExpired() public view returns (bool) {\\n        bool isPoolFull = totalReservedRewards >= totalRewardsPool;\\n        bool isStakingPeriodOver = block.timestamp >= startTime.add(duration);\\n\\n        // Calculate the remaining rewards pool\\n        uint256 remainingRewardsPool = totalRewardsPool.sub(\\n            totalReservedRewards\\n        );\\n        uint256 minRewardPerToken = getMinRewardPerToken(); // Assume this function exists\\n\\n        // Check if the remaining rewards pool is less than the smallest rewardPerToken\\n        bool isPoolEffectivelyFull = remainingRewardsPool > 0 &&\\n            remainingRewardsPool < minRewardPerToken;\\n\\n        return isPoolFull || isStakingPeriodOver || isPoolEffectivelyFull;\\n    }\\n\\n    /**\\n     * @dev Checks if the staking pool is full based on the total reserved rewards or if the staking period has expired.\\n     * The staking pool is considered full if the total reserved rewards equal the total rewards pool initially set.\\n     * The staking period is considered expired if the current block timestamp is greater than or equal to\\n     * the sum of the `startTime` and `duration`.\\n     * @return True if the staking pool is full based on the total reserved rewards or the staking period has expired, false otherwise.\\n     */\\n    function getUserStakingTransactionsCount(\\n        address user\\n    ) public view returns (uint256) {\\n        return userStakingTransactions[user].length;\\n    }\\n\\n    function getStakingTokenIds() public view returns (uint256[] memory) {\\n        return stakingTokenIds;\\n    }\\n\\n    /**\\n     * @dev Checks if the user has claimed rewards and returns the details of the last claim transaction.\\n     * @param user The address of the user to check.\\n     * @return hasClaimed A boolean indicating whether the user has claimed rewards.\\n     * @return lastClaimTransaction The details of the last claim transaction if one exists.\\n     */\\n    function hasUserClaimed(\\n        address user\\n    )\\n        public\\n        view\\n        returns (bool hasClaimed, ClaimTransaction memory lastClaimTransaction)\\n    {\\n        // Check if the user's claim transaction has a non-zero timestamp\\n        hasClaimed = userClaimTransactions[user].timestamp > 0;\\n        if (hasClaimed) {\\n            // If the user has claimed, return the claim transaction details\\n            lastClaimTransaction = userClaimTransactions[user];\\n        }\\n    }\\n\\n    function getContractData()\\n        public\\n        view\\n        returns (\\n            string memory contractName,\\n            uint256 totalRewards,\\n            uint256 rewardsFullTimestamp,\\n            uint256 reservedRewards,\\n            uint256 remainingRewards,\\n            uint256 stakingDuration,\\n            uint256 stakingStartTime,\\n            uint256 feePercentage,\\n            address feeRecipient,\\n            bool isStakingPoolFilledOrExpiredBool\\n        )\\n    {\\n        contractName = name;\\n        totalRewards = totalRewardsPool;\\n        rewardsFullTimestamp = rewardsPoolFullTimestamp;\\n        reservedRewards = totalReservedRewards;\\n        remainingRewards = totalRewardsPool.sub(totalReservedRewards);\\n        stakingDuration = duration;\\n        stakingStartTime = startTime;\\n        feePercentage = royaltyFeePercentage;\\n        feeRecipient = royaltyRecipient;\\n        isStakingPoolFilledOrExpiredBool = isStakingPoolFilledOrExpired();\\n    }\\n\\n    function getUserData(\\n        address user\\n    )\\n        public\\n        view\\n        returns (\\n            StakingTransaction[] memory stakingTransactions,\\n            ClaimTransaction memory claimTransaction,\\n            StakeInfo[] memory stakeInfosArray,\\n            uint256[] memory stakedAmounts,\\n            EligibleStakeAmount[] memory eligibleStakes\\n        )\\n    {\\n        stakingTransactions = userStakingTransactions[user];\\n        claimTransaction = userClaimTransactions[user];\\n\\n        // Use stakingTokenIds specific to this contract\\n        stakeInfosArray = new StakeInfo[](stakingTokenIds.length);\\n        stakedAmounts = new uint256[](stakingTokenIds.length);\\n\\n        for (uint256 i = 0; i < stakingTokenIds.length; i++) {\\n            uint256 tokenId = stakingTokenIds[i];\\n            stakeInfosArray[i] = stakeInfos[tokenId];\\n            stakedAmounts[i] = userStakes[user][tokenId];\\n        }\\n\\n        // Reuse the getEligibleStakingAmounts function to avoid redundancy\\n        eligibleStakes = getEligibleStakingAmounts(user);\\n    }\\n\\n    function getNumberOfStakers() public view returns (uint256) {\\n        return stakers.length;\\n    }\\n\\n    function getMinRewardPerToken() public view returns (uint256) {\\n        uint256 minReward = type(uint256).max;\\n        for (uint256 i = 0; i < stakingTokenIds.length; i++) {\\n            uint256 tokenId = stakingTokenIds[i];\\n            uint256 rewardPerToken = stakeInfos[tokenId].rewardPerToken;\\n            if (rewardPerToken < minReward) {\\n                minReward = rewardPerToken;\\n            }\\n        }\\n        return minReward == type(uint256).max ? 0 : minReward;\\n    }\\n}\\n\",\"keccak256\":\"0x6aae4cf3c302f467325fb5204fbe4a35f634a10f0060b4af9299276e3ee05b5b\",\"license\":\"MIT\"},\"contracts/ProxyViewAggregator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"./DataStakingDynamicNative.sol\\\";\\n\\ncontract ProxyViewAggregator is Ownable {\\n    DataStakingDynamicNative[] public stakingContracts;\\n\\n    /**\\n     * @dev Sets the array of DataStakingDynamicNative contract addresses.\\n     * @param _stakingContracts An array of DataStakingDynamicNative contract addresses.\\n     */\\n    function setStakingContracts(\\n        DataStakingDynamicNative[] calldata _stakingContracts\\n    ) external onlyOwner {\\n        // Here you might want to include access control, like onlyOwner modifier\\n        stakingContracts = _stakingContracts;\\n    }\\n\\n    /**\\n     * @dev Aggregates the eligible stake amounts for a user across multiple DataStakingDynamicNative contracts.\\n     * @param user The address of the user.\\n     * @return totalEligibleAmount The total sum of eligible stake amounts for the user across all pools.\\n     */\\n    function aggregateEligibleStakes(\\n        address user\\n    ) external view returns (uint256 totalEligibleAmount) {\\n        totalEligibleAmount = 0;\\n        for (uint256 i = 0; i < stakingContracts.length; i++) {\\n            DataStakingDynamicNative.EligibleStakeAmount[]\\n                memory eligibleAmounts = stakingContracts[i]\\n                    .getEligibleStakingAmounts(user);\\n            for (uint256 j = 0; j < eligibleAmounts.length; j++) {\\n                totalEligibleAmount += eligibleAmounts[j].amount;\\n            }\\n        }\\n        return totalEligibleAmount;\\n    }\\n\\n    function stakingContractsLength() public view returns (uint256) {\\n        uint256 count = 0;\\n        for (uint256 i = 0; i < stakingContracts.length; i++) {\\n            // Directly use the isStakingPoolFilledOrExpired method to check the contract's status\\n            if (!stakingContracts[i].isStakingPoolFilledOrExpired()) {\\n                count++;\\n            }\\n        }\\n        return count;\\n    }\\n}\\n\",\"keccak256\":\"0x5fb89e472dd27fd6ad9769c0675358de4f6c789cba1845abcd21bd35f400020e\",\"license\":\"MIT\"},\"contracts/lib/base64.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Base64.sol)\\n\\npragma solidity ^0.8.19;\\n\\n/**\\n * @dev Provides a set of functions to operate with Base64 strings.\\n */\\nlibrary Base64 {\\n    /**\\n     * @dev Base64 Encoding/Decoding Table\\n     * See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648\\n     */\\n    string internal constant _TABLE =\\n        \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n    string internal constant _TABLE_URL =\\n        \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\\\";\\n\\n    /**\\n     * @dev Converts a `bytes` to its Bytes64 `string` representation.\\n     */\\n    function encode(bytes memory data) internal pure returns (string memory) {\\n        return _encode(data, _TABLE, true);\\n    }\\n\\n    /**\\n     * @dev Converts a `bytes` to its Bytes64Url `string` representation.\\n     */\\n    function encodeURL(\\n        bytes memory data\\n    ) internal pure returns (string memory) {\\n        return _encode(data, _TABLE_URL, false);\\n    }\\n\\n    /**\\n     * @dev Internal table-agnostic conversion\\n     */\\n    function _encode(\\n        bytes memory data,\\n        string memory table,\\n        bool withPadding\\n    ) private pure returns (string memory) {\\n        /**\\n         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence\\n         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol\\n         */\\n        if (data.length == 0) return \\\"\\\";\\n\\n        // If padding is enabled, the final length should be `bytes` data length divided by 3 rounded up and then\\n        // multiplied by 4 so that it leaves room for padding the last chunk\\n        // - `data.length + 2`  -> Round up\\n        // - `/ 3`              -> Number of 3-bytes chunks\\n        // - `4 *`              -> 4 characters for each chunk\\n        // If padding is disabled, the final length should be `bytes` data length multiplied by 4/3 rounded up as\\n        // opposed to when padding is required to fill the last chunk.\\n        // - `4 *`              -> 4 characters for each chunk\\n        // - `data.length + 2`  -> Round up\\n        // - `/ 3`              -> Number of 3-bytes chunks\\n        uint256 resultLength = withPadding\\n            ? 4 * ((data.length + 2) / 3)\\n            : (4 * data.length + 2) / 3;\\n\\n        string memory result = new string(resultLength);\\n\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            // Prepare the lookup table (skip the first \\\"length\\\" byte)\\n            let tablePtr := add(table, 1)\\n\\n            // Prepare result pointer, jump over length\\n            let resultPtr := add(result, 32)\\n\\n            // Run over the input, 3 bytes at a time\\n            for {\\n                let dataPtr := data\\n                let endPtr := add(data, mload(data))\\n            } lt(dataPtr, endPtr) {\\n\\n            } {\\n                // Advance 3 bytes\\n                dataPtr := add(dataPtr, 3)\\n                let input := mload(dataPtr)\\n\\n                // To write each character, shift the 3 bytes (18 bits) chunk\\n                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)\\n                // and apply logical AND with 0x3F which is the number of\\n                // the previous character in the ASCII table prior to the Base64 Table\\n                // The result is then added to the table to get the character to write,\\n                // and finally write it in the result pointer but with a left shift\\n                // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits\\n\\n                mstore8(\\n                    resultPtr,\\n                    mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n                )\\n                resultPtr := add(resultPtr, 1) // Advance\\n\\n                mstore8(\\n                    resultPtr,\\n                    mload(add(tablePtr, and(shr(12, input), 0x3F)))\\n                )\\n                resultPtr := add(resultPtr, 1) // Advance\\n\\n                mstore8(\\n                    resultPtr,\\n                    mload(add(tablePtr, and(shr(6, input), 0x3F)))\\n                )\\n                resultPtr := add(resultPtr, 1) // Advance\\n\\n                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\\n                resultPtr := add(resultPtr, 1) // Advance\\n            }\\n\\n            if withPadding {\\n                // When data `bytes` is not exactly 3 bytes long\\n                // it is padded with `=` characters at the end\\n                switch mod(mload(data), 3)\\n                case 1 {\\n                    mstore8(sub(resultPtr, 1), 0x3d)\\n                    mstore8(sub(resultPtr, 2), 0x3d)\\n                }\\n                case 2 {\\n                    mstore8(sub(resultPtr, 1), 0x3d)\\n                }\\n            }\\n        }\\n\\n        return result;\\n    }\\n}\\n\",\"keccak256\":\"0x1c4ca91af9cdd16b63cd65dafb05e9788b12d261d549e5d9650d424b2be129f4\",\"license\":\"MIT\"}},\"version\":1}",
  "bytecode": "0x6080604052346200002657620000146200002b565b604051610a43620001268239610a4390f35b600080fd5b6200003562000037565b565b6200003533620000c3565b62000054905b6001600160a01b031690565b90565b62000054905462000042565b620000549062000048906001600160a01b031682565b620000549062000063565b620000549062000079565b90620000a362000054620000bf9262000084565b82546001600160a01b0319166001600160a01b03919091161790565b9055565b620000cf600062000057565b620000dc8260006200008f565b90620001146200010d7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09362000084565b9162000084565b916200011f60405190565b600090a356fe6080604052600436101561001257600080fd5b60003560e01c8063093410db146100825780631109b19a1461007d578063715018a6146100785780638da5cb5b14610073578063ba3754f81461006e578063c2514f8f146100695763f2fde38b036100a6576102fd565b6102e4565b610271565b61024a565b610214565b6101e2565b6100d2565b6001600160a01b031690565b90565b61009f81610087565b036100a657565b600080fd5b905035906100b882610096565b565b906020828203126100a657610093916100ab565b9052565b346100a6576100fd6100ed6100e83660046100ba565b6104ad565b6040519182918290815260200190565b0390f35b8061009f565b905035906100b882610101565b906020828203126100a65761009391610107565b634e487b7160e01b600052603260045260246000fd5b805482101561016157610158600191600052602060002090565b91020190600090565b610128565b610093916008021c6001600160a01b031690565b906100939154610166565b600180548210156100a6576100939161019d9161013e565b9061017a565b61009390610087906001600160a01b031682565b610093906101a3565b610093906101b7565b6100ce906101c0565b6020810192916100b891906101c9565b346100a6576100fd6101fd6101f8366004610114565b610185565b604051918291826101d2565b60009103126100a657565b346100a657610224366004610209565b61022c610609565b604051005b6100ce90610087565b6020810192916100b89190610231565b346100a65761025a366004610209565b6100fd610265610624565b6040519182918261023a565b346100a657610281366004610209565b6100fd6100ed610666565b909182601f830112156100a6578135916001600160401b0383116100a65760200192602083028401116100a657565b906020828203126100a65781356001600160401b0381116100a6576102e0920161028c565b9091565b346100a65761022c6102f73660046102bb565b90610874565b346100a65761022c6103103660046100ba565b610918565b6100936100936100939290565b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b0382111761035957604052565b610322565b906100b861036b60405190565b9283610338565b6001600160401b0381116103595760208091020190565b905051906100b882610101565b91906040838203126100a6576103c5906103b0604061035e565b936103bb8282610389565b8552602001610389565b6020830152565b909291926103e16103dc82610372565b61035e565b9381855260406020860192028301928184116100a657915b8383106104065750505050565b60206040916104158486610396565b8152019201916103f9565b9080601f830112156100a6578151610093926020016103cc565b906020828203126100a65781516001600160401b0381116100a6576100939201610420565b6040513d6000823e3d90fd5b90610474825190565b811015610161576020809102010190565b634e487b7160e01b600052601160045260246000fd5b919082018092116104a857565b610485565b906104b86000610315565b906104c36000610315565b915b826104d96104d561009360015490565b9190565b10156105cb5761052660006104fa6104f561019d87600161013e565b6101c0565b63045bccb39061051b889261050e60405190565b9586948593849360e01b90565b83526004830161023a565b03915afa9081156105c6576000916105a3575b50916105456000610315565b915b826105566104d5610093875190565b101561058c5761057f61058691610579602061057388889061046b565b51015190565b9061049b565b9260010190565b91610547565b9492509261059b915060010190565b9190926104c5565b6105c091503d806000833e6105b88183610338565b81019061043a565b38610539565b61045f565b92509050565b6105d9610971565b6100b86105f7565b6100876100936100939290565b610093906105e1565b6100b861060460006105ee565b6109b4565b6100b86105d1565b61009390610087565b6100939054610611565b610093600061061a565b80151561009f565b905051906100b88261062e565b906020828203126100a65761009391610636565b60001981146104a85760010190565b6106706000610315565b61067a6000610315565b8061068a6104d561009360015490565b1015610730576106be60206106a66104f561019d85600161013e565b63fbb6e31f906106b560405190565b93849260e01b90565b825260049082905afa80156105c6576106dd9160009161070457501590565b6106ef575b60010161067a565b61067a565b906106fc6106ea91610657565b9190506106e2565b610725915060203d8111610729575b61071d8183610338565b810190610643565b1590565b503d610713565b5090565b906100b891610741610971565b610868565b9160001960089290920291821b911b5b9181191691161790565b919061077161009361077993610315565b908354610746565b9055565b6100b891600091610760565b818110610794575050565b806107a2600060019361077d565b01610789565b90918281106107b657505050565b6100b892906107cc905b92600052602060002090565b9081019101610789565b90600160401b811161035957816107ee6100b8935490565b908281556107a8565b61009f81610611565b35610093816107f7565b906001600160401b0383116103595761082c6107c060019261009386866107d6565b92049160005b83811061083f5750505050565b600190602061085061009386610800565b9401938184015501610832565b906100b8929161080a565b906100b891600161085d565b906100b891610734565b6100b89061088a610971565b6108ee565b1561089657565b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b0390fd5b6100b8906106048161091161090b61090660006105ee565b610087565b91610087565b141561088f565b6100b89061087e565b1561092857565b60405162461bcd60e51b8152806108ea600482016020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6100b861097c610624565b61098861090b33610087565b14610921565b906001600160a01b0390610756565b906109ad610093610779926101c0565b825461098e565b6109be600061061a565b6109c982600061099d565b906109fd6109f77f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0936101c0565b916101c0565b91610a0760405190565b600090a356fea2646970667358221220f4cad27c127b67ede1ec0f6a0e5f9bdcf8b7a80b9f037e82cf1edd74cf0233ea64736f6c63430008180033",
  "deployedBytecode": "0x6080604052600436101561001257600080fd5b60003560e01c8063093410db146100825780631109b19a1461007d578063715018a6146100785780638da5cb5b14610073578063ba3754f81461006e578063c2514f8f146100695763f2fde38b036100a6576102fd565b6102e4565b610271565b61024a565b610214565b6101e2565b6100d2565b6001600160a01b031690565b90565b61009f81610087565b036100a657565b600080fd5b905035906100b882610096565b565b906020828203126100a657610093916100ab565b9052565b346100a6576100fd6100ed6100e83660046100ba565b6104ad565b6040519182918290815260200190565b0390f35b8061009f565b905035906100b882610101565b906020828203126100a65761009391610107565b634e487b7160e01b600052603260045260246000fd5b805482101561016157610158600191600052602060002090565b91020190600090565b610128565b610093916008021c6001600160a01b031690565b906100939154610166565b600180548210156100a6576100939161019d9161013e565b9061017a565b61009390610087906001600160a01b031682565b610093906101a3565b610093906101b7565b6100ce906101c0565b6020810192916100b891906101c9565b346100a6576100fd6101fd6101f8366004610114565b610185565b604051918291826101d2565b60009103126100a657565b346100a657610224366004610209565b61022c610609565b604051005b6100ce90610087565b6020810192916100b89190610231565b346100a65761025a366004610209565b6100fd610265610624565b6040519182918261023a565b346100a657610281366004610209565b6100fd6100ed610666565b909182601f830112156100a6578135916001600160401b0383116100a65760200192602083028401116100a657565b906020828203126100a65781356001600160401b0381116100a6576102e0920161028c565b9091565b346100a65761022c6102f73660046102bb565b90610874565b346100a65761022c6103103660046100ba565b610918565b6100936100936100939290565b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b0382111761035957604052565b610322565b906100b861036b60405190565b9283610338565b6001600160401b0381116103595760208091020190565b905051906100b882610101565b91906040838203126100a6576103c5906103b0604061035e565b936103bb8282610389565b8552602001610389565b6020830152565b909291926103e16103dc82610372565b61035e565b9381855260406020860192028301928184116100a657915b8383106104065750505050565b60206040916104158486610396565b8152019201916103f9565b9080601f830112156100a6578151610093926020016103cc565b906020828203126100a65781516001600160401b0381116100a6576100939201610420565b6040513d6000823e3d90fd5b90610474825190565b811015610161576020809102010190565b634e487b7160e01b600052601160045260246000fd5b919082018092116104a857565b610485565b906104b86000610315565b906104c36000610315565b915b826104d96104d561009360015490565b9190565b10156105cb5761052660006104fa6104f561019d87600161013e565b6101c0565b63045bccb39061051b889261050e60405190565b9586948593849360e01b90565b83526004830161023a565b03915afa9081156105c6576000916105a3575b50916105456000610315565b915b826105566104d5610093875190565b101561058c5761057f61058691610579602061057388889061046b565b51015190565b9061049b565b9260010190565b91610547565b9492509261059b915060010190565b9190926104c5565b6105c091503d806000833e6105b88183610338565b81019061043a565b38610539565b61045f565b92509050565b6105d9610971565b6100b86105f7565b6100876100936100939290565b610093906105e1565b6100b861060460006105ee565b6109b4565b6100b86105d1565b61009390610087565b6100939054610611565b610093600061061a565b80151561009f565b905051906100b88261062e565b906020828203126100a65761009391610636565b60001981146104a85760010190565b6106706000610315565b61067a6000610315565b8061068a6104d561009360015490565b1015610730576106be60206106a66104f561019d85600161013e565b63fbb6e31f906106b560405190565b93849260e01b90565b825260049082905afa80156105c6576106dd9160009161070457501590565b6106ef575b60010161067a565b61067a565b906106fc6106ea91610657565b9190506106e2565b610725915060203d8111610729575b61071d8183610338565b810190610643565b1590565b503d610713565b5090565b906100b891610741610971565b610868565b9160001960089290920291821b911b5b9181191691161790565b919061077161009361077993610315565b908354610746565b9055565b6100b891600091610760565b818110610794575050565b806107a2600060019361077d565b01610789565b90918281106107b657505050565b6100b892906107cc905b92600052602060002090565b9081019101610789565b90600160401b811161035957816107ee6100b8935490565b908281556107a8565b61009f81610611565b35610093816107f7565b906001600160401b0383116103595761082c6107c060019261009386866107d6565b92049160005b83811061083f5750505050565b600190602061085061009386610800565b9401938184015501610832565b906100b8929161080a565b906100b891600161085d565b906100b891610734565b6100b89061088a610971565b6108ee565b1561089657565b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b0390fd5b6100b8906106048161091161090b61090660006105ee565b610087565b91610087565b141561088f565b6100b89061087e565b1561092857565b60405162461bcd60e51b8152806108ea600482016020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6100b861097c610624565b61098861090b33610087565b14610921565b906001600160a01b0390610756565b906109ad610093610779926101c0565b825461098e565b6109be600061061a565b6109c982600061099d565b906109fd6109f77f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0936101c0565b916101c0565b91610a0760405190565b600090a356fea2646970667358221220f4cad27c127b67ede1ec0f6a0e5f9bdcf8b7a80b9f037e82cf1edd74cf0233ea64736f6c63430008180033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "aggregateEligibleStakes(address)": {
        "details": "Aggregates the eligible stake amounts for a user across multiple DataStakingDynamicNative contracts.",
        "params": {
          "user": "The address of the user."
        },
        "returns": {
          "totalEligibleAmount": "The total sum of eligible stake amounts for the user across all pools."
        }
      },
      "owner()": {
        "details": "Returns the address of the current owner."
      },
      "renounceOwnership()": {
        "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."
      },
      "setStakingContracts(address[])": {
        "details": "Sets the array of DataStakingDynamicNative contract addresses.",
        "params": {
          "_stakingContracts": "An array of DataStakingDynamicNative contract addresses."
        }
      },
      "transferOwnership(address)": {
        "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."
      }
    },
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 396,
        "contract": "contracts/ProxyViewAggregator.sol:ProxyViewAggregator",
        "label": "_owner",
        "offset": 0,
        "slot": "0",
        "type": "t_address"
      },
      {
        "astId": 8636,
        "contract": "contracts/ProxyViewAggregator.sol:ProxyViewAggregator",
        "label": "stakingContracts",
        "offset": 0,
        "slot": "1",
        "type": "t_array(t_contract(DataStakingDynamicNative)7977)dyn_storage"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_array(t_contract(DataStakingDynamicNative)7977)dyn_storage": {
        "base": "t_contract(DataStakingDynamicNative)7977",
        "encoding": "dynamic_array",
        "label": "contract DataStakingDynamicNative[]",
        "numberOfBytes": "32"
      },
      "t_contract(DataStakingDynamicNative)7977": {
        "encoding": "inplace",
        "label": "contract DataStakingDynamicNative",
        "numberOfBytes": "20"
      }
    }
  }
}