Contract Overview
Balance:
0 ETH
ETH Value:
$0.00
My Name Tag:
Not Available
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0x5fd0a0df5ee742f304e2795911c6b4bc66ff97f120245453582505b384962dd1 | 0x60806040 | 59828811 | 412 days 6 hrs ago | 0xc0de123d0ca961a3ea9d2d29e015ce74d3ec124f | IN | Create: MagicDomainRegistrarController | 0 ETH | 0.00176605 |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
MagicDomainRegistrarController
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.22 <0.9.0; /// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should /// use `int256` and `uint256`. This modified version fixes that. This version is recommended /// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in /// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`. /// Reference: https://github.com/NomicFoundation/hardhat/issues/2178 library console2 { address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); function _sendLogPayload(bytes memory payload) private view { uint256 payloadLength = payload.length; address consoleAddress = CONSOLE_ADDRESS; /// @solidity memory-safe-assembly assembly { let payloadStart := add(payload, 32) let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) } } function log() internal view { _sendLogPayload(abi.encodeWithSignature("log()")); } function logInt(int256 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); } function logUint(uint256 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); } function logString(string memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function logBool(bool p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function logAddress(address p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function logBytes(bytes memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); } function logBytes1(bytes1 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); } function logBytes2(bytes2 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); } function logBytes3(bytes3 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); } function logBytes4(bytes4 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); } function logBytes5(bytes5 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); } function logBytes6(bytes6 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); } function logBytes7(bytes7 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); } function logBytes8(bytes8 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); } function logBytes9(bytes9 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); } function logBytes10(bytes10 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); } function logBytes11(bytes11 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); } function logBytes12(bytes12 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); } function logBytes13(bytes13 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); } function logBytes14(bytes14 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); } function logBytes15(bytes15 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); } function logBytes16(bytes16 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); } function logBytes17(bytes17 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); } function logBytes18(bytes18 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); } function logBytes19(bytes19 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); } function logBytes20(bytes20 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); } function logBytes21(bytes21 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); } function logBytes22(bytes22 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); } function logBytes23(bytes23 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); } function logBytes24(bytes24 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); } function logBytes25(bytes25 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); } function logBytes26(bytes26 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); } function logBytes27(bytes27 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); } function logBytes28(bytes28 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); } function logBytes29(bytes29 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); } function logBytes30(bytes30 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); } function logBytes31(bytes31 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); } function logBytes32(bytes32 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); } function log(uint256 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); } function log(int256 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); } function log(string memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function log(bool p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function log(address p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function log(uint256 p0, uint256 p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1)); } function log(uint256 p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1)); } function log(uint256 p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1)); } function log(uint256 p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1)); } function log(string memory p0, uint256 p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); } function log(string memory p0, int256 p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1)); } function log(string memory p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); } function log(string memory p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); } function log(string memory p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); } function log(bool p0, uint256 p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1)); } function log(bool p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); } function log(bool p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); } function log(bool p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); } function log(address p0, uint256 p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1)); } function log(address p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); } function log(address p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); } function log(address p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); } function log(uint256 p0, uint256 p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2)); } function log(uint256 p0, string memory p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2)); } function log(uint256 p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2)); } function log(uint256 p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2)); } function log(uint256 p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2)); } function log(uint256 p0, bool p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2)); } function log(uint256 p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2)); } function log(uint256 p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2)); } function log(uint256 p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2)); } function log(uint256 p0, address p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2)); } function log(uint256 p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2)); } function log(uint256 p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2)); } function log(uint256 p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2)); } function log(string memory p0, uint256 p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2)); } function log(string memory p0, uint256 p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2)); } function log(string memory p0, uint256 p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2)); } function log(string memory p0, uint256 p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2)); } function log(string memory p0, string memory p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2)); } function log(string memory p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); } function log(string memory p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); } function log(string memory p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); } function log(string memory p0, bool p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2)); } function log(string memory p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); } function log(string memory p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); } function log(string memory p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); } function log(string memory p0, address p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2)); } function log(string memory p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); } function log(string memory p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); } function log(string memory p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); } function log(bool p0, uint256 p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2)); } function log(bool p0, uint256 p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2)); } function log(bool p0, uint256 p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2)); } function log(bool p0, uint256 p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2)); } function log(bool p0, string memory p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2)); } function log(bool p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); } function log(bool p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); } function log(bool p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); } function log(bool p0, bool p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2)); } function log(bool p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); } function log(bool p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); } function log(bool p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); } function log(bool p0, address p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2)); } function log(bool p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); } function log(bool p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); } function log(bool p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); } function log(address p0, uint256 p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2)); } function log(address p0, uint256 p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2)); } function log(address p0, uint256 p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2)); } function log(address p0, uint256 p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2)); } function log(address p0, string memory p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2)); } function log(address p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); } function log(address p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); } function log(address p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); } function log(address p0, bool p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2)); } function log(address p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); } function log(address p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); } function log(address p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); } function log(address p0, address p1, uint256 p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2)); } function log(address p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); } function log(address p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); } function log(address p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, uint256 p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Internal function that returns the initialized version. Returns `_initialized` */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Internal function that returns the initialized version. Returns `_initializing` */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/MathUpgradeable.sol"; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = MathUpgradeable.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, MathUpgradeable.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../StringsUpgradeable.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSAUpgradeable { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", StringsUpgradeable.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./ECDSAUpgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ * * @custom:storage-size 52 */ abstract contract EIP712Upgradeable is Initializable { /* solhint-disable var-name-mixedcase */ bytes32 private _HASHED_NAME; bytes32 private _HASHED_VERSION; bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ function __EIP712_init(string memory name, string memory version) internal onlyInitializing { __EIP712_init_unchained(name, version); } function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash()); } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev The hash of the name parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712NameHash() internal virtual view returns (bytes32) { return _HASHED_NAME; } /** * @dev The hash of the version parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712VersionHash() internal virtual view returns (bytes32) { return _HASHED_VERSION; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // EIP-712 is Final as of 2022-08-11. This file is deprecated. import "./EIP712Upgradeable.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library MathUpgradeable { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; /// Common mathematical functions used in both SD59x18 and UD60x18. Note that these global functions do not /// always operate with SD59x18 and UD60x18 numbers. /*////////////////////////////////////////////////////////////////////////// CUSTOM ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Emitted when the ending result in the fixed-point version of `mulDiv` would overflow uint256. error PRBMath_MulDiv18_Overflow(uint256 x, uint256 y); /// @notice Emitted when the ending result in `mulDiv` would overflow uint256. error PRBMath_MulDiv_Overflow(uint256 x, uint256 y, uint256 denominator); /// @notice Emitted when attempting to run `mulDiv` with one of the inputs `type(int256).min`. error PRBMath_MulDivSigned_InputTooSmall(); /// @notice Emitted when the ending result in the signed version of `mulDiv` would overflow int256. error PRBMath_MulDivSigned_Overflow(int256 x, int256 y); /*////////////////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////////////////*/ /// @dev The maximum value an uint128 number can have. uint128 constant MAX_UINT128 = type(uint128).max; /// @dev The maximum value an uint40 number can have. uint40 constant MAX_UINT40 = type(uint40).max; /// @dev How many trailing decimals can be represented. uint256 constant UNIT = 1e18; /// @dev Largest power of two that is a divisor of `UNIT`. uint256 constant UNIT_LPOTD = 262144; /// @dev The `UNIT` number inverted mod 2^256. uint256 constant UNIT_INVERSE = 78156646155174841979727994598816262306175212592076161876661_508869554232690281; /*////////////////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice Finds the zero-based index of the first one in the binary representation of x. /// @dev See the note on msb in the "Find First Set" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set /// /// Each of the steps in this implementation is equivalent to this high-level code: /// /// ```solidity /// if (x >= 2 ** 128) { /// x >>= 128; /// result += 128; /// } /// ``` /// /// Where 128 is swapped with each respective power of two factor. See the full high-level implementation here: /// https://gist.github.com/PaulRBerg/f932f8693f2733e30c4d479e8e980948 /// /// A list of the Yul instructions used below: /// - "gt" is "greater than" /// - "or" is the OR bitwise operator /// - "shl" is "shift left" /// - "shr" is "shift right" /// /// @param x The uint256 number for which to find the index of the most significant bit. /// @return result The index of the most significant bit as an uint256. function msb(uint256 x) pure returns (uint256 result) { // 2^128 assembly ("memory-safe") { let factor := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^64 assembly ("memory-safe") { let factor := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^32 assembly ("memory-safe") { let factor := shl(5, gt(x, 0xFFFFFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^16 assembly ("memory-safe") { let factor := shl(4, gt(x, 0xFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^8 assembly ("memory-safe") { let factor := shl(3, gt(x, 0xFF)) x := shr(factor, x) result := or(result, factor) } // 2^4 assembly ("memory-safe") { let factor := shl(2, gt(x, 0xF)) x := shr(factor, x) result := or(result, factor) } // 2^2 assembly ("memory-safe") { let factor := shl(1, gt(x, 0x3)) x := shr(factor, x) result := or(result, factor) } // 2^1 // No need to shift x any more. assembly ("memory-safe") { let factor := gt(x, 0x1) result := or(result, factor) } } /// @notice Calculates floor(x*y÷denominator) with full precision. /// /// @dev Credits to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv. /// /// Requirements: /// - The denominator cannot be zero. /// - The result must fit within uint256. /// /// Caveats: /// - This function does not work with fixed-point numbers. /// /// @param x The multiplicand as an uint256. /// @param y The multiplier as an uint256. /// @param denominator The divisor as an uint256. /// @return result The result as an uint256. function mulDiv(uint256 x, uint256 y, uint256 denominator) pure returns (uint256 result) { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly ("memory-safe") { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { unchecked { return prod0 / denominator; } } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (prod1 >= denominator) { revert PRBMath_MulDiv_Overflow(x, y, denominator); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly ("memory-safe") { // Compute remainder using the mulmod Yul instruction. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. unchecked { // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 lpotdod = denominator & (~denominator + 1); assembly ("memory-safe") { // Divide denominator by lpotdod. denominator := div(denominator, lpotdod) // Divide [prod1 prod0] by lpotdod. prod0 := div(prod0, lpotdod) // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one. lpotdod := add(div(sub(0, lpotdod), lpotdod), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * lpotdod; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; } } /// @notice Calculates floor(x*y÷1e18) with full precision. /// /// @dev Variant of `mulDiv` with constant folding, i.e. in which the denominator is always 1e18. Before returning the /// final result, we add 1 if `(x * y) % UNIT >= HALF_UNIT`. Without this adjustment, 6.6e-19 would be truncated to 0 /// instead of being rounded to 1e-18. See "Listing 6" and text above it at https://accu.org/index.php/journals/1717. /// /// Requirements: /// - The result must fit within uint256. /// /// Caveats: /// - The body is purposely left uncommented; to understand how this works, see the NatSpec comments in `mulDiv`. /// - It is assumed that the result can never be `type(uint256).max` when x and y solve the following two equations: /// 1. x * y = type(uint256).max * UNIT /// 2. (x * y) % UNIT >= UNIT / 2 /// /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number. /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number. /// @return result The result as an unsigned 60.18-decimal fixed-point number. function mulDiv18(uint256 x, uint256 y) pure returns (uint256 result) { uint256 prod0; uint256 prod1; assembly ("memory-safe") { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } if (prod1 >= UNIT) { revert PRBMath_MulDiv18_Overflow(x, y); } uint256 remainder; assembly ("memory-safe") { remainder := mulmod(x, y, UNIT) } if (prod1 == 0) { unchecked { return prod0 / UNIT; } } assembly ("memory-safe") { result := mul( or( div(sub(prod0, remainder), UNIT_LPOTD), mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1)) ), UNIT_INVERSE ) } } /// @notice Calculates floor(x*y÷denominator) with full precision. /// /// @dev An extension of `mulDiv` for signed numbers. Works by computing the signs and the absolute values separately. /// /// Requirements: /// - None of the inputs can be `type(int256).min`. /// - The result must fit within int256. /// /// @param x The multiplicand as an int256. /// @param y The multiplier as an int256. /// @param denominator The divisor as an int256. /// @return result The result as an int256. function mulDivSigned(int256 x, int256 y, int256 denominator) pure returns (int256 result) { if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) { revert PRBMath_MulDivSigned_InputTooSmall(); } // Get hold of the absolute values of x, y and the denominator. uint256 absX; uint256 absY; uint256 absD; unchecked { absX = x < 0 ? uint256(-x) : uint256(x); absY = y < 0 ? uint256(-y) : uint256(y); absD = denominator < 0 ? uint256(-denominator) : uint256(denominator); } // Compute the absolute value of (x*y)÷denominator. The result must fit within int256. uint256 rAbs = mulDiv(absX, absY, absD); if (rAbs > uint256(type(int256).max)) { revert PRBMath_MulDivSigned_Overflow(x, y); } // Get the signs of x, y and the denominator. uint256 sx; uint256 sy; uint256 sd; assembly ("memory-safe") { // This works thanks to two's complement. // "sgt" stands for "signed greater than" and "sub(0,1)" is max uint256. sx := sgt(x, sub(0, 1)) sy := sgt(y, sub(0, 1)) sd := sgt(denominator, sub(0, 1)) } // XOR over sx, sy and sd. What this does is to check whether there are 1 or 3 negative signs in the inputs. // If there are, the result should be negative. Otherwise, it should be positive. unchecked { result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs); } } /// @notice Calculates the binary exponent of x using the binary fraction method. /// @dev Has to use 192.64-bit fixed-point numbers. /// See https://ethereum.stackexchange.com/a/96594/24693. /// @param x The exponent as an unsigned 192.64-bit fixed-point number. /// @return result The result as an unsigned 60.18-decimal fixed-point number. function prbExp2(uint256 x) pure returns (uint256 result) { unchecked { // Start from 0.5 in the 192.64-bit fixed-point format. result = 0x800000000000000000000000000000000000000000000000; // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows // because the initial result is 2^191 and all magic factors are less than 2^65. if (x & 0xFF00000000000000 > 0) { if (x & 0x8000000000000000 > 0) { result = (result * 0x16A09E667F3BCC909) >> 64; } if (x & 0x4000000000000000 > 0) { result = (result * 0x1306FE0A31B7152DF) >> 64; } if (x & 0x2000000000000000 > 0) { result = (result * 0x1172B83C7D517ADCE) >> 64; } if (x & 0x1000000000000000 > 0) { result = (result * 0x10B5586CF9890F62A) >> 64; } if (x & 0x800000000000000 > 0) { result = (result * 0x1059B0D31585743AE) >> 64; } if (x & 0x400000000000000 > 0) { result = (result * 0x102C9A3E778060EE7) >> 64; } if (x & 0x200000000000000 > 0) { result = (result * 0x10163DA9FB33356D8) >> 64; } if (x & 0x100000000000000 > 0) { result = (result * 0x100B1AFA5ABCBED61) >> 64; } } if (x & 0xFF000000000000 > 0) { if (x & 0x80000000000000 > 0) { result = (result * 0x10058C86DA1C09EA2) >> 64; } if (x & 0x40000000000000 > 0) { result = (result * 0x1002C605E2E8CEC50) >> 64; } if (x & 0x20000000000000 > 0) { result = (result * 0x100162F3904051FA1) >> 64; } if (x & 0x10000000000000 > 0) { result = (result * 0x1000B175EFFDC76BA) >> 64; } if (x & 0x8000000000000 > 0) { result = (result * 0x100058BA01FB9F96D) >> 64; } if (x & 0x4000000000000 > 0) { result = (result * 0x10002C5CC37DA9492) >> 64; } if (x & 0x2000000000000 > 0) { result = (result * 0x1000162E525EE0547) >> 64; } if (x & 0x1000000000000 > 0) { result = (result * 0x10000B17255775C04) >> 64; } } if (x & 0xFF0000000000 > 0) { if (x & 0x800000000000 > 0) { result = (result * 0x1000058B91B5BC9AE) >> 64; } if (x & 0x400000000000 > 0) { result = (result * 0x100002C5C89D5EC6D) >> 64; } if (x & 0x200000000000 > 0) { result = (result * 0x10000162E43F4F831) >> 64; } if (x & 0x100000000000 > 0) { result = (result * 0x100000B1721BCFC9A) >> 64; } if (x & 0x80000000000 > 0) { result = (result * 0x10000058B90CF1E6E) >> 64; } if (x & 0x40000000000 > 0) { result = (result * 0x1000002C5C863B73F) >> 64; } if (x & 0x20000000000 > 0) { result = (result * 0x100000162E430E5A2) >> 64; } if (x & 0x10000000000 > 0) { result = (result * 0x1000000B172183551) >> 64; } } if (x & 0xFF00000000 > 0) { if (x & 0x8000000000 > 0) { result = (result * 0x100000058B90C0B49) >> 64; } if (x & 0x4000000000 > 0) { result = (result * 0x10000002C5C8601CC) >> 64; } if (x & 0x2000000000 > 0) { result = (result * 0x1000000162E42FFF0) >> 64; } if (x & 0x1000000000 > 0) { result = (result * 0x10000000B17217FBB) >> 64; } if (x & 0x800000000 > 0) { result = (result * 0x1000000058B90BFCE) >> 64; } if (x & 0x400000000 > 0) { result = (result * 0x100000002C5C85FE3) >> 64; } if (x & 0x200000000 > 0) { result = (result * 0x10000000162E42FF1) >> 64; } if (x & 0x100000000 > 0) { result = (result * 0x100000000B17217F8) >> 64; } } if (x & 0xFF00000000 > 0) { if (x & 0x80000000 > 0) { result = (result * 0x10000000058B90BFC) >> 64; } if (x & 0x40000000 > 0) { result = (result * 0x1000000002C5C85FE) >> 64; } if (x & 0x20000000 > 0) { result = (result * 0x100000000162E42FF) >> 64; } if (x & 0x10000000 > 0) { result = (result * 0x1000000000B17217F) >> 64; } if (x & 0x8000000 > 0) { result = (result * 0x100000000058B90C0) >> 64; } if (x & 0x4000000 > 0) { result = (result * 0x10000000002C5C860) >> 64; } if (x & 0x2000000 > 0) { result = (result * 0x1000000000162E430) >> 64; } if (x & 0x1000000 > 0) { result = (result * 0x10000000000B17218) >> 64; } } if (x & 0xFF0000 > 0) { if (x & 0x800000 > 0) { result = (result * 0x1000000000058B90C) >> 64; } if (x & 0x400000 > 0) { result = (result * 0x100000000002C5C86) >> 64; } if (x & 0x200000 > 0) { result = (result * 0x10000000000162E43) >> 64; } if (x & 0x100000 > 0) { result = (result * 0x100000000000B1721) >> 64; } if (x & 0x80000 > 0) { result = (result * 0x10000000000058B91) >> 64; } if (x & 0x40000 > 0) { result = (result * 0x1000000000002C5C8) >> 64; } if (x & 0x20000 > 0) { result = (result * 0x100000000000162E4) >> 64; } if (x & 0x10000 > 0) { result = (result * 0x1000000000000B172) >> 64; } } if (x & 0xFF00 > 0) { if (x & 0x8000 > 0) { result = (result * 0x100000000000058B9) >> 64; } if (x & 0x4000 > 0) { result = (result * 0x10000000000002C5D) >> 64; } if (x & 0x2000 > 0) { result = (result * 0x1000000000000162E) >> 64; } if (x & 0x1000 > 0) { result = (result * 0x10000000000000B17) >> 64; } if (x & 0x800 > 0) { result = (result * 0x1000000000000058C) >> 64; } if (x & 0x400 > 0) { result = (result * 0x100000000000002C6) >> 64; } if (x & 0x200 > 0) { result = (result * 0x10000000000000163) >> 64; } if (x & 0x100 > 0) { result = (result * 0x100000000000000B1) >> 64; } } if (x & 0xFF > 0) { if (x & 0x80 > 0) { result = (result * 0x10000000000000059) >> 64; } if (x & 0x40 > 0) { result = (result * 0x1000000000000002C) >> 64; } if (x & 0x20 > 0) { result = (result * 0x10000000000000016) >> 64; } if (x & 0x10 > 0) { result = (result * 0x1000000000000000B) >> 64; } if (x & 0x8 > 0) { result = (result * 0x10000000000000006) >> 64; } if (x & 0x4 > 0) { result = (result * 0x10000000000000003) >> 64; } if (x & 0x2 > 0) { result = (result * 0x10000000000000001) >> 64; } if (x & 0x1 > 0) { result = (result * 0x10000000000000001) >> 64; } } // We're doing two things at the same time: // // 1. Multiply the result by 2^n + 1, where "2^n" is the integer part and the one is added to account for // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191 // rather than 192. // 2. Convert the result to the unsigned 60.18-decimal fixed-point format. // // This works because 2^(191-ip) = 2^ip / 2^191, where "ip" is the integer part "2^n". result *= UNIT; result >>= (191 - (x >> 64)); } } /// @notice Calculates the square root of x, rounding down if x is not a perfect square. /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. /// Credits to OpenZeppelin for the explanations in code comments below. /// /// Caveats: /// - This function does not work with fixed-point numbers. /// /// @param x The uint256 number for which to calculate the square root. /// @return result The result as an uint256. function prbSqrt(uint256 x) pure returns (uint256 result) { if (x == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of x. // // We know that the "msb" (most significant bit) of x is a power of 2 such that we have: // // $$ // msb(x) <= x <= 2*msb(x)$ // $$ // // We write $msb(x)$ as $2^k$ and we get: // // $$ // k = log_2(x) // $$ // // Thus we can write the initial inequality as: // // $$ // 2^{log_2(x)} <= x <= 2*2^{log_2(x)+1} \\ // sqrt(2^k) <= sqrt(x) < sqrt(2^{k+1}) \\ // 2^{k/2} <= sqrt(x) < 2^{(k+1)/2} <= 2^{(k/2)+1} // $$ // // Consequently, $2^{log_2(x) /2}` is a good first approximation of sqrt(x) with at least one correct bit. uint256 xAux = uint256(x); result = 1; if (xAux >= 2 ** 128) { xAux >>= 128; result <<= 64; } if (xAux >= 2 ** 64) { xAux >>= 64; result <<= 32; } if (xAux >= 2 ** 32) { xAux >>= 32; result <<= 16; } if (xAux >= 2 ** 16) { xAux >>= 16; result <<= 8; } if (xAux >= 2 ** 8) { xAux >>= 8; result <<= 4; } if (xAux >= 2 ** 4) { xAux >>= 4; result <<= 2; } if (xAux >= 2 ** 2) { result <<= 1; } // At this point, `result` is an estimation with at least one bit of precision. We know the true value has at // most 128 bits, since it is the square root of a uint256. Newton's method converges quadratically (precision // doubles at every iteration). We thus need at most 7 iteration to turn our partial result with one bit of // precision into the expected uint128 result. unchecked { result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; // Round down the result in case x is not a perfect square. uint256 roundedDownResult = x / result; if (result >= roundedDownResult) { result = roundedDownResult; } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import "./ud60x18/Casting.sol"; import "./ud60x18/Constants.sol"; import "./ud60x18/Conversions.sol"; import "./ud60x18/Errors.sol"; import "./ud60x18/Helpers.sol"; import "./ud60x18/Math.sol"; import "./ud60x18/ValueType.sol";
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { MAX_UINT40 } from "../Common.sol"; import { SD59x18 } from "../sd59x18/ValueType.sol"; import { UD2x18 } from "../ud2x18/ValueType.sol"; import { UD60x18 } from "../ud60x18/ValueType.sol"; import { PRBMath_SD1x18_ToUD2x18_Underflow, PRBMath_SD1x18_ToUD60x18_Underflow, PRBMath_SD1x18_ToUint128_Underflow, PRBMath_SD1x18_ToUint256_Underflow, PRBMath_SD1x18_ToUint40_Overflow, PRBMath_SD1x18_ToUint40_Underflow } from "./Errors.sol"; import { SD1x18 } from "./ValueType.sol"; /// @notice Casts an SD1x18 number into SD59x18. /// @dev There is no overflow check because the domain of SD1x18 is a subset of SD59x18. function intoSD59x18(SD1x18 x) pure returns (SD59x18 result) { result = SD59x18.wrap(int256(SD1x18.unwrap(x))); } /// @notice Casts an SD1x18 number into UD2x18. /// - x must be positive. function intoUD2x18(SD1x18 x) pure returns (UD2x18 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert PRBMath_SD1x18_ToUD2x18_Underflow(x); } result = UD2x18.wrap(uint64(xInt)); } /// @notice Casts an SD1x18 number into UD60x18. /// @dev Requirements: /// - x must be positive. function intoUD60x18(SD1x18 x) pure returns (UD60x18 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert PRBMath_SD1x18_ToUD60x18_Underflow(x); } result = UD60x18.wrap(uint64(xInt)); } /// @notice Casts an SD1x18 number into uint256. /// @dev Requirements: /// - x must be positive. function intoUint256(SD1x18 x) pure returns (uint256 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert PRBMath_SD1x18_ToUint256_Underflow(x); } result = uint256(uint64(xInt)); } /// @notice Casts an SD1x18 number into uint128. /// @dev Requirements: /// - x must be positive. function intoUint128(SD1x18 x) pure returns (uint128 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert PRBMath_SD1x18_ToUint128_Underflow(x); } result = uint128(uint64(xInt)); } /// @notice Casts an SD1x18 number into uint40. /// @dev Requirements: /// - x must be positive. /// - x must be less than or equal to `MAX_UINT40`. function intoUint40(SD1x18 x) pure returns (uint40 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert PRBMath_SD1x18_ToUint40_Underflow(x); } if (xInt > int64(uint64(MAX_UINT40))) { revert PRBMath_SD1x18_ToUint40_Overflow(x); } result = uint40(uint64(xInt)); } /// @notice Alias for the `wrap` function. function sd1x18(int64 x) pure returns (SD1x18 result) { result = wrap(x); } /// @notice Unwraps an SD1x18 number into int64. function unwrap(SD1x18 x) pure returns (int64 result) { result = SD1x18.unwrap(x); } /// @notice Wraps an int64 number into the SD1x18 value type. function wrap(int64 x) pure returns (SD1x18 result) { result = SD1x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { SD1x18 } from "./ValueType.sol"; /// @dev Euler's number as an SD1x18 number. SD1x18 constant E = SD1x18.wrap(2_718281828459045235); /// @dev The maximum value an SD1x18 number can have. int64 constant uMAX_SD1x18 = 9_223372036854775807; SD1x18 constant MAX_SD1x18 = SD1x18.wrap(uMAX_SD1x18); /// @dev The maximum value an SD1x18 number can have. int64 constant uMIN_SD1x18 = -9_223372036854775808; SD1x18 constant MIN_SD1x18 = SD1x18.wrap(uMIN_SD1x18); /// @dev PI as an SD1x18 number. SD1x18 constant PI = SD1x18.wrap(3_141592653589793238); /// @dev The unit amount that implies how many trailing decimals can be represented. SD1x18 constant UNIT = SD1x18.wrap(1e18); int256 constant uUNIT = 1e18;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { SD1x18 } from "./ValueType.sol"; /// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in UD2x18. error PRBMath_SD1x18_ToUD2x18_Underflow(SD1x18 x); /// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in UD60x18. error PRBMath_SD1x18_ToUD60x18_Underflow(SD1x18 x); /// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in uint128. error PRBMath_SD1x18_ToUint128_Underflow(SD1x18 x); /// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in uint256. error PRBMath_SD1x18_ToUint256_Underflow(SD1x18 x); /// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in uint40. error PRBMath_SD1x18_ToUint40_Overflow(SD1x18 x); /// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in uint40. error PRBMath_SD1x18_ToUint40_Underflow(SD1x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import "./Casting.sol" as C; /// @notice The signed 1.18-decimal fixed-point number representation, which can have up to 1 digit and up to 18 decimals. /// The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity type int64. /// This is useful when end users want to use int64 to save gas, e.g. with tight variable packing in contract storage. type SD1x18 is int64; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { C.intoSD59x18, C.intoUD2x18, C.intoUD60x18, C.intoUint256, C.intoUint128, C.intoUint40, C.unwrap } for SD1x18 global;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { MAX_UINT128, MAX_UINT40 } from "../Common.sol"; import { uMAX_SD1x18, uMIN_SD1x18 } from "../sd1x18/Constants.sol"; import { SD1x18 } from "../sd1x18/ValueType.sol"; import { uMAX_UD2x18 } from "../ud2x18/Constants.sol"; import { UD2x18 } from "../ud2x18/ValueType.sol"; import { UD60x18 } from "../ud60x18/ValueType.sol"; import { PRBMath_SD59x18_IntoSD1x18_Overflow, PRBMath_SD59x18_IntoSD1x18_Underflow, PRBMath_SD59x18_IntoUD2x18_Overflow, PRBMath_SD59x18_IntoUD2x18_Underflow, PRBMath_SD59x18_IntoUD60x18_Underflow, PRBMath_SD59x18_IntoUint128_Overflow, PRBMath_SD59x18_IntoUint128_Underflow, PRBMath_SD59x18_IntoUint256_Underflow, PRBMath_SD59x18_IntoUint40_Overflow, PRBMath_SD59x18_IntoUint40_Underflow } from "./Errors.sol"; import { SD59x18 } from "./ValueType.sol"; /// @notice Casts an SD59x18 number into int256. /// @dev This is basically a functional alias for the `unwrap` function. function intoInt256(SD59x18 x) pure returns (int256 result) { result = SD59x18.unwrap(x); } /// @notice Casts an SD59x18 number into SD1x18. /// @dev Requirements: /// - x must be greater than or equal to `uMIN_SD1x18`. /// - x must be less than or equal to `uMAX_SD1x18`. function intoSD1x18(SD59x18 x) pure returns (SD1x18 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < uMIN_SD1x18) { revert PRBMath_SD59x18_IntoSD1x18_Underflow(x); } if (xInt > uMAX_SD1x18) { revert PRBMath_SD59x18_IntoSD1x18_Overflow(x); } result = SD1x18.wrap(int64(xInt)); } /// @notice Casts an SD59x18 number into UD2x18. /// @dev Requirements: /// - x must be positive. /// - x must be less than or equal to `uMAX_UD2x18`. function intoUD2x18(SD59x18 x) pure returns (UD2x18 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert PRBMath_SD59x18_IntoUD2x18_Underflow(x); } if (xInt > int256(uint256(uMAX_UD2x18))) { revert PRBMath_SD59x18_IntoUD2x18_Overflow(x); } result = UD2x18.wrap(uint64(uint256(xInt))); } /// @notice Casts an SD59x18 number into UD60x18. /// @dev Requirements: /// - x must be positive. function intoUD60x18(SD59x18 x) pure returns (UD60x18 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert PRBMath_SD59x18_IntoUD60x18_Underflow(x); } result = UD60x18.wrap(uint256(xInt)); } /// @notice Casts an SD59x18 number into uint256. /// @dev Requirements: /// - x must be positive. function intoUint256(SD59x18 x) pure returns (uint256 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert PRBMath_SD59x18_IntoUint256_Underflow(x); } result = uint256(xInt); } /// @notice Casts an SD59x18 number into uint128. /// @dev Requirements: /// - x must be positive. /// - x must be less than or equal to `uMAX_UINT128`. function intoUint128(SD59x18 x) pure returns (uint128 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert PRBMath_SD59x18_IntoUint128_Underflow(x); } if (xInt > int256(uint256(MAX_UINT128))) { revert PRBMath_SD59x18_IntoUint128_Overflow(x); } result = uint128(uint256(xInt)); } /// @notice Casts an SD59x18 number into uint40. /// @dev Requirements: /// - x must be positive. /// - x must be less than or equal to `MAX_UINT40`. function intoUint40(SD59x18 x) pure returns (uint40 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert PRBMath_SD59x18_IntoUint40_Underflow(x); } if (xInt > int256(uint256(MAX_UINT40))) { revert PRBMath_SD59x18_IntoUint40_Overflow(x); } result = uint40(uint256(xInt)); } /// @notice Alias for the `wrap` function. function sd(int256 x) pure returns (SD59x18 result) { result = wrap(x); } /// @notice Alias for the `wrap` function. function sd59x18(int256 x) pure returns (SD59x18 result) { result = wrap(x); } /// @notice Unwraps an SD59x18 number into int256. function unwrap(SD59x18 x) pure returns (int256 result) { result = SD59x18.unwrap(x); } /// @notice Wraps an int256 number into the SD59x18 value type. function wrap(int256 x) pure returns (SD59x18 result) { result = SD59x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { SD59x18 } from "./ValueType.sol"; /// NOTICE: the "u" prefix stands for "unwrapped". /// @dev Euler's number as an SD59x18 number. SD59x18 constant E = SD59x18.wrap(2_718281828459045235); /// @dev Half the UNIT number. int256 constant uHALF_UNIT = 0.5e18; SD59x18 constant HALF_UNIT = SD59x18.wrap(uHALF_UNIT); /// @dev log2(10) as an SD59x18 number. int256 constant uLOG2_10 = 3_321928094887362347; SD59x18 constant LOG2_10 = SD59x18.wrap(uLOG2_10); /// @dev log2(e) as an SD59x18 number. int256 constant uLOG2_E = 1_442695040888963407; SD59x18 constant LOG2_E = SD59x18.wrap(uLOG2_E); /// @dev The maximum value an SD59x18 number can have. int256 constant uMAX_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_792003956564819967; SD59x18 constant MAX_SD59x18 = SD59x18.wrap(uMAX_SD59x18); /// @dev The maximum whole value an SD59x18 number can have. int256 constant uMAX_WHOLE_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_000000000000000000; SD59x18 constant MAX_WHOLE_SD59x18 = SD59x18.wrap(uMAX_WHOLE_SD59x18); /// @dev The minimum value an SD59x18 number can have. int256 constant uMIN_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_792003956564819968; SD59x18 constant MIN_SD59x18 = SD59x18.wrap(uMIN_SD59x18); /// @dev The minimum whole value an SD59x18 number can have. int256 constant uMIN_WHOLE_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_000000000000000000; SD59x18 constant MIN_WHOLE_SD59x18 = SD59x18.wrap(uMIN_WHOLE_SD59x18); /// @dev PI as an SD59x18 number. SD59x18 constant PI = SD59x18.wrap(3_141592653589793238); /// @dev The unit amount that implies how many trailing decimals can be represented. int256 constant uUNIT = 1e18; SD59x18 constant UNIT = SD59x18.wrap(1e18); /// @dev Zero as an SD59x18 number. SD59x18 constant ZERO = SD59x18.wrap(0);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { SD59x18 } from "./ValueType.sol"; /// @notice Emitted when taking the absolute value of `MIN_SD59x18`. error PRBMath_SD59x18_Abs_MinSD59x18(); /// @notice Emitted when ceiling a number overflows SD59x18. error PRBMath_SD59x18_Ceil_Overflow(SD59x18 x); /// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18. error PRBMath_SD59x18_Convert_Overflow(int256 x); /// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18. error PRBMath_SD59x18_Convert_Underflow(int256 x); /// @notice Emitted when dividing two numbers and one of them is `MIN_SD59x18`. error PRBMath_SD59x18_Div_InputTooSmall(); /// @notice Emitted when dividing two numbers and one of the intermediary unsigned results overflows SD59x18. error PRBMath_SD59x18_Div_Overflow(SD59x18 x, SD59x18 y); /// @notice Emitted when taking the natural exponent of a base greater than 133.084258667509499441. error PRBMath_SD59x18_Exp_InputTooBig(SD59x18 x); /// @notice Emitted when taking the binary exponent of a base greater than 192. error PRBMath_SD59x18_Exp2_InputTooBig(SD59x18 x); /// @notice Emitted when flooring a number underflows SD59x18. error PRBMath_SD59x18_Floor_Underflow(SD59x18 x); /// @notice Emitted when taking the geometric mean of two numbers and their product is negative. error PRBMath_SD59x18_Gm_NegativeProduct(SD59x18 x, SD59x18 y); /// @notice Emitted when taking the geometric mean of two numbers and multiplying them overflows SD59x18. error PRBMath_SD59x18_Gm_Overflow(SD59x18 x, SD59x18 y); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in SD1x18. error PRBMath_SD59x18_IntoSD1x18_Overflow(SD59x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in SD1x18. error PRBMath_SD59x18_IntoSD1x18_Underflow(SD59x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in UD2x18. error PRBMath_SD59x18_IntoUD2x18_Overflow(SD59x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in UD2x18. error PRBMath_SD59x18_IntoUD2x18_Underflow(SD59x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in UD60x18. error PRBMath_SD59x18_IntoUD60x18_Underflow(SD59x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint128. error PRBMath_SD59x18_IntoUint128_Overflow(SD59x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint128. error PRBMath_SD59x18_IntoUint128_Underflow(SD59x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint256. error PRBMath_SD59x18_IntoUint256_Underflow(SD59x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint40. error PRBMath_SD59x18_IntoUint40_Overflow(SD59x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint40. error PRBMath_SD59x18_IntoUint40_Underflow(SD59x18 x); /// @notice Emitted when taking the logarithm of a number less than or equal to zero. error PRBMath_SD59x18_Log_InputTooSmall(SD59x18 x); /// @notice Emitted when multiplying two numbers and one of the inputs is `MIN_SD59x18`. error PRBMath_SD59x18_Mul_InputTooSmall(); /// @notice Emitted when multiplying two numbers and the intermediary absolute result overflows SD59x18. error PRBMath_SD59x18_Mul_Overflow(SD59x18 x, SD59x18 y); /// @notice Emitted when raising a number to a power and hte intermediary absolute result overflows SD59x18. error PRBMath_SD59x18_Powu_Overflow(SD59x18 x, uint256 y); /// @notice Emitted when taking the square root of a negative number. error PRBMath_SD59x18_Sqrt_NegativeInput(SD59x18 x); /// @notice Emitted when the calculating the square root overflows SD59x18. error PRBMath_SD59x18_Sqrt_Overflow(SD59x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { unwrap, wrap } from "./Casting.sol"; import { SD59x18 } from "./ValueType.sol"; /// @notice Implements the checked addition operation (+) in the SD59x18 type. function add(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { return wrap(unwrap(x) + unwrap(y)); } /// @notice Implements the AND (&) bitwise operation in the SD59x18 type. function and(SD59x18 x, int256 bits) pure returns (SD59x18 result) { return wrap(unwrap(x) & bits); } /// @notice Implements the equal (=) operation in the SD59x18 type. function eq(SD59x18 x, SD59x18 y) pure returns (bool result) { result = unwrap(x) == unwrap(y); } /// @notice Implements the greater than operation (>) in the SD59x18 type. function gt(SD59x18 x, SD59x18 y) pure returns (bool result) { result = unwrap(x) > unwrap(y); } /// @notice Implements the greater than or equal to operation (>=) in the SD59x18 type. function gte(SD59x18 x, SD59x18 y) pure returns (bool result) { result = unwrap(x) >= unwrap(y); } /// @notice Implements a zero comparison check function in the SD59x18 type. function isZero(SD59x18 x) pure returns (bool result) { result = unwrap(x) == 0; } /// @notice Implements the left shift operation (<<) in the SD59x18 type. function lshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) { result = wrap(unwrap(x) << bits); } /// @notice Implements the lower than operation (<) in the SD59x18 type. function lt(SD59x18 x, SD59x18 y) pure returns (bool result) { result = unwrap(x) < unwrap(y); } /// @notice Implements the lower than or equal to operation (<=) in the SD59x18 type. function lte(SD59x18 x, SD59x18 y) pure returns (bool result) { result = unwrap(x) <= unwrap(y); } /// @notice Implements the unchecked modulo operation (%) in the SD59x18 type. function mod(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(unwrap(x) % unwrap(y)); } /// @notice Implements the not equal operation (!=) in the SD59x18 type. function neq(SD59x18 x, SD59x18 y) pure returns (bool result) { result = unwrap(x) != unwrap(y); } /// @notice Implements the OR (|) bitwise operation in the SD59x18 type. function or(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(unwrap(x) | unwrap(y)); } /// @notice Implements the right shift operation (>>) in the SD59x18 type. function rshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) { result = wrap(unwrap(x) >> bits); } /// @notice Implements the checked subtraction operation (-) in the SD59x18 type. function sub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(unwrap(x) - unwrap(y)); } /// @notice Implements the unchecked addition operation (+) in the SD59x18 type. function uncheckedAdd(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { unchecked { result = wrap(unwrap(x) + unwrap(y)); } } /// @notice Implements the unchecked subtraction operation (-) in the SD59x18 type. function uncheckedSub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { unchecked { result = wrap(unwrap(x) - unwrap(y)); } } /// @notice Implements the unchecked unary minus operation (-) in the SD59x18 type. function uncheckedUnary(SD59x18 x) pure returns (SD59x18 result) { unchecked { result = wrap(-unwrap(x)); } } /// @notice Implements the XOR (^) bitwise operation in the SD59x18 type. function xor(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(unwrap(x) ^ unwrap(y)); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { MAX_UINT128, MAX_UINT40, msb, mulDiv, mulDiv18, prbExp2, prbSqrt } from "../Common.sol"; import { uHALF_UNIT, uLOG2_10, uLOG2_E, uMAX_SD59x18, uMAX_WHOLE_SD59x18, uMIN_SD59x18, uMIN_WHOLE_SD59x18, UNIT, uUNIT, ZERO } from "./Constants.sol"; import { PRBMath_SD59x18_Abs_MinSD59x18, PRBMath_SD59x18_Ceil_Overflow, PRBMath_SD59x18_Div_InputTooSmall, PRBMath_SD59x18_Div_Overflow, PRBMath_SD59x18_Exp_InputTooBig, PRBMath_SD59x18_Exp2_InputTooBig, PRBMath_SD59x18_Floor_Underflow, PRBMath_SD59x18_Gm_Overflow, PRBMath_SD59x18_Gm_NegativeProduct, PRBMath_SD59x18_Log_InputTooSmall, PRBMath_SD59x18_Mul_InputTooSmall, PRBMath_SD59x18_Mul_Overflow, PRBMath_SD59x18_Powu_Overflow, PRBMath_SD59x18_Sqrt_NegativeInput, PRBMath_SD59x18_Sqrt_Overflow } from "./Errors.sol"; import { unwrap, wrap } from "./Helpers.sol"; import { SD59x18 } from "./ValueType.sol"; /// @notice Calculate the absolute value of x. /// /// @dev Requirements: /// - x must be greater than `MIN_SD59x18`. /// /// @param x The SD59x18 number for which to calculate the absolute value. /// @param result The absolute value of x as an SD59x18 number. function abs(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = unwrap(x); if (xInt == uMIN_SD59x18) { revert PRBMath_SD59x18_Abs_MinSD59x18(); } result = xInt < 0 ? wrap(-xInt) : x; } /// @notice Calculates the arithmetic average of x and y, rounding towards zero. /// @param x The first operand as an SD59x18 number. /// @param y The second operand as an SD59x18 number. /// @return result The arithmetic average as an SD59x18 number. function avg(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = unwrap(x); int256 yInt = unwrap(y); unchecked { // This is equivalent to "x / 2 + y / 2" but faster. // This operation can never overflow. int256 sum = (xInt >> 1) + (yInt >> 1); if (sum < 0) { // If at least one of x and y is odd, we add 1 to the result, since shifting negative numbers to the right rounds // down to infinity. The right part is equivalent to "sum + (x % 2 == 1 || y % 2 == 1)" but faster. assembly ("memory-safe") { result := add(sum, and(or(xInt, yInt), 1)) } } else { // We need to add 1 if both x and y are odd to account for the double 0.5 remainder that is truncated after shifting. result = wrap(sum + (xInt & yInt & 1)); } } } /// @notice Yields the smallest whole SD59x18 number greater than or equal to x. /// /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts. /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// /// Requirements: /// - x must be less than or equal to `MAX_WHOLE_SD59x18`. /// /// @param x The SD59x18 number to ceil. /// @param result The least number greater than or equal to x, as an SD59x18 number. function ceil(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = unwrap(x); if (xInt > uMAX_WHOLE_SD59x18) { revert PRBMath_SD59x18_Ceil_Overflow(x); } int256 remainder = xInt % uUNIT; if (remainder == 0) { result = x; } else { unchecked { // Solidity uses C fmod style, which returns a modulus with the same sign as x. int256 resultInt = xInt - remainder; if (xInt > 0) { resultInt += uUNIT; } result = wrap(resultInt); } } } /// @notice Divides two SD59x18 numbers, returning a new SD59x18 number. Rounds towards zero. /// /// @dev This is a variant of `mulDiv` that works with signed numbers. Works by computing the signs and the absolute values /// separately. /// /// Requirements: /// - All from `Common.mulDiv`. /// - None of the inputs can be `MIN_SD59x18`. /// - The denominator cannot be zero. /// - The result must fit within int256. /// /// Caveats: /// - All from `Common.mulDiv`. /// /// @param x The numerator as an SD59x18 number. /// @param y The denominator as an SD59x18 number. /// @param result The quotient as an SD59x18 number. function div(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = unwrap(x); int256 yInt = unwrap(y); if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) { revert PRBMath_SD59x18_Div_InputTooSmall(); } // Get hold of the absolute values of x and y. uint256 xAbs; uint256 yAbs; unchecked { xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt); yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt); } // Compute the absolute value (x*UNIT)÷y. The resulting value must fit within int256. uint256 resultAbs = mulDiv(xAbs, uint256(uUNIT), yAbs); if (resultAbs > uint256(uMAX_SD59x18)) { revert PRBMath_SD59x18_Div_Overflow(x, y); } // Check if x and y have the same sign. This works thanks to two's complement; the left-most bit is the sign bit. bool sameSign = (xInt ^ yInt) > -1; // If the inputs don't have the same sign, the result should be negative. Otherwise, it should be positive. unchecked { result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs)); } } /// @notice Calculates the natural exponent of x. /// /// @dev Based on the formula: /// /// $$ /// e^x = 2^{x * log_2{e}} /// $$ /// /// Requirements: /// - All from `log2`. /// - x must be less than 133.084258667509499441. /// /// Caveats: /// - All from `exp2`. /// - For any x less than -41.446531673892822322, the result is zero. /// /// @param x The exponent as an SD59x18 number. /// @return result The result as an SD59x18 number. function exp(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = unwrap(x); // Without this check, the value passed to `exp2` would be less than -59.794705707972522261. if (xInt < -41_446531673892822322) { return ZERO; } // Without this check, the value passed to `exp2` would be greater than 192. if (xInt >= 133_084258667509499441) { revert PRBMath_SD59x18_Exp_InputTooBig(x); } unchecked { // Do the fixed-point multiplication inline to save gas. int256 doubleUnitProduct = xInt * uLOG2_E; result = exp2(wrap(doubleUnitProduct / uUNIT)); } } /// @notice Calculates the binary exponent of x using the binary fraction method. /// /// @dev Based on the formula: /// /// $$ /// 2^{-x} = \frac{1}{2^x} /// $$ /// /// See https://ethereum.stackexchange.com/q/79903/24693. /// /// Requirements: /// - x must be 192 or less. /// - The result must fit within `MAX_SD59x18`. /// /// Caveats: /// - For any x less than -59.794705707972522261, the result is zero. /// /// @param x The exponent as an SD59x18 number. /// @return result The result as an SD59x18 number. function exp2(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = unwrap(x); if (xInt < 0) { // 2^59.794705707972522262 is the maximum number whose inverse does not truncate down to zero. if (xInt < -59_794705707972522261) { return ZERO; } unchecked { // Do the fixed-point inversion $1/2^x$ inline to save gas. 1e36 is UNIT * UNIT. result = wrap(1e36 / unwrap(exp2(wrap(-xInt)))); } } else { // 2^192 doesn't fit within the 192.64-bit format used internally in this function. if (xInt >= 192e18) { revert PRBMath_SD59x18_Exp2_InputTooBig(x); } unchecked { // Convert x to the 192.64-bit fixed-point format. uint256 x_192x64 = uint256((xInt << 64) / uUNIT); // It is safe to convert the result to int256 with no checks because the maximum input allowed in this function is 192. result = wrap(int256(prbExp2(x_192x64))); } } } /// @notice Yields the greatest whole SD59x18 number less than or equal to x. /// /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts. /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// /// Requirements: /// - x must be greater than or equal to `MIN_WHOLE_SD59x18`. /// /// @param x The SD59x18 number to floor. /// @param result The greatest integer less than or equal to x, as an SD59x18 number. function floor(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = unwrap(x); if (xInt < uMIN_WHOLE_SD59x18) { revert PRBMath_SD59x18_Floor_Underflow(x); } int256 remainder = xInt % uUNIT; if (remainder == 0) { result = x; } else { unchecked { // Solidity uses C fmod style, which returns a modulus with the same sign as x. int256 resultInt = xInt - remainder; if (xInt < 0) { resultInt -= uUNIT; } result = wrap(resultInt); } } } /// @notice Yields the excess beyond the floor of x for positive numbers and the part of the number to the right. /// of the radix point for negative numbers. /// @dev Based on the odd function definition. https://en.wikipedia.org/wiki/Fractional_part /// @param x The SD59x18 number to get the fractional part of. /// @param result The fractional part of x as an SD59x18 number. function frac(SD59x18 x) pure returns (SD59x18 result) { result = wrap(unwrap(x) % uUNIT); } /// @notice Calculates the geometric mean of x and y, i.e. sqrt(x * y), rounding down. /// /// @dev Requirements: /// - x * y must fit within `MAX_SD59x18`, lest it overflows. /// - x * y must not be negative, since this library does not handle complex numbers. /// /// @param x The first operand as an SD59x18 number. /// @param y The second operand as an SD59x18 number. /// @return result The result as an SD59x18 number. function gm(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = unwrap(x); int256 yInt = unwrap(y); if (xInt == 0 || yInt == 0) { return ZERO; } unchecked { // Equivalent to "xy / x != y". Checking for overflow this way is faster than letting Solidity do it. int256 xyInt = xInt * yInt; if (xyInt / xInt != yInt) { revert PRBMath_SD59x18_Gm_Overflow(x, y); } // The product must not be negative, since this library does not handle complex numbers. if (xyInt < 0) { revert PRBMath_SD59x18_Gm_NegativeProduct(x, y); } // We don't need to multiply the result by `UNIT` here because the x*y product had picked up a factor of `UNIT` // during multiplication. See the comments within the `prbSqrt` function. uint256 resultUint = prbSqrt(uint256(xyInt)); result = wrap(int256(resultUint)); } } /// @notice Calculates 1 / x, rounding toward zero. /// /// @dev Requirements: /// - x cannot be zero. /// /// @param x The SD59x18 number for which to calculate the inverse. /// @return result The inverse as an SD59x18 number. function inv(SD59x18 x) pure returns (SD59x18 result) { // 1e36 is UNIT * UNIT. result = wrap(1e36 / unwrap(x)); } /// @notice Calculates the natural logarithm of x. /// /// @dev Based on the formula: /// /// $$ /// ln{x} = log_2{x} / log_2{e}$$. /// $$ /// /// Requirements: /// - All from `log2`. /// /// Caveats: /// - All from `log2`. /// - This doesn't return exactly 1 for 2.718281828459045235, for that more fine-grained precision is needed. /// /// @param x The SD59x18 number for which to calculate the natural logarithm. /// @return result The natural logarithm as an SD59x18 number. function ln(SD59x18 x) pure returns (SD59x18 result) { // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x) // can return is 195.205294292027477728. result = wrap((unwrap(log2(x)) * uUNIT) / uLOG2_E); } /// @notice Calculates the common logarithm of x. /// /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common /// logarithm based on the formula: /// /// $$ /// log_{10}{x} = log_2{x} / log_2{10} /// $$ /// /// Requirements: /// - All from `log2`. /// /// Caveats: /// - All from `log2`. /// /// @param x The SD59x18 number for which to calculate the common logarithm. /// @return result The common logarithm as an SD59x18 number. function log10(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = unwrap(x); if (xInt < 0) { revert PRBMath_SD59x18_Log_InputTooSmall(x); } // Note that the `mul` in this block is the assembly mul operation, not the SD59x18 `mul`. // prettier-ignore assembly ("memory-safe") { switch x case 1 { result := mul(uUNIT, sub(0, 18)) } case 10 { result := mul(uUNIT, sub(1, 18)) } case 100 { result := mul(uUNIT, sub(2, 18)) } case 1000 { result := mul(uUNIT, sub(3, 18)) } case 10000 { result := mul(uUNIT, sub(4, 18)) } case 100000 { result := mul(uUNIT, sub(5, 18)) } case 1000000 { result := mul(uUNIT, sub(6, 18)) } case 10000000 { result := mul(uUNIT, sub(7, 18)) } case 100000000 { result := mul(uUNIT, sub(8, 18)) } case 1000000000 { result := mul(uUNIT, sub(9, 18)) } case 10000000000 { result := mul(uUNIT, sub(10, 18)) } case 100000000000 { result := mul(uUNIT, sub(11, 18)) } case 1000000000000 { result := mul(uUNIT, sub(12, 18)) } case 10000000000000 { result := mul(uUNIT, sub(13, 18)) } case 100000000000000 { result := mul(uUNIT, sub(14, 18)) } case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) } case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) } case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) } case 1000000000000000000 { result := 0 } case 10000000000000000000 { result := uUNIT } case 100000000000000000000 { result := mul(uUNIT, 2) } case 1000000000000000000000 { result := mul(uUNIT, 3) } case 10000000000000000000000 { result := mul(uUNIT, 4) } case 100000000000000000000000 { result := mul(uUNIT, 5) } case 1000000000000000000000000 { result := mul(uUNIT, 6) } case 10000000000000000000000000 { result := mul(uUNIT, 7) } case 100000000000000000000000000 { result := mul(uUNIT, 8) } case 1000000000000000000000000000 { result := mul(uUNIT, 9) } case 10000000000000000000000000000 { result := mul(uUNIT, 10) } case 100000000000000000000000000000 { result := mul(uUNIT, 11) } case 1000000000000000000000000000000 { result := mul(uUNIT, 12) } case 10000000000000000000000000000000 { result := mul(uUNIT, 13) } case 100000000000000000000000000000000 { result := mul(uUNIT, 14) } case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) } case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) } case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) } case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) } case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) } case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) } case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) } case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) } case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) } case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) } case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) } case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) } case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) } case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) } case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) } case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) } case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) } case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) } case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) } case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) } case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) } case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) } case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) } case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) } case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) } case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) } case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) } case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) } case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) } case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) } case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) } case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) } case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) } case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) } case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) } case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) } case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) } case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) } case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) } case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) } case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) } case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) } case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) } case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) } default { result := uMAX_SD59x18 } } if (unwrap(result) == uMAX_SD59x18) { unchecked { // Do the fixed-point division inline to save gas. result = wrap((unwrap(log2(x)) * uUNIT) / uLOG2_10); } } } /// @notice Calculates the binary logarithm of x. /// /// @dev Based on the iterative approximation algorithm. /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation /// /// Requirements: /// - x must be greater than zero. /// /// Caveats: /// - The results are not perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation. /// /// @param x The SD59x18 number for which to calculate the binary logarithm. /// @return result The binary logarithm as an SD59x18 number. function log2(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = unwrap(x); if (xInt <= 0) { revert PRBMath_SD59x18_Log_InputTooSmall(x); } unchecked { // This works because of: // // $$ // log_2{x} = -log_2{\frac{1}{x}} // $$ int256 sign; if (xInt >= uUNIT) { sign = 1; } else { sign = -1; // Do the fixed-point inversion inline to save gas. The numerator is UNIT * UNIT. xInt = 1e36 / xInt; } // Calculate the integer part of the logarithm and add it to the result and finally calculate $y = x * 2^(-n)$. uint256 n = msb(uint256(xInt / uUNIT)); // This is the integer part of the logarithm as an SD59x18 number. The operation can't overflow // because n is maximum 255, UNIT is 1e18 and sign is either 1 or -1. int256 resultInt = int256(n) * uUNIT; // This is $y = x * 2^{-n}$. int256 y = xInt >> n; // If y is 1, the fractional part is zero. if (y == uUNIT) { return wrap(resultInt * sign); } // Calculate the fractional part via the iterative approximation. // The "delta >>= 1" part is equivalent to "delta /= 2", but shifting bits is faster. int256 DOUBLE_UNIT = 2e18; for (int256 delta = uHALF_UNIT; delta > 0; delta >>= 1) { y = (y * y) / uUNIT; // Is $y^2 > 2$ and so in the range [2,4)? if (y >= DOUBLE_UNIT) { // Add the 2^{-m} factor to the logarithm. resultInt = resultInt + delta; // Corresponds to z/2 on Wikipedia. y >>= 1; } } resultInt *= sign; result = wrap(resultInt); } } /// @notice Multiplies two SD59x18 numbers together, returning a new SD59x18 number. /// /// @dev This is a variant of `mulDiv` that works with signed numbers and employs constant folding, i.e. the denominator /// is always 1e18. /// /// Requirements: /// - All from `Common.mulDiv18`. /// - None of the inputs can be `MIN_SD59x18`. /// - The result must fit within `MAX_SD59x18`. /// /// Caveats: /// - To understand how this works in detail, see the NatSpec comments in `Common.mulDivSigned`. /// /// @param x The multiplicand as an SD59x18 number. /// @param y The multiplier as an SD59x18 number. /// @return result The product as an SD59x18 number. function mul(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = unwrap(x); int256 yInt = unwrap(y); if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) { revert PRBMath_SD59x18_Mul_InputTooSmall(); } // Get hold of the absolute values of x and y. uint256 xAbs; uint256 yAbs; unchecked { xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt); yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt); } uint256 resultAbs = mulDiv18(xAbs, yAbs); if (resultAbs > uint256(uMAX_SD59x18)) { revert PRBMath_SD59x18_Mul_Overflow(x, y); } // Check if x and y have the same sign. This works thanks to two's complement; the left-most bit is the sign bit. bool sameSign = (xInt ^ yInt) > -1; // If the inputs have the same sign, the result should be negative. Otherwise, it should be positive. unchecked { result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs)); } } /// @notice Raises x to the power of y. /// /// @dev Based on the formula: /// /// $$ /// x^y = 2^{log_2{x} * y} /// $$ /// /// Requirements: /// - All from `exp2`, `log2` and `mul`. /// - x cannot be zero. /// /// Caveats: /// - All from `exp2`, `log2` and `mul`. /// - Assumes 0^0 is 1. /// /// @param x Number to raise to given power y, as an SD59x18 number. /// @param y Exponent to raise x to, as an SD59x18 number /// @return result x raised to power y, as an SD59x18 number. function pow(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = unwrap(x); int256 yInt = unwrap(y); if (xInt == 0) { result = yInt == 0 ? UNIT : ZERO; } else { if (yInt == uUNIT) { result = x; } else { result = exp2(mul(log2(x), y)); } } } /// @notice Raises x (an SD59x18 number) to the power y (unsigned basic integer) using the famous algorithm /// algorithm "exponentiation by squaring". /// /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring /// /// Requirements: /// - All from `abs` and `Common.mulDiv18`. /// - The result must fit within `MAX_SD59x18`. /// /// Caveats: /// - All from `Common.mulDiv18`. /// - Assumes 0^0 is 1. /// /// @param x The base as an SD59x18 number. /// @param y The exponent as an uint256. /// @return result The result as an SD59x18 number. function powu(SD59x18 x, uint256 y) pure returns (SD59x18 result) { uint256 xAbs = uint256(unwrap(abs(x))); // Calculate the first iteration of the loop in advance. uint256 resultAbs = y & 1 > 0 ? xAbs : uint256(uUNIT); // Equivalent to "for(y /= 2; y > 0; y /= 2)" but faster. uint256 yAux = y; for (yAux >>= 1; yAux > 0; yAux >>= 1) { xAbs = mulDiv18(xAbs, xAbs); // Equivalent to "y % 2 == 1" but faster. if (yAux & 1 > 0) { resultAbs = mulDiv18(resultAbs, xAbs); } } // The result must fit within `MAX_SD59x18`. if (resultAbs > uint256(uMAX_SD59x18)) { revert PRBMath_SD59x18_Powu_Overflow(x, y); } unchecked { // Is the base negative and the exponent an odd number? int256 resultInt = int256(resultAbs); bool isNegative = unwrap(x) < 0 && y & 1 == 1; if (isNegative) { resultInt = -resultInt; } result = wrap(resultInt); } } /// @notice Calculates the square root of x, rounding down. Only the positive root is returned. /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. /// /// Requirements: /// - x cannot be negative, since this library does not handle complex numbers. /// - x must be less than `MAX_SD59x18` divided by `UNIT`. /// /// @param x The SD59x18 number for which to calculate the square root. /// @return result The result as an SD59x18 number. function sqrt(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = unwrap(x); if (xInt < 0) { revert PRBMath_SD59x18_Sqrt_NegativeInput(x); } if (xInt > uMAX_SD59x18 / uUNIT) { revert PRBMath_SD59x18_Sqrt_Overflow(x); } unchecked { // Multiply x by `UNIT` to account for the factor of `UNIT` that is picked up when multiplying two SD59x18 // numbers together (in this case, the two numbers are both the square root). uint256 resultUint = prbSqrt(uint256(xInt * uUNIT)); result = wrap(int256(resultUint)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import "./Casting.sol" as C; import "./Helpers.sol" as H; import "./Math.sol" as M; /// @notice The signed 59.18-decimal fixed-point number representation, which can have up to 59 digits and up to 18 decimals. /// The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity type int256. type SD59x18 is int256; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { C.intoInt256, C.intoSD1x18, C.intoUD2x18, C.intoUD60x18, C.intoUint256, C.intoUint128, C.intoUint40, C.unwrap } for SD59x18 global; /*////////////////////////////////////////////////////////////////////////// MATHEMATICAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ using { M.abs, M.avg, M.ceil, M.div, M.exp, M.exp2, M.floor, M.frac, M.gm, M.inv, M.log10, M.log2, M.ln, M.mul, M.pow, M.powu, M.sqrt } for SD59x18 global; /*////////////////////////////////////////////////////////////////////////// HELPER FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ using { H.add, H.and, H.eq, H.gt, H.gte, H.isZero, H.lshift, H.lt, H.lte, H.mod, H.neq, H.or, H.rshift, H.sub, H.uncheckedAdd, H.uncheckedSub, H.uncheckedUnary, H.xor } for SD59x18 global;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { MAX_UINT40 } from "../Common.sol"; import { uMAX_SD1x18 } from "../sd1x18/Constants.sol"; import { SD1x18 } from "../sd1x18/ValueType.sol"; import { SD59x18 } from "../sd59x18/ValueType.sol"; import { UD2x18 } from "../ud2x18/ValueType.sol"; import { UD60x18 } from "../ud60x18/ValueType.sol"; import { PRBMath_UD2x18_IntoSD1x18_Overflow, PRBMath_UD2x18_IntoUint40_Overflow } from "./Errors.sol"; import { UD2x18 } from "./ValueType.sol"; /// @notice Casts an UD2x18 number into SD1x18. /// - x must be less than or equal to `uMAX_SD1x18`. function intoSD1x18(UD2x18 x) pure returns (SD1x18 result) { uint64 xUint = UD2x18.unwrap(x); if (xUint > uint64(uMAX_SD1x18)) { revert PRBMath_UD2x18_IntoSD1x18_Overflow(x); } result = SD1x18.wrap(int64(xUint)); } /// @notice Casts an UD2x18 number into SD59x18. /// @dev There is no overflow check because the domain of UD2x18 is a subset of SD59x18. function intoSD59x18(UD2x18 x) pure returns (SD59x18 result) { result = SD59x18.wrap(int256(uint256(UD2x18.unwrap(x)))); } /// @notice Casts an UD2x18 number into UD60x18. /// @dev There is no overflow check because the domain of UD2x18 is a subset of UD60x18. function intoUD60x18(UD2x18 x) pure returns (UD60x18 result) { result = UD60x18.wrap(UD2x18.unwrap(x)); } /// @notice Casts an UD2x18 number into uint128. /// @dev There is no overflow check because the domain of UD2x18 is a subset of uint128. function intoUint128(UD2x18 x) pure returns (uint128 result) { result = uint128(UD2x18.unwrap(x)); } /// @notice Casts an UD2x18 number into uint256. /// @dev There is no overflow check because the domain of UD2x18 is a subset of uint256. function intoUint256(UD2x18 x) pure returns (uint256 result) { result = uint256(UD2x18.unwrap(x)); } /// @notice Casts an UD2x18 number into uint40. /// @dev Requirements: /// - x must be less than or equal to `MAX_UINT40`. function intoUint40(UD2x18 x) pure returns (uint40 result) { uint64 xUint = UD2x18.unwrap(x); if (xUint > uint64(MAX_UINT40)) { revert PRBMath_UD2x18_IntoUint40_Overflow(x); } result = uint40(xUint); } /// @notice Alias for the `wrap` function. function ud2x18(uint64 x) pure returns (UD2x18 result) { result = wrap(x); } /// @notice Unwrap an UD2x18 number into uint64. function unwrap(UD2x18 x) pure returns (uint64 result) { result = UD2x18.unwrap(x); } /// @notice Wraps an uint64 number into the UD2x18 value type. function wrap(uint64 x) pure returns (UD2x18 result) { result = UD2x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { UD2x18 } from "./ValueType.sol"; /// @dev Euler's number as an UD2x18 number. UD2x18 constant E = UD2x18.wrap(2_718281828459045235); /// @dev The maximum value an UD2x18 number can have. uint64 constant uMAX_UD2x18 = 18_446744073709551615; UD2x18 constant MAX_UD2x18 = UD2x18.wrap(uMAX_UD2x18); /// @dev PI as an UD2x18 number. UD2x18 constant PI = UD2x18.wrap(3_141592653589793238); /// @dev The unit amount that implies how many trailing decimals can be represented. uint256 constant uUNIT = 1e18; UD2x18 constant UNIT = UD2x18.wrap(1e18);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { UD2x18 } from "./ValueType.sol"; /// @notice Emitted when trying to cast a UD2x18 number that doesn't fit in SD1x18. error PRBMath_UD2x18_IntoSD1x18_Overflow(UD2x18 x); /// @notice Emitted when trying to cast a UD2x18 number that doesn't fit in uint40. error PRBMath_UD2x18_IntoUint40_Overflow(UD2x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import "./Casting.sol" as C; /// @notice The unsigned 2.18-decimal fixed-point number representation, which can have up to 2 digits and up to 18 decimals. /// The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity type uint64. /// This is useful when end users want to use uint64 to save gas, e.g. with tight variable packing in contract storage. type UD2x18 is uint64; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { C.intoSD1x18, C.intoSD59x18, C.intoUD60x18, C.intoUint256, C.intoUint128, C.intoUint40, C.unwrap } for UD2x18 global;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { MAX_UINT128, MAX_UINT40 } from "../Common.sol"; import { uMAX_SD1x18 } from "../sd1x18/Constants.sol"; import { SD1x18 } from "../sd1x18/ValueType.sol"; import { uMAX_SD59x18 } from "../sd59x18/Constants.sol"; import { SD59x18 } from "../sd59x18/ValueType.sol"; import { uMAX_UD2x18 } from "../ud2x18/Constants.sol"; import { UD2x18 } from "../ud2x18/ValueType.sol"; import { PRBMath_UD60x18_IntoSD1x18_Overflow, PRBMath_UD60x18_IntoUD2x18_Overflow, PRBMath_UD60x18_IntoSD59x18_Overflow, PRBMath_UD60x18_IntoUint128_Overflow, PRBMath_UD60x18_IntoUint40_Overflow } from "./Errors.sol"; import { UD60x18 } from "./ValueType.sol"; /// @notice Casts an UD60x18 number into SD1x18. /// @dev Requirements: /// - x must be less than or equal to `uMAX_SD1x18`. function intoSD1x18(UD60x18 x) pure returns (SD1x18 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > uint256(int256(uMAX_SD1x18))) { revert PRBMath_UD60x18_IntoSD1x18_Overflow(x); } result = SD1x18.wrap(int64(uint64(xUint))); } /// @notice Casts an UD60x18 number into UD2x18. /// @dev Requirements: /// - x must be less than or equal to `uMAX_UD2x18`. function intoUD2x18(UD60x18 x) pure returns (UD2x18 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > uMAX_UD2x18) { revert PRBMath_UD60x18_IntoUD2x18_Overflow(x); } result = UD2x18.wrap(uint64(xUint)); } /// @notice Casts an UD60x18 number into SD59x18. /// @dev Requirements: /// - x must be less than or equal to `uMAX_SD59x18`. function intoSD59x18(UD60x18 x) pure returns (SD59x18 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > uint256(uMAX_SD59x18)) { revert PRBMath_UD60x18_IntoSD59x18_Overflow(x); } result = SD59x18.wrap(int256(xUint)); } /// @notice Casts an UD60x18 number into uint128. /// @dev This is basically a functional alias for the `unwrap` function. function intoUint256(UD60x18 x) pure returns (uint256 result) { result = UD60x18.unwrap(x); } /// @notice Casts an UD60x18 number into uint128. /// @dev Requirements: /// - x must be less than or equal to `MAX_UINT128`. function intoUint128(UD60x18 x) pure returns (uint128 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > MAX_UINT128) { revert PRBMath_UD60x18_IntoUint128_Overflow(x); } result = uint128(xUint); } /// @notice Casts an UD60x18 number into uint40. /// @dev Requirements: /// - x must be less than or equal to `MAX_UINT40`. function intoUint40(UD60x18 x) pure returns (uint40 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > MAX_UINT40) { revert PRBMath_UD60x18_IntoUint40_Overflow(x); } result = uint40(xUint); } /// @notice Alias for the `wrap` function. function ud(uint256 x) pure returns (UD60x18 result) { result = wrap(x); } /// @notice Alias for the `wrap` function. function ud60x18(uint256 x) pure returns (UD60x18 result) { result = wrap(x); } /// @notice Unwraps an UD60x18 number into uint256. function unwrap(UD60x18 x) pure returns (uint256 result) { result = UD60x18.unwrap(x); } /// @notice Wraps an uint256 number into the UD60x18 value type. function wrap(uint256 x) pure returns (UD60x18 result) { result = UD60x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { UD60x18 } from "./ValueType.sol"; /// @dev Euler's number as an UD60x18 number. UD60x18 constant E = UD60x18.wrap(2_718281828459045235); /// @dev Half the UNIT number. uint256 constant uHALF_UNIT = 0.5e18; UD60x18 constant HALF_UNIT = UD60x18.wrap(uHALF_UNIT); /// @dev log2(10) as an UD60x18 number. uint256 constant uLOG2_10 = 3_321928094887362347; UD60x18 constant LOG2_10 = UD60x18.wrap(uLOG2_10); /// @dev log2(e) as an UD60x18 number. uint256 constant uLOG2_E = 1_442695040888963407; UD60x18 constant LOG2_E = UD60x18.wrap(uLOG2_E); /// @dev The maximum value an UD60x18 number can have. uint256 constant uMAX_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_584007913129639935; UD60x18 constant MAX_UD60x18 = UD60x18.wrap(uMAX_UD60x18); /// @dev The maximum whole value an UD60x18 number can have. uint256 constant uMAX_WHOLE_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_000000000000000000; UD60x18 constant MAX_WHOLE_UD60x18 = UD60x18.wrap(uMAX_WHOLE_UD60x18); /// @dev PI as an UD60x18 number. UD60x18 constant PI = UD60x18.wrap(3_141592653589793238); /// @dev The unit amount that implies how many trailing decimals can be represented. uint256 constant uUNIT = 1e18; UD60x18 constant UNIT = UD60x18.wrap(uUNIT); /// @dev Zero as an UD60x18 number. UD60x18 constant ZERO = UD60x18.wrap(0);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { uMAX_UD60x18, uUNIT } from "./Constants.sol"; import { PRBMath_UD60x18_Convert_Overflow } from "./Errors.sol"; import { UD60x18 } from "./ValueType.sol"; /// @notice Converts an UD60x18 number to a simple integer by dividing it by `UNIT`. Rounds towards zero in the process. /// @dev Rounds down in the process. /// @param x The UD60x18 number to convert. /// @return result The same number in basic integer form. function convert(UD60x18 x) pure returns (uint256 result) { result = UD60x18.unwrap(x) / uUNIT; } /// @notice Converts a simple integer to UD60x18 by multiplying it by `UNIT`. /// /// @dev Requirements: /// - x must be less than or equal to `MAX_UD60x18` divided by `UNIT`. /// /// @param x The basic integer to convert. /// @param result The same number converted to UD60x18. function convert(uint256 x) pure returns (UD60x18 result) { if (x > uMAX_UD60x18 / uUNIT) { revert PRBMath_UD60x18_Convert_Overflow(x); } unchecked { result = UD60x18.wrap(x * uUNIT); } } /// @notice Alias for the `convert` function defined above. /// @dev Here for backward compatibility. Will be removed in V4. function fromUD60x18(UD60x18 x) pure returns (uint256 result) { result = convert(x); } /// @notice Alias for the `convert` function defined above. /// @dev Here for backward compatibility. Will be removed in V4. function toUD60x18(uint256 x) pure returns (UD60x18 result) { result = convert(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { UD60x18 } from "./ValueType.sol"; /// @notice Emitted when ceiling a number overflows UD60x18. error PRBMath_UD60x18_Ceil_Overflow(UD60x18 x); /// @notice Emitted when converting a basic integer to the fixed-point format overflows UD60x18. error PRBMath_UD60x18_Convert_Overflow(uint256 x); /// @notice Emitted when taking the natural exponent of a base greater than 133.084258667509499441. error PRBMath_UD60x18_Exp_InputTooBig(UD60x18 x); /// @notice Emitted when taking the binary exponent of a base greater than 192. error PRBMath_UD60x18_Exp2_InputTooBig(UD60x18 x); /// @notice Emitted when taking the geometric mean of two numbers and multiplying them overflows UD60x18. error PRBMath_UD60x18_Gm_Overflow(UD60x18 x, UD60x18 y); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in SD1x18. error PRBMath_UD60x18_IntoSD1x18_Overflow(UD60x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in SD59x18. error PRBMath_UD60x18_IntoSD59x18_Overflow(UD60x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in UD2x18. error PRBMath_UD60x18_IntoUD2x18_Overflow(UD60x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint128. error PRBMath_UD60x18_IntoUint128_Overflow(UD60x18 x); /// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint40. error PRBMath_UD60x18_IntoUint40_Overflow(UD60x18 x); /// @notice Emitted when taking the logarithm of a number less than 1. error PRBMath_UD60x18_Log_InputTooSmall(UD60x18 x); /// @notice Emitted when calculating the square root overflows UD60x18. error PRBMath_UD60x18_Sqrt_Overflow(UD60x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { unwrap, wrap } from "./Casting.sol"; import { UD60x18 } from "./ValueType.sol"; /// @notice Implements the checked addition operation (+) in the UD60x18 type. function add(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(unwrap(x) + unwrap(y)); } /// @notice Implements the AND (&) bitwise operation in the UD60x18 type. function and(UD60x18 x, uint256 bits) pure returns (UD60x18 result) { result = wrap(unwrap(x) & bits); } /// @notice Implements the equal operation (==) in the UD60x18 type. function eq(UD60x18 x, UD60x18 y) pure returns (bool result) { result = unwrap(x) == unwrap(y); } /// @notice Implements the greater than operation (>) in the UD60x18 type. function gt(UD60x18 x, UD60x18 y) pure returns (bool result) { result = unwrap(x) > unwrap(y); } /// @notice Implements the greater than or equal to operation (>=) in the UD60x18 type. function gte(UD60x18 x, UD60x18 y) pure returns (bool result) { result = unwrap(x) >= unwrap(y); } /// @notice Implements a zero comparison check function in the UD60x18 type. function isZero(UD60x18 x) pure returns (bool result) { // This wouldn't work if x could be negative. result = unwrap(x) == 0; } /// @notice Implements the left shift operation (<<) in the UD60x18 type. function lshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) { result = wrap(unwrap(x) << bits); } /// @notice Implements the lower than operation (<) in the UD60x18 type. function lt(UD60x18 x, UD60x18 y) pure returns (bool result) { result = unwrap(x) < unwrap(y); } /// @notice Implements the lower than or equal to operation (<=) in the UD60x18 type. function lte(UD60x18 x, UD60x18 y) pure returns (bool result) { result = unwrap(x) <= unwrap(y); } /// @notice Implements the checked modulo operation (%) in the UD60x18 type. function mod(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(unwrap(x) % unwrap(y)); } /// @notice Implements the not equal operation (!=) in the UD60x18 type function neq(UD60x18 x, UD60x18 y) pure returns (bool result) { result = unwrap(x) != unwrap(y); } /// @notice Implements the OR (|) bitwise operation in the UD60x18 type. function or(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(unwrap(x) | unwrap(y)); } /// @notice Implements the right shift operation (>>) in the UD60x18 type. function rshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) { result = wrap(unwrap(x) >> bits); } /// @notice Implements the checked subtraction operation (-) in the UD60x18 type. function sub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(unwrap(x) - unwrap(y)); } /// @notice Implements the unchecked addition operation (+) in the UD60x18 type. function uncheckedAdd(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { unchecked { result = wrap(unwrap(x) + unwrap(y)); } } /// @notice Implements the unchecked subtraction operation (-) in the UD60x18 type. function uncheckedSub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { unchecked { result = wrap(unwrap(x) - unwrap(y)); } } /// @notice Implements the XOR (^) bitwise operation in the UD60x18 type. function xor(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(unwrap(x) ^ unwrap(y)); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { msb, mulDiv, mulDiv18, prbExp2, prbSqrt } from "../Common.sol"; import { unwrap, wrap } from "./Casting.sol"; import { uHALF_UNIT, uLOG2_10, uLOG2_E, uMAX_UD60x18, uMAX_WHOLE_UD60x18, UNIT, uUNIT, ZERO } from "./Constants.sol"; import { PRBMath_UD60x18_Ceil_Overflow, PRBMath_UD60x18_Exp_InputTooBig, PRBMath_UD60x18_Exp2_InputTooBig, PRBMath_UD60x18_Gm_Overflow, PRBMath_UD60x18_Log_InputTooSmall, PRBMath_UD60x18_Sqrt_Overflow } from "./Errors.sol"; import { UD60x18 } from "./ValueType.sol"; /*////////////////////////////////////////////////////////////////////////// MATHEMATICAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice Calculates the arithmetic average of x and y, rounding down. /// /// @dev Based on the formula: /// /// $$ /// avg(x, y) = (x & y) + ((xUint ^ yUint) / 2) /// $$ // /// In English, what this formula does is: /// /// 1. AND x and y. /// 2. Calculate half of XOR x and y. /// 3. Add the two results together. /// /// This technique is known as SWAR, which stands for "SIMD within a register". You can read more about it here: /// https://devblogs.microsoft.com/oldnewthing/20220207-00/?p=106223 /// /// @param x The first operand as an UD60x18 number. /// @param y The second operand as an UD60x18 number. /// @return result The arithmetic average as an UD60x18 number. function avg(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { uint256 xUint = unwrap(x); uint256 yUint = unwrap(y); unchecked { result = wrap((xUint & yUint) + ((xUint ^ yUint) >> 1)); } } /// @notice Yields the smallest whole UD60x18 number greater than or equal to x. /// /// @dev This is optimized for fractional value inputs, because for every whole value there are "1e18 - 1" fractional /// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// /// Requirements: /// - x must be less than or equal to `MAX_WHOLE_UD60x18`. /// /// @param x The UD60x18 number to ceil. /// @param result The least number greater than or equal to x, as an UD60x18 number. function ceil(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = unwrap(x); if (xUint > uMAX_WHOLE_UD60x18) { revert PRBMath_UD60x18_Ceil_Overflow(x); } assembly ("memory-safe") { // Equivalent to "x % UNIT" but faster. let remainder := mod(x, uUNIT) // Equivalent to "UNIT - remainder" but faster. let delta := sub(uUNIT, remainder) // Equivalent to "x + delta * (remainder > 0 ? 1 : 0)" but faster. result := add(x, mul(delta, gt(remainder, 0))) } } /// @notice Divides two UD60x18 numbers, returning a new UD60x18 number. Rounds towards zero. /// /// @dev Uses `mulDiv` to enable overflow-safe multiplication and division. /// /// Requirements: /// - The denominator cannot be zero. /// /// @param x The numerator as an UD60x18 number. /// @param y The denominator as an UD60x18 number. /// @param result The quotient as an UD60x18 number. function div(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(mulDiv(unwrap(x), uUNIT, unwrap(y))); } /// @notice Calculates the natural exponent of x. /// /// @dev Based on the formula: /// /// $$ /// e^x = 2^{x * log_2{e}} /// $$ /// /// Requirements: /// - All from `log2`. /// - x must be less than 133.084258667509499441. /// /// @param x The exponent as an UD60x18 number. /// @return result The result as an UD60x18 number. function exp(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = unwrap(x); // Without this check, the value passed to `exp2` would be greater than 192. if (xUint >= 133_084258667509499441) { revert PRBMath_UD60x18_Exp_InputTooBig(x); } unchecked { // We do the fixed-point multiplication inline rather than via the `mul` function to save gas. uint256 doubleUnitProduct = xUint * uLOG2_E; result = exp2(wrap(doubleUnitProduct / uUNIT)); } } /// @notice Calculates the binary exponent of x using the binary fraction method. /// /// @dev See https://ethereum.stackexchange.com/q/79903/24693. /// /// Requirements: /// - x must be 192 or less. /// - The result must fit within `MAX_UD60x18`. /// /// @param x The exponent as an UD60x18 number. /// @return result The result as an UD60x18 number. function exp2(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = unwrap(x); // Numbers greater than or equal to 2^192 don't fit within the 192.64-bit format. if (xUint >= 192e18) { revert PRBMath_UD60x18_Exp2_InputTooBig(x); } // Convert x to the 192.64-bit fixed-point format. uint256 x_192x64 = (xUint << 64) / uUNIT; // Pass x to the `prbExp2` function, which uses the 192.64-bit fixed-point number representation. result = wrap(prbExp2(x_192x64)); } /// @notice Yields the greatest whole UD60x18 number less than or equal to x. /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts. /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// @param x The UD60x18 number to floor. /// @param result The greatest integer less than or equal to x, as an UD60x18 number. function floor(UD60x18 x) pure returns (UD60x18 result) { assembly ("memory-safe") { // Equivalent to "x % UNIT" but faster. let remainder := mod(x, uUNIT) // Equivalent to "x - remainder * (remainder > 0 ? 1 : 0)" but faster. result := sub(x, mul(remainder, gt(remainder, 0))) } } /// @notice Yields the excess beyond the floor of x. /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part. /// @param x The UD60x18 number to get the fractional part of. /// @param result The fractional part of x as an UD60x18 number. function frac(UD60x18 x) pure returns (UD60x18 result) { assembly ("memory-safe") { result := mod(x, uUNIT) } } /// @notice Calculates the geometric mean of x and y, i.e. $$sqrt(x * y)$$, rounding down. /// /// @dev Requirements: /// - x * y must fit within `MAX_UD60x18`, lest it overflows. /// /// @param x The first operand as an UD60x18 number. /// @param y The second operand as an UD60x18 number. /// @return result The result as an UD60x18 number. function gm(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { uint256 xUint = unwrap(x); uint256 yUint = unwrap(y); if (xUint == 0 || yUint == 0) { return ZERO; } unchecked { // Checking for overflow this way is faster than letting Solidity do it. uint256 xyUint = xUint * yUint; if (xyUint / xUint != yUint) { revert PRBMath_UD60x18_Gm_Overflow(x, y); } // We don't need to multiply the result by `UNIT` here because the x*y product had picked up a factor of `UNIT` // during multiplication. See the comments in the `prbSqrt` function. result = wrap(prbSqrt(xyUint)); } } /// @notice Calculates 1 / x, rounding toward zero. /// /// @dev Requirements: /// - x cannot be zero. /// /// @param x The UD60x18 number for which to calculate the inverse. /// @return result The inverse as an UD60x18 number. function inv(UD60x18 x) pure returns (UD60x18 result) { unchecked { // 1e36 is UNIT * UNIT. result = wrap(1e36 / unwrap(x)); } } /// @notice Calculates the natural logarithm of x. /// /// @dev Based on the formula: /// /// $$ /// ln{x} = log_2{x} / log_2{e}$$. /// $$ /// /// Requirements: /// - All from `log2`. /// /// Caveats: /// - All from `log2`. /// - This doesn't return exactly 1 for 2.718281828459045235, for that more fine-grained precision is needed. /// /// @param x The UD60x18 number for which to calculate the natural logarithm. /// @return result The natural logarithm as an UD60x18 number. function ln(UD60x18 x) pure returns (UD60x18 result) { unchecked { // We do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value // that `log2` can return is 196.205294292027477728. result = wrap((unwrap(log2(x)) * uUNIT) / uLOG2_E); } } /// @notice Calculates the common logarithm of x. /// /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common /// logarithm based on the formula: /// /// $$ /// log_{10}{x} = log_2{x} / log_2{10} /// $$ /// /// Requirements: /// - All from `log2`. /// /// Caveats: /// - All from `log2`. /// /// @param x The UD60x18 number for which to calculate the common logarithm. /// @return result The common logarithm as an UD60x18 number. function log10(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = unwrap(x); if (xUint < uUNIT) { revert PRBMath_UD60x18_Log_InputTooSmall(x); } // Note that the `mul` in this assembly block is the assembly multiplication operation, not the UD60x18 `mul`. // prettier-ignore assembly ("memory-safe") { switch x case 1 { result := mul(uUNIT, sub(0, 18)) } case 10 { result := mul(uUNIT, sub(1, 18)) } case 100 { result := mul(uUNIT, sub(2, 18)) } case 1000 { result := mul(uUNIT, sub(3, 18)) } case 10000 { result := mul(uUNIT, sub(4, 18)) } case 100000 { result := mul(uUNIT, sub(5, 18)) } case 1000000 { result := mul(uUNIT, sub(6, 18)) } case 10000000 { result := mul(uUNIT, sub(7, 18)) } case 100000000 { result := mul(uUNIT, sub(8, 18)) } case 1000000000 { result := mul(uUNIT, sub(9, 18)) } case 10000000000 { result := mul(uUNIT, sub(10, 18)) } case 100000000000 { result := mul(uUNIT, sub(11, 18)) } case 1000000000000 { result := mul(uUNIT, sub(12, 18)) } case 10000000000000 { result := mul(uUNIT, sub(13, 18)) } case 100000000000000 { result := mul(uUNIT, sub(14, 18)) } case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) } case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) } case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) } case 1000000000000000000 { result := 0 } case 10000000000000000000 { result := uUNIT } case 100000000000000000000 { result := mul(uUNIT, 2) } case 1000000000000000000000 { result := mul(uUNIT, 3) } case 10000000000000000000000 { result := mul(uUNIT, 4) } case 100000000000000000000000 { result := mul(uUNIT, 5) } case 1000000000000000000000000 { result := mul(uUNIT, 6) } case 10000000000000000000000000 { result := mul(uUNIT, 7) } case 100000000000000000000000000 { result := mul(uUNIT, 8) } case 1000000000000000000000000000 { result := mul(uUNIT, 9) } case 10000000000000000000000000000 { result := mul(uUNIT, 10) } case 100000000000000000000000000000 { result := mul(uUNIT, 11) } case 1000000000000000000000000000000 { result := mul(uUNIT, 12) } case 10000000000000000000000000000000 { result := mul(uUNIT, 13) } case 100000000000000000000000000000000 { result := mul(uUNIT, 14) } case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) } case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) } case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) } case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) } case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) } case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) } case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) } case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) } case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) } case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) } case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) } case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) } case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) } case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) } case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) } case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) } case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) } case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) } case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) } case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) } case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) } case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) } case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) } case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) } case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) } case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) } case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) } case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) } case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) } case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) } case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) } case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) } case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) } case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) } case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) } case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) } case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) } case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) } case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) } case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) } case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) } case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) } case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) } case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) } case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 59) } default { result := uMAX_UD60x18 } } if (unwrap(result) == uMAX_UD60x18) { unchecked { // Do the fixed-point division inline to save gas. result = wrap((unwrap(log2(x)) * uUNIT) / uLOG2_10); } } } /// @notice Calculates the binary logarithm of x. /// /// @dev Based on the iterative approximation algorithm. /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation /// /// Requirements: /// - x must be greater than or equal to UNIT, otherwise the result would be negative. /// /// Caveats: /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation. /// /// @param x The UD60x18 number for which to calculate the binary logarithm. /// @return result The binary logarithm as an UD60x18 number. function log2(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = unwrap(x); if (xUint < uUNIT) { revert PRBMath_UD60x18_Log_InputTooSmall(x); } unchecked { // Calculate the integer part of the logarithm, add it to the result and finally calculate y = x * 2^(-n). uint256 n = msb(xUint / uUNIT); // This is the integer part of the logarithm as an UD60x18 number. The operation can't overflow because n // n is maximum 255 and UNIT is 1e18. uint256 resultUint = n * uUNIT; // This is $y = x * 2^{-n}$. uint256 y = xUint >> n; // If y is 1, the fractional part is zero. if (y == uUNIT) { return wrap(resultUint); } // Calculate the fractional part via the iterative approximation. // The "delta.rshift(1)" part is equivalent to "delta /= 2", but shifting bits is faster. uint256 DOUBLE_UNIT = 2e18; for (uint256 delta = uHALF_UNIT; delta > 0; delta >>= 1) { y = (y * y) / uUNIT; // Is y^2 > 2 and so in the range [2,4)? if (y >= DOUBLE_UNIT) { // Add the 2^{-m} factor to the logarithm. resultUint += delta; // Corresponds to z/2 on Wikipedia. y >>= 1; } } result = wrap(resultUint); } } /// @notice Multiplies two UD60x18 numbers together, returning a new UD60x18 number. /// @dev See the documentation for the `Common.mulDiv18` function. /// @param x The multiplicand as an UD60x18 number. /// @param y The multiplier as an UD60x18 number. /// @return result The product as an UD60x18 number. function mul(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(mulDiv18(unwrap(x), unwrap(y))); } /// @notice Raises x to the power of y. /// /// @dev Based on the formula: /// /// $$ /// x^y = 2^{log_2{x} * y} /// $$ /// /// Requirements: /// - All from `exp2`, `log2` and `mul`. /// /// Caveats: /// - All from `exp2`, `log2` and `mul`. /// - Assumes 0^0 is 1. /// /// @param x Number to raise to given power y, as an UD60x18 number. /// @param y Exponent to raise x to, as an UD60x18 number. /// @return result x raised to power y, as an UD60x18 number. function pow(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { uint256 xUint = unwrap(x); uint256 yUint = unwrap(y); if (xUint == 0) { result = yUint == 0 ? UNIT : ZERO; } else { if (yUint == uUNIT) { result = x; } else { result = exp2(mul(log2(x), y)); } } } /// @notice Raises x (an UD60x18 number) to the power y (unsigned basic integer) using the famous algorithm /// "exponentiation by squaring". /// /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring /// /// Requirements: /// - The result must fit within `MAX_UD60x18`. /// /// Caveats: /// - All from "Common.mulDiv18". /// - Assumes 0^0 is 1. /// /// @param x The base as an UD60x18 number. /// @param y The exponent as an uint256. /// @return result The result as an UD60x18 number. function powu(UD60x18 x, uint256 y) pure returns (UD60x18 result) { // Calculate the first iteration of the loop in advance. uint256 xUint = unwrap(x); uint256 resultUint = y & 1 > 0 ? xUint : uUNIT; // Equivalent to "for(y /= 2; y > 0; y /= 2)" but faster. for (y >>= 1; y > 0; y >>= 1) { xUint = mulDiv18(xUint, xUint); // Equivalent to "y % 2 == 1" but faster. if (y & 1 > 0) { resultUint = mulDiv18(resultUint, xUint); } } result = wrap(resultUint); } /// @notice Calculates the square root of x, rounding down. /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. /// /// Requirements: /// - x must be less than `MAX_UD60x18` divided by `UNIT`. /// /// @param x The UD60x18 number for which to calculate the square root. /// @return result The result as an UD60x18 number. function sqrt(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = unwrap(x); unchecked { if (xUint > uMAX_UD60x18 / uUNIT) { revert PRBMath_UD60x18_Sqrt_Overflow(x); } // Multiply x by `UNIT` to account for the factor of `UNIT` that is picked up when multiplying two UD60x18 // numbers together (in this case, the two numbers are both the square root). result = wrap(prbSqrt(xUint * uUNIT)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import "./Casting.sol" as C; import "./Helpers.sol" as H; import "./Math.sol" as M; /// @notice The unsigned 60.18-decimal fixed-point number representation, which can have up to 60 digits and up to 18 decimals. /// The values of this are bound by the minimum and the maximum values permitted by the Solidity type uint256. /// @dev The value type is defined here so it can be imported in all other files. type UD60x18 is uint256; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { C.intoSD1x18, C.intoUD2x18, C.intoSD59x18, C.intoUint128, C.intoUint256, C.intoUint40, C.unwrap } for UD60x18 global; /*////////////////////////////////////////////////////////////////////////// MATHEMATICAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// The global "using for" directive makes the functions in this library callable on the UD60x18 type. using { M.avg, M.ceil, M.div, M.exp, M.exp2, M.floor, M.frac, M.gm, M.inv, M.ln, M.log10, M.log2, M.mul, M.pow, M.powu, M.sqrt } for UD60x18 global; /*////////////////////////////////////////////////////////////////////////// HELPER FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// The global "using for" directive makes the functions in this library callable on the UD60x18 type. using { H.add, H.and, H.eq, H.gt, H.gte, H.isZero, H.lshift, H.lt, H.lte, H.mod, H.neq, H.or, H.rshift, H.sub, H.uncheckedAdd, H.uncheckedSub, H.xor } for UD60x18 global;
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {OwnableUpgradeable, Initializable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {IERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol"; import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import {AddressUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import {UD60x18, ud, convert} from "@prb/math/UD60x18.sol"; import {ECDSAUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; import {EIP712Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol"; import {IMagicDomainRegistrar} from "./interfaces/IMagicDomainRegistrar.sol"; import {IMagicDomainReverseRegistrar} from "./interfaces/IMagicDomainReverseRegistrar.sol"; import {IMagicDomainRegistrarController} from "./interfaces/IMagicDomainRegistrarController.sol"; import {LibStrings} from "./libs/LibStrings.sol"; import "forge-std/console2.sol"; /** * @dev A registrar controller for registering handling registration/renewals */ contract MagicDomainRegistrarController is OwnableUpgradeable, EIP712Upgradeable, IMagicDomainRegistrarController, IERC165Upgradeable { using LibStrings for *; using AddressUpgradeable for address; using ECDSAUpgradeable for bytes32; bytes32 public constant REGISTERARGS_TYPE_HASH = keccak256("RegisterArgs(string name,string discriminant,address owner,address resolver,uint96 nonce)"); address public signingAuthority; IMagicDomainRegistrar public registrar; IMagicDomainReverseRegistrar public reverseRegistrar; mapping(uint96 => bool) public nonceUsed; /** * @notice address = payment token, PriceInfo is how to get associated costs for payment */ mapping(address => PriceInfo) public tagChangePriceInfo; /** * @notice Stores which PriceInfo should be used when changing a tag without specifying a payment token */ address public defaultPaymentTokenAddress; function initialize( IMagicDomainRegistrar _registrar, IMagicDomainReverseRegistrar _reverseRegistrar, address _signingAuthority ) external initializer { __Ownable_init(); __EIP712_init("MagicDomains", "1.0.0"); registrar = _registrar; reverseRegistrar = _reverseRegistrar; signingAuthority = _signingAuthority; } function valid(string memory name) public pure returns (bool) { return name.strlen() >= 3; } function available(string memory name, string memory discriminant) public view override returns (bool) { return valid(name) && registrar.available(registrar.tagToId(name, discriminant)); } function register( RegisterArgs calldata _registerArgs, bytes calldata _authoritySignature ) external override { require(!nonceUsed[_registerArgs.nonce], "MagicDomainRegistrarController: Signature nonce already used"); require(bytes(_registerArgs.discriminant).length == 4, "MagicDomainRegistrarController: Invalid discriminant"); require(_registerArgs.resolver != address(0) && _registerArgs.resolver.isContract(), "MagicDomainRegistrarController: Resolver is EOA"); address signer = registerArgsToHash(_registerArgs).recover(_authoritySignature); if(signer != signingAuthority) { revert InvalidSignature(); } nonceUsed[_registerArgs.nonce] = true; registrar.register(_registerArgs.name, _registerArgs.discriminant, _registerArgs.owner); _setReverseRecord(_registerArgs.name, _registerArgs.discriminant, _registerArgs.resolver, msg.sender); emit NameRegistered( _registerArgs.name, _registerArgs.discriminant, _registerArgs.owner ); } function changeTag( RegisterArgs calldata _registerArgs, bytes calldata _authoritySignature ) external override { require(!nonceUsed[_registerArgs.nonce], "MagicDomainRegistrarController: Signature nonce already used"); require(bytes(_registerArgs.discriminant).length == 4, "MagicDomainRegistrarController: Invalid discriminant"); require(_registerArgs.resolver != address(0) && _registerArgs.resolver.isContract(), "MagicDomainRegistrarController: Resolver is EOA"); address signer = registerArgsToHash(_registerArgs).recover(_authoritySignature); if(signer != signingAuthority) { revert InvalidSignature(); } nonceUsed[_registerArgs.nonce] = true; if(defaultPaymentTokenAddress != address(0)) { _takePayment(defaultPaymentTokenAddress, _registerArgs.owner); } registrar.changeName(_registerArgs.name, _registerArgs.discriminant, _registerArgs.owner); _setReverseRecord(_registerArgs.name, _registerArgs.discriminant, _registerArgs.resolver, msg.sender); emit NameRegistered( _registerArgs.name, _registerArgs.discriminant, _registerArgs.owner ); } function withdraw() public { payable(owner()).transfer(address(this).balance); } function withdrawTokens(address _paymentToken) public { require(IERC20Upgradeable(_paymentToken).transfer(owner(), IERC20Upgradeable(_paymentToken).balanceOf(address(this))), "MagicDomainRegistrarController: Withdrawal unsuccessful"); } function setTagChangePriceInfo(address _paymentToken, PriceInfo calldata _priceInfo) external onlyOwner { require(_priceInfo.calculatePriceFromFeed == (address(_priceInfo.priceFeed) != address(0)), "MagicDomainRegistrarController: Invalid price feed configuration"); tagChangePriceInfo[_paymentToken] = _priceInfo; } function setDefaultPaymentTokenAddress(address _paymentToken) external onlyOwner { defaultPaymentTokenAddress = _paymentToken; } function supportsInterface(bytes4 interfaceID) external pure returns (bool) { return interfaceID == type(IERC165Upgradeable).interfaceId || interfaceID == type(IMagicDomainRegistrarController).interfaceId; } function domainSeparator() public view returns(bytes32) { return _domainSeparatorV4(); } function registerArgsToHash(RegisterArgs calldata _registerArgs) public view returns (bytes32) { return _hashTypedDataV4( keccak256( abi.encode( REGISTERARGS_TYPE_HASH, keccak256(bytes(_registerArgs.name)), keccak256(bytes(_registerArgs.discriminant)), _registerArgs.owner, _registerArgs.resolver, _registerArgs.nonce ) ) ); } function calculatePrice(address _paymentToken) public view returns(uint256 price_) { PriceInfo memory _priceInfo = tagChangePriceInfo[_paymentToken]; price_ = _calculatePrice(_priceInfo); } /* Internal functions */ function _takePayment(address _paymentToken, address _tagOwner) internal { PriceInfo memory _priceInfo = tagChangePriceInfo[_paymentToken]; require(_priceInfo.enabled, "MagicDomainRegistrarController: Default payment token not enabled"); uint256 price = _calculatePrice(_priceInfo); require(IERC20Upgradeable(_paymentToken).transferFrom(_tagOwner, address(this), price), "MagicDomainRegistrarController: Payment unsuccessful"); } function _calculatePrice(PriceInfo memory _priceInfo) public view returns(uint256 price_) { if(_priceInfo.calculatePriceFromFeed) { (, int256 quotePrice,,,) = _priceInfo.priceFeed.latestRoundData(); // Unfortunately no way to determine this ahead of time, and likely will never occur, but is a possibility of the oracle require(quotePrice >= 0, "MagicDomainRegistrarController: Only spot price feeds are supported."); // Complex ex: Price is 10 USD and quote price for MAGIC is 1.82 USD, 10 / 1.82 = 5.494505494505495 MAGIC // Because fixed precision is e18, value will be 5494505494505494505 and needs to be converted to payment token decimal // NOTE: It is assumed that the PriceInfo.price and price feed's price are in the same decimal unit UD60x18 priceFP = ud(_priceInfo.price).div(ud(uint256(quotePrice))); // Lastly, we must convert the price into the payment token's decimal amount if(_priceInfo.paymentTokenDecimals > 18) { // Add digits equal to the difference of fp's 18 decimals and the payment token's decimals price_ = priceFP.unwrap() * 10 ** (_priceInfo.paymentTokenDecimals - 18); } else { // Remove digits equal to the difference of fp's 18 decimals and the payment token's decimals price_ = priceFP.unwrap() / 10 ** (18 - _priceInfo.paymentTokenDecimals); } } else { price_ = _priceInfo.price; } } function _setReverseRecord( string memory name, string memory discriminant, address resolver, address owner ) internal { reverseRegistrar.setNameForAddr( msg.sender, owner, resolver, string.concat(name, ".", discriminant, ".magic") // ex: myname#1234 should be: myname.1234.magic ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IMagicDomainRegistrar { event NameRegistered(uint256 indexed id, address indexed owner); event NameRemoved(uint256 indexed id, address indexed owner); event BaseURIChanged(string from, string to); struct SubdomainMetadata { string name; string discriminant; } // Set the resolver for the TLD this registrar manages. function setResolver(address resolver) external; // Returns true iff the specified name is available for registration. function available(uint256 id) external view returns(bool); /** * @dev Register a node by semi unique name & discriminant. * @param name The semi unique name to register. * @param discriminant The discriminant to make the name unique. * @param owner The address that should own the new name. */ function register(string memory name, string memory discriminant, address owner) external; /** * @dev Exchanges the owner's current name for a new one. * @param newName The new semi unique name. * @param discriminant The discriminant to make the name unique. * @param owner The address that should own the new name. */ function changeName(string memory newName, string memory discriminant, address owner) external; /** * @dev Reclaim ownership of a node in ENS, if you own it in the registrar. */ function reclaim(string memory name, string memory discriminant, address owner) external; /** * @dev Converts a semi unique name with its discriminant into a tokenId. * @param name The semi unique name. * @param discriminant The discriminant to make the name unique. */ function tagToId(string memory name, string memory discriminant) external pure returns(uint256 tokenId_); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; interface IMagicDomainRegistrarController { event NameRegistered( string name, string discriminant, address indexed owner ); error InvalidSignature(); struct RegisterArgs { string name; string discriminant; address owner; address resolver; uint96 nonce; } /** * @dev Used to track Pricing configurations on a per-token basis * @param enabled Whether or not this pricing configuration is enabled * @param priceFeed The price feed to get derived costs from. If its 0x0 then calculatePriceFromFeed will be false * @param calculatePriceFromFeed Helper to ensure priceFeed is set correctly and determines if `price` is a different token value (and/or decimal) * @param paymentTokenDecimals The number of decimals of the base payment token. * Needed to ensure proper funds transferring when decimals in the pair differ * @param price The value set to be validated against. Can be non-payment token amounts when using a price feed */ struct PriceInfo { bool enabled; AggregatorV3Interface priceFeed; bool calculatePriceFromFeed; uint8 paymentTokenDecimals; uint256 price; } function available(string memory name, string memory discriminant) external returns (bool); function register(RegisterArgs calldata _registerArgs, bytes calldata _authoritySignature) external; function changeTag(RegisterArgs calldata _registerArgs, bytes calldata _authoritySignature) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IMagicDomainReverseRegistrar { event ReverseClaimed(address indexed addr, bytes32 indexed node); event DefaultResolverChanged(address indexed resolver); function setDefaultResolver(address resolver) external; function claim(address owner) external returns (bytes32); function claimForAddr( address addr, address owner, address resolver ) external returns (bytes32); function claimWithResolver(address owner, address resolver) external returns (bytes32); function setName(string memory name) external returns (bytes32); function setNameForAddr( address addr, address owner, address resolver, string memory name ) external returns (bytes32); function node(address addr) external pure returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; library LibStrings { /** * @dev Returns the length of a given string * Considers multi-byte characters (ASCII, etc) * * @param s The string to measure the length of * @return len_ The length of the input string */ function strlen(string memory s) internal pure returns (uint256 len_) { uint256 i = 0; uint256 bytelength = bytes(s).length; for (len_ = 0; i < bytelength; len_++) { bytes1 b = bytes(s)[i]; if (b < 0x80) { i += 1; } else if (b < 0xE0) { i += 2; } else if (b < 0xF0) { i += 3; } else if (b < 0xF8) { i += 4; } else if (b < 0xFC) { i += 5; } else { i += 6; } } } }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [ ":@chainlink/contracts/=lib/chainlink/contracts/", ":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", ":@prb/math/=lib/prb-math/src/", ":@prb/test/=lib/prb-math/lib/prb-test/src/", ":chainlink/=lib/chainlink/integration-tests/contracts/ethereum/src/", ":ds-test/=lib/forge-std/lib/ds-test/src/", ":forge-std/=lib/forge-std/src/", ":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", ":prb-math/=lib/prb-math/src/", ":prb-test/=lib/prb-math/lib/prb-test/src/", ":src/=src/" ], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
[{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"PRBMath_MulDiv_Overflow","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"discriminant","type":"string"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"NameRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"REGISTERARGS_TYPE_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"bool","name":"calculatePriceFromFeed","type":"bool"},{"internalType":"uint8","name":"paymentTokenDecimals","type":"uint8"},{"internalType":"uint256","name":"price","type":"uint256"}],"internalType":"struct IMagicDomainRegistrarController.PriceInfo","name":"_priceInfo","type":"tuple"}],"name":"_calculatePrice","outputs":[{"internalType":"uint256","name":"price_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"discriminant","type":"string"}],"name":"available","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_paymentToken","type":"address"}],"name":"calculatePrice","outputs":[{"internalType":"uint256","name":"price_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"discriminant","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"uint96","name":"nonce","type":"uint96"}],"internalType":"struct IMagicDomainRegistrarController.RegisterArgs","name":"_registerArgs","type":"tuple"},{"internalType":"bytes","name":"_authoritySignature","type":"bytes"}],"name":"changeTag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultPaymentTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IMagicDomainRegistrar","name":"_registrar","type":"address"},{"internalType":"contract IMagicDomainReverseRegistrar","name":"_reverseRegistrar","type":"address"},{"internalType":"address","name":"_signingAuthority","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"","type":"uint96"}],"name":"nonceUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"discriminant","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"uint96","name":"nonce","type":"uint96"}],"internalType":"struct IMagicDomainRegistrarController.RegisterArgs","name":"_registerArgs","type":"tuple"},{"internalType":"bytes","name":"_authoritySignature","type":"bytes"}],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"discriminant","type":"string"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"uint96","name":"nonce","type":"uint96"}],"internalType":"struct IMagicDomainRegistrarController.RegisterArgs","name":"_registerArgs","type":"tuple"}],"name":"registerArgsToHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registrar","outputs":[{"internalType":"contract IMagicDomainRegistrar","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reverseRegistrar","outputs":[{"internalType":"contract IMagicDomainReverseRegistrar","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_paymentToken","type":"address"}],"name":"setDefaultPaymentTokenAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_paymentToken","type":"address"},{"components":[{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"bool","name":"calculatePriceFromFeed","type":"bool"},{"internalType":"uint8","name":"paymentTokenDecimals","type":"uint8"},{"internalType":"uint256","name":"price","type":"uint256"}],"internalType":"struct IMagicDomainRegistrarController.PriceInfo","name":"_priceInfo","type":"tuple"}],"name":"setTagChangePriceInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signingAuthority","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tagChangePriceInfo","outputs":[{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"bool","name":"calculatePriceFromFeed","type":"bool"},{"internalType":"uint8","name":"paymentTokenDecimals","type":"uint8"},{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"valid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_paymentToken","type":"address"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061256f806100206000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c8063546c56a4116100c35780639791c0971161007c5780639791c09714610375578063a83bdc0514610388578063c0c53b8b1461039b578063e876452c146103ae578063f2fde38b146103c1578063f698da25146103d457600080fd5b8063546c56a414610300578063656fbeea14610313578063715018a614610336578063808698531461033e5780638da5cb5b1461035157806395f38e771461036257600080fd5b80632b20e397116101155780632b20e397146102815780632dab7dab146102ac5780632f2c20e5146102bf5780633ccfd60b146102d257806344d49f41146102da57806349df728c146102ed57600080fd5b806301ffc9a71461015d5780630c3f3cfb14610185578063180dc257146101985780631dc9b1c114610224578063261a3d9114610245578063275cb9f71461026c575b600080fd5b61017061016b366004611ade565b6103dc565b60405190151581526020015b60405180910390f35b610170610193366004611bab565b610413565b6101ea6101a6366004611c24565b609d602052600090815260409020805460019091015460ff808316926001600160a01b0361010082041692600160a81b8204831692600160b01b9092049091169085565b6040805195151586526001600160a01b0390941660208601529115159284019290925260ff9091166060830152608082015260a00161017c565b610237610232366004611c24565b610506565b60405190815260200161017c565b6102377fb8abcf5dcf4368294cbc8d5067bfa9f6eccabab2ab9db4b0ae79b3478d04a68881565b61027f61027a366004611c59565b610579565b005b609a54610294906001600160a01b031681565b6040516001600160a01b03909116815260200161017c565b61027f6102ba366004611c24565b6108e8565b6102376102cd366004611d0d565b610912565b61027f610a9a565b61027f6102e8366004611d9e565b610ad6565b61027f6102fb366004611c24565b610b9a565b609e54610294906001600160a01b031681565b610170610321366004611dd4565b609c6020526000908152604090205460ff1681565b61027f610cf2565b609b54610294906001600160a01b031681565b6033546001600160a01b0316610294565b61027f610370366004611c59565b610d06565b610170610383366004611dfd565b610ea6565b609954610294906001600160a01b031681565b61027f6103a9366004611e3a565b610ebb565b6102376103bc366004611e85565b611056565b61027f6103cf366004611c24565b61114f565b6102376111c5565b60006001600160e01b031982166301ffc9a760e01b148061040d57506001600160e01b0319821663be900b7b60e01b145b92915050565b600061041e83610ea6565b80156104ff5750609a54604051637db7d43560e11b81526001600160a01b03909116906396e494e890829063fb6fa86a9061045f9088908890600401611f0a565b602060405180830381865afa15801561047c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a09190611f38565b6040518263ffffffff1660e01b81526004016104be91815260200190565b602060405180830381865afa1580156104db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ff9190611f51565b9392505050565b6001600160a01b038082166000908152609d60209081526040808320815160a081018352815460ff80821615158352610100820490971694820194909452600160a81b84048616151592810192909252600160b01b9092049093166060840152600101546080830152906104ff81610912565b609c600061058d60a0860160808701611dd4565b6001600160601b0316815260208101919091526040016000205460ff16156105d05760405162461bcd60e51b81526004016105c790611f6e565b60405180910390fd5b6105dd6020840184611fb9565b90506004146105fe5760405162461bcd60e51b81526004016105c790612000565b60006106106080850160608601611c24565b6001600160a01b03161415801561064457506106446106356080850160608601611c24565b6001600160a01b03163b151590565b6106605760405162461bcd60e51b81526004016105c790612042565b60006106ad83838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506106a792508891506110569050565b906111d4565b6099549091506001600160a01b038083169116146106de57604051638baa579f60e01b815260040160405180910390fd5b6001609c60006106f460a0880160808901611dd4565b6001600160601b031681526020810191909152604001600020805460ff1916911515919091179055609e546001600160a01b03161561075257609e54610752906001600160a01b031661074d6060870160408801611c24565b6111f8565b609a546001600160a01b031663f509f86c61076d8680611fb9565b61077a6020890189611fb9565b61078a60608b0160408c01611c24565b6040518663ffffffff1660e01b81526004016107aa9594939291906120a8565b600060405180830381600087803b1580156107c457600080fd5b505af11580156107d8573d6000803e3d6000fd5b5061087992506107ec915086905080611fb9565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061082e925050506020870187611fb9565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610873925050506080880160608901611c24565b336113ad565b6108896060850160408601611c24565b6001600160a01b03167fe7d10d58c30adabd7fb60d6dd294d3f98e9f7acffc732a2b773465b844de325d6108bd8680611fb9565b6108ca6020890189611fb9565b6040516108da94939291906120ea565b60405180910390a250505050565b6108f0611453565b609e80546001600160a01b0319166001600160a01b0392909216919091179055565b6000816040015115610a8e57600082602001516001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610962573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109869190612136565b50505091505060008112156109ff5760405162461bcd60e51b81526020600482015260446024820181905260008051602061251a833981519152908201527f4f6e6c792073706f742070726963652066656564732061726520737570706f726064820152633a32b21760e11b608482015260a4016105c7565b6000610a20610a0d836114ad565b610a1a86608001516114ad565b906114b5565b90506012846060015160ff161115610a5f5760128460600151610a43919061219c565b610a4e90600a612299565b610a5890826122a8565b9250610a87565b6060840151610a6f90601261219c565b610a7a90600a612299565b610a8490826122d5565b92505b5050919050565b5060808101515b919050565b6033546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610ad3573d6000803e3d6000fd5b50565b610ade611453565b6000610af06040830160208401611c24565b6001600160a01b03161415610b0b60608301604084016122f7565b151514610b70576040805162461bcd60e51b815260206004820152602481019190915260008051602061251a83398151915260448201527f496e76616c6964207072696365206665656420636f6e66696775726174696f6e60648201526084016105c7565b6001600160a01b0382166000908152609d602052604090208190610b948282612321565b50505050565b806001600160a01b031663a9059cbb610bbb6033546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015610bff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c239190611f38565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610c6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c929190611f51565b610ad35760405162461bcd60e51b8152602060048201526037602482015260008051602061251a83398151915260448201527f5769746864726177616c20756e7375636365737366756c00000000000000000060648201526084016105c7565b610cfa611453565b610d0460006114d0565b565b609c6000610d1a60a0860160808701611dd4565b6001600160601b0316815260208101919091526040016000205460ff1615610d545760405162461bcd60e51b81526004016105c790611f6e565b610d616020840184611fb9565b9050600414610d825760405162461bcd60e51b81526004016105c790612000565b6000610d946080850160608601611c24565b6001600160a01b031614158015610db95750610db96106356080850160608601611c24565b610dd55760405162461bcd60e51b81526004016105c790612042565b6000610e1c83838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506106a792508891506110569050565b6099549091506001600160a01b03808316911614610e4d57604051638baa579f60e01b815260040160405180910390fd5b6001609c6000610e6360a0880160808901611dd4565b6001600160601b031681526020810191909152604001600020805460ff1916911515919091179055609a546001600160a01b0316635664d69c61076d8680611fb9565b60006003610eb383611522565b101592915050565b600054610100900460ff1615808015610edb5750600054600160ff909116105b80610ef55750303b158015610ef5575060005460ff166001145b610f585760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016105c7565b6000805460ff191660011790558015610f7b576000805461ff0019166101001790555b610f8361161a565b610fce6040518060400160405280600c81526020016b4d61676963446f6d61696e7360a01b815250604051806040016040528060058152602001640312e302e360dc1b815250611649565b609a80546001600160a01b038087166001600160a01b031992831617909255609b805486841690831617905560998054928516929091169190911790558015610b94576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b600061040d7fb8abcf5dcf4368294cbc8d5067bfa9f6eccabab2ab9db4b0ae79b3478d04a6886110868480611fb9565b6040516110949291906123d9565b6040519081900390206110aa6020860186611fb9565b6040516110b89291906123d9565b60405180910390208560400160208101906110d39190611c24565b6110e36080880160608901611c24565b6110f360a0890160808a01611dd4565b60408051602081019790975286019490945260608501929092526001600160a01b0390811660808501521660a08301526001600160601b031660c082015260e0016040516020818303038152906040528051906020012061167e565b611157611453565b6001600160a01b0381166111bc5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105c7565b610ad3816114d0565b60006111cf6116cc565b905090565b60008060006111e38585611747565b915091506111f08161178c565b509392505050565b6001600160a01b038083166000908152609d6020908152604091829020825160a081018452815460ff8082161515808452610100830490971694830194909452600160a81b81048416151594820194909452600160b01b9093049091166060830152600101546080820152906112ce5760405162461bcd60e51b8152602060048201526041602482015260008051602061251a83398151915260448201527f44656661756c74207061796d656e7420746f6b656e206e6f7420656e61626c656064820152601960fa1b608482015260a4016105c7565b60006112d982610912565b6040516323b872dd60e01b81526001600160a01b03858116600483015230602483015260448201839052919250908516906323b872dd906064016020604051808303816000875af1158015611332573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113569190611f51565b610b945760405162461bcd60e51b8152602060048201526034602482015260008051602061251a83398151915260448201527314185e5b595b9d081d5b9cdd58d8d95cdcd99d5b60621b60648201526084016105c7565b609b546040516001600160a01b0390911690637a806d6b903390849086906113db908a908a906020016123e9565b6040516020818303038152906040526040518563ffffffff1660e01b81526004016114099493929190612438565b6020604051808303816000875af1158015611428573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144c9190611f38565b5050505050565b6033546001600160a01b03163314610d045760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105c7565b60008161040d565b60006104ff6114cd84670de0b6b3a7640000856118d6565b90565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b805160009081905b80821015610a8757600084838151811061154657611546612476565b01602001516001600160f81b0319169050600160ff1b8110156115755761156e60018461248c565b9250611607565b600760fd1b6001600160f81b0319821610156115965761156e60028461248c565b600f60fc1b6001600160f81b0319821610156115b75761156e60038461248c565b601f60fb1b6001600160f81b0319821610156115d85761156e60048461248c565b603f60fa1b6001600160f81b0319821610156115f95761156e60058461248c565b61160460068461248c565b92505b50826116128161249f565b93505061152a565b600054610100900460ff166116415760405162461bcd60e51b81526004016105c7906124b8565b610d046119a9565b600054610100900460ff166116705760405162461bcd60e51b81526004016105c7906124b8565b61167a82826119d9565b5050565b600061040d61168b6116cc565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60006111cf7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6116fb60655490565b6066546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b600080825160410361177d5760208301516040840151606085015160001a61177187828585611a1a565b94509450505050611785565b506000905060025b9250929050565b60008160048111156117a0576117a0612503565b036117a85750565b60018160048111156117bc576117bc612503565b036118095760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016105c7565b600281600481111561181d5761181d612503565b0361186a5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016105c7565b600381600481111561187e5761187e612503565b03610ad35760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016105c7565b600080806000198587098587029250828110838203039150508060000361191057838281611906576119066122bf565b04925050506104ff565b83811061194157604051630c740aef60e31b81526004810187905260248101869052604481018590526064016105c7565b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b600054610100900460ff166119d05760405162461bcd60e51b81526004016105c7906124b8565b610d04336114d0565b600054610100900460ff16611a005760405162461bcd60e51b81526004016105c7906124b8565b815160209283012081519190920120606591909155606655565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611a515750600090506003611ad5565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611aa5573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611ace57600060019250925050611ad5565b9150600090505b94509492505050565b600060208284031215611af057600080fd5b81356001600160e01b0319811681146104ff57600080fd5b634e487b7160e01b600052604160045260246000fd5b600082601f830112611b2f57600080fd5b813567ffffffffffffffff80821115611b4a57611b4a611b08565b604051601f8301601f19908116603f01168101908282118183101715611b7257611b72611b08565b81604052838152866020858801011115611b8b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611bbe57600080fd5b823567ffffffffffffffff80821115611bd657600080fd5b611be286838701611b1e565b93506020850135915080821115611bf857600080fd5b50611c0585828601611b1e565b9150509250929050565b6001600160a01b0381168114610ad357600080fd5b600060208284031215611c3657600080fd5b81356104ff81611c0f565b600060a08284031215611c5357600080fd5b50919050565b600080600060408486031215611c6e57600080fd5b833567ffffffffffffffff80821115611c8657600080fd5b611c9287838801611c41565b94506020860135915080821115611ca857600080fd5b818601915086601f830112611cbc57600080fd5b813581811115611ccb57600080fd5b876020828501011115611cdd57600080fd5b6020830194508093505050509250925092565b8015158114610ad357600080fd5b60ff81168114610ad357600080fd5b600060a08284031215611d1f57600080fd5b60405160a0810181811067ffffffffffffffff82111715611d4257611d42611b08565b6040528235611d5081611cf0565b81526020830135611d6081611c0f565b60208201526040830135611d7381611cf0565b60408201526060830135611d8681611cfe565b60608201526080928301359281019290925250919050565b60008060c08385031215611db157600080fd5b8235611dbc81611c0f565b9150611dcb8460208501611c41565b90509250929050565b600060208284031215611de657600080fd5b81356001600160601b03811681146104ff57600080fd5b600060208284031215611e0f57600080fd5b813567ffffffffffffffff811115611e2657600080fd5b611e3284828501611b1e565b949350505050565b600080600060608486031215611e4f57600080fd5b8335611e5a81611c0f565b92506020840135611e6a81611c0f565b91506040840135611e7a81611c0f565b809150509250925092565b600060208284031215611e9757600080fd5b813567ffffffffffffffff811115611eae57600080fd5b611e3284828501611c41565b60005b83811015611ed5578181015183820152602001611ebd565b50506000910152565b60008151808452611ef6816020860160208601611eba565b601f01601f19169290920160200192915050565b604081526000611f1d6040830185611ede565b8281036020840152611f2f8185611ede565b95945050505050565b600060208284031215611f4a57600080fd5b5051919050565b600060208284031215611f6357600080fd5b81516104ff81611cf0565b6020808252603c9082015260008051602061251a83398151915260408201527f5369676e6174757265206e6f6e636520616c7265616479207573656400000000606082015260800190565b6000808335601e19843603018112611fd057600080fd5b83018035915067ffffffffffffffff821115611feb57600080fd5b60200191503681900382131561178557600080fd5b602080825260349082015260008051602061251a833981519152604082015273125b9d985b1a5908191a5cd8dc9a5b5a5b985b9d60621b606082015260800190565b6020808252602f9082015260008051602061251a83398151915260408201526e5265736f6c76657220697320454f4160881b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006120bc60608301878961207f565b82810360208401526120cf81868861207f565b91505060018060a01b03831660408301529695505050505050565b6040815260006120fe60408301868861207f565b828103602084015261211181858761207f565b979650505050505050565b805169ffffffffffffffffffff81168114610a9557600080fd5b600080600080600060a0868803121561214e57600080fd5b6121578661211c565b945060208601519350604086015192506060860151915061217a6080870161211c565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b60ff828116828216039081111561040d5761040d612186565b600181815b808511156121f05781600019048211156121d6576121d6612186565b808516156121e357918102915b93841c93908002906121ba565b509250929050565b6000826122075750600161040d565b816122145750600061040d565b816001811461222a576002811461223457612250565b600191505061040d565b60ff84111561224557612245612186565b50506001821b61040d565b5060208310610133831016604e8410600b8410161715612273575081810a61040d565b61227d83836121b5565b806000190482111561229157612291612186565b029392505050565b60006104ff60ff8416836121f8565b808202811582820484141761040d5761040d612186565b634e487b7160e01b600052601260045260246000fd5b6000826122f257634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561230957600080fd5b81356104ff81611cf0565b6000813561040d81611cfe565b813561232c81611cf0565b815460ff19811691151560ff169182178355602084013561234c81611c0f565b610100600160a81b0360089190911b166001600160a81b03198216831781178455604085013561237b81611cf0565b6001600160b01b0319929092169092179190911790151560a81b60ff60a81b161781556123cb6123ad60608401612314565b82805460ff60b01b191660b09290921b60ff60b01b16919091179055565b608082013560018201555050565b8183823760009101908152919050565b600083516123fb818460208801611eba565b601760f91b9083019081528351612419816001840160208801611eba565b652e6d6167696360d01b60019290910191820152600701949350505050565b6001600160a01b03858116825284811660208301528316604082015260806060820181905260009061246c90830184611ede565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b8082018082111561040d5761040d612186565b6000600182016124b1576124b1612186565b5060010190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052602160045260246000fdfe4d61676963446f6d61696e526567697374726172436f6e74726f6c6c65723a20a2646970667358221220737cd8c4cf95d86af21f213e5246ffb2cceb10833ac6a9a33b11d62098b3e9e064736f6c63430008110033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101585760003560e01c8063546c56a4116100c35780639791c0971161007c5780639791c09714610375578063a83bdc0514610388578063c0c53b8b1461039b578063e876452c146103ae578063f2fde38b146103c1578063f698da25146103d457600080fd5b8063546c56a414610300578063656fbeea14610313578063715018a614610336578063808698531461033e5780638da5cb5b1461035157806395f38e771461036257600080fd5b80632b20e397116101155780632b20e397146102815780632dab7dab146102ac5780632f2c20e5146102bf5780633ccfd60b146102d257806344d49f41146102da57806349df728c146102ed57600080fd5b806301ffc9a71461015d5780630c3f3cfb14610185578063180dc257146101985780631dc9b1c114610224578063261a3d9114610245578063275cb9f71461026c575b600080fd5b61017061016b366004611ade565b6103dc565b60405190151581526020015b60405180910390f35b610170610193366004611bab565b610413565b6101ea6101a6366004611c24565b609d602052600090815260409020805460019091015460ff808316926001600160a01b0361010082041692600160a81b8204831692600160b01b9092049091169085565b6040805195151586526001600160a01b0390941660208601529115159284019290925260ff9091166060830152608082015260a00161017c565b610237610232366004611c24565b610506565b60405190815260200161017c565b6102377fb8abcf5dcf4368294cbc8d5067bfa9f6eccabab2ab9db4b0ae79b3478d04a68881565b61027f61027a366004611c59565b610579565b005b609a54610294906001600160a01b031681565b6040516001600160a01b03909116815260200161017c565b61027f6102ba366004611c24565b6108e8565b6102376102cd366004611d0d565b610912565b61027f610a9a565b61027f6102e8366004611d9e565b610ad6565b61027f6102fb366004611c24565b610b9a565b609e54610294906001600160a01b031681565b610170610321366004611dd4565b609c6020526000908152604090205460ff1681565b61027f610cf2565b609b54610294906001600160a01b031681565b6033546001600160a01b0316610294565b61027f610370366004611c59565b610d06565b610170610383366004611dfd565b610ea6565b609954610294906001600160a01b031681565b61027f6103a9366004611e3a565b610ebb565b6102376103bc366004611e85565b611056565b61027f6103cf366004611c24565b61114f565b6102376111c5565b60006001600160e01b031982166301ffc9a760e01b148061040d57506001600160e01b0319821663be900b7b60e01b145b92915050565b600061041e83610ea6565b80156104ff5750609a54604051637db7d43560e11b81526001600160a01b03909116906396e494e890829063fb6fa86a9061045f9088908890600401611f0a565b602060405180830381865afa15801561047c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a09190611f38565b6040518263ffffffff1660e01b81526004016104be91815260200190565b602060405180830381865afa1580156104db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ff9190611f51565b9392505050565b6001600160a01b038082166000908152609d60209081526040808320815160a081018352815460ff80821615158352610100820490971694820194909452600160a81b84048616151592810192909252600160b01b9092049093166060840152600101546080830152906104ff81610912565b609c600061058d60a0860160808701611dd4565b6001600160601b0316815260208101919091526040016000205460ff16156105d05760405162461bcd60e51b81526004016105c790611f6e565b60405180910390fd5b6105dd6020840184611fb9565b90506004146105fe5760405162461bcd60e51b81526004016105c790612000565b60006106106080850160608601611c24565b6001600160a01b03161415801561064457506106446106356080850160608601611c24565b6001600160a01b03163b151590565b6106605760405162461bcd60e51b81526004016105c790612042565b60006106ad83838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506106a792508891506110569050565b906111d4565b6099549091506001600160a01b038083169116146106de57604051638baa579f60e01b815260040160405180910390fd5b6001609c60006106f460a0880160808901611dd4565b6001600160601b031681526020810191909152604001600020805460ff1916911515919091179055609e546001600160a01b03161561075257609e54610752906001600160a01b031661074d6060870160408801611c24565b6111f8565b609a546001600160a01b031663f509f86c61076d8680611fb9565b61077a6020890189611fb9565b61078a60608b0160408c01611c24565b6040518663ffffffff1660e01b81526004016107aa9594939291906120a8565b600060405180830381600087803b1580156107c457600080fd5b505af11580156107d8573d6000803e3d6000fd5b5061087992506107ec915086905080611fb9565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061082e925050506020870187611fb9565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610873925050506080880160608901611c24565b336113ad565b6108896060850160408601611c24565b6001600160a01b03167fe7d10d58c30adabd7fb60d6dd294d3f98e9f7acffc732a2b773465b844de325d6108bd8680611fb9565b6108ca6020890189611fb9565b6040516108da94939291906120ea565b60405180910390a250505050565b6108f0611453565b609e80546001600160a01b0319166001600160a01b0392909216919091179055565b6000816040015115610a8e57600082602001516001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610962573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109869190612136565b50505091505060008112156109ff5760405162461bcd60e51b81526020600482015260446024820181905260008051602061251a833981519152908201527f4f6e6c792073706f742070726963652066656564732061726520737570706f726064820152633a32b21760e11b608482015260a4016105c7565b6000610a20610a0d836114ad565b610a1a86608001516114ad565b906114b5565b90506012846060015160ff161115610a5f5760128460600151610a43919061219c565b610a4e90600a612299565b610a5890826122a8565b9250610a87565b6060840151610a6f90601261219c565b610a7a90600a612299565b610a8490826122d5565b92505b5050919050565b5060808101515b919050565b6033546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610ad3573d6000803e3d6000fd5b50565b610ade611453565b6000610af06040830160208401611c24565b6001600160a01b03161415610b0b60608301604084016122f7565b151514610b70576040805162461bcd60e51b815260206004820152602481019190915260008051602061251a83398151915260448201527f496e76616c6964207072696365206665656420636f6e66696775726174696f6e60648201526084016105c7565b6001600160a01b0382166000908152609d602052604090208190610b948282612321565b50505050565b806001600160a01b031663a9059cbb610bbb6033546001600160a01b031690565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015610bff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c239190611f38565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610c6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c929190611f51565b610ad35760405162461bcd60e51b8152602060048201526037602482015260008051602061251a83398151915260448201527f5769746864726177616c20756e7375636365737366756c00000000000000000060648201526084016105c7565b610cfa611453565b610d0460006114d0565b565b609c6000610d1a60a0860160808701611dd4565b6001600160601b0316815260208101919091526040016000205460ff1615610d545760405162461bcd60e51b81526004016105c790611f6e565b610d616020840184611fb9565b9050600414610d825760405162461bcd60e51b81526004016105c790612000565b6000610d946080850160608601611c24565b6001600160a01b031614158015610db95750610db96106356080850160608601611c24565b610dd55760405162461bcd60e51b81526004016105c790612042565b6000610e1c83838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506106a792508891506110569050565b6099549091506001600160a01b03808316911614610e4d57604051638baa579f60e01b815260040160405180910390fd5b6001609c6000610e6360a0880160808901611dd4565b6001600160601b031681526020810191909152604001600020805460ff1916911515919091179055609a546001600160a01b0316635664d69c61076d8680611fb9565b60006003610eb383611522565b101592915050565b600054610100900460ff1615808015610edb5750600054600160ff909116105b80610ef55750303b158015610ef5575060005460ff166001145b610f585760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016105c7565b6000805460ff191660011790558015610f7b576000805461ff0019166101001790555b610f8361161a565b610fce6040518060400160405280600c81526020016b4d61676963446f6d61696e7360a01b815250604051806040016040528060058152602001640312e302e360dc1b815250611649565b609a80546001600160a01b038087166001600160a01b031992831617909255609b805486841690831617905560998054928516929091169190911790558015610b94576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b600061040d7fb8abcf5dcf4368294cbc8d5067bfa9f6eccabab2ab9db4b0ae79b3478d04a6886110868480611fb9565b6040516110949291906123d9565b6040519081900390206110aa6020860186611fb9565b6040516110b89291906123d9565b60405180910390208560400160208101906110d39190611c24565b6110e36080880160608901611c24565b6110f360a0890160808a01611dd4565b60408051602081019790975286019490945260608501929092526001600160a01b0390811660808501521660a08301526001600160601b031660c082015260e0016040516020818303038152906040528051906020012061167e565b611157611453565b6001600160a01b0381166111bc5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105c7565b610ad3816114d0565b60006111cf6116cc565b905090565b60008060006111e38585611747565b915091506111f08161178c565b509392505050565b6001600160a01b038083166000908152609d6020908152604091829020825160a081018452815460ff8082161515808452610100830490971694830194909452600160a81b81048416151594820194909452600160b01b9093049091166060830152600101546080820152906112ce5760405162461bcd60e51b8152602060048201526041602482015260008051602061251a83398151915260448201527f44656661756c74207061796d656e7420746f6b656e206e6f7420656e61626c656064820152601960fa1b608482015260a4016105c7565b60006112d982610912565b6040516323b872dd60e01b81526001600160a01b03858116600483015230602483015260448201839052919250908516906323b872dd906064016020604051808303816000875af1158015611332573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113569190611f51565b610b945760405162461bcd60e51b8152602060048201526034602482015260008051602061251a83398151915260448201527314185e5b595b9d081d5b9cdd58d8d95cdcd99d5b60621b60648201526084016105c7565b609b546040516001600160a01b0390911690637a806d6b903390849086906113db908a908a906020016123e9565b6040516020818303038152906040526040518563ffffffff1660e01b81526004016114099493929190612438565b6020604051808303816000875af1158015611428573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144c9190611f38565b5050505050565b6033546001600160a01b03163314610d045760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105c7565b60008161040d565b60006104ff6114cd84670de0b6b3a7640000856118d6565b90565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b805160009081905b80821015610a8757600084838151811061154657611546612476565b01602001516001600160f81b0319169050600160ff1b8110156115755761156e60018461248c565b9250611607565b600760fd1b6001600160f81b0319821610156115965761156e60028461248c565b600f60fc1b6001600160f81b0319821610156115b75761156e60038461248c565b601f60fb1b6001600160f81b0319821610156115d85761156e60048461248c565b603f60fa1b6001600160f81b0319821610156115f95761156e60058461248c565b61160460068461248c565b92505b50826116128161249f565b93505061152a565b600054610100900460ff166116415760405162461bcd60e51b81526004016105c7906124b8565b610d046119a9565b600054610100900460ff166116705760405162461bcd60e51b81526004016105c7906124b8565b61167a82826119d9565b5050565b600061040d61168b6116cc565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60006111cf7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6116fb60655490565b6066546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b600080825160410361177d5760208301516040840151606085015160001a61177187828585611a1a565b94509450505050611785565b506000905060025b9250929050565b60008160048111156117a0576117a0612503565b036117a85750565b60018160048111156117bc576117bc612503565b036118095760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016105c7565b600281600481111561181d5761181d612503565b0361186a5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016105c7565b600381600481111561187e5761187e612503565b03610ad35760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016105c7565b600080806000198587098587029250828110838203039150508060000361191057838281611906576119066122bf565b04925050506104ff565b83811061194157604051630c740aef60e31b81526004810187905260248101869052604481018590526064016105c7565b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b600054610100900460ff166119d05760405162461bcd60e51b81526004016105c7906124b8565b610d04336114d0565b600054610100900460ff16611a005760405162461bcd60e51b81526004016105c7906124b8565b815160209283012081519190920120606591909155606655565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611a515750600090506003611ad5565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611aa5573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611ace57600060019250925050611ad5565b9150600090505b94509492505050565b600060208284031215611af057600080fd5b81356001600160e01b0319811681146104ff57600080fd5b634e487b7160e01b600052604160045260246000fd5b600082601f830112611b2f57600080fd5b813567ffffffffffffffff80821115611b4a57611b4a611b08565b604051601f8301601f19908116603f01168101908282118183101715611b7257611b72611b08565b81604052838152866020858801011115611b8b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611bbe57600080fd5b823567ffffffffffffffff80821115611bd657600080fd5b611be286838701611b1e565b93506020850135915080821115611bf857600080fd5b50611c0585828601611b1e565b9150509250929050565b6001600160a01b0381168114610ad357600080fd5b600060208284031215611c3657600080fd5b81356104ff81611c0f565b600060a08284031215611c5357600080fd5b50919050565b600080600060408486031215611c6e57600080fd5b833567ffffffffffffffff80821115611c8657600080fd5b611c9287838801611c41565b94506020860135915080821115611ca857600080fd5b818601915086601f830112611cbc57600080fd5b813581811115611ccb57600080fd5b876020828501011115611cdd57600080fd5b6020830194508093505050509250925092565b8015158114610ad357600080fd5b60ff81168114610ad357600080fd5b600060a08284031215611d1f57600080fd5b60405160a0810181811067ffffffffffffffff82111715611d4257611d42611b08565b6040528235611d5081611cf0565b81526020830135611d6081611c0f565b60208201526040830135611d7381611cf0565b60408201526060830135611d8681611cfe565b60608201526080928301359281019290925250919050565b60008060c08385031215611db157600080fd5b8235611dbc81611c0f565b9150611dcb8460208501611c41565b90509250929050565b600060208284031215611de657600080fd5b81356001600160601b03811681146104ff57600080fd5b600060208284031215611e0f57600080fd5b813567ffffffffffffffff811115611e2657600080fd5b611e3284828501611b1e565b949350505050565b600080600060608486031215611e4f57600080fd5b8335611e5a81611c0f565b92506020840135611e6a81611c0f565b91506040840135611e7a81611c0f565b809150509250925092565b600060208284031215611e9757600080fd5b813567ffffffffffffffff811115611eae57600080fd5b611e3284828501611c41565b60005b83811015611ed5578181015183820152602001611ebd565b50506000910152565b60008151808452611ef6816020860160208601611eba565b601f01601f19169290920160200192915050565b604081526000611f1d6040830185611ede565b8281036020840152611f2f8185611ede565b95945050505050565b600060208284031215611f4a57600080fd5b5051919050565b600060208284031215611f6357600080fd5b81516104ff81611cf0565b6020808252603c9082015260008051602061251a83398151915260408201527f5369676e6174757265206e6f6e636520616c7265616479207573656400000000606082015260800190565b6000808335601e19843603018112611fd057600080fd5b83018035915067ffffffffffffffff821115611feb57600080fd5b60200191503681900382131561178557600080fd5b602080825260349082015260008051602061251a833981519152604082015273125b9d985b1a5908191a5cd8dc9a5b5a5b985b9d60621b606082015260800190565b6020808252602f9082015260008051602061251a83398151915260408201526e5265736f6c76657220697320454f4160881b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006120bc60608301878961207f565b82810360208401526120cf81868861207f565b91505060018060a01b03831660408301529695505050505050565b6040815260006120fe60408301868861207f565b828103602084015261211181858761207f565b979650505050505050565b805169ffffffffffffffffffff81168114610a9557600080fd5b600080600080600060a0868803121561214e57600080fd5b6121578661211c565b945060208601519350604086015192506060860151915061217a6080870161211c565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b60ff828116828216039081111561040d5761040d612186565b600181815b808511156121f05781600019048211156121d6576121d6612186565b808516156121e357918102915b93841c93908002906121ba565b509250929050565b6000826122075750600161040d565b816122145750600061040d565b816001811461222a576002811461223457612250565b600191505061040d565b60ff84111561224557612245612186565b50506001821b61040d565b5060208310610133831016604e8410600b8410161715612273575081810a61040d565b61227d83836121b5565b806000190482111561229157612291612186565b029392505050565b60006104ff60ff8416836121f8565b808202811582820484141761040d5761040d612186565b634e487b7160e01b600052601260045260246000fd5b6000826122f257634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561230957600080fd5b81356104ff81611cf0565b6000813561040d81611cfe565b813561232c81611cf0565b815460ff19811691151560ff169182178355602084013561234c81611c0f565b610100600160a81b0360089190911b166001600160a81b03198216831781178455604085013561237b81611cf0565b6001600160b01b0319929092169092179190911790151560a81b60ff60a81b161781556123cb6123ad60608401612314565b82805460ff60b01b191660b09290921b60ff60b01b16919091179055565b608082013560018201555050565b8183823760009101908152919050565b600083516123fb818460208801611eba565b601760f91b9083019081528351612419816001840160208801611eba565b652e6d6167696360d01b60019290910191820152600701949350505050565b6001600160a01b03858116825284811660208301528316604082015260806060820181905260009061246c90830184611ede565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b8082018082111561040d5761040d612186565b6000600182016124b1576124b1612186565b5060010190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052602160045260246000fdfe4d61676963446f6d61696e526567697374726172436f6e74726f6c6c65723a20a2646970667358221220737cd8c4cf95d86af21f213e5246ffb2cceb10833ac6a9a33b11d62098b3e9e064736f6c63430008110033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.