ETH Price: $2,530.09 (+1.43%)
Gas: 4.86 Gwei

Transaction Decoder

Block:
14013716 at Jan-16-2022 02:04:21 AM +UTC
Transaction Fee:
0.007665793553659616 ETH $19.40
Gas Used:
81,104 Gas / 94.518070054 Gwei

Emitted Events:

106 WTF.Transfer( from=[Sender] 0x000000ca24da2f62df5858b9c3505dc151533693, to=[Receiver] WTF, tokens=149233160210502846894 )
107 WTF.Transfer( from=[Sender] 0x000000ca24da2f62df5858b9c3505dc151533693, to=0x000000aA1B36334dDf8b153F3fF853C96B0485cC, tokens=3581595845052068325458 )
108 WTF.Reward( amount=111924870157877135171 )

Account State Difference:

  Address   Before After State Difference Code
0x000000CA...151533693
1.425983305335610022 Eth
Nonce: 2181
1.418317511781950406 Eth
Nonce: 2182
0.007665793553659616
(Luxor Technology: Mining)
125.860018608909959433 Eth125.860433050349959433 Eth0.00041444144
0xA68Dd8cB...D479c4a33

Execution Trace

WTF.transfer( _to=0x000000aA1B36334dDf8b153F3fF853C96B0485cC, _tokens=3730829005262571172352 ) => ( True )
{"ERC20.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.11;\n\ninterface ERC20 {\n\tfunction allowance(address, address) external view returns (uint256);\n\tfunction balanceOf(address) external view returns (uint256);\n\tfunction transfer(address, uint256) external returns (bool);\n\tfunction transferFrom(address, address, uint256) external returns (bool);\n}"},"Metadata.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.11;\n\nimport \"./WTFNFT.sol\";\n\ninterface PriceOracle {\n\tfunction getPrice() external view returns (uint256);\n}\n\n\ncontract Metadata {\n\t\n\tstring public name = \"fees.wtf NFT\";\n\tstring public symbol = \"fees.wtf\";\n\n\tstring constant private TABLE = \u0027ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\u0027;\n\n\tWTFNFT public nft;\n\tPriceOracle public oracle;\n\n\tconstructor(WTFNFT _nft) {\n\t\tnft = _nft;\n\t\toracle = PriceOracle(0xe89b5B2770Aa1a6BcfAc6F3517510aB8e9146651);\n\t}\n\n\tfunction setPriceOracle(PriceOracle _oracle) external {\n\t\trequire(msg.sender == nft.owner());\n\t\toracle = _oracle;\n\t}\n\n\n\tfunction tokenURI(uint256 _tokenId) external view returns (string memory) {\n\t\t( , , address _user, uint256[7] memory _info) = nft.getToken(_tokenId);\n\t\treturn rawTokenURI(_user, _info[0], _info[1], _info[2], _info[3], _info[4], _info[5], _info[6], oracle.getPrice());\n\t}\n\n\tfunction rawTokenURI(address _user, uint256 _totalFees, uint256 _failFees, uint256 _totalGas, uint256 _avgGwei, uint256 _totalDonated, uint256 _totalTxs, uint256 _failTxs, uint256 _price) public pure returns (string memory) {\n\t\tstring memory _json = string(abi.encodePacked(\u0027{\"name\":\"\u0027, _trimAddress(_user, 6), \u0027\",\"description\":\"[fees.wtf](https://fees.wtf) snapshot at block 13916450 for [\u0027, _address2str(_user), \u0027](https://etherscan.io/address/\u0027, _address2str(_user), \u0027)\",\u0027));\n\t\t_json = string(abi.encodePacked(_json, \u0027\"image\":\"data:image/svg+xml;base64,\u0027, _encode(bytes(getRawSVG(_totalFees, _failFees, _totalGas, _avgGwei, _totalDonated, _totalTxs, _failTxs, _price))), \u0027\",\"attributes\":[\u0027));\n\t\tif (_totalFees \u003e 0) {\n\t\t\t_json = string(abi.encodePacked(_json, \u0027{\"trait_type\":\"Total Fees\",\"value\":\u0027, _uint2str(_totalFees, 18, 5, false, true), \u0027}\u0027));\n\t\t\t_json = string(abi.encodePacked(_json, \u0027,{\"trait_type\":\"Fail Fees\",\"value\":\u0027, _uint2str(_failFees, 18, 5, false, true), \u0027}\u0027));\n\t\t\t_json = string(abi.encodePacked(_json, \u0027,{\"trait_type\":\"Total Gas\",\"value\":\u0027, _uint2str(_totalGas, 0, 0, false, false), \u0027}\u0027));\n\t\t\t_json = string(abi.encodePacked(_json, \u0027,{\"trait_type\":\"Average Gwei\",\"value\":\u0027, _uint2str(_avgGwei, 9, 5, false, true), \u0027}\u0027));\n\t\t\t_json = string(abi.encodePacked(_json, \u0027,{\"trait_type\":\"Total Transactions\",\"value\":\u0027, _uint2str(_totalTxs, 0, 0, false, false), \u0027}\u0027));\n\t\t\t_json = string(abi.encodePacked(_json, \u0027,{\"trait_type\":\"Failed Transactions\",\"value\":\u0027, _uint2str(_failTxs, 0, 0, false, false), \u0027}\u0027));\n\t\t\t_json = string(abi.encodePacked(_json, \u0027,{\"display_type\":\"number\",\"trait_type\":\"Spender Level\",\"value\":\u0027, _uint2str(_logn(_totalFees / 1e13, 2), 0, 0, false, false), \u0027}\u0027));\n\t\t\t_json = string(abi.encodePacked(_json, \u0027,{\"display_type\":\"number\",\"trait_type\":\"Oof Level\",\"value\":\u0027, _uint2str(_logn(_failFees / 1e13, 2), 0, 0, false, false), \u0027}\u0027));\n\t\t}\n\t\tif (_totalDonated \u003e 0) {\n\t\t\t_json = string(abi.encodePacked(_json, _totalFees \u003e 0 ? \u0027,\u0027 : \u0027\u0027, \u0027{\"display_type\":\"number\",\"trait_type\":\"Donator Level\",\"value\":\u0027, _uint2str(_logn(_totalDonated / 1e14, 10) + 1, 0, 0, false, false), \u0027}\u0027));\n\t\t}\n\t\t_json = string(abi.encodePacked(_json, \u0027]}\u0027));\n\t\treturn string(abi.encodePacked(\"data:application/json;base64,\", _encode(bytes(_json))));\n\t}\n\n\tfunction getSVG(uint256 _tokenId) public view returns (string memory) {\n\t\tuint256[7] memory _info = nft.getTokenCompressedInfo(_tokenId);\n\t\treturn getRawSVG(_info[0], _info[1], _info[2], _info[3], _info[4], _info[5], _info[6], oracle.getPrice());\n\t}\n\n\tfunction getRawSVG(uint256 _totalFees, uint256 _failFees, uint256 _totalGas, uint256 _avgGwei, uint256 _totalDonated, uint256 _totalTxs, uint256 _failTxs, uint256 _price) public pure returns (string memory svg) {\n\t\tsvg = string(abi.encodePacked(\"\u003csvg xmlns=\u0027http://www.w3.org/2000/svg\u0027 version=\u00271.1\u0027 preserveAspectRatio=\u0027xMidYMid meet\u0027 viewBox=\u00270 0 512 512\u0027 width=\u0027100%\u0027 height=\u0027100%\u0027\u003e\"));\n\t\tsvg = string(abi.encodePacked(svg, \"\u003cdefs\u003e\u003cstyle type=\u0027text/css\u0027\u003etext{text-anchor:middle;alignment-baseline:central;}tspan\u003etspan{fill:#03a9f4;font-weight:700;}\u003c/style\u003e\u003c/defs\u003e\"));\n\t\tsvg = string(abi.encodePacked(svg, \"\u003crect width=\u0027100%\u0027 height=\u0027100%\u0027 fill=\u0027#222222\u0027 /\u003e\"));\n\t\tsvg = string(abi.encodePacked(svg, \"\u003ctext x=\u00270\u0027 y=\u0027256\u0027 transform=\u0027translate(256)\u0027 fill=\u0027#f0f8ff\u0027 font-family=\u0027Arial,sans-serif\u0027 font-weight=\u0027600\u0027 font-size=\u002730\u0027\u003e\"));\n\t\tif (_totalFees \u003e 0) {\n\t\t\tsvg = string(abi.encodePacked(svg, unicode\"\u003ctspan x=\u00270\u0027 dy=\u0027-183\u0027\u003eYou spent \u003ctspan\u003eΞ\", _uint2str(_totalFees, 18, 5, true, false), \"\u003c/tspan\u003e on gas\u003c/tspan\u003e\"));\n\t\t\tsvg = string(abi.encodePacked(svg, \"\u003ctspan x=\u00270\u0027 dy=\u002735\u0027\u003ebefore block 13916450.\u003c/tspan\u003e\"));\n\t\t\tsvg = string(abi.encodePacked(svg, \"\u003ctspan x=\u00270\u0027 dy=\u002735\u0027\u003eRight now, that\u0027s\u003c/tspan\u003e\"));\n\t\t\tsvg = string(abi.encodePacked(svg, \"\u003ctspan x=\u00270\u0027 dy=\u002735\u0027\u003e\u003ctspan\u003e$\", _uint2str(_totalFees * _price / 1e18, 18, 2, true, true), \"\u003c/tspan\u003e.\u003c/tspan\u003e\"));\n\t\t\tsvg = string(abi.encodePacked(svg, \"\u003ctspan x=\u00270\u0027 dy=\u002770\u0027\u003eYou used \u003ctspan\u003e\", _uint2str(_totalGas, 0, 0, true, false), \"\u003c/tspan\u003e\u003c/tspan\u003e\"));\n\t\t\tsvg = string(abi.encodePacked(svg, \"\u003ctspan x=\u00270\u0027 dy=\u002735\u0027\u003egas to send \u003ctspan\u003e\", _uint2str(_totalTxs, 0, 0, true, false), \"\u003c/tspan\u003e\u003c/tspan\u003e\"));\n\t\t\tsvg = string(abi.encodePacked(svg, \"\u003ctspan x=\u00270\u0027 dy=\u002735\u0027\u003etransaction\", _totalTxs == 1 ? \"\" : \"s\", \", with an average\u003c/tspan\u003e\"));\n\t\t\tsvg = string(abi.encodePacked(svg, \"\u003ctspan x=\u00270\u0027 dy=\u002735\u0027\u003eprice of \u003ctspan\u003e\", _uint2str(_avgGwei, 9, 3, true, false), \"\u003c/tspan\u003e Gwei.\u003c/tspan\u003e\"));\n\t\t\tsvg = string(abi.encodePacked(svg, \"\u003ctspan x=\u00270\u0027 dy=\u002770\u0027\u003e\u003ctspan\u003e\", _uint2str(_failTxs, 0, 0, true, false), \"\u003c/tspan\u003e of them failed,\u003c/tspan\u003e\"));\n\t\t\tsvg = string(abi.encodePacked(svg, \"\u003ctspan x=\u00270\u0027 dy=\u002735\u0027\u003ecosting you \u003ctspan\u003e\", _failFees == 0 ? \"nothing\" : string(abi.encodePacked(unicode\"Ξ\", _uint2str(_failFees, 18, 5, true, false))), \"\u003c/tspan\u003e.\u003c/tspan\u003e\u003c/text\u003e\"));\n\t\t} else {\n\t\t\tsvg = string(abi.encodePacked(svg, \"\u003ctspan x=\u00270\u0027 dy=\u00278\u0027\u003eDid not qualify.\u003c/tspan\u003e\u003c/text\u003e\"));\n\t\t}\n\t\tif (_totalDonated \u003e 0) {\n\t\t\tfor (uint256 i = 0; i \u003c= _logn(_totalDonated / 1e14, 10); i++) {\n\t\t\t\tfor (uint256 j = 0; j \u003c 4; j++) {\n\t\t\t\t\tstring memory _prefix = string(abi.encodePacked(\"\u003ctext x=\u0027\", j \u003c 2 ? \"16\" : \"496\", \"\u0027 y=\u0027\", j % 2 == 0 ? \"18\" : \"498\", \"\u0027 font-size=\u002710\u0027 transform=\u0027translate(\"));\n\t\t\t\t\tsvg = string(abi.encodePacked(svg, _prefix, j \u003c 2 ? \"\" : \"-\", _uint2str(16 * i, 0, 0, false, false), \")\u0027\u003e\", unicode\"❤️\u003c/text\u003e\"));\n\t\t\t\t\tif (i \u003e 0) {\n\t\t\t\t\t\tsvg = string(abi.encodePacked(svg, _prefix, \"0,\", j % 2 == 0 ? \"\" : \"-\", _uint2str(16 * i, 0, 0, false, false), \")\u0027\u003e\", unicode\"❤️\u003c/text\u003e\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsvg = string(abi.encodePacked(svg, \"\u003ctext x=\u00270\u0027 y=\u0027500\u0027 transform=\u0027translate(256)\u0027 fill=\u0027#f0f8ff\u0027 font-family=\u0027Arial,sans-serif\u0027 font-weight=\u0027600\u0027 font-size=\u002710\u0027\u003e\u003ctspan\u003efees\u003ctspan\u003e.wtf\u003c/tspan\u003e\u003c/tspan\u003e\u003c/text\u003e\u003c/svg\u003e\"));\n\t}\n\n\n\tfunction _logn(uint256 _num, uint256 _n) internal pure returns (uint256) {\n\t\trequire(_n \u003e 0);\n\t\tuint256 _count = 0;\n\t\twhile (_num \u003e _n - 1) {\n\t\t\t_num /= _n;\n\t\t\t_count++;\n\t\t}\n\t\treturn _count;\n\t}\n\t\n\tfunction _address2str(address _address) internal pure returns (string memory str) {\n\t\tstr = \"0x\";\n\t\tfor (uint256 i; i \u003c 40; i++) {\n\t\t\tuint256 _hex = (uint160(_address) \u003e\u003e (4 * (39 - i))) % 16;\n\t\t\tbytes memory _char = new bytes(1);\n\t\t\t_char[0] = bytes1(uint8(_hex) + (_hex \u003e 9 ? 87 : 48));\n\t\t\tstr = string(abi.encodePacked(str, string(_char)));\n\t\t}\n\t}\n\n\tfunction _trimAddress(address _address, uint256 _padding) internal pure returns (string memory str) {\n\t\trequire(_padding \u003c 20);\n\t\tstr = \"\";\n\t\tbytes memory _strAddress = bytes(_address2str(_address));\n\t\tuint256 _length = 2 * _padding + 2;\n\t\tfor (uint256 i = 0; i \u003c 2 * _padding + 2; i++) {\n\t\t\tbytes memory _char = new bytes(1);\n\t\t\t_char[0] = _strAddress[i \u003c _padding + 2 ? i : 42 + i - _length];\n\t\t\tstr = string(abi.encodePacked(str, string(_char)));\n\t\t\tif (i == _padding + 1) {\n\t\t\t\tstr = string(abi.encodePacked(str, unicode\"…\"));\n\t\t\t}\n\t\t}\n\t}\n\t\n\tfunction _uint2str(uint256 _value, uint256 _scale, uint256 _maxDecimals, bool _commas, bool _full) internal pure returns (string memory str) {\n\t\tuint256 _d = _scale \u003e _maxDecimals ? _maxDecimals : _scale;\n\t\tuint256 _n = _value / 10**(_scale \u003e _d ? _scale - _d : 0);\n\t\tif (_n == 0) {\n\t\t\treturn \"0\";\n\t\t}\n\t\tuint256 _digits = 1;\n\t\tuint256 _tmp = _n;\n\t\twhile (_tmp \u003e 9) {\n\t\t\t_tmp /= 10;\n\t\t\t_digits++;\n\t\t}\n\t\t_tmp = _digits \u003e _d ? _digits : _d + 1;\n\t\tuint256 _offset = (!_full \u0026\u0026 _tmp \u003e _d + 1 ? _tmp - _d - 1 \u003e _d ? _d : _tmp - _d - 1 : 0);\n\t\tfor (uint256 i = 0; i \u003c _tmp - _offset; i++) {\n\t\t\tuint256 _dec = i \u003c _tmp - _digits ? 0 : (_n / (10**(_tmp - i - 1))) % 10;\n\t\t\tbytes memory _char = new bytes(1);\n\t\t\t_char[0] = bytes1(uint8(_dec) + 48);\n\t\t\tstr = string(abi.encodePacked(str, string(_char)));\n\t\t\tif (i \u003c _tmp - _d - 1) {\n\t\t\t\tif (_commas \u0026\u0026 (i + 1) % 3 == (_tmp - _d) % 3) {\n\t\t\t\t\tstr = string(abi.encodePacked(str, \",\"));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!_full \u0026\u0026 (_n / 10**_offset) % 10**(_tmp - _offset - i - 1) == 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (i == _tmp - _d - 1) {\n\t\t\t\t\tstr = string(abi.encodePacked(str, \".\"));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tfunction _encode(bytes memory _data) internal pure returns (string memory result) {\n\t\tif (_data.length == 0) return \u0027\u0027;\n\t\tstring memory _table = TABLE;\n\t\tuint256 _encodedLen = 4 * ((_data.length + 2) / 3);\n\t\tresult = new string(_encodedLen + 32);\n\n\t\tassembly {\n\t\t\tmstore(result, _encodedLen)\n\t\t\tlet tablePtr := add(_table, 1)\n\t\t\tlet dataPtr := _data\n\t\t\tlet endPtr := add(dataPtr, mload(_data))\n\t\t\tlet resultPtr := add(result, 32)\n\n\t\t\tfor {} lt(dataPtr, endPtr) {}\n\t\t\t{\n\t\t\t\tdataPtr := add(dataPtr, 3)\n\t\t\t\tlet input := mload(dataPtr)\n\t\t\t\tmstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F)))))\n\t\t\t\tresultPtr := add(resultPtr, 1)\n\t\t\t\tmstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F)))))\n\t\t\t\tresultPtr := add(resultPtr, 1)\n\t\t\t\tmstore(resultPtr, shl(248, mload(add(tablePtr, and(shr( 6, input), 0x3F)))))\n\t\t\t\tresultPtr := add(resultPtr, 1)\n\t\t\t\tmstore(resultPtr, shl(248, mload(add(tablePtr, and(        input,  0x3F)))))\n\t\t\t\tresultPtr := add(resultPtr, 1)\n\t\t\t}\n\t\t\tswitch mod(mload(_data), 3)\n\t\t\tcase 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }\n\t\t\tcase 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }\n\t\t}\n\t\treturn result;\n\t}\n}"},"PRBMath.sol":{"content":"// SPDX-License-Identifier: Unlicense\npragma solidity \u003e=0.8.4;\n\n/// @notice Emitted when the result overflows uint256.\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\n\n/// @notice Emitted when the result overflows uint256.\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\n\n/// @notice Emitted when one of the inputs is type(int256).min.\nerror PRBMath__MulDivSignedInputTooSmall();\n\n/// @notice Emitted when the intermediary absolute result overflows int256.\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\n\n/// @notice Emitted when the input is MIN_SD59x18.\nerror PRBMathSD59x18__AbsInputTooSmall();\n\n/// @notice Emitted when ceiling a number overflows SD59x18.\nerror PRBMathSD59x18__CeilOverflow(int256 x);\n\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\nerror PRBMathSD59x18__DivInputTooSmall();\n\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\n\n/// @notice Emitted when the input is greater than 133.084258667509499441.\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\n\n/// @notice Emitted when the input is greater than 192.\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\n\n/// @notice Emitted when flooring a number underflows SD59x18.\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\n\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\n\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\n\n/// @notice Emitted when the product of the inputs is negative.\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\n\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\n\n/// @notice Emitted when the input is less than or equal to zero.\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\n\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\nerror PRBMathSD59x18__MulInputTooSmall();\n\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\n\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\n\n/// @notice Emitted when the input is negative.\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\n\n/// @notice Emitted when the calculating the square root overflows SD59x18.\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\n\n/// @notice Emitted when addition overflows UD60x18.\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\n\n/// @notice Emitted when ceiling a number overflows UD60x18.\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\n\n/// @notice Emitted when the input is greater than 133.084258667509499441.\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\n\n/// @notice Emitted when the input is greater than 192.\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\n\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\n\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\n\n/// @notice Emitted when the input is less than 1.\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\n\n/// @notice Emitted when the calculating the square root overflows UD60x18.\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\n\n/// @notice Emitted when subtraction underflows UD60x18.\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\n\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\nlibrary PRBMath {\n\t/// STRUCTS ///\n\n\tstruct SD59x18 {\n\t\tint256 value;\n\t}\n\n\tstruct UD60x18 {\n\t\tuint256 value;\n\t}\n\n\t/// STORAGE ///\n\n\t/// @dev How many trailing decimals can be represented.\n\tuint256 internal constant SCALE = 1e18;\n\n\t/// @dev Largest power of two divisor of SCALE.\n\tuint256 internal constant SCALE_LPOTD = 262144;\n\n\t/// @dev SCALE inverted mod 2^256.\n\tuint256 internal constant SCALE_INVERSE =\n\t\t78156646155174841979727994598816262306175212592076161876661_508869554232690281;\n\n\t/// FUNCTIONS ///\n\n\t/// @notice Calculates the binary exponent of x using the binary fraction method.\n\t/// @dev Has to use 192.64-bit fixed-point numbers.\n\t/// See https://ethereum.stackexchange.com/a/96594/24693.\n\t/// @param x The exponent as an unsigned 192.64-bit fixed-point number.\n\t/// @return result The result as an unsigned 60.18-decimal fixed-point number.\n\tfunction exp2(uint256 x) internal pure returns (uint256 result) {\n\t\tunchecked {\n\t\t\t// Start from 0.5 in the 192.64-bit fixed-point format.\n\t\t\tresult = 0x800000000000000000000000000000000000000000000000;\n\n\t\t\t// Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\n\t\t\t// because the initial result is 2^191 and all magic factors are less than 2^65.\n\t\t\tif (x \u0026 0x8000000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x16A09E667F3BCC909) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x4000000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1306FE0A31B7152DF) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x2000000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1172B83C7D517ADCE) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x1000000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10B5586CF9890F62A) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x800000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1059B0D31585743AE) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x400000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x102C9A3E778060EE7) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x200000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10163DA9FB33356D8) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x100000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100B1AFA5ABCBED61) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x80000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10058C86DA1C09EA2) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x40000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1002C605E2E8CEC50) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x20000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100162F3904051FA1) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x10000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000B175EFFDC76BA) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x8000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100058BA01FB9F96D) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x4000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10002C5CC37DA9492) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x2000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000162E525EE0547) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x1000000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000B17255775C04) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x800000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000058B91B5BC9AE) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x400000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100002C5C89D5EC6D) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x200000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000162E43F4F831) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x100000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000B1721BCFC9A) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x80000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000058B90CF1E6E) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x40000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000002C5C863B73F) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x20000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000162E430E5A2) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x10000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000B172183551) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x8000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000058B90C0B49) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x4000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000002C5C8601CC) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x2000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000162E42FFF0) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x1000000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000B17217FBB) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x800000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000058B90BFCE) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x400000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000002C5C85FE3) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x200000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000162E42FF1) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x100000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000000B17217F8) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x80000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000058B90BFC) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x40000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000002C5C85FE) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x20000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000000162E42FF) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x10000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000000B17217F) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x8000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000000058B90C0) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x4000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000002C5C860) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x2000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000000162E430) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x1000000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000B17218) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x800000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000000058B90C) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x400000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000000002C5C86) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x200000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000162E43) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x100000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000000000B1721) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x80000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000058B91) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x40000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000000002C5C8) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x20000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000000000162E4) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x10000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000000000B172) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x8000 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000000000058B9) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x4000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000002C5D) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x2000 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000000000162E) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x1000 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000000B17) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x800 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000000000058C) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x400 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000000000002C6) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x200 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000000163) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x100 \u003e 0) {\n\t\t\t\tresult = (result * 0x100000000000000B1) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x80 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000000059) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x40 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000000000002C) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x20 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000000016) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x10 \u003e 0) {\n\t\t\t\tresult = (result * 0x1000000000000000B) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x8 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000000006) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x4 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000000003) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x2 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000000001) \u003e\u003e 64;\n\t\t\t}\n\t\t\tif (x \u0026 0x1 \u003e 0) {\n\t\t\t\tresult = (result * 0x10000000000000001) \u003e\u003e 64;\n\t\t\t}\n\n\t\t\t// We\u0027re doing two things at the same time:\n\t\t\t//\n\t\t\t//   1. Multiply the result by 2^n + 1, where \"2^n\" is the integer part and the one is added to account for\n\t\t\t//      the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\n\t\t\t//      rather than 192.\n\t\t\t//   2. Convert the result to the unsigned 60.18-decimal fixed-point format.\n\t\t\t//\n\t\t\t// This works because 2^(191-ip) = 2^ip / 2^191, where \"ip\" is the integer part \"2^n\".\n\t\t\tresult *= SCALE;\n\t\t\tresult \u003e\u003e= (191 - (x \u003e\u003e 64));\n\t\t}\n\t}\n\n\t/// @notice Finds the zero-based index of the first one in the binary representation of x.\n\t/// @dev See the note on msb in the \"Find First Set\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\n\t/// @param x The uint256 number for which to find the index of the most significant bit.\n\t/// @return msb The index of the most significant bit as an uint256.\n\tfunction mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n\t\tif (x \u003e= 2**128) {\n\t\t\tx \u003e\u003e= 128;\n\t\t\tmsb += 128;\n\t\t}\n\t\tif (x \u003e= 2**64) {\n\t\t\tx \u003e\u003e= 64;\n\t\t\tmsb += 64;\n\t\t}\n\t\tif (x \u003e= 2**32) {\n\t\t\tx \u003e\u003e= 32;\n\t\t\tmsb += 32;\n\t\t}\n\t\tif (x \u003e= 2**16) {\n\t\t\tx \u003e\u003e= 16;\n\t\t\tmsb += 16;\n\t\t}\n\t\tif (x \u003e= 2**8) {\n\t\t\tx \u003e\u003e= 8;\n\t\t\tmsb += 8;\n\t\t}\n\t\tif (x \u003e= 2**4) {\n\t\t\tx \u003e\u003e= 4;\n\t\t\tmsb += 4;\n\t\t}\n\t\tif (x \u003e= 2**2) {\n\t\t\tx \u003e\u003e= 2;\n\t\t\tmsb += 2;\n\t\t}\n\t\tif (x \u003e= 2**1) {\n\t\t\t// No need to shift x any more.\n\t\t\tmsb += 1;\n\t\t}\n\t}\n\n\t/// @notice Calculates floor(x*y÷denominator) with full precision.\n\t///\n\t/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\n\t///\n\t/// Requirements:\n\t/// - The denominator cannot be zero.\n\t/// - The result must fit within uint256.\n\t///\n\t/// Caveats:\n\t/// - This function does not work with fixed-point numbers.\n\t///\n\t/// @param x The multiplicand as an uint256.\n\t/// @param y The multiplier as an uint256.\n\t/// @param denominator The divisor as an uint256.\n\t/// @return result The result as an uint256.\n\tfunction mulDiv(\n\t\tuint256 x,\n\t\tuint256 y,\n\t\tuint256 denominator\n\t) internal pure returns (uint256 result) {\n\t\t// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n\t\t// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n\t\t// variables such that product = prod1 * 2^256 + prod0.\n\t\tuint256 prod0; // Least significant 256 bits of the product\n\t\tuint256 prod1; // Most significant 256 bits of the product\n\t\tassembly {\n\t\t\tlet mm := mulmod(x, y, not(0))\n\t\t\tprod0 := mul(x, y)\n\t\t\tprod1 := sub(sub(mm, prod0), lt(mm, prod0))\n\t\t}\n\n\t\t// Handle non-overflow cases, 256 by 256 division.\n\t\tif (prod1 == 0) {\n\t\t\tunchecked {\n\t\t\t\tresult = prod0 / denominator;\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\t// Make sure the result is less than 2^256. Also prevents denominator == 0.\n\t\tif (prod1 \u003e= denominator) {\n\t\t\trevert PRBMath__MulDivOverflow(prod1, denominator);\n\t\t}\n\n\t\t///////////////////////////////////////////////\n\t\t// 512 by 256 division.\n\t\t///////////////////////////////////////////////\n\n\t\t// Make division exact by subtracting the remainder from [prod1 prod0].\n\t\tuint256 remainder;\n\t\tassembly {\n\t\t\t// Compute remainder using mulmod.\n\t\t\tremainder := mulmod(x, y, denominator)\n\n\t\t\t// Subtract 256 bit number from 512 bit number.\n\t\t\tprod1 := sub(prod1, gt(remainder, prod0))\n\t\t\tprod0 := sub(prod0, remainder)\n\t\t}\n\n\t\t// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always \u003e= 1.\n\t\t// See https://cs.stackexchange.com/q/138556/92363.\n\t\tunchecked {\n\t\t\t// Does not overflow because the denominator cannot be zero at this stage in the function.\n\t\t\tuint256 lpotdod = denominator \u0026 (~denominator + 1);\n\t\t\tassembly {\n\t\t\t\t// Divide denominator by lpotdod.\n\t\t\t\tdenominator := div(denominator, lpotdod)\n\n\t\t\t\t// Divide [prod1 prod0] by lpotdod.\n\t\t\t\tprod0 := div(prod0, lpotdod)\n\n\t\t\t\t// Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\n\t\t\t\tlpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\n\t\t\t}\n\n\t\t\t// Shift in bits from prod1 into prod0.\n\t\t\tprod0 |= prod1 * lpotdod;\n\n\t\t\t// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n\t\t\t// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n\t\t\t// four bits. That is, denominator * inv = 1 mod 2^4.\n\t\t\tuint256 inverse = (3 * denominator) ^ 2;\n\n\t\t\t// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel\u0027s lifting lemma, this also works\n\t\t\t// in modular arithmetic, doubling the correct bits in each step.\n\t\t\tinverse *= 2 - denominator * inverse; // inverse mod 2^8\n\t\t\tinverse *= 2 - denominator * inverse; // inverse mod 2^16\n\t\t\tinverse *= 2 - denominator * inverse; // inverse mod 2^32\n\t\t\tinverse *= 2 - denominator * inverse; // inverse mod 2^64\n\t\t\tinverse *= 2 - denominator * inverse; // inverse mod 2^128\n\t\t\tinverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n\t\t\t// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n\t\t\t// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n\t\t\t// less than 2^256, this is the final result. We don\u0027t need to compute the high bits of the result and prod1\n\t\t\t// is no longer required.\n\t\t\tresult = prod0 * inverse;\n\t\t\treturn result;\n\t\t}\n\t}\n\n\t/// @notice Calculates floor(x*y÷1e18) with full precision.\n\t///\n\t/// @dev Variant of \"mulDiv\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\n\t/// final result, we add 1 if (x * y) % SCALE \u003e= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\n\t/// being rounded to 1e-18.  See \"Listing 6\" and text above it at https://accu.org/index.php/journals/1717.\n\t///\n\t/// Requirements:\n\t/// - The result must fit within uint256.\n\t///\n\t/// Caveats:\n\t/// - The body is purposely left uncommented; see the NatSpec comments in \"PRBMath.mulDiv\" to understand how this works.\n\t/// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\n\t///     1. x * y = type(uint256).max * SCALE\n\t///     2. (x * y) % SCALE \u003e= SCALE / 2\n\t///\n\t/// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\n\t/// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\n\t/// @return result The result as an unsigned 60.18-decimal fixed-point number.\n\tfunction mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\n\t\tuint256 prod0;\n\t\tuint256 prod1;\n\t\tassembly {\n\t\t\tlet mm := mulmod(x, y, not(0))\n\t\t\tprod0 := mul(x, y)\n\t\t\tprod1 := sub(sub(mm, prod0), lt(mm, prod0))\n\t\t}\n\n\t\tif (prod1 \u003e= SCALE) {\n\t\t\trevert PRBMath__MulDivFixedPointOverflow(prod1);\n\t\t}\n\n\t\tuint256 remainder;\n\t\tuint256 roundUpUnit;\n\t\tassembly {\n\t\t\tremainder := mulmod(x, y, SCALE)\n\t\t\troundUpUnit := gt(remainder, 499999999999999999)\n\t\t}\n\n\t\tif (prod1 == 0) {\n\t\t\tunchecked {\n\t\t\t\tresult = (prod0 / SCALE) + roundUpUnit;\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\tassembly {\n\t\t\tresult := add(\n\t\t\t\tmul(\n\t\t\t\t\tor(\n\t\t\t\t\t\tdiv(sub(prod0, remainder), SCALE_LPOTD),\n\t\t\t\t\t\tmul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\n\t\t\t\t\t),\n\t\t\t\t\tSCALE_INVERSE\n\t\t\t\t),\n\t\t\t\troundUpUnit\n\t\t\t)\n\t\t}\n\t}\n\n\t/// @notice Calculates floor(x*y÷denominator) with full precision.\n\t///\n\t/// @dev An extension of \"mulDiv\" for signed numbers. Works by computing the signs and the absolute values separately.\n\t///\n\t/// Requirements:\n\t/// - None of the inputs can be type(int256).min.\n\t/// - The result must fit within int256.\n\t///\n\t/// @param x The multiplicand as an int256.\n\t/// @param y The multiplier as an int256.\n\t/// @param denominator The divisor as an int256.\n\t/// @return result The result as an int256.\n\tfunction mulDivSigned(\n\t\tint256 x,\n\t\tint256 y,\n\t\tint256 denominator\n\t) internal pure returns (int256 result) {\n\t\tif (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\n\t\t\trevert PRBMath__MulDivSignedInputTooSmall();\n\t\t}\n\n\t\t// Get hold of the absolute values of x, y and the denominator.\n\t\tuint256 ax;\n\t\tuint256 ay;\n\t\tuint256 ad;\n\t\tunchecked {\n\t\t\tax = x \u003c 0 ? uint256(-x) : uint256(x);\n\t\t\tay = y \u003c 0 ? uint256(-y) : uint256(y);\n\t\t\tad = denominator \u003c 0 ? uint256(-denominator) : uint256(denominator);\n\t\t}\n\n\t\t// Compute the absolute value of (x*y)÷denominator. The result must fit within int256.\n\t\tuint256 rAbs = mulDiv(ax, ay, ad);\n\t\tif (rAbs \u003e uint256(type(int256).max)) {\n\t\t\trevert PRBMath__MulDivSignedOverflow(rAbs);\n\t\t}\n\n\t\t// Get the signs of x, y and the denominator.\n\t\tuint256 sx;\n\t\tuint256 sy;\n\t\tuint256 sd;\n\t\tassembly {\n\t\t\tsx := sgt(x, sub(0, 1))\n\t\t\tsy := sgt(y, sub(0, 1))\n\t\t\tsd := sgt(denominator, sub(0, 1))\n\t\t}\n\n\t\t// XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\n\t\t// If yes, the result should be negative.\n\t\tresult = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\n\t}\n\n\t/// @notice Calculates the square root of x, rounding down.\n\t/// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n\t///\n\t/// Caveats:\n\t/// - This function does not work with fixed-point numbers.\n\t///\n\t/// @param x The uint256 number for which to calculate the square root.\n\t/// @return result The result as an uint256.\n\tfunction sqrt(uint256 x) internal pure returns (uint256 result) {\n\t\tif (x == 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Set the initial guess to the least power of two that is greater than or equal to sqrt(x).\n\t\tuint256 xAux = uint256(x);\n\t\tresult = 1;\n\t\tif (xAux \u003e= 0x100000000000000000000000000000000) {\n\t\t\txAux \u003e\u003e= 128;\n\t\t\tresult \u003c\u003c= 64;\n\t\t}\n\t\tif (xAux \u003e= 0x10000000000000000) {\n\t\t\txAux \u003e\u003e= 64;\n\t\t\tresult \u003c\u003c= 32;\n\t\t}\n\t\tif (xAux \u003e= 0x100000000) {\n\t\t\txAux \u003e\u003e= 32;\n\t\t\tresult \u003c\u003c= 16;\n\t\t}\n\t\tif (xAux \u003e= 0x10000) {\n\t\t\txAux \u003e\u003e= 16;\n\t\t\tresult \u003c\u003c= 8;\n\t\t}\n\t\tif (xAux \u003e= 0x100) {\n\t\t\txAux \u003e\u003e= 8;\n\t\t\tresult \u003c\u003c= 4;\n\t\t}\n\t\tif (xAux \u003e= 0x10) {\n\t\t\txAux \u003e\u003e= 4;\n\t\t\tresult \u003c\u003c= 2;\n\t\t}\n\t\tif (xAux \u003e= 0x8) {\n\t\t\tresult \u003c\u003c= 1;\n\t\t}\n\n\t\t// The operations can never overflow because the result is max 2^127 when it enters this block.\n\t\tunchecked {\n\t\t\tresult = (result + x / result) \u003e\u003e 1;\n\t\t\tresult = (result + x / result) \u003e\u003e 1;\n\t\t\tresult = (result + x / result) \u003e\u003e 1;\n\t\t\tresult = (result + x / result) \u003e\u003e 1;\n\t\t\tresult = (result + x / result) \u003e\u003e 1;\n\t\t\tresult = (result + x / result) \u003e\u003e 1;\n\t\t\tresult = (result + x / result) \u003e\u003e 1; // Seven iterations should be enough\n\t\t\tuint256 roundedDownResult = x / result;\n\t\t\treturn result \u003e= roundedDownResult ? roundedDownResult : result;\n\t\t}\n\t}\n}"},"PRBMathUD60x18.sol":{"content":"// SPDX-License-Identifier: Unlicense\npragma solidity \u003e=0.8.4;\n\nimport \"./PRBMath.sol\";\n\n/// @title PRBMathUD60x18\n/// @author Paul Razvan Berg\n/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18\n/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60\n/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the\n/// maximum values permitted by the Solidity type uint256.\nlibrary PRBMathUD60x18 {\n\t/// @dev Half the SCALE number.\n\tuint256 internal constant HALF_SCALE = 5e17;\n\n\t/// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.\n\tuint256 internal constant LOG2_E = 1_442695040888963407;\n\n\t/// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.\n\tuint256 internal constant MAX_UD60x18 =\n\t\t115792089237316195423570985008687907853269984665640564039457_584007913129639935;\n\n\t/// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.\n\tuint256 internal constant MAX_WHOLE_UD60x18 =\n\t\t115792089237316195423570985008687907853269984665640564039457_000000000000000000;\n\n\t/// @dev How many trailing decimals can be represented.\n\tuint256 internal constant SCALE = 1e18;\n\n\t/// @notice Calculates the arithmetic average of x and y, rounding down.\n\t/// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\n\t/// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\n\t/// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.\n\tfunction avg(uint256 x, uint256 y) internal pure returns (uint256 result) {\n\t\t// The operations can never overflow.\n\t\tunchecked {\n\t\t\t// The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need\n\t\t\t// to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.\n\t\t\tresult = (x \u003e\u003e 1) + (y \u003e\u003e 1) + (x \u0026 y \u0026 1);\n\t\t}\n\t}\n\n\t/// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.\n\t///\n\t/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\n\t/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n\t///\n\t/// Requirements:\n\t/// - x must be less than or equal to MAX_WHOLE_UD60x18.\n\t///\n\t/// @param x The unsigned 60.18-decimal fixed-point number to ceil.\n\t/// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.\n\tfunction ceil(uint256 x) internal pure returns (uint256 result) {\n\t\tif (x \u003e MAX_WHOLE_UD60x18) {\n\t\t\trevert PRBMathUD60x18__CeilOverflow(x);\n\t\t}\n\t\tassembly {\n\t\t\t// Equivalent to \"x % SCALE\" but faster.\n\t\t\tlet remainder := mod(x, SCALE)\n\n\t\t\t// Equivalent to \"SCALE - remainder\" but faster.\n\t\t\tlet delta := sub(SCALE, remainder)\n\n\t\t\t// Equivalent to \"x + delta * (remainder \u003e 0 ? 1 : 0)\" but faster.\n\t\t\tresult := add(x, mul(delta, gt(remainder, 0)))\n\t\t}\n\t}\n\n\t/// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.\n\t///\n\t/// @dev Uses mulDiv to enable overflow-safe multiplication and division.\n\t///\n\t/// Requirements:\n\t/// - The denominator cannot be zero.\n\t///\n\t/// @param x The numerator as an unsigned 60.18-decimal fixed-point number.\n\t/// @param y The denominator as an unsigned 60.18-decimal fixed-point number.\n\t/// @param result The quotient as an unsigned 60.18-decimal fixed-point number.\n\tfunction div(uint256 x, uint256 y) internal pure returns (uint256 result) {\n\t\tresult = PRBMath.mulDiv(x, SCALE, y);\n\t}\n\n\t/// @notice Returns Euler\u0027s number as an unsigned 60.18-decimal fixed-point number.\n\t/// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).\n\tfunction e() internal pure returns (uint256 result) {\n\t\tresult = 2_718281828459045235;\n\t}\n\n\t/// @notice Calculates the natural exponent of x.\n\t///\n\t/// @dev Based on the insight that e^x = 2^(x * log2(e)).\n\t///\n\t/// Requirements:\n\t/// - All from \"log2\".\n\t/// - x must be less than 133.084258667509499441.\n\t///\n\t/// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\n\t/// @return result The result as an unsigned 60.18-decimal fixed-point number.\n\tfunction exp(uint256 x) internal pure returns (uint256 result) {\n\t\t// Without this check, the value passed to \"exp2\" would be greater than 192.\n\t\tif (x \u003e= 133_084258667509499441) {\n\t\t\trevert PRBMathUD60x18__ExpInputTooBig(x);\n\t\t}\n\n\t\t// Do the fixed-point multiplication inline to save gas.\n\t\tunchecked {\n\t\t\tuint256 doubleScaleProduct = x * LOG2_E;\n\t\t\tresult = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);\n\t\t}\n\t}\n\n\t/// @notice Calculates the binary exponent of x using the binary fraction method.\n\t///\n\t/// @dev See https://ethereum.stackexchange.com/q/79903/24693.\n\t///\n\t/// Requirements:\n\t/// - x must be 192 or less.\n\t/// - The result must fit within MAX_UD60x18.\n\t///\n\t/// @param x The exponent as an unsigned 60.18-decimal fixed-point number.\n\t/// @return result The result as an unsigned 60.18-decimal fixed-point number.\n\tfunction exp2(uint256 x) internal pure returns (uint256 result) {\n\t\t// 2^192 doesn\u0027t fit within the 192.64-bit format used internally in this function.\n\t\tif (x \u003e= 192e18) {\n\t\t\trevert PRBMathUD60x18__Exp2InputTooBig(x);\n\t\t}\n\n\t\tunchecked {\n\t\t\t// Convert x to the 192.64-bit fixed-point format.\n\t\t\tuint256 x192x64 = (x \u003c\u003c 64) / SCALE;\n\n\t\t\t// Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.\n\t\t\tresult = PRBMath.exp2(x192x64);\n\t\t}\n\t}\n\n\t/// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.\n\t/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.\n\t/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.\n\t/// @param x The unsigned 60.18-decimal fixed-point number to floor.\n\t/// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.\n\tfunction floor(uint256 x) internal pure returns (uint256 result) {\n\t\tassembly {\n\t\t\t// Equivalent to \"x % SCALE\" but faster.\n\t\t\tlet remainder := mod(x, SCALE)\n\n\t\t\t// Equivalent to \"x - remainder * (remainder \u003e 0 ? 1 : 0)\" but faster.\n\t\t\tresult := sub(x, mul(remainder, gt(remainder, 0)))\n\t\t}\n\t}\n\n\t/// @notice Yields the excess beyond the floor of x.\n\t/// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.\n\t/// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.\n\t/// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.\n\tfunction frac(uint256 x) internal pure returns (uint256 result) {\n\t\tassembly {\n\t\t\tresult := mod(x, SCALE)\n\t\t}\n\t}\n\n\t/// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.\n\t///\n\t/// @dev Requirements:\n\t/// - x must be less than or equal to MAX_UD60x18 divided by SCALE.\n\t///\n\t/// @param x The basic integer to convert.\n\t/// @param result The same number in unsigned 60.18-decimal fixed-point representation.\n\tfunction fromUint(uint256 x) internal pure returns (uint256 result) {\n\t\tunchecked {\n\t\t\tif (x \u003e MAX_UD60x18 / SCALE) {\n\t\t\t\trevert PRBMathUD60x18__FromUintOverflow(x);\n\t\t\t}\n\t\t\tresult = x * SCALE;\n\t\t}\n\t}\n\n\t/// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.\n\t///\n\t/// @dev Requirements:\n\t/// - x * y must fit within MAX_UD60x18, lest it overflows.\n\t///\n\t/// @param x The first operand as an unsigned 60.18-decimal fixed-point number.\n\t/// @param y The second operand as an unsigned 60.18-decimal fixed-point number.\n\t/// @return result The result as an unsigned 60.18-decimal fixed-point number.\n\tfunction gm(uint256 x, uint256 y) internal pure returns (uint256 result) {\n\t\tif (x == 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tunchecked {\n\t\t\t// Checking for overflow this way is faster than letting Solidity do it.\n\t\t\tuint256 xy = x * y;\n\t\t\tif (xy / x != y) {\n\t\t\t\trevert PRBMathUD60x18__GmOverflow(x, y);\n\t\t\t}\n\n\t\t\t// We don\u0027t need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE\n\t\t\t// during multiplication. See the comments within the \"sqrt\" function.\n\t\t\tresult = PRBMath.sqrt(xy);\n\t\t}\n\t}\n\n\t/// @notice Calculates 1 / x, rounding toward zero.\n\t///\n\t/// @dev Requirements:\n\t/// - x cannot be zero.\n\t///\n\t/// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.\n\t/// @return result The inverse as an unsigned 60.18-decimal fixed-point number.\n\tfunction inv(uint256 x) internal pure returns (uint256 result) {\n\t\tunchecked {\n\t\t\t// 1e36 is SCALE * SCALE.\n\t\t\tresult = 1e36 / x;\n\t\t}\n\t}\n\n\t/// @notice Calculates the natural logarithm of x.\n\t///\n\t/// @dev Based on the insight that ln(x) = log2(x) / log2(e).\n\t///\n\t/// Requirements:\n\t/// - All from \"log2\".\n\t///\n\t/// Caveats:\n\t/// - All from \"log2\".\n\t/// - This doesn\u0027t return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.\n\t///\n\t/// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.\n\t/// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.\n\tfunction ln(uint256 x) internal pure returns (uint256 result) {\n\t\t// Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)\n\t\t// can return is 196205294292027477728.\n\t\tunchecked {\n\t\t\tresult = (log2(x) * SCALE) / LOG2_E;\n\t\t}\n\t}\n\n\t/// @notice Calculates the common logarithm of x.\n\t///\n\t/// @dev First checks if x is an exact power of ten and it stops if yes. If it\u0027s not, calculates the common\n\t/// logarithm based on the insight that log10(x) = log2(x) / log2(10).\n\t///\n\t/// Requirements:\n\t/// - All from \"log2\".\n\t///\n\t/// Caveats:\n\t/// - All from \"log2\".\n\t///\n\t/// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.\n\t/// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.\n\tfunction log10(uint256 x) internal pure returns (uint256 result) {\n\t\tif (x \u003c SCALE) {\n\t\t\trevert PRBMathUD60x18__LogInputTooSmall(x);\n\t\t}\n\n\t\t// Note that the \"mul\" in this block is the assembly multiplication operation, not the \"mul\" function defined\n\t\t// in this contract.\n\t\t// prettier-ignore\n\t\tassembly {\n\t\t\tswitch x\n\t\t\tcase 1 { result := mul(SCALE, sub(0, 18)) }\n\t\t\tcase 10 { result := mul(SCALE, sub(1, 18)) }\n\t\t\tcase 100 { result := mul(SCALE, sub(2, 18)) }\n\t\t\tcase 1000 { result := mul(SCALE, sub(3, 18)) }\n\t\t\tcase 10000 { result := mul(SCALE, sub(4, 18)) }\n\t\t\tcase 100000 { result := mul(SCALE, sub(5, 18)) }\n\t\t\tcase 1000000 { result := mul(SCALE, sub(6, 18)) }\n\t\t\tcase 10000000 { result := mul(SCALE, sub(7, 18)) }\n\t\t\tcase 100000000 { result := mul(SCALE, sub(8, 18)) }\n\t\t\tcase 1000000000 { result := mul(SCALE, sub(9, 18)) }\n\t\t\tcase 10000000000 { result := mul(SCALE, sub(10, 18)) }\n\t\t\tcase 100000000000 { result := mul(SCALE, sub(11, 18)) }\n\t\t\tcase 1000000000000 { result := mul(SCALE, sub(12, 18)) }\n\t\t\tcase 10000000000000 { result := mul(SCALE, sub(13, 18)) }\n\t\t\tcase 100000000000000 { result := mul(SCALE, sub(14, 18)) }\n\t\t\tcase 1000000000000000 { result := mul(SCALE, sub(15, 18)) }\n\t\t\tcase 10000000000000000 { result := mul(SCALE, sub(16, 18)) }\n\t\t\tcase 100000000000000000 { result := mul(SCALE, sub(17, 18)) }\n\t\t\tcase 1000000000000000000 { result := 0 }\n\t\t\tcase 10000000000000000000 { result := SCALE }\n\t\t\tcase 100000000000000000000 { result := mul(SCALE, 2) }\n\t\t\tcase 1000000000000000000000 { result := mul(SCALE, 3) }\n\t\t\tcase 10000000000000000000000 { result := mul(SCALE, 4) }\n\t\t\tcase 100000000000000000000000 { result := mul(SCALE, 5) }\n\t\t\tcase 1000000000000000000000000 { result := mul(SCALE, 6) }\n\t\t\tcase 10000000000000000000000000 { result := mul(SCALE, 7) }\n\t\t\tcase 100000000000000000000000000 { result := mul(SCALE, 8) }\n\t\t\tcase 1000000000000000000000000000 { result := mul(SCALE, 9) }\n\t\t\tcase 10000000000000000000000000000 { result := mul(SCALE, 10) }\n\t\t\tcase 100000000000000000000000000000 { result := mul(SCALE, 11) }\n\t\t\tcase 1000000000000000000000000000000 { result := mul(SCALE, 12) }\n\t\t\tcase 10000000000000000000000000000000 { result := mul(SCALE, 13) }\n\t\t\tcase 100000000000000000000000000000000 { result := mul(SCALE, 14) }\n\t\t\tcase 1000000000000000000000000000000000 { result := mul(SCALE, 15) }\n\t\t\tcase 10000000000000000000000000000000000 { result := mul(SCALE, 16) }\n\t\t\tcase 100000000000000000000000000000000000 { result := mul(SCALE, 17) }\n\t\t\tcase 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }\n\t\t\tcase 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }\n\t\t\tcase 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }\n\t\t\tcase 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }\n\t\t\tcase 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }\n\t\t\tcase 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }\n\t\t\tcase 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }\n\t\t\tcase 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }\n\t\t\tcase 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }\n\t\t\tcase 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }\n\t\t\tcase 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }\n\t\t\tcase 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }\n\t\t\tcase 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }\n\t\t\tcase 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }\n\t\t\tcase 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }\n\t\t\tcase 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }\n\t\t\tcase 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }\n\t\t\tcase 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }\n\t\t\tcase 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }\n\t\t\tcase 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }\n\t\t\tcase 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }\n\t\t\tcase 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }\n\t\t\tcase 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }\n\t\t\tcase 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }\n\t\t\tcase 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }\n\t\t\tcase 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }\n\t\t\tcase 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }\n\t\t\tcase 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }\n\t\t\tcase 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }\n\t\t\tcase 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }\n\t\t\tcase 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }\n\t\t\tcase 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }\n\t\t\tcase 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }\n\t\t\tcase 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }\n\t\t\tcase 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }\n\t\t\tcase 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }\n\t\t\tcase 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }\n\t\t\tcase 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }\n\t\t\tcase 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }\n\t\t\tcase 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }\n\t\t\tcase 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }\n\t\t\tcase 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }\n\t\t\tdefault {\n\t\t\t\tresult := MAX_UD60x18\n\t\t\t}\n\t\t}\n\n\t\tif (result == MAX_UD60x18) {\n\t\t\t// Do the fixed-point division inline to save gas. The denominator is log2(10).\n\t\t\tunchecked {\n\t\t\t\tresult = (log2(x) * SCALE) / 3_321928094887362347;\n\t\t\t}\n\t\t}\n\t}\n\n\t/// @notice Calculates the binary logarithm of x.\n\t///\n\t/// @dev Based on the iterative approximation algorithm.\n\t/// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation\n\t///\n\t/// Requirements:\n\t/// - x must be greater than or equal to SCALE, otherwise the result would be negative.\n\t///\n\t/// Caveats:\n\t/// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.\n\t///\n\t/// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.\n\t/// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.\n\tfunction log2(uint256 x) internal pure returns (uint256 result) {\n\t\tif (x \u003c SCALE) {\n\t\t\trevert PRBMathUD60x18__LogInputTooSmall(x);\n\t\t}\n\t\tunchecked {\n\t\t\t// Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).\n\t\t\tuint256 n = PRBMath.mostSignificantBit(x / SCALE);\n\n\t\t\t// The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can\u0027t overflow\n\t\t\t// because n is maximum 255 and SCALE is 1e18.\n\t\t\tresult = n * SCALE;\n\n\t\t\t// This is y = x * 2^(-n).\n\t\t\tuint256 y = x \u003e\u003e n;\n\n\t\t\t// If y = 1, the fractional part is zero.\n\t\t\tif (y == SCALE) {\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t// Calculate the fractional part via the iterative approximation.\n\t\t\t// The \"delta \u003e\u003e= 1\" part is equivalent to \"delta /= 2\", but shifting bits is faster.\n\t\t\tfor (uint256 delta = HALF_SCALE; delta \u003e 0; delta \u003e\u003e= 1) {\n\t\t\t\ty = (y * y) / SCALE;\n\n\t\t\t\t// Is y^2 \u003e 2 and so in the range [2,4)?\n\t\t\t\tif (y \u003e= 2 * SCALE) {\n\t\t\t\t\t// Add the 2^(-m) factor to the logarithm.\n\t\t\t\t\tresult += delta;\n\n\t\t\t\t\t// Corresponds to z/2 on Wikipedia.\n\t\t\t\t\ty \u003e\u003e= 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal\n\t/// fixed-point number.\n\t/// @dev See the documentation for the \"PRBMath.mulDivFixedPoint\" function.\n\t/// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\n\t/// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\n\t/// @return result The product as an unsigned 60.18-decimal fixed-point number.\n\tfunction mul(uint256 x, uint256 y) internal pure returns (uint256 result) {\n\t\tresult = PRBMath.mulDivFixedPoint(x, y);\n\t}\n\n\t/// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.\n\tfunction pi() internal pure returns (uint256 result) {\n\t\tresult = 3_141592653589793238;\n\t}\n\n\t/// @notice Raises x to the power of y.\n\t///\n\t/// @dev Based on the insight that x^y = 2^(log2(x) * y).\n\t///\n\t/// Requirements:\n\t/// - All from \"exp2\", \"log2\" and \"mul\".\n\t///\n\t/// Caveats:\n\t/// - All from \"exp2\", \"log2\" and \"mul\".\n\t/// - Assumes 0^0 is 1.\n\t///\n\t/// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.\n\t/// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.\n\t/// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.\n\tfunction pow(uint256 x, uint256 y) internal pure returns (uint256 result) {\n\t\tif (x == 0) {\n\t\t\tresult = y == 0 ? SCALE : uint256(0);\n\t\t} else {\n\t\t\tresult = exp2(mul(log2(x), y));\n\t\t}\n\t}\n\n\t/// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the\n\t/// famous algorithm \"exponentiation by squaring\".\n\t///\n\t/// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring\n\t///\n\t/// Requirements:\n\t/// - The result must fit within MAX_UD60x18.\n\t///\n\t/// Caveats:\n\t/// - All from \"mul\".\n\t/// - Assumes 0^0 is 1.\n\t///\n\t/// @param x The base as an unsigned 60.18-decimal fixed-point number.\n\t/// @param y The exponent as an uint256.\n\t/// @return result The result as an unsigned 60.18-decimal fixed-point number.\n\tfunction powu(uint256 x, uint256 y) internal pure returns (uint256 result) {\n\t\t// Calculate the first iteration of the loop in advance.\n\t\tresult = y \u0026 1 \u003e 0 ? x : SCALE;\n\n\t\t// Equivalent to \"for(y /= 2; y \u003e 0; y /= 2)\" but faster.\n\t\tfor (y \u003e\u003e= 1; y \u003e 0; y \u003e\u003e= 1) {\n\t\t\tx = PRBMath.mulDivFixedPoint(x, x);\n\n\t\t\t// Equivalent to \"y % 2 == 1\" but faster.\n\t\t\tif (y \u0026 1 \u003e 0) {\n\t\t\t\tresult = PRBMath.mulDivFixedPoint(result, x);\n\t\t\t}\n\t\t}\n\t}\n\n\t/// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.\n\tfunction scale() internal pure returns (uint256 result) {\n\t\tresult = SCALE;\n\t}\n\n\t/// @notice Calculates the square root of x, rounding down.\n\t/// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\n\t///\n\t/// Requirements:\n\t/// - x must be less than MAX_UD60x18 / SCALE.\n\t///\n\t/// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.\n\t/// @return result The result as an unsigned 60.18-decimal fixed-point .\n\tfunction sqrt(uint256 x) internal pure returns (uint256 result) {\n\t\tunchecked {\n\t\t\tif (x \u003e MAX_UD60x18 / SCALE) {\n\t\t\t\trevert PRBMathUD60x18__SqrtOverflow(x);\n\t\t\t}\n\t\t\t// Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned\n\t\t\t// 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).\n\t\t\tresult = PRBMath.sqrt(x * SCALE);\n\t\t}\n\t}\n\n\t/// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.\n\t/// @param x The unsigned 60.18-decimal fixed-point number to convert.\n\t/// @return result The same number in basic integer form.\n\tfunction toUint(uint256 x) internal pure returns (uint256 result) {\n\t\tunchecked {\n\t\t\tresult = x / SCALE;\n\t\t}\n\t}\n}"},"StakingRewards.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.11;\n\nimport \"./WTF.sol\";\nimport \"./ERC20.sol\";\nimport \"./PRBMathUD60x18.sol\";\n\ncontract StakingRewards {\n\n\tusing PRBMathUD60x18 for uint256;\n\n\tuint256 constant private FLOAT_SCALAR = 2**64;\n\tuint256 constant private PERCENT_FEE = 5; // only for WTF staking\n\tuint256 constant private X_TICK = 30 days;\n\n\tstruct User {\n\t\tuint256 deposited;\n\t\tint256 scaledPayout;\n\t}\n\n\tstruct Info {\n\t\tuint256 totalRewards;\n\t\tuint256 startTime;\n\t\tuint256 lastUpdated;\n\t\tuint256 pendingFee;\n\t\tuint256 scaledRewardsPerToken;\n\t\tuint256 totalDeposited;\n\t\tmapping(address =\u003e User) users;\n\t\tWTF wtf;\n\t\tERC20 token;\n\t}\n\tInfo private info;\n\n\n\tevent Deposit(address indexed user, uint256 amount, uint256 fee);\n\tevent Withdraw(address indexed user, uint256 amount, uint256 fee);\n\tevent Claim(address indexed user, uint256 amount);\n\tevent Reinvest(address indexed user, uint256 amount);\n\tevent Reward(uint256 amount);\n\n\n\tconstructor(uint256 _totalRewards, uint256 _stakingRewardsStart, ERC20 _token) {\n\t\tinfo.totalRewards = _totalRewards;\n\t\tinfo.startTime = block.timestamp \u003c _stakingRewardsStart ? _stakingRewardsStart : block.timestamp;\n\t\tinfo.lastUpdated = startTime();\n\t\tinfo.wtf = WTF(msg.sender);\n\t\tinfo.token = _token;\n\t}\n\n\tfunction update() public {\n\t\tuint256 _now = block.timestamp;\n\t\tif (_now \u003e info.lastUpdated \u0026\u0026 totalDeposited() \u003e 0) {\n\t\t\tuint256 _reward = info.totalRewards.mul(_delta(_getX(info.lastUpdated), _getX(_now)));\n\t\t\tif (info.pendingFee \u003e 0) {\n\t\t\t\t_reward += info.pendingFee;\n\t\t\t\tinfo.pendingFee = 0;\n\t\t\t}\n\t\t\tuint256 _balanceBefore = info.wtf.balanceOf(address(this));\n\t\t\tinfo.wtf.claimRewards();\n\t\t\t_reward += info.wtf.balanceOf(address(this)) - _balanceBefore;\n\t\t\tinfo.lastUpdated = _now;\n\t\t\t_disburse(_reward);\n\t\t}\n\t}\n\n\tfunction deposit(uint256 _amount) external {\n\t\tdepositFor(msg.sender, _amount);\n\t}\n\n\tfunction depositFor(address _user, uint256 _amount) public {\n\t\trequire(_amount \u003e 0);\n\t\tupdate();\n\t\tuint256 _balanceBefore = info.token.balanceOf(address(this));\n\t\tinfo.token.transferFrom(msg.sender, address(this), _amount);\n\t\tuint256 _amountReceived = info.token.balanceOf(address(this)) - _balanceBefore;\n\t\t_deposit(_user, _amountReceived);\n\t}\n\n\tfunction tokenCallback(address _from, uint256 _tokens, bytes calldata) external returns (bool) {\n\t\trequire(_isWTF() \u0026\u0026 msg.sender == tokenAddress());\n\t\trequire(_tokens \u003e 0);\n\t\tupdate();\n\t\t_deposit(_from, _tokens);\n\t\treturn true;\n\t}\n\n\tfunction disburse(uint256 _amount) public {\n\t\trequire(_amount \u003e 0);\n\t\tupdate();\n\t\tuint256 _balanceBefore = info.wtf.balanceOf(address(this));\n\t\tinfo.wtf.transferFrom(msg.sender, address(this), _amount);\n\t\tuint256 _amountReceived = info.wtf.balanceOf(address(this)) - _balanceBefore;\n\t\t_processFee(_amountReceived);\n\t}\n\n\tfunction withdrawAll() public {\n\t\tuint256 _deposited = depositedOf(msg.sender);\n\t\tif (_deposited \u003e 0) {\n\t\t\twithdraw(_deposited);\n\t\t}\n\t}\n\n\tfunction withdraw(uint256 _amount) public {\n\t\trequire(_amount \u003e 0 \u0026\u0026 _amount \u003c= depositedOf(msg.sender));\n\t\tupdate();\n\t\tinfo.totalDeposited -= _amount;\n\t\tinfo.users[msg.sender].deposited -= _amount;\n\t\tinfo.users[msg.sender].scaledPayout -= int256(_amount * info.scaledRewardsPerToken);\n\t\tuint256 _fee = _calculateFee(_amount);\n\t\tinfo.token.transfer(msg.sender, _amount - _fee);\n\t\t_processFee(_fee);\n\t\temit Withdraw(msg.sender, _amount, _fee);\n\t}\n\n\tfunction claim() public {\n\t\tupdate();\n\t\tuint256 _rewards = rewardsOf(msg.sender);\n\t\tif (_rewards \u003e 0) {\n\t\t\tinfo.users[msg.sender].scaledPayout += int256(_rewards * FLOAT_SCALAR);\n\t\t\tinfo.wtf.transfer(msg.sender, _rewards);\n\t\t\temit Claim(msg.sender, _rewards);\n\t\t}\n\t}\n\n\tfunction reinvest() public {\n\t\trequire(_isWTF());\n\t\tupdate();\n\t\tuint256 _rewards = rewardsOf(msg.sender);\n\t\tif (_rewards \u003e 0) {\n\t\t\tinfo.users[msg.sender].scaledPayout += int256(_rewards * FLOAT_SCALAR);\n\t\t\t_deposit(msg.sender, _rewards);\n\t\t\temit Reinvest(msg.sender, _rewards);\n\t\t}\n\t}\n\n\t\n\tfunction wtfAddress() public view returns (address) {\n\t\treturn address(info.wtf);\n\t}\n\t\n\tfunction tokenAddress() public view returns (address) {\n\t\treturn address(info.token);\n\t}\n\n\tfunction startTime() public view returns (uint256) {\n\t\treturn info.startTime;\n\t}\n\n\tfunction totalDeposited() public view returns (uint256) {\n\t\treturn info.totalDeposited;\n\t}\n\n\tfunction depositedOf(address _user) public view returns (uint256) {\n\t\treturn info.users[_user].deposited;\n\t}\n\t\n\tfunction rewardsOf(address _user) public view returns (uint256) {\n\t\treturn uint256(int256(info.scaledRewardsPerToken * depositedOf(_user)) - info.users[_user].scaledPayout) / FLOAT_SCALAR;\n\t}\n\t\n\tfunction currentRatePerDay() public view returns (uint256) {\n\t\tif (block.timestamp \u003c startTime()) {\n\t\t\treturn info.totalRewards.mul(_delta(_getX(startTime()), _getX(startTime() + 24 hours)));\n\t\t} else {\n\t\t\treturn info.totalRewards.mul(_delta(_getX(block.timestamp), _getX(block.timestamp + 24 hours)));\n\t\t}\n\t}\n\n\tfunction totalDistributed() public view returns (uint256) {\n\t\treturn info.totalRewards.mul(_sum(_getX(block.timestamp)));\n\t}\n\n\tfunction allInfoFor(address _user) external view returns (uint256 startingTime, uint256 totalRewardsDistributed, uint256 rewardsRatePerDay, uint256 currentFeePercent, uint256 totalTokensDeposited, uint256 virtualRewards, uint256 userWTF, uint256 userBalance, uint256 userAllowance, uint256 userDeposited, uint256 userRewards) {\n\t\tstartingTime = startTime();\n\t\ttotalRewardsDistributed = totalDistributed();\n\t\trewardsRatePerDay = currentRatePerDay();\n\t\tcurrentFeePercent = _calculateFee(1e20);\n\t\ttotalTokensDeposited = totalDeposited();\n\t\tvirtualRewards = block.timestamp \u003e info.lastUpdated ? info.totalRewards.mul(_delta(_getX(info.lastUpdated), _getX(block.timestamp))) : 0;\n\t\tuserWTF = info.wtf.balanceOf(_user);\n\t\tuserBalance = info.token.balanceOf(_user);\n\t\tuserAllowance = info.token.allowance(_user, address(this));\n\t\tuserDeposited = depositedOf(_user);\n\t\tuserRewards = rewardsOf(_user);\n\t}\n\n\t\n\tfunction _deposit(address _user, uint256 _amount) internal {\n\t\tuint256 _fee = _calculateFee(_amount);\n\t\tuint256 _deposited = _amount - _fee;\n\t\tinfo.totalDeposited += _deposited;\n\t\tinfo.users[_user].deposited += _deposited;\n\t\tinfo.users[_user].scaledPayout += int256(_deposited * info.scaledRewardsPerToken);\n\t\t_processFee(_fee);\n\t\temit Deposit(_user, _amount, _fee);\n\t}\n\t\n\tfunction _processFee(uint256 _fee) internal {\n\t\tif (_fee \u003e 0) {\n\t\t\tif (block.timestamp \u003c startTime() || totalDeposited() == 0) {\n\t\t\t\tinfo.pendingFee += _fee;\n\t\t\t} else {\n\t\t\t\t_disburse(_fee);\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction _disburse(uint256 _amount) internal {\n\t\tinfo.scaledRewardsPerToken += _amount * FLOAT_SCALAR / totalDeposited();\n\t\temit Reward(_amount);\n\t}\n\n\n\tfunction _isWTF() internal view returns (bool) {\n\t\treturn wtfAddress() == tokenAddress();\n\t}\n\n\tfunction _calculateFee(uint256 _amount) internal view returns (uint256) {\n\t\treturn _isWTF() ? (_amount * PERCENT_FEE / 100).mul(1e18 - _sum(_getX(block.timestamp))) : 0;\n\t}\n\t\n\tfunction _getX(uint256 t) internal view returns (uint256) {\n\t\tuint256 _start = startTime();\n\t\tif (t \u003c _start) {\n\t\t\treturn 0;\n\t\t} else {\n\t\t\treturn ((t - _start) * 1e18).div(X_TICK * 1e18);\n\t\t}\n\t}\n\n\tfunction _sum(uint256 x) internal pure returns (uint256) {\n\t\tuint256 _e2x = x.exp2();\n\t\treturn (_e2x - 1e18).div(_e2x);\n\t}\n\n\tfunction _delta(uint256 x1, uint256 x2) internal pure returns (uint256) {\n\t\trequire(x2 \u003e= x1);\n\t\treturn _sum(x2) - _sum(x1);\n\t}\n}"},"Treasury.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.11;\n\nimport \"./ERC20.sol\";\nimport \"./WTF.sol\";\nimport \"./StakingRewards.sol\";\n\n\ncontract FeeManager {\n\n\tWTF private wtf;\n\n\tconstructor() {\n\t\twtf = WTF(msg.sender);\n\t}\n\n\tfunction disburse() external {\n\t\twtf.claimRewards();\n\t\tuint256 _balance = wtf.balanceOf(address(this));\n\t\tif (_balance \u003e 0) {\n\t\t\tuint256 _oneFifth = _balance / 5;\n\t\t\tTreasury(payable(wtf.treasuryAddress())).collect();\n\t\t\twtf.transfer(wtf.treasuryAddress(), _oneFifth); // 20%\n\t\t\tStakingRewards(wtf.stakingRewardsAddress()).disburse(_oneFifth); // 20%\n\t\t\tStakingRewards(wtf.lpStakingRewardsAddress()).disburse(3 * _oneFifth); // 60%\n\t\t}\n\t}\n\n\n\tfunction wtfAddress() external view returns (address) {\n\t\treturn address(wtf);\n\t}\n}\n\n\ncontract TeamReferral {\n\treceive() external payable {}\n\tfunction release() external {\n\t\taddress _this = address(this);\n\t\trequire(_this.balance \u003e 0);\n\t\tpayable(0x6129E7bCb71C0d7D4580141C4E6a995f16293F42).transfer(_this.balance / 10); // 10%\n\t\tpayable(0xc9AebdD8fD0d52c35A32fD9155467Cf28Ce474c3).transfer(_this.balance / 3); // 30%\n\t\tpayable(0xdEE79eD62B42e30EA7EbB6f1b7A3f04143D18b7F).transfer(_this.balance / 2); // 30%\n\t\tpayable(0x575446Aa9E9647C40edB7a467e45C5916add1538).transfer(_this.balance); // 30%\n\t}\n}\n\n\ncontract Treasury {\n\n\taddress public owner;\n\tuint256 public lockedUntil;\n\tWTF private wtf;\n\n\tmodifier _onlyOwner() {\n\t\trequire(msg.sender == owner);\n\t\t_;\n\t}\n\n\tconstructor() {\n\t\towner = 0x65dd4990719bE9B20322e4E8D3Bd77a4401a0357;\n\t\tlockedUntil = block.timestamp + 30 days;\n\t\twtf = WTF(msg.sender);\n\t}\n\n\treceive() external payable {}\n\n\tfunction setOwner(address _owner) external _onlyOwner {\n\t\towner = _owner;\n\t}\n\n\tfunction transferETH(address payable _destination, uint256 _amount) external _onlyOwner {\n\t\trequire(isUnlocked());\n\t\t_destination.transfer(_amount);\n\t}\n\n\tfunction transferTokens(ERC20 _token, address _destination, uint256 _amount) external _onlyOwner {\n\t\trequire(isUnlocked());\n\t\t_token.transfer(_destination, _amount);\n\t}\n\n\tfunction collect() external {\n\t\twtf.claimRewards();\n\t}\n\n\n\tfunction isUnlocked() public view returns (bool) {\n\t\treturn block.timestamp \u003e lockedUntil;\n\t}\n\n\tfunction wtfAddress() external view returns (address) {\n\t\treturn address(wtf);\n\t}\n}"},"WTF.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.11;\n\nimport \"./WTFNFT.sol\";\nimport \"./Treasury.sol\";\nimport \"./StakingRewards.sol\";\n\ninterface Callable {\n\tfunction tokenCallback(address _from, uint256 _tokens, bytes calldata _data) external returns (bool);\n}\n\ninterface Router {\n\tfunction WETH() external pure returns (address);\n\tfunction factory() external pure returns (address);\n}\n\ninterface Factory {\n\tfunction createPair(address, address) external returns (address);\n}\n\ninterface Pair {\n\tfunction token0() external view returns (address);\n\tfunction totalSupply() external view returns (uint256);\n\tfunction balanceOf(address) external view returns (uint256);\n\tfunction getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n}\n\n\ncontract WTF {\n\n\tuint256 constant private FLOAT_SCALAR = 2**64;\n\tuint256 constant private UINT_MAX = type(uint256).max;\n\tuint256 constant private TRANSFER_FEE_SCALE = 1000; // 1 = 0.1%\n\tuint256 constant private WTF_STAKING_SUPPLY = 2e25; // 20M WTF\n\tuint256 constant private LP_STAKING_SUPPLY = 4e25; // 40M WTF\n\tuint256 constant private TREASURY_SUPPLY = 4e25; // 40M WTF\n\tuint256 constant private BASE_UPGRADE_COST = 1e19; // 10 WTF\n\tuint256 constant private SERVICE_FEE = 0.01 ether;\n\n\tstring constant public name = \"fees.wtf\";\n\tstring constant public symbol = \"WTF\";\n\tuint8 constant public decimals = 18;\n\n\tstruct User {\n\t\tuint256 balance;\n\t\tmapping(address =\u003e uint256) allowance;\n\t\tint256 scaledPayout;\n\t\tuint256 reflinkLevel;\n\t\tbool unlocked;\n\t}\n\n\tstruct Info {\n\t\tbytes32 merkleRoot;\n\t\tuint256 openingTime;\n\t\tuint256 closingTime;\n\t\tuint256 totalSupply;\n\t\tuint256 scaledRewardsPerToken;\n\t\tmapping(uint256 =\u003e uint256) claimedWTFBitMap;\n\t\tmapping(uint256 =\u003e uint256) claimedNFTBitMap;\n\t\tmapping(address =\u003e User) users;\n\t\tmapping(address =\u003e bool) toWhitelist;\n\t\tmapping(address =\u003e bool) fromWhitelist;\n\t\taddress owner;\n\t\tRouter router;\n\t\tPair pair;\n\t\tbool weth0;\n\t\tWTFNFT nft;\n\t\tTeamReferral team;\n\t\tTreasury treasury;\n\t\tStakingRewards stakingRewards;\n\t\tStakingRewards lpStakingRewards;\n\t\taddress feeManager;\n\t\tuint256 transferFee;\n\t\tuint256 feeManagerPercent;\n\t}\n\tInfo private info;\n\n\n\tevent Transfer(address indexed from, address indexed to, uint256 tokens);\n\tevent Approval(address indexed owner, address indexed spender, uint256 tokens);\n\tevent WhitelistUpdated(address indexed user, bool fromWhitelisted, bool toWhitelisted);\n\tevent ReflinkRewards(address indexed referrer, uint256 amount);\n\tevent ClaimRewards(address indexed user, uint256 amount);\n\tevent Reward(uint256 amount);\n\n\tmodifier _onlyOwner() {\n\t\trequire(msg.sender == owner());\n\t\t_;\n\t}\n\n\n\tconstructor(bytes32 _merkleRoot, uint256 _openingTime, uint256 _stakingRewardsStart) {\n\t\tinfo.merkleRoot = _merkleRoot;\n\t\tinfo.openingTime = block.timestamp \u003c _openingTime ? _openingTime : block.timestamp;\n\t\tinfo.closingTime = openingTime() + 30 days;\n\t\tinfo.router = Router(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);\n\t\tinfo.pair = Pair(Factory(info.router.factory()).createPair(info.router.WETH(), address(this)));\n\t\tinfo.weth0 = info.pair.token0() == info.router.WETH();\n\t\tinfo.transferFee = 40; // 4%\n\t\tinfo.feeManagerPercent = 25; // 25%\n\t\tinfo.owner = 0x65dd4990719bE9B20322e4E8D3Bd77a4401a0357;\n\t\tinfo.nft = new WTFNFT();\n\t\tinfo.team = new TeamReferral();\n\t\tinfo.treasury = new Treasury();\n\t\t_mint(treasuryAddress(), TREASURY_SUPPLY);\n\t\tinfo.stakingRewards = new StakingRewards(WTF_STAKING_SUPPLY, _stakingRewardsStart, ERC20(address(this)));\n\t\t_mint(stakingRewardsAddress(), WTF_STAKING_SUPPLY);\n\t\tinfo.lpStakingRewards = new StakingRewards(LP_STAKING_SUPPLY, _stakingRewardsStart, ERC20(pairAddress()));\n\t\t_mint(lpStakingRewardsAddress(), LP_STAKING_SUPPLY);\n\t\tinfo.feeManager = address(new FeeManager());\n\t\t_approve(feeManagerAddress(), stakingRewardsAddress(), UINT_MAX);\n\t\t_approve(feeManagerAddress(), lpStakingRewardsAddress(), UINT_MAX);\n\t}\n\n\tfunction setOwner(address _owner) external _onlyOwner {\n\t\tinfo.owner = _owner;\n\t}\n\n\tfunction setFeeManager(address _feeManager) external _onlyOwner {\n\t\tinfo.feeManager = _feeManager;\n\t}\n\n\tfunction setClosingTime(uint256 _closingTime) external _onlyOwner {\n\t\tinfo.closingTime = _closingTime;\n\t}\n\n\tfunction setTransferFee(uint256 _transferFee) external _onlyOwner {\n\t\trequire(_transferFee \u003c= 100); // ≤10%\n\t\tinfo.transferFee = _transferFee;\n\t}\n\n\tfunction setFeeManagerPercent(uint256 _feeManagerPercent) external _onlyOwner {\n\t\trequire(_feeManagerPercent \u003c= 100);\n\t\tinfo.feeManagerPercent = _feeManagerPercent;\n\t}\n\n\tfunction setWhitelisted(address _address, bool _fromWhitelisted, bool _toWhitelisted) external _onlyOwner {\n\t\tinfo.fromWhitelist[_address] = _fromWhitelisted;\n\t\tinfo.toWhitelist[_address] = _toWhitelisted;\n\t\temit WhitelistUpdated(_address, _fromWhitelisted, _toWhitelisted);\n\t}\n\n\n\tfunction disburse(uint256 _amount) external {\n\t\trequire(_amount \u003e 0);\n\t\tuint256 _balanceBefore = balanceOf(address(this));\n\t\t_transfer(msg.sender, address(this), _amount);\n\t\tuint256 _amountReceived = balanceOf(address(this)) - _balanceBefore;\n\t\t_disburse(_amountReceived);\n\t}\n\n\tfunction sweep() external {\n\t\tif (address(this).balance \u003e 0) {\n\t\t\tteamAddress().transfer(address(this).balance);\n\t\t}\n\t}\n\n\tfunction upgradeReflink(uint256 _toLevel) external {\n\t\tuint256 _currentLevel = reflinkLevel(msg.sender);\n\t\trequire(_currentLevel \u003c _toLevel);\n\t\tuint256 _totalCost = 0;\n\t\tfor (uint256 i = _currentLevel; i \u003c _toLevel; i++) {\n\t\t\t_totalCost += upgradeCost(i);\n\t\t}\n\t\tburn(_totalCost);\n\t\tinfo.users[msg.sender].reflinkLevel = _toLevel;\n\t}\n\n\tfunction unlock(address _account, address payable _referrer) external payable {\n\t\trequire(block.timestamp \u003c closingTime());\n\t\trequire(!isUnlocked(_account));\n\t\trequire(msg.value == SERVICE_FEE);\n\t\tuint256 _refFee = 0;\n\t\tif (_referrer != address(0x0)) {\n\t\t\t_refFee = SERVICE_FEE * reflinkPercent(_referrer) / 100;\n\t\t\t!_referrer.send(_refFee);\n\t\t\temit ReflinkRewards(_referrer, _refFee);\n\t\t}\n\t\tuint256 _remaining = SERVICE_FEE - _refFee;\n\t\tteamAddress().transfer(_remaining);\n\t\temit ReflinkRewards(teamAddress(), _remaining);\n\t\tinfo.users[_account].unlocked = true;\n\t}\n\t\n\tfunction claim(address _account, uint256[9] calldata _data, bytes32[] calldata _proof) external {\n\t\t// Data array in format: (index, amount, totalFees, failFees, totalGas, avgGwei, totalDonated, totalTxs, failTxs)\n\t\tclaimWTF(_account, _data, _proof);\n\t\tclaimNFT(_account, _data, _proof);\n\t}\n\t\n\tfunction claimWTF(address _account, uint256[9] calldata _data, bytes32[] calldata _proof) public {\n\t\trequire(isOpen());\n\t\trequire(isUnlocked(_account));\n\t\tuint256 _index = _data[0];\n\t\tuint256 _amount = _data[1];\n\t\trequire(!isClaimedWTF(_index));\n\t\trequire(_verify(_proof, keccak256(abi.encodePacked(_account, _data))));\n\t\tuint256 _claimedWordIndex = _index / 256;\n\t\tuint256 _claimedBitIndex = _index % 256;\n\t\tinfo.claimedWTFBitMap[_claimedWordIndex] = info.claimedWTFBitMap[_claimedWordIndex] | (1 \u003c\u003c _claimedBitIndex);\n\t\t_mint(_account, _amount);\n\t}\n\n\tfunction claimNFT(address _account, uint256[9] calldata _data, bytes32[] calldata _proof) public {\n\t\trequire(isOpen());\n\t\trequire(isUnlocked(_account));\n\t\tuint256 _index = _data[0];\n\t\trequire(!isClaimedNFT(_index));\n\t\trequire(_verify(_proof, keccak256(abi.encodePacked(_account, _data))));\n\t\tuint256 _claimedWordIndex = _index / 256;\n\t\tuint256 _claimedBitIndex = _index % 256;\n\t\tinfo.claimedNFTBitMap[_claimedWordIndex] = info.claimedNFTBitMap[_claimedWordIndex] | (1 \u003c\u003c _claimedBitIndex);\n\t\tinfo.nft.mint(_account, _data[2], _data[3], _data[4], _data[5], _data[6], _data[7], _data[8]);\n\t}\n\n\tfunction claimRewards() external {\n\t\tboostRewards();\n\t\tuint256 _rewards = rewardsOf(msg.sender);\n\t\tif (_rewards \u003e 0) {\n\t\t\tinfo.users[msg.sender].scaledPayout += int256(_rewards * FLOAT_SCALAR);\n\t\t\t_transfer(address(this), msg.sender, _rewards);\n\t\t\temit ClaimRewards(msg.sender, _rewards);\n\t\t}\n\t}\n\n\tfunction boostRewards() public {\n\t\taddress _this = address(this);\n\t\tuint256 _rewards = rewardsOf(_this);\n\t\tif (_rewards \u003e 0) {\n\t\t\tinfo.users[_this].scaledPayout += int256(_rewards * FLOAT_SCALAR);\n\t\t\t_disburse(_rewards);\n\t\t\temit ClaimRewards(_this, _rewards);\n\t\t}\n\t}\n\n\tfunction burn(uint256 _tokens) public {\n\t\trequire(balanceOf(msg.sender) \u003e= _tokens);\n\t\tinfo.totalSupply -= _tokens;\n\t\tinfo.users[msg.sender].balance -= _tokens;\n\t\tinfo.users[msg.sender].scaledPayout -= int256(_tokens * info.scaledRewardsPerToken);\n\t\temit Transfer(msg.sender, address(0x0), _tokens);\n\t}\n\n\tfunction transfer(address _to, uint256 _tokens) external returns (bool) {\n\t\treturn _transfer(msg.sender, _to, _tokens);\n\t}\n\n\tfunction approve(address _spender, uint256 _tokens) external returns (bool) {\n\t\treturn _approve(msg.sender, _spender, _tokens);\n\t}\n\n\tfunction transferFrom(address _from, address _to, uint256 _tokens) external returns (bool) {\n\t\tuint256 _allowance = allowance(_from, msg.sender);\n\t\trequire(_allowance \u003e= _tokens);\n\t\tif (_allowance != UINT_MAX) {\n\t\t\tinfo.users[_from].allowance[msg.sender] -= _tokens;\n\t\t}\n\t\treturn _transfer(_from, _to, _tokens);\n\t}\n\n\tfunction transferAndCall(address _to, uint256 _tokens, bytes calldata _data) external returns (bool) {\n\t\tuint256 _balanceBefore = balanceOf(_to);\n\t\t_transfer(msg.sender, _to, _tokens);\n\t\tuint256 _tokensReceived = balanceOf(_to) - _balanceBefore;\n\t\tuint32 _size;\n\t\tassembly {\n\t\t\t_size := extcodesize(_to)\n\t\t}\n\t\tif (_size \u003e 0) {\n\t\t\trequire(Callable(_to).tokenCallback(msg.sender, _tokensReceived, _data));\n\t\t}\n\t\treturn true;\n\t}\n\t\n\n\tfunction pairAddress() public view returns (address) {\n\t\treturn address(info.pair);\n\t}\n\n\tfunction nftAddress() external view returns (address) {\n\t\treturn address(info.nft);\n\t}\n\n\tfunction teamAddress() public view returns (address payable) {\n\t\treturn payable(address(info.team));\n\t}\n\n\tfunction treasuryAddress() public view returns (address) {\n\t\treturn address(info.treasury);\n\t}\n\n\tfunction stakingRewardsAddress() public view returns (address) {\n\t\treturn address(info.stakingRewards);\n\t}\n\n\tfunction lpStakingRewardsAddress() public view returns (address) {\n\t\treturn address(info.lpStakingRewards);\n\t}\n\n\tfunction feeManagerAddress() public view returns (address) {\n\t\treturn info.feeManager;\n\t}\n\n\tfunction owner() public view returns (address) {\n\t\treturn info.owner;\n\t}\n\n\tfunction transferFee() public view returns (uint256) {\n\t\treturn info.transferFee;\n\t}\n\n\tfunction feeManagerPercent() public view returns (uint256) {\n\t\treturn info.feeManagerPercent;\n\t}\n\n\tfunction isFromWhitelisted(address _address) public view returns (bool) {\n\t\treturn info.fromWhitelist[_address];\n\t}\n\n\tfunction isToWhitelisted(address _address) public view returns (bool) {\n\t\treturn info.toWhitelist[_address];\n\t}\n\n\tfunction merkleRoot() public view returns (bytes32) {\n\t\treturn info.merkleRoot;\n\t}\n\n\tfunction openingTime() public view returns (uint256) {\n\t\treturn info.openingTime;\n\t}\n\n\tfunction closingTime() public view returns (uint256) {\n\t\treturn info.closingTime;\n\t}\n\n\tfunction isOpen() public view returns (bool) {\n\t\treturn block.timestamp \u003e openingTime() \u0026\u0026 block.timestamp \u003c closingTime();\n\t}\n\n\tfunction isUnlocked(address _user) public view returns (bool) {\n\t\treturn info.users[_user].unlocked;\n\t}\n\n\tfunction isClaimedWTF(uint256 _index) public view returns (bool) {\n\t\tuint256 _claimedWordIndex = _index / 256;\n\t\tuint256 _claimedBitIndex = _index % 256;\n\t\tuint256 _claimedWord = info.claimedWTFBitMap[_claimedWordIndex];\n\t\tuint256 _mask = (1 \u003c\u003c _claimedBitIndex);\n\t\treturn _claimedWord \u0026 _mask == _mask;\n\t}\n\n\tfunction isClaimedNFT(uint256 _index) public view returns (bool) {\n\t\tuint256 _claimedWordIndex = _index / 256;\n\t\tuint256 _claimedBitIndex = _index % 256;\n\t\tuint256 _claimedWord = info.claimedNFTBitMap[_claimedWordIndex];\n\t\tuint256 _mask = (1 \u003c\u003c _claimedBitIndex);\n\t\treturn _claimedWord \u0026 _mask == _mask;\n\t}\n\t\n\tfunction totalSupply() public view returns (uint256) {\n\t\treturn info.totalSupply;\n\t}\n\n\tfunction balanceOf(address _user) public view returns (uint256) {\n\t\treturn info.users[_user].balance;\n\t}\n\n\tfunction rewardsOf(address _user) public view returns (uint256) {\n\t\treturn uint256(int256(info.scaledRewardsPerToken * balanceOf(_user)) - info.users[_user].scaledPayout) / FLOAT_SCALAR;\n\t}\n\n\tfunction allowance(address _user, address _spender) public view returns (uint256) {\n\t\treturn info.users[_user].allowance[_spender];\n\t}\n\n\tfunction reflinkLevel(address _user) public view returns (uint256) {\n\t\treturn info.users[_user].reflinkLevel;\n\t}\n\n\tfunction reflinkPercent(address _user) public view returns (uint256) {\n\t\treturn 10 * (reflinkLevel(_user) + 1);\n\t}\n\n\tfunction upgradeCost(uint256 _reflinkLevel) public pure returns (uint256) {\n\t\trequire(_reflinkLevel \u003c 4);\n\t\treturn BASE_UPGRADE_COST * 10**_reflinkLevel;\n\t}\n\n\tfunction reflinkInfoFor(address _user) external view returns (uint256 balance, uint256 level, uint256 percent) {\n\t\treturn (balanceOf(_user), reflinkLevel(_user), reflinkPercent(_user));\n\t}\n\n\tfunction claimInfoFor(uint256 _index, address _user) external view returns (uint256 openTime, uint256 closeTime, bool unlocked, bool claimedWTF, bool claimedNFT, uint256 wethReserve, uint256 wtfReserve) {\n\t\topenTime = openingTime();\n\t\tcloseTime = closingTime();\n\t\tunlocked = isUnlocked(_user);\n\t\tclaimedWTF = isClaimedWTF(_index);\n\t\tclaimedNFT = isClaimedNFT(_index);\n\t\t( , , wethReserve, wtfReserve, , , ) = allInfoFor(address(0x0));\n\t}\n\n\tfunction allInfoFor(address _user) public view returns (uint256 totalTokens, uint256 totalLPTokens, uint256 wethReserve, uint256 wtfReserve, uint256 userBalance, uint256 userRewards, uint256 userLPBalance) {\n\t\ttotalTokens = totalSupply();\n\t\ttotalLPTokens = info.pair.totalSupply();\n\t\t(uint256 _res0, uint256 _res1, ) = info.pair.getReserves();\n\t\twethReserve = info.weth0 ? _res0 : _res1;\n\t\twtfReserve = info.weth0 ? _res1 : _res0;\n\t\tuserBalance = balanceOf(_user);\n\t\tuserRewards = rewardsOf(_user);\n\t\tuserLPBalance = info.pair.balanceOf(_user);\n\t}\n\n\n\tfunction _mint(address _account, uint256 _amount) internal {\n\t\tinfo.totalSupply += _amount;\n\t\tinfo.users[_account].balance += _amount;\n\t\tinfo.users[_account].scaledPayout += int256(_amount * info.scaledRewardsPerToken);\n\t\temit Transfer(address(0x0), _account, _amount);\n\t}\n\t\n\tfunction _approve(address _owner, address _spender, uint256 _tokens) internal returns (bool) {\n\t\tinfo.users[_owner].allowance[_spender] = _tokens;\n\t\temit Approval(_owner, _spender, _tokens);\n\t\treturn true;\n\t}\n\t\n\tfunction _transfer(address _from, address _to, uint256 _tokens) internal returns (bool) {\n\t\trequire(balanceOf(_from) \u003e= _tokens);\n\t\tinfo.users[_from].balance -= _tokens;\n\t\tinfo.users[_from].scaledPayout -= int256(_tokens * info.scaledRewardsPerToken);\n\t\tuint256 _fee = 0;\n\t\tif (!_isExcludedFromFee(_from, _to)) {\n\t\t\t_fee = _tokens * transferFee() / TRANSFER_FEE_SCALE;\n\t\t\taddress _this = address(this);\n\t\t\tinfo.users[_this].balance += _fee;\n\t\t\tinfo.users[_this].scaledPayout += int256(_fee * info.scaledRewardsPerToken);\n\t\t\temit Transfer(_from, _this, _fee);\n\t\t}\n\t\tuint256 _transferred = _tokens - _fee;\n\t\tinfo.users[_to].balance += _transferred;\n\t\tinfo.users[_to].scaledPayout += int256(_transferred * info.scaledRewardsPerToken);\n\t\temit Transfer(_from, _to, _transferred);\n\t\tif (_fee \u003e 0) {\n\t\t\tuint256 _feeManagerRewards = _fee * feeManagerPercent() / 100;\n\t\t\tinfo.users[feeManagerAddress()].scaledPayout -= int256(_feeManagerRewards * FLOAT_SCALAR);\n\t\t\t_disburse(_fee - _feeManagerRewards);\n\t\t}\n\t\treturn true;\n\t}\n\n\tfunction _disburse(uint256 _amount) internal {\n\t\tif (_amount \u003e 0) {\n\t\t\tinfo.scaledRewardsPerToken += _amount * FLOAT_SCALAR / totalSupply();\n\t\t\temit Reward(_amount);\n\t\t}\n\t}\n\n\n\tfunction _isExcludedFromFee(address _from, address _to) internal view returns (bool) {\n\t\treturn isFromWhitelisted(_from) || isToWhitelisted(_to)\n\t\t\t|| _from == address(this) || _to == address(this)\n\t\t\t|| _from == feeManagerAddress() || _to == feeManagerAddress()\n\t\t\t|| _from == treasuryAddress() || _to == treasuryAddress()\n\t\t\t|| _from == stakingRewardsAddress() || _to == stakingRewardsAddress()\n\t\t\t|| _from == lpStakingRewardsAddress() || _to == lpStakingRewardsAddress();\n\t}\n\t\n\tfunction _verify(bytes32[] memory _proof, bytes32 _leaf) internal view returns (bool) {\n\t\tbytes32 _computedHash = _leaf;\n\t\tfor (uint256 i = 0; i \u003c _proof.length; i++) {\n\t\t\tbytes32 _proofElement = _proof[i];\n\t\t\tif (_computedHash \u003c= _proofElement) {\n\t\t\t\t_computedHash = keccak256(abi.encodePacked(_computedHash, _proofElement));\n\t\t\t} else {\n\t\t\t\t_computedHash = keccak256(abi.encodePacked(_proofElement, _computedHash));\n\t\t\t}\n\t\t}\n\t\treturn _computedHash == merkleRoot();\n\t}\n}"},"WTFNFT.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.11;\n\nimport \"./Metadata.sol\";\n\ninterface Receiver {\n\tfunction onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external returns (bytes4);\n}\n\n\ncontract WTFNFT {\n\n\tstruct User {\n\t\tuint256 balance;\n\t\tmapping(uint256 =\u003e uint256) list;\n\t\tmapping(address =\u003e bool) approved;\n\t\tmapping(uint256 =\u003e uint256) indexOf;\n\t\tuint256 tokenIndex;\n\t}\n\n\tstruct Token {\n\t\taddress user;\n\t\taddress owner;\n\t\taddress approved;\n\t\tuint128 totalFees;\n\t\tuint128 failFees;\n\t\tuint128 totalGas;\n\t\tuint128 avgGwei;\n\t\tuint128 totalDonated;\n\t\tuint64 totalTxs;\n\t\tuint64 failTxs;\n\t}\n\n\tstruct Info {\n\t\tuint256 totalSupply;\n\t\tmapping(uint256 =\u003e Token) list;\n\t\tmapping(address =\u003e User) users;\n\t\tMetadata metadata;\n\t\taddress wtf;\n\t\taddress owner;\n\t}\n\tInfo private info;\n\n\tmapping(bytes4 =\u003e bool) public supportsInterface;\n\n\tevent Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\tevent Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\tevent ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\tevent Mint(address indexed owner, uint256 indexed tokenId, uint256 totalFees, uint256 failFees, uint256 totalGas, uint256 avgGwei, uint256 totalDonated, uint256 totalTxs, uint256 failTxs);\n\n\n\tmodifier _onlyOwner() {\n\t\trequire(msg.sender == owner());\n\t\t_;\n\t}\n\n\n\tconstructor() {\n\t\tinfo.metadata = new Metadata(this);\n\t\tinfo.wtf = msg.sender;\n\t\tinfo.owner = 0xdEE79eD62B42e30EA7EbB6f1b7A3f04143D18b7F;\n\t\tsupportsInterface[0x01ffc9a7] = true; // ERC-165\n\t\tsupportsInterface[0x80ac58cd] = true; // ERC-721\n\t\tsupportsInterface[0x5b5e139f] = true; // Metadata\n\t\tsupportsInterface[0x780e9d63] = true; // Enumerable\n\t}\n\n\tfunction setOwner(address _owner) external _onlyOwner {\n\t\tinfo.owner = _owner;\n\t}\n\n\tfunction setMetadata(Metadata _metadata) external _onlyOwner {\n\t\tinfo.metadata = _metadata;\n\t}\n\n\t\n\tfunction mint(address _receiver, uint256 _totalFees, uint256 _failFees, uint256 _totalGas, uint256 _avgGwei, uint256 _totalDonated, uint256 _totalTxs, uint256 _failTxs) public {\n\t\trequire(msg.sender == wtfAddress());\n\t\tuint256 _tokenId = info.totalSupply++;\n\t\tinfo.users[_receiver].tokenIndex = totalSupply();\n\t\tToken storage _newToken = info.list[_tokenId];\n\t\t_newToken.user = _receiver;\n\t\t_newToken.owner = _receiver;\n\t\t_newToken.totalFees = uint128(_totalFees);\n\t\t_newToken.failFees = uint128(_failFees);\n\t\t_newToken.totalGas = uint128(_totalGas);\n\t\t_newToken.avgGwei = uint128(_avgGwei);\n\t\t_newToken.totalDonated = uint128(_totalDonated);\n\t\t_newToken.totalTxs = uint64(_totalTxs);\n\t\t_newToken.failTxs = uint64(_failTxs);\n\t\tuint256 _index = info.users[_receiver].balance++;\n\t\tinfo.users[_receiver].indexOf[_tokenId] = _index + 1;\n\t\tinfo.users[_receiver].list[_index] = _tokenId;\n\t\temit Transfer(address(0x0), _receiver, _tokenId);\n\t\temit Mint(_receiver, _tokenId, _totalFees, _failFees, _totalGas, _avgGwei, _totalDonated, _totalTxs, _failTxs);\n\t}\n\t\n\tfunction approve(address _approved, uint256 _tokenId) external {\n\t\trequire(msg.sender == ownerOf(_tokenId));\n\t\tinfo.list[_tokenId].approved = _approved;\n\t\temit Approval(msg.sender, _approved, _tokenId);\n\t}\n\n\tfunction setApprovalForAll(address _operator, bool _approved) external {\n\t\tinfo.users[msg.sender].approved[_operator] = _approved;\n\t\temit ApprovalForAll(msg.sender, _operator, _approved);\n\t}\n\n\tfunction transferFrom(address _from, address _to, uint256 _tokenId) external {\n\t\t_transfer(_from, _to, _tokenId);\n\t}\n\n\tfunction safeTransferFrom(address _from, address _to, uint256 _tokenId) external {\n\t\tsafeTransferFrom(_from, _to, _tokenId, \"\");\n\t}\n\n\tfunction safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) public {\n\t\t_transfer(_from, _to, _tokenId);\n\t\tuint32 _size;\n\t\tassembly {\n\t\t\t_size := extcodesize(_to)\n\t\t}\n\t\tif (_size \u003e 0) {\n\t\t\trequire(Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) == 0x150b7a02);\n\t\t}\n\t}\n\n\n\tfunction name() external view returns (string memory) {\n\t\treturn info.metadata.name();\n\t}\n\n\tfunction symbol() external view returns (string memory) {\n\t\treturn info.metadata.symbol();\n\t}\n\n\tfunction tokenURI(uint256 _tokenId) external view returns (string memory) {\n\t\treturn info.metadata.tokenURI(_tokenId);\n\t}\n\n\tfunction metadataAddress() public view returns (address) {\n\t\treturn address(info.metadata);\n\t}\n\n\tfunction wtfAddress() public view returns (address) {\n\t\treturn info.wtf;\n\t}\n\n\tfunction owner() public view returns (address) {\n\t\treturn info.owner;\n\t}\n\n\tfunction totalSupply() public view returns (uint256) {\n\t\treturn info.totalSupply;\n\t}\n\n\tfunction balanceOf(address _owner) public view returns (uint256) {\n\t\treturn info.users[_owner].balance;\n\t}\n\n\tfunction ownerOf(uint256 _tokenId) public view returns (address) {\n\t\trequire(_tokenId \u003c totalSupply());\n\t\treturn info.list[_tokenId].owner;\n\t}\n\n\tfunction getUser(uint256 _tokenId) public view returns (address) {\n\t\trequire(_tokenId \u003c totalSupply());\n\t\treturn info.list[_tokenId].user;\n\t}\n\n\tfunction getApproved(uint256 _tokenId) public view returns (address) {\n\t\trequire(_tokenId \u003c totalSupply());\n\t\treturn info.list[_tokenId].approved;\n\t}\n\n\tfunction getTotalFees(uint256 _tokenId) public view returns (uint256) {\n\t\trequire(_tokenId \u003c totalSupply());\n\t\treturn info.list[_tokenId].totalFees;\n\t}\n\n\tfunction getFailFees(uint256 _tokenId) public view returns (uint256) {\n\t\trequire(_tokenId \u003c totalSupply());\n\t\treturn info.list[_tokenId].failFees;\n\t}\n\n\tfunction getTotalGas(uint256 _tokenId) public view returns (uint256) {\n\t\trequire(_tokenId \u003c totalSupply());\n\t\treturn info.list[_tokenId].totalGas;\n\t}\n\n\tfunction getAvgGwei(uint256 _tokenId) public view returns (uint256) {\n\t\trequire(_tokenId \u003c totalSupply());\n\t\treturn info.list[_tokenId].avgGwei;\n\t}\n\n\tfunction getTotalDonated(uint256 _tokenId) public view returns (uint256) {\n\t\trequire(_tokenId \u003c totalSupply());\n\t\treturn info.list[_tokenId].totalDonated;\n\t}\n\n\tfunction getTotalTxs(uint256 _tokenId) public view returns (uint256) {\n\t\trequire(_tokenId \u003c totalSupply());\n\t\treturn info.list[_tokenId].totalTxs;\n\t}\n\n\tfunction getFailTxs(uint256 _tokenId) public view returns (uint256) {\n\t\trequire(_tokenId \u003c totalSupply());\n\t\treturn info.list[_tokenId].failTxs;\n\t}\n\n\tfunction isApprovedForAll(address _owner, address _operator) public view returns (bool) {\n\t\treturn info.users[_owner].approved[_operator];\n\t}\n\n\tfunction tokenIdOf(address _user) public view returns (uint256) {\n\t\tuint256 _index = info.users[_user].tokenIndex;\n\t\trequire(_index \u003e 0);\n\t\treturn _index - 1;\n\t}\n\n\tfunction tokenByIndex(uint256 _index) public view returns (uint256) {\n\t\trequire(_index \u003c totalSupply());\n\t\treturn _index;\n\t}\n\n\tfunction tokenOfOwnerByIndex(address _owner, uint256 _index) public view returns (uint256) {\n\t\trequire(_index \u003c balanceOf(_owner));\n\t\treturn info.users[_owner].list[_index];\n\t}\n\n\tfunction getTokenCompressedInfo(uint256 _tokenId) public view returns (uint256[7] memory compressedInfo) {\n\t\tcompressedInfo[0] = getTotalFees(_tokenId);\n\t\tcompressedInfo[1] = getFailFees(_tokenId);\n\t\tcompressedInfo[2] = getTotalGas(_tokenId);\n\t\tcompressedInfo[3] = getAvgGwei(_tokenId);\n\t\tcompressedInfo[4] = getTotalDonated(_tokenId);\n\t\tcompressedInfo[5] = getTotalTxs(_tokenId);\n\t\tcompressedInfo[6] = getFailTxs(_tokenId);\n\t}\n\n\tfunction getToken(uint256 _tokenId) public view returns (address tokenOwner, address approved, address user, uint256[7] memory compressedInfo) {\n\t\treturn (ownerOf(_tokenId), getApproved(_tokenId), getUser(_tokenId), getTokenCompressedInfo(_tokenId));\n\t}\n\n\tfunction getTokens(uint256[] memory _tokenIds) public view returns (address[] memory owners, address[] memory approveds, address[] memory users, uint256[7][] memory compressedInfos) {\n\t\tuint256 _length = _tokenIds.length;\n\t\towners = new address[](_length);\n\t\tapproveds = new address[](_length);\n\t\tusers = new address[](_length);\n\t\tcompressedInfos = new uint256[7][](_length);\n\t\tfor (uint256 i = 0; i \u003c _length; i++) {\n\t\t\t(owners[i], approveds[i], users[i], compressedInfos[i]) = getToken(_tokenIds[i]);\n\t\t}\n\t}\n\n\tfunction getTokensTable(uint256 _limit, uint256 _page, bool _isAsc) public view returns (uint256[] memory tokenIds, address[] memory owners, address[] memory approveds, address[] memory users, uint256[7][] memory compressedInfos, uint256 totalTokens, uint256 totalPages) {\n\t\trequire(_limit \u003e 0);\n\t\ttotalTokens = totalSupply();\n\n\t\tif (totalTokens \u003e 0) {\n\t\t\ttotalPages = (totalTokens / _limit) + (totalTokens % _limit == 0 ? 0 : 1);\n\t\t\trequire(_page \u003c totalPages);\n\n\t\t\tuint256 _offset = _limit * _page;\n\t\t\tif (_page == totalPages - 1 \u0026\u0026 totalTokens % _limit != 0) {\n\t\t\t\t_limit = totalTokens % _limit;\n\t\t\t}\n\n\t\t\ttokenIds = new uint256[](_limit);\n\t\t\tfor (uint256 i = 0; i \u003c _limit; i++) {\n\t\t\t\ttokenIds[i] = tokenByIndex(_isAsc ? _offset + i : totalTokens - _offset - i - 1);\n\t\t\t}\n\t\t} else {\n\t\t\ttotalPages = 0;\n\t\t\ttokenIds = new uint256[](0);\n\t\t}\n\t\t(owners, approveds, users, compressedInfos) = getTokens(tokenIds);\n\t}\n\n\tfunction getOwnerTokensTable(address _owner, uint256 _limit, uint256 _page, bool _isAsc) public view returns (uint256[] memory tokenIds, address[] memory approveds, address[] memory users, uint256[7][] memory compressedInfos, uint256 totalTokens, uint256 totalPages) {\n\t\trequire(_limit \u003e 0);\n\t\ttotalTokens = balanceOf(_owner);\n\n\t\tif (totalTokens \u003e 0) {\n\t\t\ttotalPages = (totalTokens / _limit) + (totalTokens % _limit == 0 ? 0 : 1);\n\t\t\trequire(_page \u003c totalPages);\n\n\t\t\tuint256 _offset = _limit * _page;\n\t\t\tif (_page == totalPages - 1 \u0026\u0026 totalTokens % _limit != 0) {\n\t\t\t\t_limit = totalTokens % _limit;\n\t\t\t}\n\n\t\t\ttokenIds = new uint256[](_limit);\n\t\t\tfor (uint256 i = 0; i \u003c _limit; i++) {\n\t\t\t\ttokenIds[i] = tokenOfOwnerByIndex(_owner, _isAsc ? _offset + i : totalTokens - _offset - i - 1);\n\t\t\t}\n\t\t} else {\n\t\t\ttotalPages = 0;\n\t\t\ttokenIds = new uint256[](0);\n\t\t}\n\t\t( , approveds, users, compressedInfos) = getTokens(tokenIds);\n\t}\n\n\tfunction allInfoFor(address _owner) external view returns (uint256 supply, uint256 ownerBalance) {\n\t\treturn (totalSupply(), balanceOf(_owner));\n\t}\n\n\t\n\tfunction _transfer(address _from, address _to, uint256 _tokenId) internal {\n\t\taddress _owner = ownerOf(_tokenId);\n\t\taddress _approved = getApproved(_tokenId);\n\t\trequire(_from == _owner);\n\t\trequire(msg.sender == _owner || msg.sender == _approved || isApprovedForAll(_owner, msg.sender));\n\n\t\tinfo.list[_tokenId].owner = _to;\n\t\tif (_approved != address(0x0)) {\n\t\t\tinfo.list[_tokenId].approved = address(0x0);\n\t\t\temit Approval(address(0x0), address(0x0), _tokenId);\n\t\t}\n\n\t\tuint256 _index = info.users[_from].indexOf[_tokenId] - 1;\n\t\tuint256 _moved = info.users[_from].list[info.users[_from].balance - 1];\n\t\tinfo.users[_from].list[_index] = _moved;\n\t\tinfo.users[_from].indexOf[_moved] = _index + 1;\n\t\tinfo.users[_from].balance--;\n\t\tdelete info.users[_from].indexOf[_tokenId];\n\t\tuint256 _newIndex = info.users[_to].balance++;\n\t\tinfo.users[_to].indexOf[_tokenId] = _newIndex + 1;\n\t\tinfo.users[_to].list[_newIndex] = _tokenId;\n\t\temit Transfer(_from, _to, _tokenId);\n\t}\n}\n"}}