Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
410088 | 26 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Verifier
Compiler Version
v0.8.13+commit.abaa5c0e
ZkSolc Version
v1.5.8
Optimization Enabled:
Yes with Mode 3
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "./common/Errors.sol"; import "./libraries/MathHelper.sol"; import "./interfaces/IVerifier.sol"; contract Verifier is EIP712Upgradeable, OwnableUpgradeable, IVerifier { Point[8] internal pubkeys; Point[256] internal aggregatePubkey; bool[256] internal isAggregatePubkeyLatest; uint256 internal nSigner; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize(Point[8] memory initialSet) external initializer { __Ownable_init(); for (uint256 i = 0; i < 8; ++i) { if (!isPointNone(initialSet[i])) { _assignPubkey(i, initialSet[i].x, initialSet[i].y); } } } function revertGasInfo(uint256 i, uint256 gasUsed) external pure { revert( string.concat( "G ", MathHelper.uint2str(uint128(i)), " ", MathHelper.uint2str(uint128(gasUsed)) ) ); } function assignPubKey( uint256 i, uint256 x, uint256 y ) public onlyOwner { _assignPubkey(i, x, y); } function _assignPubkey( uint256 i, uint256 x, uint256 y ) internal { require(i < 8); if (isPointNone(pubkeys[i])) { nSigner += 1; } pubkeys[i] = Point(x, y); for (uint256 s = (1 << i); s < 256; s = (s + 1) | (1 << i)) { isAggregatePubkeyLatest[s] = false; } } function deletePubkey(uint256 index) public onlyOwner { if (!isPointNone(pubkeys[index])) { nSigner -= 1; delete pubkeys[index]; } } function getPubkey(uint8 index) public view returns (Point memory) { return pubkeys[index]; } function getPubkeyAddress(uint8 index) public view returns (address) { Point memory p = getPubkey(index); return address(uint160(uint256(keccak256(abi.encode(p.x, p.y))))); } function getAggregatePubkey(uint8 signerBitmask) internal returns (Point memory) { if (signerBitmask == 0 || isAggregatePubkeyLatest[signerBitmask]) return aggregatePubkey[signerBitmask]; Point memory res; for (uint256 i = 0; i < 8; ++i) { if ((signerBitmask >> i) % 2 == 1) { require(!isPointNone(pubkeys[i])); res = pointAdd( getAggregatePubkey(signerBitmask ^ uint8(1 << i)), pubkeys[i] ); break; } } aggregatePubkey[signerBitmask] = res; isAggregatePubkeyLatest[signerBitmask] = true; return res; } // determine if 2/3 of the signers are included in this signing mask // and if the keys are present function checkQuorum(uint8 signerBitmask) internal view returns (bool) { uint256 nSigned = 0; for (uint256 i = 0; i < 8; ++i) { bool signed = ((signerBitmask >> i) & 1) == 1; if (signed) { if (isPointNone(pubkeys[i])) { return false; } nSigned += 1; } } return nSigned * 2 > nSigner; } function requireValidSignature( bytes32 message, bytes32 e, bytes32 s, uint8 signerBitmask ) public { require(checkQuorum(signerBitmask)); Point memory pubkey = getAggregatePubkey(signerBitmask); require( verify( pubkey.y % 2 == 0 ? 27 : 28, bytes32(pubkey.x), message, e, s ), "Verification failed" ); } /// SCHNORR IMPLEMENTATION BELOW // secp256k1 group order uint256 public constant Q = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; // parity := public key y-coord parity (27 or 28) // px := public key x-coord // message := 32-byte message // e := schnorr signature challenge // s := schnorr signature function verify( uint8 parity, bytes32 px, bytes32 message, bytes32 e, bytes32 s ) internal pure returns (bool) { // ecrecover = (m, v, r, s); bytes32 sp = bytes32(Q - mulmod(uint256(s), uint256(px), Q)); bytes32 ep = bytes32(Q - mulmod(uint256(e), uint256(px), Q)); require(sp != 0); // the ecrecover precompile implementation checks that the `r` and `s` // inputs are non-zero (in this case, `px` and `ep`), thus we don't need to // check if they're zero. address R = ecrecover(sp, parity, px, ep); require(R != address(0), "ecrecover failed"); return e == keccak256(abi.encodePacked(R, uint8(parity), px, message)); } uint256 public constant _P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; struct Point { uint256 x; uint256 y; } function pow( uint256 a, uint256 b, uint256 mod ) internal pure returns (uint256) { // a ^ b % mod uint256 res = 1; while (b > 0) { if (b % 2 == 1) { res = mulmod(res, a, mod); } a = mulmod(a, a, mod); b /= 2; } return res; } function isPointNone(Point memory u) internal pure returns (bool) { return u.x == 0 && u.y == 0; } function pointAdd(Point memory u, Point memory v) internal pure returns (Point memory) { if (isPointNone(u)) return v; if (isPointNone(v)) return u; uint256 lam = 0; if (u.x == v.x) { if (u.y != v.y) return Point(0, 0); lam = mulmod(3, u.x, _P); lam = mulmod(lam, u.x, _P); lam = mulmod(lam, pow(mulmod(2, v.y, _P), _P - 2, _P), _P); } else { lam = mulmod( addmod(v.y, _P - u.y, _P), pow(addmod(v.x, _P - u.x, _P), _P - 2, _P), _P ); } uint256 x3 = mulmod(lam, lam, _P); x3 = addmod(x3, _P - u.x, _P); x3 = addmod(x3, _P - v.x, _P); uint256 y3 = addmod(u.x, _P - x3, _P); y3 = mulmod(y3, lam, _P); y3 = addmod(y3, _P - u.y, _P); return Point(x3, y3); } function checkIndividualSignature( bytes32 digest, bytes memory signature, uint8 signerIndex ) public view returns (bool) { address expectedAddress = getPubkeyAddress(signerIndex); address recovered = ECDSA.recover(digest, signature); return expectedAddress == recovered; } function requireValidTxSignatures( bytes calldata txn, uint64 idx, bytes[] calldata signatures ) public { bytes32 data = keccak256( abi.encodePacked(uint256(block.chainid), uint256(idx), txn) ); bytes32 hashedMsg = keccak256( abi.encodePacked("\x19Ethereum Signed Message:\n32", data) ); uint256 nSignatures = 0; for (uint256 i = 0; i < signatures.length; i++) { if (signatures[i].length > 0) { nSignatures += 1; require( checkIndividualSignature( hashedMsg, signatures[i], uint8(i) ), "invalid signature" ); } } require(nSignatures == nSigner, "not enough signatures"); } function validateSignature( bytes32 sender, address linkedSigner, bytes32 digest, bytes memory signature ) public pure { address recovered = ECDSA.recover(digest, signature); require( (recovered != address(0)) && ((recovered == address(uint160(bytes20(sender)))) || (recovered == linkedSigner)), ERR_INVALID_SIGNATURE ); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface IVerifier { function requireValidSignature( bytes32 message, bytes32 e, bytes32 s, uint8 signerBitmask ) external; function revertGasInfo(uint256 i, uint256 gasUsed) external pure; function validateSignature( bytes32 sender, address linkedSigner, bytes32 digest, bytes memory signature ) external pure; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "./MathSD21x18.sol"; /// @title MathHelper /// @dev Provides basic math functions library MathHelper { using MathSD21x18 for int128; /// @notice Returns market id for two given product ids function max(int128 a, int128 b) internal pure returns (int128) { return a > b ? a : b; } function min(int128 a, int128 b) internal pure returns (int128) { return a < b ? a : b; } function abs(int128 val) internal pure returns (int128) { return val < 0 ? -val : val; } // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(int128 y) internal pure returns (int128 z) { require(y >= 0, "ds-math-sqrt-non-positive"); if (y > 3) { z = y; int128 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } function sqrt256(int256 y) internal pure returns (int256 z) { require(y >= 0, "ds-math-sqrt-non-positive"); if (y > 3) { z = y; int256 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } function int2str(int128 value) internal pure returns (string memory) { if (value == 0) { return "0"; } bool negative = value < 0; uint128 absval = uint128(negative ? -value : value); string memory out = uint2str(absval); if (negative) { out = string.concat("-", out); } return out; } function uint2str(uint128 value) internal pure returns (string memory) { if (value == 0) { return "0"; } uint128 temp = value; uint128 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint128(value % 10))); value /= 10; } return string(buffer); } // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.1.0/contracts/math/SignedSafeMath.sol#L86 function add(int128 x, int128 y) internal pure returns (int128) { int128 z = x + y; require((y >= 0 && z >= x) || (y < 0 && z < x), "ds-math-add-overflow"); return z; } // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.1.0/contracts/math/SignedSafeMath.sol#L69 function sub(int128 x, int128 y) internal pure returns (int128) { int128 z = x - y; require( (y >= 0 && z <= x) || (y < 0 && z > x), "ds-math-sub-underflow" ); return z; } function mul(int128 x, int128 y) internal pure returns (int128 z) { require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow"); } function floor(int128 x, int128 y) internal pure returns (int128 z) { require(y > 0, "ds-math-floor-neg-mod"); int128 r = x % y; if (r == 0) { z = x; } else { z = (x >= 0 ? x - r : x - r - y); } } function ceil(int128 x, int128 y) internal pure returns (int128 z) { require(y > 0, "ds-math-ceil-neg-mod"); int128 r = x % y; if (r == 0) { z = x; } else { z = (x >= 0 ? x + y - r : x - r); } } // we don't need to floor base with sizeIncrement in this function // because this function is only used by `view` functions, which means // the returned values will not be written into storage. function ammEquilibrium( int128 base, int128 quote, int128 priceX18 ) internal pure returns (int128, int128) { if (base == 0 || quote == 0) { return (0, 0); } int256 k = int256(base) * quote; // base * price * base == k // base = sqrt(k / price); base = int128(MathHelper.sqrt256((k * 1e18) / priceX18)); quote = (base == 0) ? int128(0) : int128(k / base); return (base, quote); } function isSwapValid( int128 baseDelta, int128 quoteDelta, int128 base, int128 quote ) internal pure returns (bool) { if ( base == 0 || quote == 0 || base + baseDelta <= 0 || quote + quoteDelta <= 0 ) { return false; } int256 kPrev = int256(base) * quote; int256 kNew = int256(base + baseDelta) * (quote + quoteDelta); return kNew > kPrev; } function swap( int128 amountSwap, int128 base, int128 quote, int128 priceX18, int128 sizeIncrement, int128 lpSpreadX18 ) internal pure returns (int128, int128) { // (amountSwap % sizeIncrement) is guaranteed to be 0 if (base == 0 || quote == 0) { return (0, 0); } int128 currentPriceX18 = quote.div(base); int128 keepRateX18 = 1e18 - lpSpreadX18; // selling if (amountSwap > 0) { priceX18 = priceX18.div(keepRateX18); if (priceX18 >= currentPriceX18) { return (0, 0); } } else { priceX18 = priceX18.mul(keepRateX18); if (priceX18 <= currentPriceX18) { return (0, 0); } } int256 k = int256(base) * quote; int128 baseAtPrice = int128( (MathHelper.sqrt256(k) * 1e9) / MathHelper.sqrt(priceX18) ); // base -> base + amountSwap int128 baseSwapped; if ( (amountSwap > 0 && base + amountSwap > baseAtPrice) || (amountSwap < 0 && base + amountSwap < baseAtPrice) ) { // we hit price limits before we exhaust amountSwap if (baseAtPrice >= base) { baseSwapped = MathHelper.floor( baseAtPrice - base, sizeIncrement ); } else { baseSwapped = MathHelper.ceil( baseAtPrice - base, sizeIncrement ); } } else { // just swap it all // amountSwap is already guaranteed to adhere to sizeIncrement baseSwapped = amountSwap; } int128 quoteSwapped = int128(k / (base + baseSwapped) - quote); if (amountSwap > 0) { quoteSwapped = quoteSwapped.mul(keepRateX18); } else { quoteSwapped = quoteSwapped.div(keepRateX18); } return (baseSwapped, quoteSwapped); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; // Trying to take an action on vertex when string constant ERR_REQUIRES_DEPOSIT = "RS"; // ERC20 Transfer failed string constant ERR_TRANSFER_FAILED = "TF"; // Unauthorized string constant ERR_UNAUTHORIZED = "U"; // Invalid product string constant ERR_INVALID_PRODUCT = "IP"; // Subaccount health too low string constant ERR_SUBACCT_HEALTH = "SH"; // Not liquidatable string constant ERR_NOT_LIQUIDATABLE = "NL"; // Liquidator health too low string constant ERR_NOT_LIQUIDATABLE_INITIAL = "NLI"; // Liquidatee has positive initial health string constant ERR_LIQUIDATED_TOO_MUCH = "LTM"; // Trying to liquidate quote, or string constant ERR_INVALID_LIQUIDATION_PARAMS = "NILP"; // Trying to liquidate perp but the amount is not divisible by sizeIncrement string constant ERR_INVALID_LIQUIDATION_AMOUNT = "NILA"; // Tried to liquidate too little, too much or signs are different string constant ERR_NOT_LIQUIDATABLE_AMT = "NLA"; // Tried to liquidate liabilities before perps string constant ERR_NOT_LIQUIDATABLE_LIABILITIES = "NLL"; // Tried to finalize subaccount that cannot be finalized string constant ERR_NOT_FINALIZABLE_SUBACCOUNT = "NFS"; // Not enough quote to settle string constant ERR_CANNOT_SETTLE = "CS"; // Not enough insurance to settle string constant ERR_NO_INSURANCE = "NI"; // Above reserve ratio string constant ERR_RESERVE_RATIO = "RR"; // Invalid socialize amount string constant ERR_INVALID_SOCIALIZE_AMT = "ISA"; // Socializing product with no open interest string constant ERR_NO_OPEN_INTEREST = "NOI"; // FOK not filled, this isn't rly an error so this is jank string constant ERR_FOK_NOT_FILLED = "ENF"; // bad product config via weights string constant ERR_BAD_PRODUCT_CONFIG = "BPC"; // subacct name too long string constant ERR_LONG_NAME = "LN"; // already registered in health group string constant ERR_ALREADY_REGISTERED = "AR"; // invalid health group provided string constant ERR_INVALID_HEALTH_GROUP = "IHG"; string constant ERR_GETTING_ZERO_HEALTH_GROUP = "GZHG"; // trying to burn more LP than owned string constant ERR_INSUFFICIENT_LP = "ILP"; // taker order subaccount fails risk or is invalid string constant ERR_INVALID_TAKER = "IT"; // maker order subaccount fails risk or is invalid string constant ERR_INVALID_MAKER = "IM"; string constant ERR_INVALID_SIGNATURE = "IS"; string constant ERR_ORDERS_CANNOT_BE_MATCHED = "OCBM"; string constant ERR_INVALID_LP_AMOUNT = "ILA"; string constant ERR_SLIPPAGE_TOO_HIGH = "STH"; string constant ERR_SUBACCOUNT_NOT_FOUND = "SNF"; string constant ERR_INVALID_PRICE = "IPR"; string constant ERR_INVALID_TIME = "ITI"; // states on node and engine are not same string constant ERR_DSYNC = "DSYNC"; string constant ERR_INVALID_SWAP_PARAMS = "ISP"; string constant ERR_CONVERSION_OVERFLOW = "CO"; string constant ERR_ONLY_CLEARINGHOUSE_CAN_SET_BOOK = "OCCSB"; // we match on containing these strings in sequencer string constant ERR_INVALID_SUBMISSION_INDEX = "IX"; string constant ERR_NO_SLOW_MODE_TXS_REMAINING = "no slow mode transactions remaining"; string constant ERR_INVALID_COUNT = "IC"; string constant ERR_SLOW_TX_TOO_RECENT = "STTR"; string constant ERR_WALLET_NOT_TRANSFERABLE = "WNT"; string constant ERR_WALLET_SANCTIONED = "WS"; string constant ERR_SLOW_MODE_WRONG_SENDER = "SMWS"; string constant ERR_WRONG_NONCE = "WN"; // initially wanted to call this // ERR_FULL_UTILIZATION but the shortened // error string may make people mad on the frontend string constant ERR_MAX_UTILIZATION = "MU"; string constant ERR_INVALID_RISK_GROUP = "IRG"; string constant ERR_VERIFY_SCHNORR = "VSR"; string constant ERR_DEPOSIT_TOO_SMALL = "DTS"; string constant ERR_CODE_NOT_MATCH = "CNM";
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import "prb-math/contracts/PRBMathSD59x18.sol"; library MathSD21x18 { using PRBMathSD59x18 for int256; int128 private constant ONE_X18 = 1000000000000000000; int128 private constant MIN_X18 = -0x80000000000000000000000000000000; int128 private constant MAX_X18 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; string private constant ERR_OVERFLOW = "OF"; string private constant ERR_DIV_BY_ZERO = "DBZ"; function fromInt(int128 x) internal pure returns (int128) { unchecked { int256 result = int256(x) * ONE_X18; require(result >= MIN_X18 && result <= MAX_X18, ERR_OVERFLOW); return int128(result); } } function mulDiv( int128 x, int128 y, int128 z ) internal pure returns (int128) { unchecked { require(z != 0, ERR_DIV_BY_ZERO); int256 result = (int256(x) * y) / z; require(result >= MIN_X18 && result <= MAX_X18, ERR_OVERFLOW); return int128(result); } } function toInt(int128 x) internal pure returns (int128) { unchecked { return int128(x / ONE_X18); } } function add(int128 x, int128 y) internal pure returns (int128) { unchecked { int256 result = int256(x) + y; require(result >= MIN_X18 && result <= MAX_X18, ERR_OVERFLOW); return int128(result); } } function sub(int128 x, int128 y) internal pure returns (int128) { unchecked { int256 result = int256(x) - y; require(result >= MIN_X18 && result <= MAX_X18, ERR_OVERFLOW); return int128(result); } } function mul(int128 x, int128 y) internal pure returns (int128) { unchecked { int256 result = (int256(x) * y) / ONE_X18; require(result >= MIN_X18 && result <= MAX_X18, ERR_OVERFLOW); return int128(result); } } function div(int128 x, int128 y) internal pure returns (int128) { unchecked { require(y != 0, ERR_DIV_BY_ZERO); int256 result = (int256(x) * ONE_X18) / y; require(result >= MIN_X18 && result <= MAX_X18, ERR_OVERFLOW); return int128(result); } } function abs(int128 x) internal pure returns (int128) { unchecked { require(x != MIN_X18, ERR_OVERFLOW); return x < 0 ? -x : x; } } function sqrt(int128 x) internal pure returns (int128) { unchecked { int256 result = int256(x).sqrt(); require(result >= MIN_X18 && result <= MAX_X18, ERR_OVERFLOW); return int128(result); } } // note that y is not X18 function pow(int128 x, int128 y) internal pure returns (int128) { unchecked { require(y >= 0, ERR_OVERFLOW); int128 result = ONE_X18; for (int128 i = 1; i <= y; i *= 2) { if (i & y != 0) { result = mul(result, x); } x = mul(x, x); } return result; } } }
// 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.8.0-rc.2) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // 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", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0-rc.2) (utils/cryptography/draft-EIP712.sol) pragma solidity ^0.8.0; // EIP-712 is Final as of 2022-08-11. This file is deprecated. import "./EIP712Upgradeable.sol";
// SPDX-License-Identifier: Unlicense pragma solidity >=0.8.4; import "./PRBMath.sol"; /// @title PRBMathSD59x18 /// @author Paul Razvan Berg /// @notice Smart contract library for advanced fixed-point math that works with int256 numbers considered to have 18 /// trailing decimals. We call this number representation signed 59.18-decimal fixed-point, since the numbers can have /// a sign and there can be up to 59 digits in the integer part and up to 18 decimals in the fractional part. The numbers /// are bound by the minimum and the maximum values permitted by the Solidity type int256. library PRBMathSD59x18 { /// @dev log2(e) as a signed 59.18-decimal fixed-point number. int256 internal constant LOG2_E = 1_442695040888963407; /// @dev Half the SCALE number. int256 internal constant HALF_SCALE = 5e17; /// @dev The maximum value a signed 59.18-decimal fixed-point number can have. int256 internal constant MAX_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_792003956564819967; /// @dev The maximum whole value a signed 59.18-decimal fixed-point number can have. int256 internal constant MAX_WHOLE_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_000000000000000000; /// @dev The minimum value a signed 59.18-decimal fixed-point number can have. int256 internal constant MIN_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_792003956564819968; /// @dev The minimum whole value a signed 59.18-decimal fixed-point number can have. int256 internal constant MIN_WHOLE_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_000000000000000000; /// @dev How many trailing decimals can be represented. int256 internal constant SCALE = 1e18; /// INTERNAL FUNCTIONS /// /// @notice Calculate the absolute value of x. /// /// @dev Requirements: /// - x must be greater than MIN_SD59x18. /// /// @param x The number to calculate the absolute value for. /// @param result The absolute value of x. function abs(int256 x) internal pure returns (int256 result) { unchecked { if (x == MIN_SD59x18) { revert PRBMathSD59x18__AbsInputTooSmall(); } result = x < 0 ? -x : x; } } /// @notice Calculates the arithmetic average of x and y, rounding down. /// @param x The first operand as a signed 59.18-decimal fixed-point number. /// @param y The second operand as a signed 59.18-decimal fixed-point number. /// @return result The arithmetic average as a signed 59.18-decimal fixed-point number. function avg(int256 x, int256 y) internal pure returns (int256 result) { // The operations can never overflow. unchecked { int256 sum = (x >> 1) + (y >> 1); if (sum < 0) { // If at least one of x and y is odd, we add 1 to the result. This is because shifting negative numbers to the // right rounds down to infinity. assembly { result := add(sum, and(or(x, y), 1)) } } else { // If both x and y are odd, we add 1 to the result. This is because if both numbers are odd, the 0.5 // remainder gets truncated twice. result = sum + (x & y & 1); } } } /// @notice Yields the least greatest signed 59.18 decimal fixed-point 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 signed 59.18-decimal fixed-point number to ceil. /// @param result The least integer greater than or equal to x, as a signed 58.18-decimal fixed-point number. function ceil(int256 x) internal pure returns (int256 result) { if (x > MAX_WHOLE_SD59x18) { revert PRBMathSD59x18__CeilOverflow(x); } unchecked { int256 remainder = x % SCALE; if (remainder == 0) { result = x; } else { // Solidity uses C fmod style, which returns a modulus with the same sign as x. result = x - remainder; if (x > 0) { result += SCALE; } } } } /// @notice Divides two signed 59.18-decimal fixed-point numbers, returning a new signed 59.18-decimal fixed-point number. /// /// @dev Variant of "mulDiv" that works with signed numbers. Works by computing the signs and the absolute values separately. /// /// Requirements: /// - All from "PRBMath.mulDiv". /// - None of the inputs can be MIN_SD59x18. /// - The denominator cannot be zero. /// - The result must fit within int256. /// /// Caveats: /// - All from "PRBMath.mulDiv". /// /// @param x The numerator as a signed 59.18-decimal fixed-point number. /// @param y The denominator as a signed 59.18-decimal fixed-point number. /// @param result The quotient as a signed 59.18-decimal fixed-point number. function div(int256 x, int256 y) internal pure returns (int256 result) { if (x == MIN_SD59x18 || y == MIN_SD59x18) { revert PRBMathSD59x18__DivInputTooSmall(); } // Get hold of the absolute values of x and y. uint256 ax; uint256 ay; unchecked { ax = x < 0 ? uint256(-x) : uint256(x); ay = y < 0 ? uint256(-y) : uint256(y); } // Compute the absolute value of (x*SCALE)÷y. The result must fit within int256. uint256 rAbs = PRBMath.mulDiv(ax, uint256(SCALE), ay); if (rAbs > uint256(MAX_SD59x18)) { revert PRBMathSD59x18__DivOverflow(rAbs); } // Get the signs of x and y. uint256 sx; uint256 sy; assembly { sx := sgt(x, sub(0, 1)) sy := sgt(y, sub(0, 1)) } // XOR over sx and sy. This is basically checking whether the inputs have the same sign. If yes, the result // should be positive. Otherwise, it should be negative. result = sx ^ sy == 1 ? -int256(rAbs) : int256(rAbs); } /// @notice Returns Euler's number as a signed 59.18-decimal fixed-point number. /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant). function e() internal pure returns (int256 result) { result = 2_718281828459045235; } /// @notice Calculates the natural exponent of x. /// /// @dev Based on the insight that e^x = 2^(x * log2(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 a signed 59.18-decimal fixed-point number. /// @return result The result as a signed 59.18-decimal fixed-point number. function exp(int256 x) internal pure returns (int256 result) { // Without this check, the value passed to "exp2" would be less than -59.794705707972522261. if (x < -41_446531673892822322) { return 0; } // Without this check, the value passed to "exp2" would be greater than 192. if (x >= 133_084258667509499441) { revert PRBMathSD59x18__ExpInputTooBig(x); } // Do the fixed-point multiplication inline to save gas. unchecked { int256 doubleScaleProduct = x * LOG2_E; result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE); } } /// @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_SD59x18. /// /// Caveats: /// - For any x less than -59.794705707972522261, the result is zero. /// /// @param x The exponent as a signed 59.18-decimal fixed-point number. /// @return result The result as a signed 59.18-decimal fixed-point number. function exp2(int256 x) internal pure returns (int256 result) { // This works because 2^(-x) = 1/2^x. if (x < 0) { // 2^59.794705707972522262 is the maximum number whose inverse does not truncate down to zero. if (x < -59_794705707972522261) { return 0; } // Do the fixed-point inversion inline to save gas. The numerator is SCALE * SCALE. unchecked { result = 1e36 / exp2(-x); } } else { // 2^192 doesn't fit within the 192.64-bit format used internally in this function. if (x >= 192e18) { revert PRBMathSD59x18__Exp2InputTooBig(x); } unchecked { // Convert x to the 192.64-bit fixed-point format. uint256 x192x64 = (uint256(x) << 64) / uint256(SCALE); // Safe to convert the result to int256 directly because the maximum input allowed is 192. result = int256(PRBMath.exp2(x192x64)); } } } /// @notice Yields the greatest signed 59.18 decimal fixed-point 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 signed 59.18-decimal fixed-point number to floor. /// @param result The greatest integer less than or equal to x, as a signed 58.18-decimal fixed-point number. function floor(int256 x) internal pure returns (int256 result) { if (x < MIN_WHOLE_SD59x18) { revert PRBMathSD59x18__FloorUnderflow(x); } unchecked { int256 remainder = x % SCALE; if (remainder == 0) { result = x; } else { // Solidity uses C fmod style, which returns a modulus with the same sign as x. result = x - remainder; if (x < 0) { result -= SCALE; } } } } /// @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 signed 59.18-decimal fixed-point number to get the fractional part of. /// @param result The fractional part of x as a signed 59.18-decimal fixed-point number. function frac(int256 x) internal pure returns (int256 result) { unchecked { result = x % SCALE; } } /// @notice Converts a number from basic integer form to signed 59.18-decimal fixed-point representation. /// /// @dev Requirements: /// - x must be greater than or equal to MIN_SD59x18 divided by SCALE. /// - x must be less than or equal to MAX_SD59x18 divided by SCALE. /// /// @param x The basic integer to convert. /// @param result The same number in signed 59.18-decimal fixed-point representation. function fromInt(int256 x) internal pure returns (int256 result) { unchecked { if (x < MIN_SD59x18 / SCALE) { revert PRBMathSD59x18__FromIntUnderflow(x); } if (x > MAX_SD59x18 / SCALE) { revert PRBMathSD59x18__FromIntOverflow(x); } result = x * SCALE; } } /// @notice Calculates 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 cannot be negative. /// /// @param x The first operand as a signed 59.18-decimal fixed-point number. /// @param y The second operand as a signed 59.18-decimal fixed-point number. /// @return result The result as a signed 59.18-decimal fixed-point number. function gm(int256 x, int256 y) internal pure returns (int256 result) { if (x == 0) { return 0; } unchecked { // Checking for overflow this way is faster than letting Solidity do it. int256 xy = x * y; if (xy / x != y) { revert PRBMathSD59x18__GmOverflow(x, y); } // The product cannot be negative. if (xy < 0) { revert PRBMathSD59x18__GmNegativeProduct(x, y); } // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE // during multiplication. See the comments within the "sqrt" function. result = int256(PRBMath.sqrt(uint256(xy))); } } /// @notice Calculates 1 / x, rounding toward zero. /// /// @dev Requirements: /// - x cannot be zero. /// /// @param x The signed 59.18-decimal fixed-point number for which to calculate the inverse. /// @return result The inverse as a signed 59.18-decimal fixed-point number. function inv(int256 x) internal pure returns (int256 result) { unchecked { // 1e36 is SCALE * SCALE. result = 1e36 / x; } } /// @notice Calculates the natural logarithm of x. /// /// @dev Based on the insight that ln(x) = log2(x) / log2(e). /// /// Requirements: /// - All from "log2". /// /// Caveats: /// - All from "log2". /// - This doesn't return exactly 1 for 2718281828459045235, for that we would need more fine-grained precision. /// /// @param x The signed 59.18-decimal fixed-point number for which to calculate the natural logarithm. /// @return result The natural logarithm as a signed 59.18-decimal fixed-point number. function ln(int256 x) internal pure returns (int256 result) { // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x) // can return is 195205294292027477728. unchecked { result = (log2(x) * SCALE) / LOG2_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 insight that log10(x) = log2(x) / log2(10). /// /// Requirements: /// - All from "log2". /// /// Caveats: /// - All from "log2". /// /// @param x The signed 59.18-decimal fixed-point number for which to calculate the common logarithm. /// @return result The common logarithm as a signed 59.18-decimal fixed-point number. function log10(int256 x) internal pure returns (int256 result) { if (x <= 0) { revert PRBMathSD59x18__LogInputTooSmall(x); } // Note that the "mul" in this block is the assembly mul operation, not the "mul" function defined in this contract. // prettier-ignore assembly { switch x case 1 { result := mul(SCALE, sub(0, 18)) } case 10 { result := mul(SCALE, sub(1, 18)) } case 100 { result := mul(SCALE, sub(2, 18)) } case 1000 { result := mul(SCALE, sub(3, 18)) } case 10000 { result := mul(SCALE, sub(4, 18)) } case 100000 { result := mul(SCALE, sub(5, 18)) } case 1000000 { result := mul(SCALE, sub(6, 18)) } case 10000000 { result := mul(SCALE, sub(7, 18)) } case 100000000 { result := mul(SCALE, sub(8, 18)) } case 1000000000 { result := mul(SCALE, sub(9, 18)) } case 10000000000 { result := mul(SCALE, sub(10, 18)) } case 100000000000 { result := mul(SCALE, sub(11, 18)) } case 1000000000000 { result := mul(SCALE, sub(12, 18)) } case 10000000000000 { result := mul(SCALE, sub(13, 18)) } case 100000000000000 { result := mul(SCALE, sub(14, 18)) } case 1000000000000000 { result := mul(SCALE, sub(15, 18)) } case 10000000000000000 { result := mul(SCALE, sub(16, 18)) } case 100000000000000000 { result := mul(SCALE, sub(17, 18)) } case 1000000000000000000 { result := 0 } case 10000000000000000000 { result := SCALE } case 100000000000000000000 { result := mul(SCALE, 2) } case 1000000000000000000000 { result := mul(SCALE, 3) } case 10000000000000000000000 { result := mul(SCALE, 4) } case 100000000000000000000000 { result := mul(SCALE, 5) } case 1000000000000000000000000 { result := mul(SCALE, 6) } case 10000000000000000000000000 { result := mul(SCALE, 7) } case 100000000000000000000000000 { result := mul(SCALE, 8) } case 1000000000000000000000000000 { result := mul(SCALE, 9) } case 10000000000000000000000000000 { result := mul(SCALE, 10) } case 100000000000000000000000000000 { result := mul(SCALE, 11) } case 1000000000000000000000000000000 { result := mul(SCALE, 12) } case 10000000000000000000000000000000 { result := mul(SCALE, 13) } case 100000000000000000000000000000000 { result := mul(SCALE, 14) } case 1000000000000000000000000000000000 { result := mul(SCALE, 15) } case 10000000000000000000000000000000000 { result := mul(SCALE, 16) } case 100000000000000000000000000000000000 { result := mul(SCALE, 17) } case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) } case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) } case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) } case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) } case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) } case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) } case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) } case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) } case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) } case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) } case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) } case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) } case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) } case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) } case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) } case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) } case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) } case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) } case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) } case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) } case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) } case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) } case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) } case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) } case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) } case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) } case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) } case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) } case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) } case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) } case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) } case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) } case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) } case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) } case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) } case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) } case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) } case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) } case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) } case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) } case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) } default { result := MAX_SD59x18 } } if (result == MAX_SD59x18) { // Do the fixed-point division inline to save gas. The denominator is log2(10). unchecked { result = (log2(x) * SCALE) / 3_321928094887362347; } } } /// @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 signed 59.18-decimal fixed-point number for which to calculate the binary logarithm. /// @return result The binary logarithm as a signed 59.18-decimal fixed-point number. function log2(int256 x) internal pure returns (int256 result) { if (x <= 0) { revert PRBMathSD59x18__LogInputTooSmall(x); } unchecked { // This works because log2(x) = -log2(1/x). int256 sign; if (x >= SCALE) { sign = 1; } else { sign = -1; // Do the fixed-point inversion inline to save gas. The numerator is SCALE * SCALE. assembly { x := div(1000000000000000000000000000000000000, x) } } // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n). uint256 n = PRBMath.mostSignificantBit(uint256(x / SCALE)); // The integer part of the logarithm as a signed 59.18-decimal fixed-point number. The operation can't overflow // because n is maximum 255, SCALE is 1e18 and sign is either 1 or -1. result = int256(n) * SCALE; // This is y = x * 2^(-n). int256 y = x >> n; // If y = 1, the fractional part is zero. if (y == SCALE) { return result * sign; } // Calculate the fractional part via the iterative approximation. // The "delta >>= 1" part is equivalent to "delta /= 2", but shifting bits is faster. for (int256 delta = int256(HALF_SCALE); delta > 0; delta >>= 1) { y = (y * y) / SCALE; // Is y^2 > 2 and so in the range [2,4)? if (y >= 2 * SCALE) { // Add the 2^(-m) factor to the logarithm. result += delta; // Corresponds to z/2 on Wikipedia. y >>= 1; } } result *= sign; } } /// @notice Multiplies two signed 59.18-decimal fixed-point numbers together, returning a new signed 59.18-decimal /// fixed-point number. /// /// @dev Variant of "mulDiv" that works with signed numbers and employs constant folding, i.e. the denominator is /// always 1e18. /// /// Requirements: /// - All from "PRBMath.mulDivFixedPoint". /// - None of the inputs can be MIN_SD59x18 /// - The result must fit within MAX_SD59x18. /// /// Caveats: /// - The body is purposely left uncommented; see the NatSpec comments in "PRBMath.mulDiv" to understand how this works. /// /// @param x The multiplicand as a signed 59.18-decimal fixed-point number. /// @param y The multiplier as a signed 59.18-decimal fixed-point number. /// @return result The product as a signed 59.18-decimal fixed-point number. function mul(int256 x, int256 y) internal pure returns (int256 result) { if (x == MIN_SD59x18 || y == MIN_SD59x18) { revert PRBMathSD59x18__MulInputTooSmall(); } unchecked { uint256 ax; uint256 ay; ax = x < 0 ? uint256(-x) : uint256(x); ay = y < 0 ? uint256(-y) : uint256(y); uint256 rAbs = PRBMath.mulDivFixedPoint(ax, ay); if (rAbs > uint256(MAX_SD59x18)) { revert PRBMathSD59x18__MulOverflow(rAbs); } uint256 sx; uint256 sy; assembly { sx := sgt(x, sub(0, 1)) sy := sgt(y, sub(0, 1)) } result = sx ^ sy == 1 ? -int256(rAbs) : int256(rAbs); } } /// @notice Returns PI as a signed 59.18-decimal fixed-point number. function pi() internal pure returns (int256 result) { result = 3_141592653589793238; } /// @notice Raises x to the power of y. /// /// @dev Based on the insight that x^y = 2^(log2(x) * y). /// /// Requirements: /// - All from "exp2", "log2" and "mul". /// - z 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 a signed 59.18-decimal fixed-point number. /// @param y Exponent to raise x to, as a signed 59.18-decimal fixed-point number. /// @return result x raised to power y, as a signed 59.18-decimal fixed-point number. function pow(int256 x, int256 y) internal pure returns (int256 result) { if (x == 0) { result = y == 0 ? SCALE : int256(0); } else { result = exp2(mul(log2(x), y)); } } /// @notice Raises x (signed 59.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the /// famous algorithm "exponentiation by squaring". /// /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring /// /// Requirements: /// - All from "abs" and "PRBMath.mulDivFixedPoint". /// - The result must fit within MAX_SD59x18. /// /// Caveats: /// - All from "PRBMath.mulDivFixedPoint". /// - Assumes 0^0 is 1. /// /// @param x The base as a signed 59.18-decimal fixed-point number. /// @param y The exponent as an uint256. /// @return result The result as a signed 59.18-decimal fixed-point number. function powu(int256 x, uint256 y) internal pure returns (int256 result) { uint256 xAbs = uint256(abs(x)); // Calculate the first iteration of the loop in advance. uint256 rAbs = y & 1 > 0 ? xAbs : uint256(SCALE); // Equivalent to "for(y /= 2; y > 0; y /= 2)" but faster. uint256 yAux = y; for (yAux >>= 1; yAux > 0; yAux >>= 1) { xAbs = PRBMath.mulDivFixedPoint(xAbs, xAbs); // Equivalent to "y % 2 == 1" but faster. if (yAux & 1 > 0) { rAbs = PRBMath.mulDivFixedPoint(rAbs, xAbs); } } // The result must fit within the 59.18-decimal fixed-point representation. if (rAbs > uint256(MAX_SD59x18)) { revert PRBMathSD59x18__PowuOverflow(rAbs); } // Is the base negative and the exponent an odd number? bool isNegative = x < 0 && y & 1 == 1; result = isNegative ? -int256(rAbs) : int256(rAbs); } /// @notice Returns 1 as a signed 59.18-decimal fixed-point number. function scale() internal pure returns (int256 result) { result = SCALE; } /// @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 cannot be negative. /// - x must be less than MAX_SD59x18 / SCALE. /// /// @param x The signed 59.18-decimal fixed-point number for which to calculate the square root. /// @return result The result as a signed 59.18-decimal fixed-point . function sqrt(int256 x) internal pure returns (int256 result) { unchecked { if (x < 0) { revert PRBMathSD59x18__SqrtNegativeInput(x); } if (x > MAX_SD59x18 / SCALE) { revert PRBMathSD59x18__SqrtOverflow(x); } // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two signed // 59.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root). result = int256(PRBMath.sqrt(uint256(x * SCALE))); } } /// @notice Converts a signed 59.18-decimal fixed-point number to basic integer form, rounding down in the process. /// @param x The signed 59.18-decimal fixed-point number to convert. /// @return result The same number in basic integer form. function toInt(int256 x) internal pure returns (int256 result) { unchecked { result = x / SCALE; } } }
// 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.8.0-rc.2) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { 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 = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _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, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { 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.8.0-rc.2) (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.8.0-rc.2) (utils/cryptography/EIP712.sol) 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: Unlicense pragma solidity >=0.8.4; /// @notice Emitted when the result overflows uint256. error PRBMath__MulDivFixedPointOverflow(uint256 prod1); /// @notice Emitted when the result overflows uint256. error PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator); /// @notice Emitted when one of the inputs is type(int256).min. error PRBMath__MulDivSignedInputTooSmall(); /// @notice Emitted when the intermediary absolute result overflows int256. error PRBMath__MulDivSignedOverflow(uint256 rAbs); /// @notice Emitted when the input is MIN_SD59x18. error PRBMathSD59x18__AbsInputTooSmall(); /// @notice Emitted when ceiling a number overflows SD59x18. error PRBMathSD59x18__CeilOverflow(int256 x); /// @notice Emitted when one of the inputs is MIN_SD59x18. error PRBMathSD59x18__DivInputTooSmall(); /// @notice Emitted when one of the intermediary unsigned results overflows SD59x18. error PRBMathSD59x18__DivOverflow(uint256 rAbs); /// @notice Emitted when the input is greater than 133.084258667509499441. error PRBMathSD59x18__ExpInputTooBig(int256 x); /// @notice Emitted when the input is greater than 192. error PRBMathSD59x18__Exp2InputTooBig(int256 x); /// @notice Emitted when flooring a number underflows SD59x18. error PRBMathSD59x18__FloorUnderflow(int256 x); /// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18. error PRBMathSD59x18__FromIntOverflow(int256 x); /// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18. error PRBMathSD59x18__FromIntUnderflow(int256 x); /// @notice Emitted when the product of the inputs is negative. error PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y); /// @notice Emitted when multiplying the inputs overflows SD59x18. error PRBMathSD59x18__GmOverflow(int256 x, int256 y); /// @notice Emitted when the input is less than or equal to zero. error PRBMathSD59x18__LogInputTooSmall(int256 x); /// @notice Emitted when one of the inputs is MIN_SD59x18. error PRBMathSD59x18__MulInputTooSmall(); /// @notice Emitted when the intermediary absolute result overflows SD59x18. error PRBMathSD59x18__MulOverflow(uint256 rAbs); /// @notice Emitted when the intermediary absolute result overflows SD59x18. error PRBMathSD59x18__PowuOverflow(uint256 rAbs); /// @notice Emitted when the input is negative. error PRBMathSD59x18__SqrtNegativeInput(int256 x); /// @notice Emitted when the calculating the square root overflows SD59x18. error PRBMathSD59x18__SqrtOverflow(int256 x); /// @notice Emitted when addition overflows UD60x18. error PRBMathUD60x18__AddOverflow(uint256 x, uint256 y); /// @notice Emitted when ceiling a number overflows UD60x18. error PRBMathUD60x18__CeilOverflow(uint256 x); /// @notice Emitted when the input is greater than 133.084258667509499441. error PRBMathUD60x18__ExpInputTooBig(uint256 x); /// @notice Emitted when the input is greater than 192. error PRBMathUD60x18__Exp2InputTooBig(uint256 x); /// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18. error PRBMathUD60x18__FromUintOverflow(uint256 x); /// @notice Emitted when multiplying the inputs overflows UD60x18. error PRBMathUD60x18__GmOverflow(uint256 x, uint256 y); /// @notice Emitted when the input is less than 1. error PRBMathUD60x18__LogInputTooSmall(uint256 x); /// @notice Emitted when the calculating the square root overflows UD60x18. error PRBMathUD60x18__SqrtOverflow(uint256 x); /// @notice Emitted when subtraction underflows UD60x18. error PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y); /// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library /// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point /// representation. When it does not, it is explicitly mentioned in the NatSpec documentation. library PRBMath { /// STRUCTS /// struct SD59x18 { int256 value; } struct UD60x18 { uint256 value; } /// STORAGE /// /// @dev How many trailing decimals can be represented. uint256 internal constant SCALE = 1e18; /// @dev Largest power of two divisor of SCALE. uint256 internal constant SCALE_LPOTD = 262144; /// @dev SCALE inverted mod 2^256. uint256 internal constant SCALE_INVERSE = 78156646155174841979727994598816262306175212592076161876661_508869554232690281; /// FUNCTIONS /// /// @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 exp2(uint256 x) internal 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 & 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 & 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 & 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 & 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 & 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 & 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 & 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 & 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 *= SCALE; result >>= (191 - (x >> 64)); } } /// @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 /// @param x The uint256 number for which to find the index of the most significant bit. /// @return msb The index of the most significant bit as an uint256. function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) { if (x >= 2**128) { x >>= 128; msb += 128; } if (x >= 2**64) { x >>= 64; msb += 64; } if (x >= 2**32) { x >>= 32; msb += 32; } if (x >= 2**16) { x >>= 16; msb += 16; } if (x >= 2**8) { x >>= 8; msb += 8; } if (x >= 2**4) { x >>= 4; msb += 4; } if (x >= 2**2) { x >>= 2; msb += 2; } if (x >= 2**1) { // No need to shift x any more. msb += 1; } } /// @notice Calculates floor(x*y÷denominator) with full precision. /// /// @dev Credit 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 ) internal 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 { 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 { result = prod0 / denominator; } return result; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (prod1 >= denominator) { revert PRBMath__MulDivOverflow(prod1, denominator); } /////////////////////////////////////////////// // 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. unchecked { // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 lpotdod = denominator & (~denominator + 1); assembly { // 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; return result; } } /// @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) % SCALE >= HALF_SCALE. Without this, 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; see the NatSpec comments in "PRBMath.mulDiv" to understand how this works. /// - 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 * SCALE /// 2. (x * y) % SCALE >= SCALE / 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 mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) { uint256 prod0; uint256 prod1; assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } if (prod1 >= SCALE) { revert PRBMath__MulDivFixedPointOverflow(prod1); } uint256 remainder; uint256 roundUpUnit; assembly { remainder := mulmod(x, y, SCALE) roundUpUnit := gt(remainder, 499999999999999999) } if (prod1 == 0) { unchecked { result = (prod0 / SCALE) + roundUpUnit; return result; } } assembly { result := add( mul( or( div(sub(prod0, remainder), SCALE_LPOTD), mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1)) ), SCALE_INVERSE ), roundUpUnit ) } } /// @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 ) internal pure returns (int256 result) { if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) { revert PRBMath__MulDivSignedInputTooSmall(); } // Get hold of the absolute values of x, y and the denominator. uint256 ax; uint256 ay; uint256 ad; unchecked { ax = x < 0 ? uint256(-x) : uint256(x); ay = y < 0 ? uint256(-y) : uint256(y); ad = denominator < 0 ? uint256(-denominator) : uint256(denominator); } // Compute the absolute value of (x*y)÷denominator. The result must fit within int256. uint256 rAbs = mulDiv(ax, ay, ad); if (rAbs > uint256(type(int256).max)) { revert PRBMath__MulDivSignedOverflow(rAbs); } // Get the signs of x, y and the denominator. uint256 sx; uint256 sy; uint256 sd; assembly { sx := sgt(x, sub(0, 1)) sy := sgt(y, sub(0, 1)) sd := sgt(denominator, sub(0, 1)) } // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs. // If yes, the result should be negative. result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs); } /// @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. /// /// 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 sqrt(uint256 x) internal pure returns (uint256 result) { if (x == 0) { return 0; } // Set the initial guess to the least power of two that is greater than or equal to sqrt(x). uint256 xAux = uint256(x); result = 1; if (xAux >= 0x100000000000000000000000000000000) { xAux >>= 128; result <<= 64; } if (xAux >= 0x10000000000000000) { xAux >>= 64; result <<= 32; } if (xAux >= 0x100000000) { xAux >>= 32; result <<= 16; } if (xAux >= 0x10000) { xAux >>= 16; result <<= 8; } if (xAux >= 0x100) { xAux >>= 8; result <<= 4; } if (xAux >= 0x10) { xAux >>= 4; result <<= 2; } if (xAux >= 0x8) { result <<= 1; } // The operations can never overflow because the result is max 2^127 when it enters this block. 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; // Seven iterations should be enough uint256 roundedDownResult = x / result; return result >= roundedDownResult ? roundedDownResult : result; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0-rc.2) (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://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return 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 (last updated v4.8.0-rc.2) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { 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 * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0-rc.2) (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 // OpenZeppelin Contracts (last updated v4.8.0-rc.2) (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.8.0-rc.2) (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 * 8) < value ? 1 : 0); } } }
{ "optimizer": { "enabled": true, "mode": "3", "fallback_to_optimizing_for_size": true }, "outputSelection": { "*": { "*": [ "abi" ] } }, "detectMissingLibraries": false, "forceEVMLA": false, "enableEraVMExtensions": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","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":"Q","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_P","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"assignPubKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"digest","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint8","name":"signerIndex","type":"uint8"}],"name":"checkIndividualSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"deletePubkey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"index","type":"uint8"}],"name":"getPubkey","outputs":[{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Verifier.Point","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"index","type":"uint8"}],"name":"getPubkeyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Verifier.Point[8]","name":"initialSet","type":"tuple[8]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"message","type":"bytes32"},{"internalType":"bytes32","name":"e","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"signerBitmask","type":"uint8"}],"name":"requireValidSignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"txn","type":"bytes"},{"internalType":"uint64","name":"idx","type":"uint64"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"requireValidTxSignatures","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"name":"revertGasInfo","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"address","name":"linkedSigner","type":"address"},{"internalType":"bytes32","name":"digest","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"validateSignature","outputs":[],"stateMutability":"pure","type":"function"}]
Contract Creation Code
9c4d535b00000000000000000000000000000000000000000000000000000000000000000100033df0a3c3c230bc33af8b578b1406c2d4a709afa9dbb9060d6f2848dc0200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x0002000000000002000900000000000200010000000103550000006004100270000002d40040019d0000008003000039000000400030043f0000000100200190000000210000c13d000002d402400197000000040020008c000004910000413d000000000401043b000000e004400270000002dc0040009c0000004a0000a13d000002dd0040009c000000660000213d000002e30040009c000000b60000213d000002e60040009c000001750000613d000002e70040009c000004910000c13d0000000001000416000000000001004b000004910000c13d0000006701000039000000000101041a000002f101100197000000800010043f000002f80100004100000b4c0001042e0000000001000416000000000001004b000004910000c13d000000000100041a0000ff00001001900000003e0000c13d000000ff0210018f000000ff0020008c000000390000613d000000ff011001bf000000000010041b000000ff01000039000000800010043f0000000001000414000002d40010009c000002d401008041000000c001100210000002d9011001c70000800d020000390000000103000039000002da040000410b4b0b410000040f0000000100200190000004910000613d000000200100003900000100001004430000012000000443000002db0100004100000b4c0001042e000002d501000041000000800010043f0000002001000039000000840010043f0000002701000039000000a40010043f000002d601000041000000c40010043f000002d701000041000000e40010043f000002d80100004100000b4d00010430000002e80040009c000000730000a13d000002e90040009c000000cd0000213d000002ec0040009c0000018e0000613d000002ed0040009c000004910000c13d000000240020008c000004910000413d0000000002000416000000000002004b000004910000c13d0000000401100370000000000101043b000000ff0010008c000004910000213d0b4b071c0000040f0000000021010434000000400300043d000000000113043600000000020204330000000000210435000002d40030009c000002d40300804100000040013002100000030f011001c700000b4c0001042e000002de0040009c000001540000213d000002e10040009c000002300000613d000002e20040009c000004910000c13d0000000001000416000000000001004b000004910000c13d000002f701000041000000800010043f000002f80100004100000b4c0001042e000002ee0040009c000002800000613d000002ef0040009c000002a30000613d000002f00040009c000004910000c13d000000440020008c000004910000413d0000000002000416000000000002004b000004910000c13d0000000401100370000000000101043b0000031e011001970b4b0ae50000040f00000024020000390000000102200367000000000202043b000800000001001d0000031e012001970b4b0ae50000040f0000031f02000041000000400400043d000900000004001d0000002003400039000000000023043500000008020000290000000053020434000800000003001d000700000001001d000000220240003900000000010500190b4b06bb0000040f00000320010000410000000803000029000000090230002900000022032000390000000000130435000000230220003900000007010000290000000013010434000700000003001d0b4b06bb0000040f0000000702000029000000080320002900000003023000390000000901000029000000000021043500000023023000390b4b06780000040f000002d501000041000000400200043d000800000002001d0000000000120435000000040120003900000009020000290b4b06c90000040f00000008020000290000000001210049000002d40010009c000002d4010080410000006001100210000002d40020009c000002d4020080410000004002200210000000000121019f00000b4d00010430000002e40040009c000002aa0000613d000002e50040009c000004910000c13d000000640020008c000004910000413d0000000001000416000000000001004b000004910000c13d0b4b068a0000040f00000001030003670000000401300370000000000101043b0000002402300370000000000202043b0000004403300370000000000303043b0b4b06df0000040f000000400100043d000002d40010009c000002d401008041000000400110021000000b4c0001042e000002ea0040009c000002bf0000613d000002eb0040009c000004910000c13d000002040020008c000004910000413d0000000004000416000000000004004b000004910000c13d0000018004000039000000400040043f0000000404000039000000400220008a0000030505200197000000000024004b000000000600001900000305060020410000030507400197000000000857013f000000000057004b00000000070000190000030507004041000003050080009c000000000706c019000000000007004b000004910000c13d000000400600043d000002fc0060009c000002e70000213d0000004007600039000000400070043f000000000741034f000000000707043b00000000077604360000002008400039000000000881034f000000000808043b00000000008704350000000003630436000001c40040008c0000004004400039000000db0000413d000000000300041a0000ffff003001900000000002030019000003460000c13d0000ff00003001900000032a0120019700000001031001bf000000000030041b000000400100043d0000038d0000c13d0000032b0230019700000100022001bf000000000020041b0000000002000411000002f1062001970000006702000039000000000302041a0000030104300197000000000464019f000000000042041b000002d40010009c000002d40100804100000040011002100000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f000002f1053001970000030b011001c70000800d02000039000000030300003900000303040000410b4b0b410000040f0000000100200190000004910000613d000002b1010000390000000003000019000001210000013d000000070030008c0000000103300039000003fd0000813d0000000504300210000000800440003900000000040404330000000054040434000000000505043300000000005401a00000011e0000613d000000400700043d000002fc0070009c000002e70000213d0000004006700039000000400060043f00000001083002100000009906800039000000000906041a000000000a9704360000009a07800039000000000807041a00000000008a043500000000008901a00000013a0000c13d000000000801041a000000010880003a000004850000613d000000000081041b000000400800043d000002fc0080009c000002e70000213d0000004009800039000000400090043f000000200980003900000000005904350000000000480435000000000046041b000000000057041b000000010430020f00000000050400190000000306500210000000f80660018f000000ff0660020f0000032c066001670000000507500270000002a907700039000000000807041a000000000668016f000000000067041b0000000105500039000000000545019f000001000050008c000001460000413d0000011e0000013d000002df0040009c000002d00000613d000002e00040009c000004910000c13d000000240020008c000004910000413d0000000002000416000000000002004b000004910000c13d0000000401100370000000000101043b000002f10010009c000004910000213d0000006702000039000000000202041a000002f1022001970000000003000411000000000032004b000002ed0000c13d000002f1001001980000035d0000c13d000002d501000041000000800010043f0000002001000039000000840010043f0000002601000039000000a40010043f000002f201000041000000c40010043f000002f301000041000000e40010043f000002d80100004100000b4d000104300000000001000416000000000001004b000004910000c13d0000006701000039000000000201041a000002f1052001970000000003000411000000000035004b000002ed0000c13d0000030102200197000000000021041b0000000001000414000002d40010009c000002d401008041000000c00110021000000302011001c70000800d020000390000000303000039000003030400004100000000060000190b4b0b410000040f0000000100200190000004910000613d000003040100004100000b4c0001042e000000640020008c000004910000413d0000000003000416000000000003004b000004910000c13d0000000403100370000000000303043b000002f40030009c000004910000213d0000002304300039000000000024004b000004910000813d000700040030003d0000000704100360000000000404043b000800000004001d000002f40040009c000004910000213d00000008033000290000002403300039000000000023004b000004910000213d0000002403100370000000000303043b000600000003001d000002f40030009c000004910000213d0000004403100370000000000303043b000300000003001d000002f40030009c000004910000213d00000003030000290000002303300039000000000023004b000004910000813d00000003030000290000000403300039000000000131034f000000000101043b000200000001001d000002f40010009c000004910000213d0000000301000029000900240010003d000000020100002900000005011002100000000901100029000000000021004b000004910000213d000003100100004100000000001004430000000001000414000002d40010009c000002d401008041000000c00110021000000311011001c70000800b020000390b4b0b460000040f0000000100200190000003980000613d000000000101043b000000a00010043f0000000601000029000000c00010043f00000008030000290000032d023001980000001f0330018f000000e001200039000000070400002900000020044000390000000104400367000001dd0000613d000000e005000039000000000604034f000000006706043c0000000005750436000000000015004b000001d90000c13d000000000003004b000001ea0000613d000000000224034f0000000303300210000000000401043300000000043401cf000000000434022f000000000202043b0000010003300089000000000232022f00000000023201cf000000000242019f00000000002104350000000803000029000000e00130003900000000000104350000007f013000390000032d021001970000004001300039000000800010043f000002f50020009c000002e70000213d0000008002200039000000400020043f000002d40010009c000002d40100804100000060011002100000000002000414000002d40020009c000002d402008041000000c002200210000000000121019f00000312011001c700008010020000390b4b0b460000040f0000000100200190000004910000613d000000000301043b000000400100043d0000002002100039000003130400004100000000004204350000003c0410003900000000003404350000003c030000390000000000310435000003140010009c000002e70000213d0000006003100039000000400030043f000002d40020009c000002d40200804100000040022002100000000001010433000002d40010009c000002d4010080410000006001100210000000000121019f0000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f0000030b011001c700008010020000390b4b0b460000040f0000000100200190000004910000613d000000000101043b000100000001001d000000020000006b000800000000001d000005680000c13d000000400200043d000002d40020009c000002d40100004100000000010240190000004001100210000002b103000039000000000303041a000000080030006b000006580000c13d00000b4c0001042e000000840020008c000004910000413d0000000003000416000000000003004b000004910000c13d0000002403100370000000000303043b000900000003001d000002f10030009c000004910000213d0000006403100370000000000403043b000002f40040009c000004910000213d0000002303400039000000000023004b000004910000813d0000000405400039000000000351034f000000000303043b000002f40030009c000002e70000213d0000001f073000390000032d077001970000003f077000390000032d07700197000002f50070009c000002e70000213d00000024044000390000008007700039000000400070043f000000800030043f0000000004430019000000000024004b000004910000213d0000002002500039000000000421034f0000032d053001980000001f0630018f000000a0025000390000025f0000613d000000a007000039000000000804034f000000008908043c0000000007970436000000000027004b0000025b0000c13d000000000006004b0000026c0000613d000000000454034f0000000305600210000000000602043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000420435000000a00230003900000000000204350000004401100370000000000101043b000000800200043d000000410020008c000006470000c13d000000c00200043d000002f90020009c0000043f0000a13d000000400100043d00000064021000390000031903000041000000000032043500000044021000390000031a03000041000000000032043500000024021000390000002203000039000003f20000013d000000840020008c000004910000413d0000000002000416000000000002004b000004910000c13d0000006401100370000000000101043b000000ff0010008c000004910000213d000000000300001900000000020000190000028f0000013d000000070030008c00000001033000390000030b0000813d000000000431022f00000001004001900000028c0000613d000000400400043d000003220040009c000002e70000813d0000004005400039000000400050043f00000001053002100000009906500039000000000606041a00000000046404360000009a05500039000000000505041a000000000054043500000000005601a0000004910000613d000000010220003a0000028c0000c13d000004850000013d0000000001000416000000000001004b000004910000c13d0000032101000041000000800010043f000002f80100004100000b4c0001042e000000240020008c000004910000413d0000000002000416000000000002004b000004910000c13d0000000401100370000000000101043b0000006702000039000000000202041a000002f1022001970000000003000411000000000032004b000002ed0000c13d000000070010008c000002f60000a13d0000031b01000041000000000010043f0000003201000039000000040010043f0000031c0100004100000b4d00010430000000240020008c000004910000413d0000000002000416000000000002004b000004910000c13d0000000401100370000000000101043b000000ff0010008c000004910000213d0b4b07400000040f000000400200043d0000000000120435000002d40020009c000002d4020080410000004001200210000002f6011001c700000b4c0001042e000000640020008c000004910000413d0000000003000416000000000003004b000004910000c13d0000002403100370000000000403043b000002f40040009c000004910000213d0000002303400039000000000023004b000004910000813d0000000405400039000000000351034f000000000303043b000002f40030009c000002e70000213d0000001f073000390000032d077001970000003f077000390000032d07700197000002f50070009c0000035f0000a13d0000031b01000041000000000010043f0000004101000039000000040010043f0000031c0100004100000b4d00010430000002d501000041000000800010043f0000002001000039000000840010043f000000a40010043f000002ff01000041000000c40010043f000003000100004100000b4d00010430000000c002000039000000400020043f00000001021002100000009901200039000000000301041a000000800030043f0000009a02200039000000000402041a000000a00040043f00000000004301a0000003090000613d000002b103000039000000000403041a000000000004004b000004850000613d000000010440008a000000000043041b000000000001041b000000000002041b000002fe0100004100000b4c0001042e000003230020009c000004850000213d000002b103000039000000000303041a0000000102200210000000000032004b000004910000a13d0b4b07830000040f00000001070003670000004402700370000000000302043b000002f70230009c0000000003028019000000008a010434000002f702a0009c00000000020a401900000000313200a9000003246430012a00000080051002700000000409700370000000000b09043b0000002407700370000000000907043b000000000708043300000001007001900000001c0c0000390000001b0c006039000003250030009c0000032d0000213d0000008007600210000000000757019f00000326084000d1000000000078004b000003320000a13d000000010440008a000000000006004b000003320000c13d0000031e0040009c000000020400808a0000008003300210000000000353019f0000031e0440019700000327044000d10000000003430019000003246430012a0000031e01100197000003250030009c000003400000213d0000008005600210000000000515019f00000326074000d1000000000057004b000004120000a13d000000010540008a000000000006004b000004130000c13d0000031e0050009c000000020540808a000004130000013d000900000003001d00000306010000410000000000100443000000000100041000000004001004430000000001000414000002d40010009c000002d401008041000000c00110021000000307011001c700008002020000390b4b0b460000040f0000000100200190000003980000613d0000000903000029000000ff0230018f000000000101043b000000010020008c000003e90000c13d000000000001004b000003e90000c13d000000000200041a000000fb0000013d0b4b06a10000040f000000c80000013d00000024044000390000008007700039000000400070043f000000800030043f0000000004430019000000000024004b000004910000213d0000002002500039000000000421034f0000032d053001980000001f0630018f000000a002500039000003720000613d000000a007000039000000000804034f000000008908043c0000000007970436000000000027004b0000036e0000c13d000000000006004b0000037f0000613d000000000454034f0000000305600210000000000602043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000420435000000a00230003900000000000204350000004402100370000000000302043b000000ff0030008c000004910000213d0000000401100370000000000101043b00000080020000390b4b0a070000040f000000000001004b0000000001000039000000010100c039000002c90000013d0000ff0000200190000003990000c13d00000064021000390000030c03000041000000000032043500000044021000390000030d03000041000000000032043500000024021000390000002b03000039000003f20000013d000000000001042f0000000002000411000002f1062001970000006702000039000000000302041a0000030104300197000000000464019f000000000042041b000002d40010009c000002d40100804100000040011002100000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f000002f1053001970000030b011001c70000800d02000039000000030300003900000303040000410b4b0b410000040f0000000100200190000004910000613d000002b1010000390000000003000019000003b60000013d000000070030008c0000000103300039000000c80000813d0000000504300210000000800440003900000000040404330000000054040434000000000505043300000000005401a0000003b30000613d000000400700043d000002fc0070009c000002e70000213d0000004006700039000000400060043f00000001083002100000009906800039000000000906041a000000000a9704360000009a07800039000000000807041a00000000008a043500000000008901a0000003cf0000c13d000000000801041a000000010880003a000004850000613d000000000081041b000000400800043d000002fc0080009c000002e70000213d0000004009800039000000400090043f000000200980003900000000005904350000000000480435000000000046041b000000000057041b000000010430020f00000000050400190000000306500210000000f80660018f000000ff0660020f0000032c066001670000000507500270000002a907700039000000000807041a000000000668016f000000000067041b0000000105500039000000000545019f000001000050008c000003db0000413d000003b30000013d000000400100043d00000064021000390000030803000041000000000032043500000044021000390000030903000041000000000032043500000024021000390000002e030000390000000000320435000002d5020000410000000000210435000000040210003900000020030000390000000000320435000002d40010009c000002d40100804100000040011002100000030a011001c700000b4d00010430000000000200041a0000032e01200197000000000010041b0000000103000039000000400100043d0000000000310435000002d40010009c000002d40100804100000040011002100000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f0000030e011001c70000800d02000039000002da040000410b4b0b410000040f0000000100200190000000c80000c13d000004910000013d00000000050400190000008003300210000000000113019f0000031e0350019700000327033000d10000000001310019000002f70010009c000004850000213d000002f70390009c000000000309401900000000323200a9000003246430012a0000008005200270000003250030009c000004260000213d0000008007600210000000000757019f00000326084000d1000000000078004b0000042b0000a13d000000010440008a000000000006004b0000042b0000c13d0000031e0040009c000000020400808a0000008003300210000000000353019f0000031e0440019700000327044000d10000000003430019000003246430012a0000031e02200197000003250030009c000004390000213d0000008005600210000000000525019f00000326074000d1000000000057004b0000047d0000a13d000000010540008a000000000006004b0000047e0000c13d0000031e0050009c000000020540808a0000047e0000013d000000400300043d0000006004300039000000e00500043d000000a00600043d000000000024043500000040023000390000000000620435000000f802500270000000200430003900000000002404350000000000130435000000000000043f000002d40030009c000002d40300804100000040013002100000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f000002fa011001c700000001020000390b4b0b460000040f0000006003100270000002d403300197000000200030008c000000200400003900000000040340190000001f0540018f0000002004400190000004640000613d000000000601034f0000000007000019000000006806043c0000000007870436000000000047004b000004600000c13d000000000005004b000004710000613d000000000641034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f00000000005404350000000100200190000004dc0000613d000000000100043d000002f101100198000005170000c13d000000400100043d000000440210003900000318030000410000000000320435000000240210003900000018030000390000064d0000013d00000000050400190000008003300210000000000223019f0000031e0350019700000327033000d10000000002320019000002f70020009c0000048b0000a13d0000031b01000041000000000010043f0000001101000039000000040010043f0000031c0100004100000b4d0001043000080000000c001d00070000000b001d00090000000a001d000600000009001d000002f70010009c000004930000c13d000000000100001900000b4d00010430000002f702200099000000400300043d00000060043000390000000000240435000000400230003900000009040000290000000000420435000000200230003900000008040000290000000000420435000002f7011000990000000000130435000000000000043f000002d40030009c000002d40300804100000040013002100000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f000002fa011001c700000001020000390b4b0b460000040f0000006003100270000002d404300197000000200040008c000000200300003900000000030440190000001f0530018f0000002003300190000004b90000613d000000000601034f0000000007000019000000006806043c0000000007870436000000000037004b000004b50000c13d000000000005004b000004c60000613d000000000631034f0000000305500210000000000703043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000530435000000400300043d0000000100200190000004fa0000613d000000000100043d000002f1001001980000052f0000c13d000000440130003900000329020000410000000000210435000000240130003900000010020000390000000000210435000002d5010000410000000000130435000000040130003900000020020000390000000000210435000002d40030009c000002d403008041000000400130021000000316011001c700000b4d000104300000001f0530018f000002fb06300198000000400200043d0000000004620019000004e70000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000004e30000c13d000000000005004b000004f40000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000002d40020009c000002d4020080410000004002200210000000000112019f00000b4d000104300000001f0540018f000002fb064001980000000002630019000005040000613d000000000701034f0000000008030019000000007907043c0000000008980436000000000028004b000005000000c13d000000000005004b000005110000613d000000000161034f0000000305500210000000000602043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001204350000006001400210000002d40030009c000002d4030080410000004002300210000000000112019f00000b4d00010430000000400200043d000002fc0020009c000002e70000213d00000004030000390000000103300367000000000303043b0000004004200039000000400040043f0000002004200039000002fd05000041000000000054043500000002040000390000000000420435000000400500043d000000090010006c0000055e0000613d0000006003300270000000000031004b0000055e0000613d000002d501000041000800000005001d00000000001504350000000401500039000000ab0000013d0000006002100210000000200130003900000000002104350000000802000029000000f8022002100000003404300039000000000024043500000055023000390000000704000029000000000042043500000035023000390000000904000029000000000042043500000055020000390000000000230435000002f50030009c000002e70000213d0000008002300039000000400020043f000002d40010009c000002d40100804100000040011002100000000002030433000002d40020009c000002d4020080410000006002200210000000000112019f0000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f0000030b011001c700008010020000390b4b0b460000040f0000000100200190000004910000613d000000000301034f000000400200043d000002d40020009c000002d40100004100000000010240190000004001100210000000000303043b000000060030006c000005620000c13d00000b4c0001042e000002d40050009c000002d405008041000000400150021000000b4c0001042e000000440320003900000328040000410000000000430435000000240320003900000013040000390000065d0000013d000000000200003100000001010003670000000009000019000800000000001d000005700000013d0000000109900039000000020090006c000002260000813d000000030420006a00000005039002100000000903300029000000000331034f000000000303043b000000430440008a00000305054001970000030506300197000000000756013f000000000056004b00000000050000190000030505004041000000000043004b00000000040000190000030504008041000003050070009c000000000504c019000000000005004b000004910000c13d0000000904300029000000000341034f000000000303043b000002f40030009c000004910000213d0000000005320049000000200440003900000305065001970000030507400197000000000867013f000000000067004b00000000060000190000030506004041000000000054004b00000000050000190000030505002041000003050080009c000000000605c019000000000006004b000004910000c13d000000000003004b0000056d0000613d0000000805000029000800010050003e000004850000613d0000001f053000390000032d055001970000003f055000390000032d05500197000000400800043d0000000005580019000000000085004b00000000060000390000000106004039000002f40050009c000002e70000213d0000000100600190000002e70000c13d000000400050043f000000000a3804360000000005430019000000000025004b000004910000213d000000000241034f0000032d0430019800000000014a0019000005b80000613d000000000502034f00000000060a0019000000005705043c0000000006760436000000000016004b000005b40000c13d0000001f05300190000005c50000613d000000000242034f0000000304500210000000000501043300000000054501cf000000000545022f000000000202043b0000010004400089000000000242022f00000000024201cf000000000252019f000000000021043500000000013a00190000000000010435000000400200043d000002fc0020009c000002e70000213d000000ff0190018f0000004003200039000000400030043f000000200320003900000000000304350000000000020435000000080010008c000002b90000813d000000400200043d000002fc0020009c000002e70000213d0000004003200039000000400030043f00000001011002100000009903100039000000000303041a00000000023204360000009a01100039000000000401041a0000000000420435000000400100043d00000040021000390000000000420435000000400200003900000000022104360000000000320435000003140010009c000002e70000213d0000006003100039000000400030043f000002d40020009c000002d40200804100000040022002100000000001010433000002d40010009c000002d4010080410000006001100210000000000121019f0000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f0000030b011001c70000801002000039000500000009001d000700000008001d00060000000a001d0b4b0b460000040f000000060400002900000007030000290000000100200190000004910000613d000000000201043b0000000001030433000000410010008c000006470000c13d000400000002001d00000040013000390000000001010433000002f90010009c000002760000213d000000600230003900000000020204330000000003040433000000400400043d0000006005400039000000000015043500000040014000390000000000310435000000f8012002700000002002400039000000000012043500000001010000290000000000140435000000000000043f000002d40040009c000002d40400804100000040014002100000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f000002fa011001c700000001020000390b4b0b460000040f0000006003100270000002d403300197000000200030008c0000002005000039000000000503401900000020045001900000062e0000613d000000000601034f0000000007000019000000006806043c0000000007870436000000000047004b0000062a0000c13d0000001f055001900000063b0000613d000000000641034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f000000000054043500000001002001900000000509000029000006650000613d000000000100043d000002f100100198000004760000613d000000040110014f000002f100100198000006710000c13d000000000200003100000001010003670000056d0000013d000000400100043d00000044021000390000031503000041000000000032043500000024021000390000001f030000390000000000320435000002d5020000410000000000210435000000040210003900000020030000390000000000320435000002d40010009c000002d401008041000000400110021000000316011001c700000b4d0001043000000044032000390000031d040000410000000000430435000000240320003900000015040000390000000000430435000002d503000041000000000032043500000004022000390000002003000039000000000032043500000316011001c700000b4d000104300000001f0530018f000002fb06300198000000400200043d0000000004620019000004e70000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000066c0000c13d000004e70000013d000000400100043d000000440210003900000317030000410000000000320435000000240210003900000011030000390000064d0000013d0000001f022000390000032d022001970000000001120019000000000021004b00000000020000390000000102004039000002f40010009c000006840000213d0000000100200190000006840000c13d000000400010043f000000000001042d0000031b01000041000000000010043f0000004101000039000000040010043f0000031c0100004100000b4d000104300000006701000039000000000101041a000002f1011001970000000002000411000000000021004b000006910000c13d000000000001042d000000400100043d0000004402100039000002ff030000410000000000320435000002d502000041000000000021043500000024021000390000002003000039000000000032043500000004021000390000000000320435000002d40010009c000002d401008041000000400110021000000316011001c700000b4d00010430000002f1061001970000006701000039000000000201041a0000030103200197000000000363019f000000000031041b000000400100043d000002d40010009c000002d40100804100000040011002100000000003000414000002d40030009c000002d403008041000000c003300210000000000113019f000002f1052001970000030b011001c70000800d02000039000000030300003900000303040000410b4b0b410000040f0000000100200190000006b90000613d000000000001042d000000000100001900000b4d00010430000000000003004b000006c80000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000034004b000006be0000413d000006c80000a13d00000000012300190000000000010435000000000001042d00000020030000390000000004310436000000003202043400000000002404350000004001100039000000000002004b000006db0000613d000000000400001900000000051400190000000006430019000000000606043300000000006504350000002004400039000000000024004b000006d10000413d000006db0000a13d000000000312001900000000000304350000001f022000390000032d022001970000000001210019000000000001042d000000080010008c000007140000813d000000400500043d000003220050009c0000070e0000813d0000004004500039000000400040043f00000001061002100000009904600039000000000704041a00000000087504360000009a05600039000000000605041a000000000068043500000000006701a0000006f40000c13d000002b106000039000000000706041a000000010770003a000007160000613d000000000076041b000000400600043d000002fc0060009c0000070e0000213d0000004007600039000000400070043f000000200760003900000000003704350000000000260435000000000024041b000000000035041b000000010110020f00000000030100190000000304300210000000f80440018f000000ff0440020f0000032c044001670000000505300270000002a905500039000000000605041a000000000446016f000000000045041b0000000103300039000000000313019f000001000030008c000007000000413d000000000001042d0000031b01000041000000000010043f0000004101000039000000040010043f0000031c0100004100000b4d00010430000000000100001900000b4d000104300000031b01000041000000000010043f0000001101000039000000040010043f0000031c0100004100000b4d00010430000000400200043d000003220020009c000007340000813d0000004003200039000000400030043f000000200320003900000000000304350000000000020435000000080010008c0000073a0000813d000000400200043d000002fc0020009c000007340000213d0000004003200039000000400030043f00000001011002100000009903100039000000000303041a00000000033204360000009a01100039000000000101041a00000000001304350000000001020019000000000001042d0000031b01000041000000000010043f0000004101000039000000040010043f0000031c0100004100000b4d000104300000031b01000041000000000010043f0000003201000039000000040010043f0000031c0100004100000b4d00010430000000400200043d000003220020009c000007750000813d0000004003200039000000400030043f000000200320003900000000000304350000000000020435000000080010008c0000077b0000813d000000400200043d000002fc0020009c000007750000213d0000004003200039000000400030043f00000001011002100000009903100039000000000303041a00000000023204360000009a01100039000000000401041a0000000000420435000000400100043d00000040021000390000000000420435000000400200003900000000022104360000000000320435000003140010009c000007750000213d0000006003100039000000400030043f000002d40020009c000002d40200804100000040022002100000000001010433000002d40010009c000002d4010080410000006001100210000000000121019f0000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f0000030b011001c700008010020000390b4b0b460000040f0000000100200190000007810000613d000000000101043b000002f101100197000000000001042d0000031b01000041000000000010043f0000004101000039000000040010043f0000031c0100004100000b4d000104300000031b01000041000000000010043f0000003201000039000000040010043f0000031c0100004100000b4d00010430000000000100001900000b4d0001043000080000000000020000000008010019000000400100043d000003220010009c000009ee0000813d0000004002100039000000400020043f000000200210003900000000000204350000000000010435000000ff00800190000007b50000613d000001000080008c000009f40000813d0000000301800210000000f80210018f000000ff0420020f0000000501800270000002a903100039000000000103041a0000000000410170000007b70000c13d000300000004001d000400000003001d000500000002001d000000400100043d000002fc0010009c000009ee0000213d0000004002100039000000400020043f000000000601043600000000000604350000000100800190000007c40000c13d0000000200800190000007c80000c13d0000000400800190000007cc0000c13d0000000800800190000007d00000c13d0000001000800190000007d40000c13d0000002000800190000007d80000c13d0000004000800190000007dc0000c13d0000008000800190000007e00000c13d0000000002000019000009de0000013d000000ff0080008c000009f40000213d000000400100043d000002fc0010009c000009ee0000213d0000004002100039000000400020043f0000000102800210000000a903200039000000000303041a0000000003310436000000aa02200039000000000202041a0000000000230435000000000001042d00000001010000390000009a040000390000009905000039000007e30000013d00000002010000390000009c040000390000009b05000039000007e30000013d00000004010000390000009e040000390000009d05000039000007e30000013d0000000801000039000000a0040000390000009f05000039000007e30000013d0000001001000039000000a204000039000000a105000039000007e30000013d0000002001000039000000a404000039000000a305000039000007e30000013d0000004001000039000000a604000039000000a505000039000007e30000013d0000008001000039000000a804000039000000a705000039000000400200043d000002fc0020009c000009ee0000213d0000004003200039000000400030043f000100000005001d000000000305041a0000000002320436000200000004001d000000000404041a000000000042043500000000004301a0000009fa0000613d000000000181013f000600000008001d0b4b07830000040f00000006080000290000000002010019000000400100043d000002fc0010009c00000002040000290000000105000029000009ee0000213d0000004003100039000000400030043f000000000305041a0000000006310436000000000304041a00000000003604350000000003000415000000400400043d000002fc0040009c000009ee0000213d0000004005400039000000400050043f0000002005400039000000000005043500000000000404350000000004020433000000000004004b000008100000c13d00000020052000390000000005050433000000000005004b000009da0000613d00000020052000390000000001010433000000000001004b000008170000c13d0000000007060433000000000007004b000009180000613d0000000002050433000000000014004b000008820000c13d0000000005060433000000000052004b000008f50000c13d000003210520009c00000000050240190000007f06500270000003340660019700000001055002100000008007500270000000000676019f0000031e6760012a00000080066002100000032408500197000000000686019f00000331087000d1000000000068004b000000010770208a0000031e0670019700000332066000d100000000085600190000032f060000410000000105000039000008390000013d000000010880008a000000800aa0021000000000099a019f0000031e0880019700000332088000d100000000088900190000000106600272000008fb0000613d000003210980009a0000000100600190000008620000613d000003210a50009c00000000050a8019000003210080009c000000000a090019000000000a08401900000000b55a00a90000031edab0012a000000800c5002700000033000b0009c0000084c0000213d000000800dd00210000000000dcd019f000003310ea000d10000000000de004b000000010aa0208a0000084d0000013d000000010aa0008a000000800bb00210000000000bcb019f0000031e0aa00197000003320aa000d1000000000bab00190000031ecab0012a0000031e055001970000033000b0009c0000085c0000213d000000800cc00210000000000c5c019f000003310da000d10000000000cd004b000000010aa0208a0000085d0000013d000000010aa0008a000000800bb0021000000000055b019f0000031e0aa00197000003320aa000d10000000005a50019000003210080009c000000000809801900000000a98800a90000033300a0009c0000032c08000041000008370000213d0000031ec8a0012a000000800b9002700000033000a0009c000008720000213d000000800cc00210000000000cbc019f000003310d8000d10000000000cd004b000000010880208a000008730000013d000000010880008a000000800aa00210000000000aba019f0000031e0880019700000332088000d1000000000a8a00190000031eb8a0012a0000031e099001970000033000a0009c000008310000213d000000800bb00210000000000b9b019f000003310c8000d10000000000bc004b000000010880208a000008320000013d000003210020009c00000a010000213d0000032107200099000000000002004b00000000070060190000000006060433000003210560009c00000000060580190000000005760019000003210850009c0000000005088019000000000076001a0000000005084019000003210040009c00000a010000213d0000032107400099000000000004004b0000000007006019000003210810009c00000000080140190000000009780019000003210a90009c00000000090a8019000000000078001a00000000090a40190000032f070000410000000108000039000008a60000013d000000010990008a000000800bb00210000000000aab019f0000031e0990019700000332099000d100000000099a00190000000107700272000008ef0000613d000003210a90009a0000000100700190000008cf0000613d000003210b80009c00000000080b8019000003210090009c000000000b0a0019000000000b09401900000000c88b00a90000031eebc0012a000000800d8002700000033000c0009c000008b90000213d000000800ee00210000000000ede019f000003310fb000d10000000000ef004b000000010bb0208a000008ba0000013d000000010bb0008a000000800cc00210000000000cdc019f0000031e0bb00197000003320bb000d1000000000cbc00190000031edbc0012a0000031e088001970000033000c0009c000008c90000213d000000800dd00210000000000d8d019f000003310eb000d10000000000de004b000000010bb0208a000008ca0000013d000000010bb0008a000000800cc0021000000000088c019f0000031e0bb00197000003320bb000d10000000008b80019000003210090009c00000000090a801900000000ba9900a90000033300b0009c0000032c09000041000008a40000213d0000031ed9b0012a000000800ca002700000033000b0009c000008df0000213d000000800dd00210000000000dcd019f000003310e9000d10000000000de004b000000010990208a000008e00000013d000000010990008a000000800bb00210000000000bcb019f0000031e0990019700000332099000d1000000000b9b00190000031ec9b0012a0000031e0aa001970000033000b0009c0000089e0000213d000000800cc00210000000000cac019f000003310d9000d10000000000cd004b000000010990208a0000089f0000013d000003210680009c0000000008068019000003210650009c000000000506801900000000675800a9000009360000013d000000400100043d000002fc0010009c00000000050000190000000002000019000009d50000a13d000009ee0000013d000003210640009c000000000604401900000003876000c900000080097002700000008008800210000000000898019f0000031e097001970000031e8a80012a0000008008800210000000000898019f0000033109a000d1000000000089004b000000010aa0208a0000031e08a0019700000332088000d10000000007780019000003210870009c000000000708801900000000866700a90000031ea780012a0000008009600270000003300080009c0000091b0000213d000000800aa00210000000000a9a019f000003310b7000d10000000000ab004b000000010770208a0000091c0000013d00000000060500190000000001020019000009da0000013d000000010770008a0000008008800210000000000898019f0000031e0770019700000332077000d100000000087800190000031e9780012a0000031e06600197000003300080009c0000092b0000213d0000008009900210000000000969019f000003310a7000d100000000009a004b000000010770208a0000092c0000013d000000010770008a0000008008800210000000000668019f0000031e0770019700000332077000d10000000006760019000003210760009c0000000006078019000003210750009c000000000507801900000000675600a90000031e9560012a0000008008700270000003300060009c000009400000213d0000008009900210000000000989019f000003310a5000d100000000009a004b000000010550208a000009410000013d000000010550008a0000008006600210000000000686019f0000031e0550019700000332055000d100000000055600190000031e9650012a0000031e08700197000003300050009c0000094f0000213d0000008007900210000000000787019f00000331096000d1000000000079004b000009500000a13d000000010660008a000003210740009c00000a010000213d0000008005500210000000000585019f0000031e0660019700000332066000d10000000006650019000003210560009c000000000605801900000000956600a90000031eb890012a000000800a500270000003300090009c000009640000213d000000800bb00210000000000bab019f000003310c8000d10000000000bc004b000000010880208a000009650000013d000000010880008a00000080099002100000000009a9019f0000031e0880019700000332088000d100000000098900190000031ea890012a0000031e05500197000003300090009c000009740000213d000000800aa00210000000000a5a019f000003310b8000d10000000000ab004b000000010880208a000009750000013d000000010880008a000003210010009c00000a010000213d000003210a4000990000008009900210000000000559019f0000031e0880019700000332088000d10000000005850019000003210850009c0000000005088019000000000004004b000000000a0060190000000009a50019000003210890009c00000000090880190000000000a5001a0000000009084019000003210a100099000000000001004b000000000a006019000003210190009c00000000090180190000000008a90019000003210580009a0000000000a9001a000009fc0000413d000003210080009c00000000080580190000000001000415000000080110008a00000005011002100000000005080019000003210040009c000000000407801900000000075000890000032108500099000003210080009c00000000080780190000000007480019000003210970009c0000000007098019000000000048001a0000000007094019000003210470009c000000000704801900000000746700a90000031e9670012a0000008008400270000003300070009c000009ad0000213d0000008009900210000000000989019f000003310a6000d100000000009a004b000000010660208a000009ae0000013d000000010660008a0000008007700210000000000787019f0000031e0660019700000332066000d100000000076700190000031e8670012a0000031e04400197000003300070009c000009bd0000213d0000008008800210000000000848019f00000331096000d1000000000089004b000000010660208a000009be0000013d000000010660008a0000008007700210000000000447019f0000031e0660019700000332066000d100000000046400190000000501100270000000000104001f000003210020009c00000a010000213d000000400100043d000002fc0010009c0000000608000029000009ee0000213d0000032106200099000000000002004b0000000006006019000003210240009c00000000040280190000000002640019000003210720009c0000000002078019000000000064001a00000000020740190000004004100039000000400040043f000000200610003900000000002604350000000000510435000000000200041500000000022300490000000002000002000000000201043300000005050000290000000103800210000000a904300039000000000024041b000000aa023000390000000003060433000000000032041b000000010200008a000000030220014f0000000404000029000000000304041a000000000223016f000000010350020f000000000232019f000000000024041b000000000001042d0000031b01000041000000000010043f0000004101000039000000040010043f0000031c0100004100000b4d000104300000031b01000041000000000010043f0000003201000039000000040010043f0000031c0100004100000b4d00010430000000000100001900000b4d000104300000000001000415000000070110008a0000000501100210000003210050009c000009950000a13d0000031b01000041000000000010043f0000001101000039000000040010043f0000031c0100004100000b4d000104300003000000000002000000400400043d000003220040009c00000a850000813d0000004005400039000000400050043f000000200540003900000000000504350000000000040435000000080030008c00000a8b0000813d000000400400043d000002fc0040009c00000a850000213d0000004005400039000000400050043f00000001053002100000009903500039000000000303041a00000000043404360000009a05500039000000000605041a0000000000640435000000400500043d00000040045000390000000000640435000000400400003900000000044504360000000000340435000003140050009c00000a850000213d000300000002001d000200000001001d0000006003500039000000400030043f000002d40040009c000002d40400804100000040024002100000000001050433000002d40010009c000002d4010080410000006001100210000000000121019f0000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f0000030b011001c700008010020000390b4b0b460000040f000000010020019000000a910000613d000000400200043d000000000401043b00000003050000290000000013050434000000410030008c00000a930000c13d000100000004001d00000040035000390000000003030433000002f90030009c00000aa30000213d0000006004500039000000000404043300000000010104330000006005200039000000000035043500000040032000390000000000130435000000f8014002700000002003200039000000000013043500000002010000290000000000120435000000000000043f000002d40020009c000002d40200804100000040012002100000000002000414000002d40020009c000002d402008041000000c002200210000000000112019f000002fa011001c700000001020000390b4b0b460000040f0000006003100270000002d403300197000000200030008c000000200400003900000000040340190000001f0540018f000000200440019000000a6d0000613d000000000601034f0000000007000019000000006806043c0000000007870436000000000047004b00000a690000c13d000000000005004b00000a7a0000613d000000000641034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000000010020019000000ab60000613d000000000100043d000002f100100198000000010200002900000ad40000613d000000000121013f000002f10010019800000000010000390000000101006039000000000001042d0000031b01000041000000000010043f0000004101000039000000040010043f0000031c0100004100000b4d000104300000031b01000041000000000010043f0000003201000039000000040010043f0000031c0100004100000b4d00010430000000000100001900000b4d0001043000000044012000390000031503000041000000000031043500000024012000390000001f030000390000000000310435000002d5010000410000000000120435000000040120003900000020030000390000000000310435000002d40020009c000002d402008041000000400120021000000316011001c700000b4d0001043000000064012000390000031903000041000000000031043500000044012000390000031a030000410000000000310435000000240120003900000022030000390000000000310435000002d5010000410000000000120435000000040120003900000020030000390000000000310435000002d40020009c000002d40200804100000040012002100000030a011001c700000b4d000104300000001f0530018f000002fb06300198000000400200043d000000000462001900000ac10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000abd0000c13d000000000005004b00000ace0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000002d40020009c000002d4020080410000004002200210000000000112019f00000b4d00010430000000400100043d000000440210003900000318030000410000000000320435000000240210003900000018030000390000000000320435000002d5020000410000000000210435000000040210003900000020030000390000000000320435000002d40010009c000002d401008041000000400110021000000316011001c700000b4d000104300000031e0010019800000b220000613d000000000401001900000000030000190000031e023001970000031e0020009c00000b2e0000613d00000001032000390000031e054001970000000a0450011a0000000a0050008c00000ae90000813d000003360020009c00000b3a0000213d000000200220003900000337052001970000003f025000390000033804200197000000400200043d0000000004420019000000000024004b00000000060000390000000106004039000002f40040009c00000b3a0000213d000000010060019000000b3a0000c13d000000400040043f0000000004320436000000000005004b00000b0c0000613d0000000005540019000000000600003100000001066003670000000007040019000000006806043c0000000007870436000000000057004b00000b080000c13d0000031e0330019800000b2e0000613d000000010330008a0000000005020433000000000035004b00000b340000a13d0000031e051001970000000a0650011a0000000a076000c90000000001710049000000000743001900000000080704330000033908800197000000f801100210000000000181019f0000033a011001c700000000001704350000000a0050008c000000000106001900000b0c0000813d0000000001020019000000000001042d000000400200043d000003220020009c00000b3a0000813d0000004001200039000000400010043f00000020012000390000033a030000410000000000310435000000010100003900000000001204350000000001020019000000000001042d0000031b01000041000000000010043f0000001101000039000000040010043f0000031c0100004100000b4d000104300000031b01000041000000000010043f0000003201000039000000040010043f0000031c0100004100000b4d000104300000031b01000041000000000010043f0000004101000039000000040010043f0000031c0100004100000b4d00010430000000000001042f00000b44002104210000000102000039000000000001042d0000000002000019000000000001042d00000b49002104230000000102000039000000000001042d0000000002000019000000000001042d00000b4b0000043200000b4c0001042e00000b4d000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff08c379a000000000000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320696e697469616c697a696e6700000000000000000000000000000000000000000000000000000000000000000000000000000000000000008400000080000000000000000002000000000000000000000000000000000000200000008000000000000000007f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498000000020000000000000000000000000000004000000100000000000000000000000000000000000000000000000000000000000000000000000000715018a500000000000000000000000000000000000000000000000000000000c945d35900000000000000000000000000000000000000000000000000000000eb764a2500000000000000000000000000000000000000000000000000000000eb764a2600000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000c945d35a00000000000000000000000000000000000000000000000000000000e493ef8c00000000000000000000000000000000000000000000000000000000bbef84b300000000000000000000000000000000000000000000000000000000bbef84b400000000000000000000000000000000000000000000000000000000be13bac400000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000008da5cb5b0000000000000000000000000000000000000000000000000000000055757dbe000000000000000000000000000000000000000000000000000000005d1816d8000000000000000000000000000000000000000000000000000000005d1816d9000000000000000000000000000000000000000000000000000000005fcb7d580000000000000000000000000000000000000000000000000000000055757dbf0000000000000000000000000000000000000000000000000000000055e7673b000000000000000000000000000000000000000000000000000000002ac478b600000000000000000000000000000000000000000000000000000000354f622a000000000000000000000000000000000000000000000000000000003c64c215000000000000000000000000ffffffffffffffffffffffffffffffffffffffff4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffff7f0000000000000000000000000000000000000020000000000000000000000000fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414100000000000000000000000000000000000000200000008000000000000000007fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000000ffffffffffffffbf49530000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000004f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65720000000000000000000000000000000000000064000000800000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000008000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0000000000000000000000000000000000000000000000080000000000000000080000000000000000000000000000000000000000000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000647920696e697469616c697a6564000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320616c726561000000000000000000000000000000000000008400000000000000000000000002000000000000000000000000000000000000000000000000000000000000006e697469616c697a696e67000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069020000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000009a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b02000002000000000000000000000000000000040000000000000000000000000200000000000000000000000000000000000000000000a0000000000000000019457468657265756d205369676e6564204d6573736167653a0a333200000000000000000000000000000000000000000000000000000000ffffffffffffff9f45434453413a20696e76616c6964207369676e6174757265206c656e677468000000000000000000000000000000000000000064000000000000000000000000696e76616c6964207369676e617475726500000000000000000000000000000045434453413a20696e76616c6964207369676e61747572650000000000000000756500000000000000000000000000000000000000000000000000000000000045434453413a20696e76616c6964207369676e6174757265202773272076616c4e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000006e6f7420656e6f756768207369676e617475726573000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff47200000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f000000000000000000000000000000000000000000000000ffffffffffffffc07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000fffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffd0000000000000000000000000000000100000000000000000000000000000000baaedce6af48a03bbfd25e8cd0364141000000000000000000000000000000014551231950b75fc4402da1732fc9bebf566572696669636174696f6e206661696c65640000000000000000000000000065637265636f766572206661696c656400000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00fffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2dfffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffefffffc2f00000000000000000000000000000000000000000000000000000001000003d1fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e0000000000000000000000000000000100000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30000000000000000000000000000000000000000000000000fffffffffffffffe00000000000000000000000000000001ffffffffffffffffffffffffffffffe000000000000000000000000000000003ffffffffffffffffffffffffffffffe000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064708c8c87c2f2cfec9eecf244efdf08677321446bc212ed753adc443922dd6
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.