Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 111622186 | 865 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
PriceOracle
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.8.0;
import '@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol';
import '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';
import '@openzeppelin/contracts/utils/cryptography/ECDSA.sol';
import '@openzeppelin/contracts/utils/math/SafeCast.sol';
import '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';
import '@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol';
import '@mimic-fi/v3-authorizer/contracts/Authorized.sol';
import '@mimic-fi/v3-helpers/contracts/math/FixedPoint.sol';
import '@mimic-fi/v3-helpers/contracts/utils/BytesHelpers.sol';
import './interfaces/IPriceOracle.sol';
/**
* @title OnChainOracle
* @dev Price oracle mixing both on-chain and off-chain oracle alternatives
*
* The on-chain oracle that interfaces with Chainlink feeds to provide rates between two tokens. This oracle only
* operates with ERC20 tokens, it does not allow querying quotes for any other denomination. Additionally, it only
* supports feeds that implement ChainLink's proposed `AggregatorV3Interface` interface.
*
* The off-chain oracle that uses off-chain signatures to compute prices between two tokens
*/
contract PriceOracle is IPriceOracle, Authorized, ReentrancyGuardUpgradeable {
using FixedPoint for uint256;
using BytesHelpers for bytes;
using EnumerableSet for EnumerableSet.AddressSet;
// Number of decimals used for fixed point operations: 18
uint256 private constant FP_DECIMALS = 18;
// Maximum number of decimals supported for a token when computing inverse quotes: 36
uint256 private constant INVERSE_FEED_MAX_DECIMALS = 36;
// It allows denoting a single token to pivot between feeds in case a direct path is not available
address public pivot;
// Mapping of feeds from "token A" to "token B"
mapping (address => mapping (address => address)) public override getFeed;
// Enumerable set of trusted signers
EnumerableSet.AddressSet private _signers;
/**
* @dev Feed data, only used during initialization
* @param base Token to rate
* @param quote Token used for the price rate
* @param feed Chainlink oracle to fetch the given pair price
*/
struct FeedData {
address base;
address quote;
address feed;
}
/**
* @dev Initializes the price oracle
* @param _authorizer Address of the authorizer to be set
* @param _signer Address of the initial allowed signer
* @param _pivot Address of the token to be used as the pivot
* @param _feeds List of feeds to be initialized with
*/
function initialize(address _authorizer, address _signer, address _pivot, FeedData[] memory _feeds)
external
initializer
{
__PriceOracle_init(_authorizer, _signer, _pivot, _feeds);
}
/**
* @dev Initializes the price oracle. It does call upper contracts initializers.
* @param _authorizer Address of the authorizer to be set
* @param _signer Address of the initial allowed signer
* @param _pivot Address of the token to be used as the pivot
* @param _feeds List of feeds to be initialized with
*/
function __PriceOracle_init(address _authorizer, address _signer, address _pivot, FeedData[] memory _feeds)
internal
onlyInitializing
{
__ReentrancyGuard_init();
__Authorized_init(_authorizer);
__PriceOracle_init_unchained(_authorizer, _signer, _pivot, _feeds);
}
/**
* @dev Initializes the price oracle. It does not call upper contracts initializers.
* @param _signer Address of the initial allowed signer
* @param _pivot Address of the token to be used as the pivot
* @param _feeds List of feeds to be initialized with
*/
function __PriceOracle_init_unchained(address, address _signer, address _pivot, FeedData[] memory _feeds)
internal
onlyInitializing
{
_setSigner(_signer, true);
pivot = _pivot;
for (uint256 i = 0; i < _feeds.length; i++) _setFeed(_feeds[i].base, _feeds[i].quote, _feeds[i].feed);
}
/**
* @dev Tells whether an address is as an allowed signer or not
* @param signer Address of the signer being queried
*/
function isSignerAllowed(address signer) public view override returns (bool) {
return _signers.contains(signer);
}
/**
* @dev Tells the list of allowed signers
*/
function getAllowedSigners() external view override returns (address[] memory) {
return _signers.values();
}
/**
* @dev Tells the digest expected to be signed by the off-chain oracle signers for a list of prices
* @param prices List of prices to be signed
*/
function getPricesDigest(PriceData[] memory prices) public pure override returns (bytes32) {
return ECDSA.toEthSignedMessageHash(keccak256(abi.encode(prices)));
}
/**
* @dev Tells the price of a token (base) in a given quote. The response is expressed using the corresponding
* number of decimals so that when performing a fixed point product of it by a `base` amount it results in
* a value expressed in `quote` decimals.
* @param base Token to rate
* @param quote Token used for the price rate
*/
function getPrice(address base, address quote) public view override returns (uint256) {
if (base == quote) return FixedPoint.ONE;
// If `base * result / 1e18` must be expressed in `quote` decimals, then
uint256 baseDecimals = IERC20Metadata(base).decimals();
uint256 quoteDecimals = IERC20Metadata(quote).decimals();
bool areBaseDecimalsTooBig = baseDecimals > quoteDecimals + FP_DECIMALS;
if (areBaseDecimalsTooBig) revert PriceOracleBaseDecimalsTooBig(base, baseDecimals, quote, quoteDecimals);
// No need for checked math as we are checking it manually beforehand
uint256 resultDecimals = quoteDecimals + FP_DECIMALS - baseDecimals;
(uint256 price, uint256 decimals) = _getPrice(base, quote);
return _scalePrice(price, decimals, resultDecimals);
}
/**
/**
* @dev Tries fetching a price for base/quote pair from an external encoded data. It fall-backs using the on-chain
* oracle in case the require price is missing. It reverts in case the off-chain data verification fails.
* @param base Token to rate
* @param quote Token used for the price rate
* @param data Encoded prices data along with its corresponding signature
*/
function getPrice(address base, address quote, bytes memory data) external view override returns (uint256) {
if (base == quote) return FixedPoint.ONE;
PriceData[] memory prices = _decodePricesData(data);
for (uint256 i = 0; i < prices.length; i++) {
PriceData memory price = prices[i];
if (price.base == base && price.quote == quote) {
bool isPastDeadline = price.deadline < block.timestamp;
if (isPastDeadline) revert PriceOracleOutdatedPrice(base, quote, price.deadline, block.timestamp);
return price.rate;
}
}
return getPrice(base, quote);
}
/**
* @dev Sets a signer condition
* @param signer Address of the signer to be set
* @param allowed Whether the requested signer is allowed
*/
function setSigner(address signer, bool allowed) external override nonReentrant authP(authParams(signer, allowed)) {
_setSigner(signer, allowed);
}
/**
* @dev Sets a feed for a (base, quote) pair. Sender must be authorized.
* @param base Token base to be set
* @param quote Token quote to be set
* @param feed Feed to be set
*/
function setFeed(address base, address quote, address feed)
external
override
nonReentrant
authP(authParams(base, quote, feed))
{
_setFeed(base, quote, feed);
}
/**
* @dev Tells the price of a token (base) in a given quote.
* @param base Token to rate
* @param quote Token used for the price rate
* @return price Requested price rate
* @return decimals Decimals of the requested price rate
*/
function _getPrice(address base, address quote) internal view returns (uint256 price, uint256 decimals) {
address feed = getFeed[base][quote];
if (feed != address(0)) return _getFeedData(feed);
address inverseFeed = getFeed[quote][base];
if (inverseFeed != address(0)) return _getInversePrice(inverseFeed);
address baseFeed = getFeed[base][pivot];
address quoteFeed = getFeed[quote][pivot];
if (baseFeed != address(0) && quoteFeed != address(0)) return _getPivotPrice(baseFeed, quoteFeed);
revert PriceOracleMissingFeed(base, quote);
}
/**
* @dev Fetches data from a Chainlink feed
* @param feed Address of the Chainlink feed to fetch data from. It must support ChainLink `AggregatorV3Interface`.
* @return price Requested price
* @return decimals Decimals of the requested price
*/
function _getFeedData(address feed) internal view returns (uint256 price, uint256 decimals) {
decimals = AggregatorV3Interface(feed).decimals();
(, int256 priceInt, , , ) = AggregatorV3Interface(feed).latestRoundData();
price = SafeCast.toUint256(priceInt);
}
/**
* @dev Tells a price based on an inverse feed
* @param inverseFeed Feed of the inverse pair
* @return price Requested price rate
* @return decimals Decimals of the requested price rate
*/
function _getInversePrice(address inverseFeed) internal view returns (uint256 price, uint256 decimals) {
(uint256 inversePrice, uint256 inverseFeedDecimals) = _getFeedData(inverseFeed);
bool areInverseFeedDecimalsTooBig = inverseFeedDecimals > INVERSE_FEED_MAX_DECIMALS;
if (areInverseFeedDecimalsTooBig) revert PriceOracleInverseFeedDecimalsTooBig(inverseFeed, inverseFeedDecimals);
// Prices are requested for different purposes, we are rounding down always to follow a single strategy
price = FixedPoint.ONE.divDown(inversePrice);
decimals = INVERSE_FEED_MAX_DECIMALS - inverseFeedDecimals;
}
/**
* @dev Report a price based on two relative feeds
* @param baseFeed Feed of the base token
* @param quoteFeed Feed of the quote token
* @return price Requested price rate
* @return decimals Decimals of the requested price rate
*/
function _getPivotPrice(address baseFeed, address quoteFeed)
internal
view
returns (uint256 price, uint256 decimals)
{
(uint256 basePrice, uint256 baseFeedDecimals) = _getFeedData(baseFeed);
(uint256 quotePrice, uint256 quoteFeedDecimals) = _getFeedData(quoteFeed);
bool areQuoteFeedDecimalsTooBig = quoteFeedDecimals > baseFeedDecimals + FP_DECIMALS;
if (areQuoteFeedDecimalsTooBig) revert PriceOracleQuoteFeedDecimalsTooBig(quoteFeedDecimals, baseFeedDecimals);
// Price is base/quote = (base/pivot) / (quote/pivot)
// Prices are requested for different purposes, we are rounding down always to follow a single strategy
price = basePrice.divDown(quotePrice);
decimals = baseFeedDecimals + FP_DECIMALS - quoteFeedDecimals;
}
/**
* @dev Upscales or downscale a price rate
* @param price Value to be scaled
* @param priceDecimals Decimals in which `price` is originally represented
* @return resultDecimals Decimals requested for the result
*/
function _scalePrice(uint256 price, uint256 priceDecimals, uint256 resultDecimals) internal pure returns (uint256) {
return
resultDecimals >= priceDecimals
? (price * 10**(resultDecimals - priceDecimals))
: (price / 10**(priceDecimals - resultDecimals));
}
/**
* @dev Decodes a list of off-chain encoded prices. It returns an empty array in case it is malformed. It reverts
* if the data is considered properly encoded but the signer is not allowed.
* @param data Data to be decoded
*/
function _decodePricesData(bytes memory data) internal view returns (PriceData[] memory) {
if (!_isOffChainDataEncodedProperly(data)) return new PriceData[](0);
(PriceData[] memory prices, bytes memory signature) = abi.decode(data, (PriceData[], bytes));
(address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(getPricesDigest(prices), signature);
bool isSignerValid = error == ECDSA.RecoverError.NoError && isSignerAllowed(recovered);
if (!isSignerValid) revert PriceOracleInvalidSigner(recovered);
return prices;
}
/**
* @dev Sets the off-chain oracle signer
* @param signer Address of the signer to be set
*/
function _setSigner(address signer, bool allowed) internal {
allowed ? _signers.add(signer) : _signers.remove(signer);
emit SignerSet(signer, allowed);
}
/**
* @dev Sets a new feed for a (base, quote) pair
* @param base Token base to be set
* @param quote Token quote to be set
* @param feed Feed to be set
*/
function _setFeed(address base, address quote, address feed) internal {
getFeed[base][quote] = feed;
emit FeedSet(base, quote, feed);
}
/**
* @dev Tells if a data array is encoded as expected for a list off-chain prices
* @param data Data to be evaluated
*/
function _isOffChainDataEncodedProperly(bytes memory data) private pure returns (bool) {
// Check the minimum expected data length based on how ABI encoding works.
// Considering the structure (PriceData[], bytes), the encoding should have the following pattern:
//
// [ PRICES OFFSET ][ SIG OFFSET ][ PRICES DATA LENGTH ][ PRICES DATA ][ SIG LENGTH ][ VRS SIG ]
// [ 32 ][ 32 ][ 32 ][ N * 128 ][ 32 ][ 32 * 3 ]
//
// Therefore the minimum length expected is:
uint256 minimumLength = 32 + 32 + 32 + 32 + 96;
if (data.length < minimumLength) return false;
// There must be at least the same number of bytes specified by the prices offset value:
uint256 pricesOffset = data.toUint256(0);
if (data.length < pricesOffset) return false;
// The exact expected data length can be now computed based on the prices length:
uint256 pricesLength = data.toUint256(pricesOffset);
if (data.length != minimumLength + (pricesLength * 128)) return false;
// The signature offset can be computed based on the prices length:
uint256 signatureOffset = data.toUint256(32);
if (signatureOffset != (32 * 3) + (pricesLength * 128)) return false;
// Finally the signature length must be 64 or 65:
uint256 signatureLength = data.toUint256(signatureOffset);
if (signatureLength != 64 && signatureLength != 65) return false;
// Finally confirm the data types for each of the price data attributes:
for (uint256 i = 0; i < pricesLength; i++) {
uint256 offset = i * 128;
// Base should be a valid address
uint256 priceBase = data.toUint256(32 * 3 + offset);
if (priceBase > type(uint160).max) return false;
// Quote should be a valid address
uint256 priceQuote = data.toUint256(32 * 4 + offset);
if (priceQuote > type(uint160).max) return false;
}
// Otherwise the data can be decoded properly
return true;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
// getRoundData and latestRoundData should both raise "No data present"
// if they do not have data to report, instead of returning unset values
// which could be misinterpreted as actual reported values.
function getRoundData(uint80 _roundId)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.8.17;
import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';
import './AuthorizedHelpers.sol';
import './interfaces/IAuthorized.sol';
import './interfaces/IAuthorizer.sol';
/**
* @title Authorized
* @dev Implementation using an authorizer as its access-control mechanism. It offers `auth` and `authP` modifiers to
* tag its own functions in order to control who can access them against the authorizer referenced.
*/
contract Authorized is IAuthorized, Initializable, AuthorizedHelpers {
// Authorizer reference
address public override authorizer;
/**
* @dev Modifier that should be used to tag protected functions
*/
modifier auth() {
_authenticate(msg.sender, msg.sig);
_;
}
/**
* @dev Modifier that should be used to tag protected functions with params
*/
modifier authP(uint256[] memory params) {
_authenticate(msg.sender, msg.sig, params);
_;
}
/**
* @dev Creates a new authorized contract. Note that initializers are disabled at creation time.
*/
constructor() {
_disableInitializers();
}
/**
* @dev Initializes the authorized contract. It does call upper contracts initializers.
* @param _authorizer Address of the authorizer to be set
*/
function __Authorized_init(address _authorizer) internal onlyInitializing {
__Authorized_init_unchained(_authorizer);
}
/**
* @dev Initializes the authorized contract. It does not call upper contracts initializers.
* @param _authorizer Address of the authorizer to be set
*/
function __Authorized_init_unchained(address _authorizer) internal onlyInitializing {
authorizer = _authorizer;
}
/**
* @dev Reverts if `who` is not allowed to call `what`
* @param who Address to be authenticated
* @param what Function selector to be authenticated
*/
function _authenticate(address who, bytes4 what) internal view {
_authenticate(who, what, new uint256[](0));
}
/**
* @dev Reverts if `who` is not allowed to call `what` with `how`
* @param who Address to be authenticated
* @param what Function selector to be authenticated
* @param how Params to be authenticated
*/
function _authenticate(address who, bytes4 what, uint256[] memory how) internal view {
if (!_isAuthorized(who, what, how)) revert AuthSenderNotAllowed(who, what, how);
}
/**
* @dev Tells whether `who` has any permission on this contract
* @param who Address asking permissions for
*/
function _hasPermissions(address who) internal view returns (bool) {
return IAuthorizer(authorizer).hasPermissions(who, address(this));
}
/**
* @dev Tells whether `who` is allowed to call `what`
* @param who Address asking permission for
* @param what Function selector asking permission for
*/
function _isAuthorized(address who, bytes4 what) internal view returns (bool) {
return _isAuthorized(who, what, new uint256[](0));
}
/**
* @dev Tells whether `who` is allowed to call `what` with `how`
* @param who Address asking permission for
* @param what Function selector asking permission for
* @param how Params asking permission for
*/
function _isAuthorized(address who, bytes4 what, uint256[] memory how) internal view returns (bool) {
return IAuthorizer(authorizer).isAuthorized(who, address(this), what, how);
}
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.8.17;
/**
* @title AuthorizedHelpers
* @dev Syntax sugar methods to operate with authorizer params easily
*/
contract AuthorizedHelpers {
function authParams(address p1) internal pure returns (uint256[] memory r) {
return authParams(uint256(uint160(p1)));
}
function authParams(bytes32 p1) internal pure returns (uint256[] memory r) {
return authParams(uint256(p1));
}
function authParams(uint256 p1) internal pure returns (uint256[] memory r) {
r = new uint256[](1);
r[0] = p1;
}
function authParams(address p1, bool p2) internal pure returns (uint256[] memory r) {
r = new uint256[](2);
r[0] = uint256(uint160(p1));
r[1] = p2 ? 1 : 0;
}
function authParams(address p1, uint256 p2) internal pure returns (uint256[] memory r) {
r = new uint256[](2);
r[0] = uint256(uint160(p1));
r[1] = p2;
}
function authParams(address p1, address p2) internal pure returns (uint256[] memory r) {
r = new uint256[](2);
r[0] = uint256(uint160(p1));
r[1] = uint256(uint160(p2));
}
function authParams(bytes32 p1, bytes32 p2) internal pure returns (uint256[] memory r) {
r = new uint256[](2);
r[0] = uint256(p1);
r[1] = uint256(p2);
}
function authParams(address p1, address p2, uint256 p3) internal pure returns (uint256[] memory r) {
r = new uint256[](3);
r[0] = uint256(uint160(p1));
r[1] = uint256(uint160(p2));
r[2] = p3;
}
function authParams(address p1, address p2, address p3) internal pure returns (uint256[] memory r) {
r = new uint256[](3);
r[0] = uint256(uint160(p1));
r[1] = uint256(uint160(p2));
r[2] = uint256(uint160(p3));
}
function authParams(address p1, address p2, bytes4 p3) internal pure returns (uint256[] memory r) {
r = new uint256[](3);
r[0] = uint256(uint160(p1));
r[1] = uint256(uint160(p2));
r[2] = uint256(uint32(p3));
}
function authParams(address p1, uint256 p2, uint256 p3) internal pure returns (uint256[] memory r) {
r = new uint256[](3);
r[0] = uint256(uint160(p1));
r[1] = p2;
r[2] = p3;
}
function authParams(address p1, address p2, uint256 p3, uint256 p4) internal pure returns (uint256[] memory r) {
r = new uint256[](4);
r[0] = uint256(uint160(p1));
r[1] = uint256(uint160(p2));
r[2] = p3;
r[3] = p4;
}
function authParams(address p1, uint256 p2, uint256 p3, uint256 p4) internal pure returns (uint256[] memory r) {
r = new uint256[](4);
r[0] = uint256(uint160(p1));
r[1] = p2;
r[2] = p3;
r[3] = p4;
}
function authParams(bytes32 p1, address p2, uint256 p3, bool p4) internal pure returns (uint256[] memory r) {
r = new uint256[](4);
r[0] = uint256(p1);
r[1] = uint256(uint160(p2));
r[2] = p3;
r[3] = p4 ? 1 : 0;
}
function authParams(address p1, uint256 p2, uint256 p3, uint256 p4, uint256 p5)
internal
pure
returns (uint256[] memory r)
{
r = new uint256[](5);
r[0] = uint256(uint160(p1));
r[1] = p2;
r[2] = p3;
r[3] = p4;
r[4] = p5;
}
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.8.0;
/**
* @dev Authorized interface
*/
interface IAuthorized {
/**
* @dev Sender `who` is not allowed to call `what` with `how`
*/
error AuthSenderNotAllowed(address who, bytes4 what, uint256[] how);
/**
* @dev Tells the address of the authorizer reference
*/
function authorizer() external view returns (address);
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.8.0;
/**
* @dev Authorizer interface
*/
interface IAuthorizer {
/**
* @dev Permission change
* @param where Address of the contract to change a permission for
* @param changes List of permission changes to be executed
*/
struct PermissionChange {
address where;
GrantPermission[] grants;
RevokePermission[] revokes;
}
/**
* @dev Grant permission data
* @param who Address to be authorized
* @param what Function selector to be authorized
* @param params List of params to restrict the given permission
*/
struct GrantPermission {
address who;
bytes4 what;
Param[] params;
}
/**
* @dev Revoke permission data
* @param who Address to be unauthorized
* @param what Function selector to be unauthorized
*/
struct RevokePermission {
address who;
bytes4 what;
}
/**
* @dev Params used to validate permissions params against
* @param op ID of the operation to compute in order to validate a permission param
* @param value Comparison value
*/
struct Param {
uint8 op;
uint248 value;
}
/**
* @dev Sender is not authorized to call `what` on `where` with `how`
*/
error AuthorizerSenderNotAllowed(address who, address where, bytes4 what, uint256[] how);
/**
* @dev The operation param is invalid
*/
error AuthorizerInvalidParamOp(uint8 op);
/**
* @dev Emitted every time `who`'s permission to perform `what` on `where` is granted with `params`
*/
event Authorized(address indexed who, address indexed where, bytes4 indexed what, Param[] params);
/**
* @dev Emitted every time `who`'s permission to perform `what` on `where` is revoked
*/
event Unauthorized(address indexed who, address indexed where, bytes4 indexed what);
/**
* @dev Tells whether `who` has any permission on `where`
* @param who Address asking permission for
* @param where Target address asking permission for
*/
function hasPermissions(address who, address where) external view returns (bool);
/**
* @dev Tells the number of permissions `who` has on `where`
* @param who Address asking permission for
* @param where Target address asking permission for
*/
function getPermissionsLength(address who, address where) external view returns (uint256);
/**
* @dev Tells whether `who` is allowed to call `what` on `where` with `how`
* @param who Address asking permission for
* @param where Target address asking permission for
* @param what Function selector asking permission for
* @param how Params asking permission for
*/
function isAuthorized(address who, address where, bytes4 what, uint256[] memory how) external view returns (bool);
/**
* @dev Tells the params set for a given permission
* @param who Address asking permission params of
* @param where Target address asking permission params of
* @param what Function selector asking permission params of
*/
function getPermissionParams(address who, address where, bytes4 what) external view returns (Param[] memory);
/**
* @dev Executes a list of permission changes
* @param changes List of permission changes to be executed
*/
function changePermissions(PermissionChange[] memory changes) external;
/**
* @dev Authorizes `who` to call `what` on `where` restricted by `params`
* @param who Address to be authorized
* @param where Target address to be granted for
* @param what Function selector to be granted
* @param params Optional params to restrict a permission attempt
*/
function authorize(address who, address where, bytes4 what, Param[] memory params) external;
/**
* @dev Unauthorizes `who` to call `what` on `where`. Sender must be authorized.
* @param who Address to be authorized
* @param where Target address to be revoked for
* @param what Function selector to be revoked
*/
function unauthorize(address who, address where, bytes4 what) external;
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.8.0;
/**
* @title FixedPoint
* @dev Math library to operate with fixed point values with 18 decimals
*/
library FixedPoint {
// 1 in fixed point value: 18 decimal places
uint256 internal constant ONE = 1e18;
/**
* @dev Multiplication overflow
*/
error FixedPointMulOverflow(uint256 a, uint256 b);
/**
* @dev Division by zero
*/
error FixedPointZeroDivision();
/**
* @dev Division internal error
*/
error FixedPointDivInternal(uint256 a, uint256 aInflated);
/**
* @dev Multiplies two fixed point numbers rounding down
*/
function mulDown(uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
uint256 product = a * b;
if (a != 0 && product / a != b) revert FixedPointMulOverflow(a, b);
return product / ONE;
}
}
/**
* @dev Multiplies two fixed point numbers rounding up
*/
function mulUp(uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
uint256 product = a * b;
if (a != 0 && product / a != b) revert FixedPointMulOverflow(a, b);
return product == 0 ? 0 : (((product - 1) / ONE) + 1);
}
}
/**
* @dev Divides two fixed point numbers rounding down
*/
function divDown(uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
if (b == 0) revert FixedPointZeroDivision();
if (a == 0) return 0;
uint256 aInflated = a * ONE;
if (aInflated / a != ONE) revert FixedPointDivInternal(a, aInflated);
return aInflated / b;
}
}
/**
* @dev Divides two fixed point numbers rounding up
*/
function divUp(uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
if (b == 0) revert FixedPointZeroDivision();
if (a == 0) return 0;
uint256 aInflated = a * ONE;
if (aInflated / a != ONE) revert FixedPointDivInternal(a, aInflated);
return ((aInflated - 1) / b) + 1;
}
}
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.8.0;
/**
* @title BytesHelpers
* @dev Provides a list of Bytes helper methods
*/
library BytesHelpers {
/**
* @dev The length is shorter than start plus 32
*/
error BytesOutOfBounds(uint256 start, uint256 length);
/**
* @dev Concatenates an address to a bytes array
*/
function concat(bytes memory self, address value) internal pure returns (bytes memory) {
return abi.encodePacked(self, value);
}
/**
* @dev Concatenates an uint24 to a bytes array
*/
function concat(bytes memory self, uint24 value) internal pure returns (bytes memory) {
return abi.encodePacked(self, value);
}
/**
* @dev Decodes a bytes array into an uint256
*/
function toUint256(bytes memory self) internal pure returns (uint256) {
return toUint256(self, 0);
}
/**
* @dev Reads an uint256 from a bytes array starting at a given position
*/
function toUint256(bytes memory self, uint256 start) internal pure returns (uint256 result) {
if (self.length < start + 32) revert BytesOutOfBounds(start, self.length);
assembly {
result := mload(add(add(self, 0x20), start))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
*/
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.
*
* `initializer` is equivalent to `reinitializer(1)`, so 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.
*
* 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.
*/
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.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (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 functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
// Check the signature length
// - case 65: r,s,v signature (standard)
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @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 if (signature.length == 64) {
bytes32 r;
bytes32 vs;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/SafeCast.sol)
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toUint248(uint256 value) internal pure returns (uint248) {
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toUint240(uint256 value) internal pure returns (uint240) {
require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toUint232(uint256 value) internal pure returns (uint232) {
require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.2._
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toUint216(uint256 value) internal pure returns (uint216) {
require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toUint208(uint256 value) internal pure returns (uint208) {
require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toUint200(uint256 value) internal pure returns (uint200) {
require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toUint192(uint256 value) internal pure returns (uint192) {
require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toUint184(uint256 value) internal pure returns (uint184) {
require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toUint176(uint256 value) internal pure returns (uint176) {
require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toUint168(uint256 value) internal pure returns (uint168) {
require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toUint160(uint256 value) internal pure returns (uint160) {
require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toUint152(uint256 value) internal pure returns (uint152) {
require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toUint144(uint256 value) internal pure returns (uint144) {
require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toUint136(uint256 value) internal pure returns (uint136) {
require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v2.5._
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toUint120(uint256 value) internal pure returns (uint120) {
require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toUint112(uint256 value) internal pure returns (uint112) {
require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.2._
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toUint88(uint256 value) internal pure returns (uint88) {
require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toUint80(uint256 value) internal pure returns (uint80) {
require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toUint72(uint256 value) internal pure returns (uint72) {
require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v2.5._
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toUint56(uint256 value) internal pure returns (uint56) {
require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toUint48(uint256 value) internal pure returns (uint48) {
require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toUint40(uint256 value) internal pure returns (uint40) {
require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v2.5._
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toUint24(uint256 value) internal pure returns (uint24) {
require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v2.5._
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v2.5._
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*
* _Available since v3.0._
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toInt248(int256 value) internal pure returns (int248) {
require(value >= type(int248).min && value <= type(int248).max, "SafeCast: value doesn't fit in 248 bits");
return int248(value);
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toInt240(int256 value) internal pure returns (int240) {
require(value >= type(int240).min && value <= type(int240).max, "SafeCast: value doesn't fit in 240 bits");
return int240(value);
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toInt232(int256 value) internal pure returns (int232) {
require(value >= type(int232).min && value <= type(int232).max, "SafeCast: value doesn't fit in 232 bits");
return int232(value);
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.7._
*/
function toInt224(int256 value) internal pure returns (int224) {
require(value >= type(int224).min && value <= type(int224).max, "SafeCast: value doesn't fit in 224 bits");
return int224(value);
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toInt216(int256 value) internal pure returns (int216) {
require(value >= type(int216).min && value <= type(int216).max, "SafeCast: value doesn't fit in 216 bits");
return int216(value);
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toInt208(int256 value) internal pure returns (int208) {
require(value >= type(int208).min && value <= type(int208).max, "SafeCast: value doesn't fit in 208 bits");
return int208(value);
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toInt200(int256 value) internal pure returns (int200) {
require(value >= type(int200).min && value <= type(int200).max, "SafeCast: value doesn't fit in 200 bits");
return int200(value);
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toInt192(int256 value) internal pure returns (int192) {
require(value >= type(int192).min && value <= type(int192).max, "SafeCast: value doesn't fit in 192 bits");
return int192(value);
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toInt184(int256 value) internal pure returns (int184) {
require(value >= type(int184).min && value <= type(int184).max, "SafeCast: value doesn't fit in 184 bits");
return int184(value);
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toInt176(int256 value) internal pure returns (int176) {
require(value >= type(int176).min && value <= type(int176).max, "SafeCast: value doesn't fit in 176 bits");
return int176(value);
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toInt168(int256 value) internal pure returns (int168) {
require(value >= type(int168).min && value <= type(int168).max, "SafeCast: value doesn't fit in 168 bits");
return int168(value);
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toInt160(int256 value) internal pure returns (int160) {
require(value >= type(int160).min && value <= type(int160).max, "SafeCast: value doesn't fit in 160 bits");
return int160(value);
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toInt152(int256 value) internal pure returns (int152) {
require(value >= type(int152).min && value <= type(int152).max, "SafeCast: value doesn't fit in 152 bits");
return int152(value);
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toInt144(int256 value) internal pure returns (int144) {
require(value >= type(int144).min && value <= type(int144).max, "SafeCast: value doesn't fit in 144 bits");
return int144(value);
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toInt136(int256 value) internal pure returns (int136) {
require(value >= type(int136).min && value <= type(int136).max, "SafeCast: value doesn't fit in 136 bits");
return int136(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toInt120(int256 value) internal pure returns (int120) {
require(value >= type(int120).min && value <= type(int120).max, "SafeCast: value doesn't fit in 120 bits");
return int120(value);
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toInt112(int256 value) internal pure returns (int112) {
require(value >= type(int112).min && value <= type(int112).max, "SafeCast: value doesn't fit in 112 bits");
return int112(value);
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toInt104(int256 value) internal pure returns (int104) {
require(value >= type(int104).min && value <= type(int104).max, "SafeCast: value doesn't fit in 104 bits");
return int104(value);
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.7._
*/
function toInt96(int256 value) internal pure returns (int96) {
require(value >= type(int96).min && value <= type(int96).max, "SafeCast: value doesn't fit in 96 bits");
return int96(value);
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toInt88(int256 value) internal pure returns (int88) {
require(value >= type(int88).min && value <= type(int88).max, "SafeCast: value doesn't fit in 88 bits");
return int88(value);
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toInt80(int256 value) internal pure returns (int80) {
require(value >= type(int80).min && value <= type(int80).max, "SafeCast: value doesn't fit in 80 bits");
return int80(value);
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toInt72(int256 value) internal pure returns (int72) {
require(value >= type(int72).min && value <= type(int72).max, "SafeCast: value doesn't fit in 72 bits");
return int72(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toInt56(int256 value) internal pure returns (int56) {
require(value >= type(int56).min && value <= type(int56).max, "SafeCast: value doesn't fit in 56 bits");
return int56(value);
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toInt48(int256 value) internal pure returns (int48) {
require(value >= type(int48).min && value <= type(int48).max, "SafeCast: value doesn't fit in 48 bits");
return int48(value);
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toInt40(int256 value) internal pure returns (int40) {
require(value >= type(int40).min && value <= type(int40).max, "SafeCast: value doesn't fit in 40 bits");
return int40(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toInt24(int256 value) internal pure returns (int24) {
require(value >= type(int24).min && value <= type(int24).max, "SafeCast: value doesn't fit in 24 bits");
return int24(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*
* _Available since v3.0._
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_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) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
return _values(set._inner);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.8.0;
import '@mimic-fi/v3-authorizer/contracts/interfaces/IAuthorized.sol';
/**
* @title IPriceOracle
* @dev Price oracle interface
*
* Tells the price of a token (base) in a given quote based the following rule: the response is expressed using the
* corresponding number of decimals so that when performing a fixed point product of it by a `base` amount it results
* in a value expressed in `quote` decimals. For example, if `base` is ETH and `quote` is USDC, then the returned
* value is expected to be expressed using 6 decimals:
*
* FixedPoint.mul(X[ETH], price[USDC/ETH]) = FixedPoint.mul(X[18], price[6]) = X * price [6]
*/
interface IPriceOracle is IAuthorized {
/**
* @dev Price data
* @param base Token to rate
* @param quote Token used for the price rate
* @param rate Price of a token (base) expressed in `quote`
* @param deadline Expiration timestamp until when the given quote is considered valid
*/
struct PriceData {
address base;
address quote;
uint256 rate;
uint256 deadline;
}
/**
* @dev The signer is not allowed
*/
error PriceOracleInvalidSigner(address signer);
/**
* @dev The feed for the given (base, quote) pair doesn't exist
*/
error PriceOracleMissingFeed(address base, address quote);
/**
* @dev The price deadline is in the past
*/
error PriceOracleOutdatedPrice(address base, address quote, uint256 deadline, uint256 currentTimestamp);
/**
* @dev The base decimals are bigger than the quote decimals plus the fixed point decimals
*/
error PriceOracleBaseDecimalsTooBig(address base, uint256 baseDecimals, address quote, uint256 quoteDecimals);
/**
* @dev The inverse feed decimals are bigger than the maximum inverse feed decimals
*/
error PriceOracleInverseFeedDecimalsTooBig(address inverseFeed, uint256 inverseFeedDecimals);
/**
* @dev The quote feed decimals are bigger than the base feed decimals plus the fixed point decimals
*/
error PriceOracleQuoteFeedDecimalsTooBig(uint256 quoteFeedDecimals, uint256 baseFeedDecimals);
/**
* @dev Emitted every time a signer is changed
*/
event SignerSet(address indexed signer, bool allowed);
/**
* @dev Emitted every time a feed is set for (base, quote) pair
*/
event FeedSet(address indexed base, address indexed quote, address feed);
/**
* @dev Tells whether an address is as an allowed signer or not
* @param signer Address of the signer being queried
*/
function isSignerAllowed(address signer) external view returns (bool);
/**
* @dev Tells the list of allowed signers
*/
function getAllowedSigners() external view returns (address[] memory);
/**
* @dev Tells the digest expected to be signed by the off-chain oracle signers for a list of prices
* @param prices List of prices to be signed
*/
function getPricesDigest(PriceData[] memory prices) external view returns (bytes32);
/**
* @dev Tells the price of a token `base` expressed in a token `quote`
* @param base Token to rate
* @param quote Token used for the price rate
*/
function getPrice(address base, address quote) external view returns (uint256);
/**
* @dev Tells the price of a token `base` expressed in a token `quote`
* @param base Token to rate
* @param quote Token used for the price rate
* @param data Encoded data to validate in order to compute the requested rate
*/
function getPrice(address base, address quote, bytes memory data) external view returns (uint256);
/**
* @dev Tells the feed address for (base, quote) pair. It returns the zero address if there is no one set.
* @param base Token to be rated
* @param quote Token used for the price rate
*/
function getFeed(address base, address quote) external view returns (address);
/**
* @dev Sets a signer condition
* @param signer Address of the signer to be set
* @param allowed Whether the requested signer is allowed
*/
function setSigner(address signer, bool allowed) external;
/**
* @dev Sets a feed for a (base, quote) pair
* @param base Token base to be set
* @param quote Token quote to be set
* @param feed Feed to be set
*/
function setFeed(address base, address quote, address feed) external;
}{
"optimizer": {
"enabled": true,
"runs": 10000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"},{"internalType":"uint256[]","name":"how","type":"uint256[]"}],"name":"AuthSenderNotAllowed","type":"error"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"}],"name":"BytesOutOfBounds","type":"error"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"aInflated","type":"uint256"}],"name":"FixedPointDivInternal","type":"error"},{"inputs":[],"name":"FixedPointZeroDivision","type":"error"},{"inputs":[{"internalType":"address","name":"base","type":"address"},{"internalType":"uint256","name":"baseDecimals","type":"uint256"},{"internalType":"address","name":"quote","type":"address"},{"internalType":"uint256","name":"quoteDecimals","type":"uint256"}],"name":"PriceOracleBaseDecimalsTooBig","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"PriceOracleInvalidSigner","type":"error"},{"inputs":[{"internalType":"address","name":"inverseFeed","type":"address"},{"internalType":"uint256","name":"inverseFeedDecimals","type":"uint256"}],"name":"PriceOracleInverseFeedDecimalsTooBig","type":"error"},{"inputs":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"}],"name":"PriceOracleMissingFeed","type":"error"},{"inputs":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"currentTimestamp","type":"uint256"}],"name":"PriceOracleOutdatedPrice","type":"error"},{"inputs":[{"internalType":"uint256","name":"quoteFeedDecimals","type":"uint256"},{"internalType":"uint256","name":"baseFeedDecimals","type":"uint256"}],"name":"PriceOracleQuoteFeedDecimalsTooBig","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"base","type":"address"},{"indexed":true,"internalType":"address","name":"quote","type":"address"},{"indexed":false,"internalType":"address","name":"feed","type":"address"}],"name":"FeedSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"signer","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"SignerSet","type":"event"},{"inputs":[],"name":"authorizer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedSigners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getFeed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"},{"internalType":"uint256","name":"rate","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IPriceOracle.PriceData[]","name":"prices","type":"tuple[]"}],"name":"getPricesDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_authorizer","type":"address"},{"internalType":"address","name":"_signer","type":"address"},{"internalType":"address","name":"_pivot","type":"address"},{"components":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"},{"internalType":"address","name":"feed","type":"address"}],"internalType":"struct PriceOracle.FeedData[]","name":"_feeds","type":"tuple[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isSignerAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pivot","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"},{"internalType":"address","name":"feed","type":"address"}],"name":"setFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b506200001c62000022565b620000e4565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015620000e2576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6129ea80620000f46000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063ac41865a11610081578063d2edb6dd1161005b578063d2edb6dd146101b9578063d77fe1cd146101fa578063dddf6ff91461021a57600080fd5b8063ac41865a14610148578063cc47cae91461015b578063d09edf311461016e57600080fd5b806333162394116100b257806333162394146100f6578063355efdd914610114578063a60216901461013557600080fd5b8063230a7658146100ce57806331cb6105146100e3575b600080fd5b6100e16100dc366004611e54565b61023d565b005b6100e16100f1366004611ead565b610302565b6100fe6103bf565b60405161010b9190611ee6565b60405180910390f35b610127610122366004612050565b6103d0565b60405190815260200161010b565b6100e1610143366004612119565b610568565b610127610156366004612228565b610702565b610127610169366004612256565b6108ee565b6000546101949062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010b565b6101946101c7366004612228565b603460209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff1681565b6033546101949073ffffffffffffffffffffffffffffffffffffffff1681565b61022d610228366004612332565b610982565b604051901515815260200161010b565b6002600154036102ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026001556102be83838361098f565b6102ed336000357fffffffff000000000000000000000000000000000000000000000000000000001683610a5a565b6102f8848484610aa6565b5050600180555050565b60026001540361036e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016102a5565b600260015561037d8282610b3e565b6103ac336000357fffffffff000000000000000000000000000000000000000000000000000000001683610a5a565b6103b68383610bcb565b50506001805550565b60606103cb6035610c42565b905090565b60008273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036104145750670de0b6b3a7640000610561565b600061041f83610c4f565b905060005b81518110156105525760008282815181106104415761044161234f565b602002602001015190508673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161480156104b957508573ffffffffffffffffffffffffffffffffffffffff16816020015173ffffffffffffffffffffffffffffffffffffffff16145b1561053f576060810151421180156105305760608201516040517fe3b0edfb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808b1660048301528916602482015260448101919091524260648201526084016102a5565b50604001519250610561915050565b508061054a816123ad565b915050610424565b5061055d8585610702565b9150505b9392505050565b600054610100900460ff16158080156105885750600054600160ff909116105b806105a25750303b1580156105a2575060005460ff166001145b61062e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016102a5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561068c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61069885858585610d84565b80156106fb57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036107465750670de0b6b3a76400006108e8565b60008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610793573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b791906123e5565b60ff16905060008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610809573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082d91906123e5565b60ff169050600061083f601283612408565b8311905080156108a9576040517f979a1d5b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80881660048301526024820185905286166044820152606481018390526084016102a5565b6000836108b7601285612408565b6108c1919061241b565b90506000806108d08989610e3e565b915091506108df828285610fca565b96505050505050505b92915050565b60006108e882604051602001610904919061242e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000084830152603c8085019190915282518085039091018152605c909301909152815191012090565b60006108e860358361101f565b604080516003808252608082019092526060916020820183803683370190505090508373ffffffffffffffffffffffffffffffffffffffff16816000815181106109db576109db61234f565b6020026020010181815250508273ffffffffffffffffffffffffffffffffffffffff1681600181518110610a1157610a1161234f565b6020026020010181815250508173ffffffffffffffffffffffffffffffffffffffff1681600281518110610a4757610a4761234f565b6020026020010181815250509392505050565b610a6583838361104e565b610aa1578282826040517f960c80da0000000000000000000000000000000000000000000000000000000081526004016102a5939291906124e6565b505050565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526034602090815260408083208786168085529083529281902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001695871695861790555193845290927f285223a4171e109a39625d11cc785e338bfe64401273078192ce054455d0c785910160405180910390a3505050565b60408051600280825260608083018452926020830190803683370190505090508273ffffffffffffffffffffffffffffffffffffffff1681600081518110610b8857610b8861234f565b60200260200101818152505081610ba0576000610ba3565b60015b60ff1681600181518110610bb957610bb961234f565b60200260200101818152505092915050565b80610be057610bdb6035836110f1565b610beb565b610beb603583611113565b508173ffffffffffffffffffffffffffffffffffffffff167ffc4acb499491cd850a8a21ab98c7f128850c0f0e5f1a875a62b7fa055c2ecf1982604051610c36911515815260200190565b60405180910390a25050565b6060600061056183611135565b6060610c5a82611191565b610ccd576040805160008082526020820190925290610cc6565b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610c745790505b5092915050565b60008083806020019051810190610ce491906125ab565b91509150600080610cfd610cf7856108ee565b84611332565b9092509050600080826004811115610d1757610d176126b2565b148015610d285750610d2883610982565b905080610d79576040517f9a74fc4800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016102a5565b509295945050505050565b600054610100900460ff16610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b610e23611392565b610e2c84611433565b610e38848484846114d6565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152603460209081526040808320858516845290915281205490918291168015610e9057610e8681611638565b9250925050610fc3565b73ffffffffffffffffffffffffffffffffffffffff80851660009081526034602090815260408083208985168452909152902054168015610edf57610ed481611737565b935093505050610fc3565b73ffffffffffffffffffffffffffffffffffffffff80871660009081526034602081815260408084206033548616808652908352818520548b871686529383528185209085529091529091205490821691168115801590610f55575073ffffffffffffffffffffffffffffffffffffffff811615155b15610f7157610f6482826117cf565b9550955050505050610fc3565b6040517fcb84d12b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808a166004830152881660248201526044016102a5565b9250929050565b600082821015610ff857610fde828461241b565b610fe990600a612801565b610ff3908561283c565b611017565b611002838361241b565b61100d90600a612801565b6110179085612877565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610561565b600080546040517f285228950000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff16906328522895906110b090879030908890889060040161288e565b602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101791906128f9565b60006105618373ffffffffffffffffffffffffffffffffffffffff8416611876565b60006105618373ffffffffffffffffffffffffffffffffffffffff8416611969565b60608160000180548060200260200160405190810160405280929190818152602001828054801561118557602002820191906000526020600020905b815481526020019060010190808311611171575b50505050509050919050565b60008060e0905080835110156111aa5750600092915050565b60006111b684826119b8565b905080845110156111cb575060009392505050565b60006111d785836119b8565b90506111e4816080612877565b6111ee9084612408565b85511461120057506000949350505050565b600061120d8660206119b8565b905061121a826080612877565b611225906060612408565b81146112375750600095945050505050565b600061124387836119b8565b905080604014158015611257575080604114155b15611269575060009695505050505050565b60005b83811015611324576000611281826080612877565b9050600061129a611293836060612408565b8b906119b8565b905073ffffffffffffffffffffffffffffffffffffffff8111156112c8575060009998505050505050505050565b60006112df6112d8846080612408565b8c906119b8565b905073ffffffffffffffffffffffffffffffffffffffff81111561130e575060009a9950505050505050505050565b505050808061131c906123ad565b91505061126c565b506001979650505050505050565b60008082516041036113685760208301516040840151606085015160001a61135c87828585611a15565b94509450505050610fc3565b82516040036113865760208301516040840151610ed4868383611b2d565b50600090506002610fc3565b600054610100900460ff16611429576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b611431611b7f565b565b600054610100900460ff166114ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b6114d381611c1c565b50565b600054610100900460ff1661156d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b611578836001610bcb565b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905560005b81518110156106fb576116268282815181106115d9576115d961234f565b6020026020010151600001518383815181106115f7576115f761234f565b6020026020010151602001518484815181106116155761161561234f565b602002602001015160400151610aa6565b80611630816123ad565b9150506115bb565b6000808273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611686573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116aa91906123e5565b60ff16905060008373ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156116fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117209190612935565b50505091505061172f81611d00565b925050915091565b60008060008061174685611638565b90925090506024811180156117a6576040517f6dd967aa00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87166004820152602481018390526044016102a5565b6117b8670de0b6b3a764000084611d70565b94506117c582602461241b565b9350505050915091565b6000806000806117de86611638565b915091506000806117ee87611638565b90925090506000611800601285612408565b821190508015611846576040517f46cd794e00000000000000000000000000000000000000000000000000000000815260048101839052602481018590526044016102a5565b6118508584611d70565b96508161185e601286612408565b611868919061241b565b955050505050509250929050565b6000818152600183016020526040812054801561195f57600061189a60018361241b565b85549091506000906118ae9060019061241b565b90508181146119135760008660000182815481106118ce576118ce61234f565b90600052602060002001549050808760000184815481106118f1576118f161234f565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061192457611924612985565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108e8565b60009150506108e8565b60008181526001830160205260408120546119b0575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108e8565b5060006108e8565b60006119c5826020612408565b83511015611a0c5782516040517f9b722da70000000000000000000000000000000000000000000000000000000081526102a5918491600401918252602082015260400190565b50016020015190565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611a4c5750600090506003611b24565b8460ff16601b14158015611a6457508460ff16601c14155b15611a755750600090506004611b24565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611ac9573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611b1d57600060019250925050611b24565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831681611b6360ff86901c601b612408565b9050611b7187828885611a15565b935093505050935093915050565b600054610100900460ff16611c16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b60018055565b600054610100900460ff16611cb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b6000805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff909216919091179055565b600080821215611d6c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016102a5565b5090565b600081600003611dac576040517fb8a2f92100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82600003611dbc575060006108e8565b670de0b6b3a764000083810290848281611dd857611dd861280d565b0414611e1a576040517fea7b49e600000000000000000000000000000000000000000000000000000000815260048101859052602481018290526044016102a5565b828181611e2957611e2961280d565b04949350505050565b73ffffffffffffffffffffffffffffffffffffffff811681146114d357600080fd5b600080600060608486031215611e6957600080fd5b8335611e7481611e32565b92506020840135611e8481611e32565b91506040840135611e9481611e32565b809150509250925092565b80151581146114d357600080fd5b60008060408385031215611ec057600080fd5b8235611ecb81611e32565b91506020830135611edb81611e9f565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015611f3457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611f02565b50909695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611f9257611f92611f40565b60405290565b6040516080810167ffffffffffffffff81118282101715611f9257611f92611f40565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561200257612002611f40565b604052919050565b600067ffffffffffffffff82111561202457612024611f40565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60008060006060848603121561206557600080fd5b833561207081611e32565b9250602084013561208081611e32565b9150604084013567ffffffffffffffff81111561209c57600080fd5b8401601f810186136120ad57600080fd5b80356120c06120bb8261200a565b611fbb565b8181528760208385010111156120d557600080fd5b816020840160208301376000602083830101528093505050509250925092565b600067ffffffffffffffff82111561210f5761210f611f40565b5060051b60200190565b6000806000806080858703121561212f57600080fd5b843561213a81611e32565b935060208581013561214b81611e32565b935060408681013561215c81611e32565b935060608781013567ffffffffffffffff81111561217957600080fd5b8801601f81018a1361218a57600080fd5b80356121986120bb826120f5565b8181529083028201850190858101908c8311156121b457600080fd5b928601925b828410156122175784848e0312156121d15760008081fd5b6121d9611f6f565b84356121e481611e32565b8152848801356121f381611e32565b818901528487013561220481611e32565b81880152825292840192908601906121b9565b999c989b5096995050505050505050565b6000806040838503121561223b57600080fd5b823561224681611e32565b91506020830135611edb81611e32565b6000602080838503121561226957600080fd5b823567ffffffffffffffff81111561228057600080fd5b8301601f8101851361229157600080fd5b803561229f6120bb826120f5565b81815260079190911b820183019083810190878311156122be57600080fd5b928401925b8284101561232757608084890312156122dc5760008081fd5b6122e4611f98565b84356122ef81611e32565b8152848601356122fe81611e32565b8187015260408581013590820152606080860135908201528252608090930192908401906122c3565b979650505050505050565b60006020828403121561234457600080fd5b813561056181611e32565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036123de576123de61237e565b5060010190565b6000602082840312156123f757600080fd5b815160ff8116811461056157600080fd5b808201808211156108e8576108e861237e565b818103818111156108e8576108e861237e565b602080825282518282018190526000919060409081850190868401855b8281101561249e578151805173ffffffffffffffffffffffffffffffffffffffff90811686528782015116878601528581015186860152606090810151908501526080909301929085019060010161244b565b5091979650505050505050565b600081518084526020808501945080840160005b838110156124db578151875295820195908201906001016124bf565b509495945050505050565b73ffffffffffffffffffffffffffffffffffffffff841681527fffffffff000000000000000000000000000000000000000000000000000000008316602082015260606040820152600061253d60608301846124ab565b95945050505050565b600082601f83011261255757600080fd5b81516125656120bb8261200a565b8181526020858184870101111561257b57600080fd5b60005b8381101561259957858101820151838201830152810161257e565b50600092820101919091529392505050565b60008060408084860312156125bf57600080fd5b835167ffffffffffffffff808211156125d757600080fd5b818601915086601f8301126125eb57600080fd5b815160206125fb6120bb836120f5565b82815260079290921b8401810191818101908a84111561261a57600080fd5b948201945b83861015612681576080868c0312156126385760008081fd5b612640611f98565b865161264b81611e32565b81528684015161265a81611e32565b8185015286880151888201526060808801519082015282526080909501949082019061261f565b9189015191975090945050508083111561269a57600080fd5b50506126a885828601612546565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600181815b8085111561273a57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156127205761272061237e565b8085161561272d57918102915b93841c93908002906126e6565b509250929050565b600082612751575060016108e8565b8161275e575060006108e8565b8160018114612774576002811461277e5761279a565b60019150506108e8565b60ff84111561278f5761278f61237e565b50506001821b6108e8565b5060208310610133831016604e8410600b84101617156127bd575081810a6108e8565b6127c783836126e1565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156127f9576127f961237e565b029392505050565b60006105618383612742565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612872577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176108e8576108e861237e565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152507fffffffff0000000000000000000000000000000000000000000000000000000084166040830152608060608301526128ef60808301846124ab565b9695505050505050565b60006020828403121561290b57600080fd5b815161056181611e9f565b805169ffffffffffffffffffff8116811461293057600080fd5b919050565b600080600080600060a0868803121561294d57600080fd5b61295686612916565b945060208601519350604086015192506060860151915061297960808701612916565b90509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212206fd140288d566ac8b266c3854581bb432f513c9e005d3ad8915c02d0edc9988964736f6c63430008110033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100c95760003560e01c8063ac41865a11610081578063d2edb6dd1161005b578063d2edb6dd146101b9578063d77fe1cd146101fa578063dddf6ff91461021a57600080fd5b8063ac41865a14610148578063cc47cae91461015b578063d09edf311461016e57600080fd5b806333162394116100b257806333162394146100f6578063355efdd914610114578063a60216901461013557600080fd5b8063230a7658146100ce57806331cb6105146100e3575b600080fd5b6100e16100dc366004611e54565b61023d565b005b6100e16100f1366004611ead565b610302565b6100fe6103bf565b60405161010b9190611ee6565b60405180910390f35b610127610122366004612050565b6103d0565b60405190815260200161010b565b6100e1610143366004612119565b610568565b610127610156366004612228565b610702565b610127610169366004612256565b6108ee565b6000546101949062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010b565b6101946101c7366004612228565b603460209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff1681565b6033546101949073ffffffffffffffffffffffffffffffffffffffff1681565b61022d610228366004612332565b610982565b604051901515815260200161010b565b6002600154036102ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026001556102be83838361098f565b6102ed336000357fffffffff000000000000000000000000000000000000000000000000000000001683610a5a565b6102f8848484610aa6565b5050600180555050565b60026001540361036e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016102a5565b600260015561037d8282610b3e565b6103ac336000357fffffffff000000000000000000000000000000000000000000000000000000001683610a5a565b6103b68383610bcb565b50506001805550565b60606103cb6035610c42565b905090565b60008273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036104145750670de0b6b3a7640000610561565b600061041f83610c4f565b905060005b81518110156105525760008282815181106104415761044161234f565b602002602001015190508673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161480156104b957508573ffffffffffffffffffffffffffffffffffffffff16816020015173ffffffffffffffffffffffffffffffffffffffff16145b1561053f576060810151421180156105305760608201516040517fe3b0edfb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808b1660048301528916602482015260448101919091524260648201526084016102a5565b50604001519250610561915050565b508061054a816123ad565b915050610424565b5061055d8585610702565b9150505b9392505050565b600054610100900460ff16158080156105885750600054600160ff909116105b806105a25750303b1580156105a2575060005460ff166001145b61062e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016102a5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561068c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61069885858585610d84565b80156106fb57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036107465750670de0b6b3a76400006108e8565b60008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610793573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b791906123e5565b60ff16905060008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610809573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082d91906123e5565b60ff169050600061083f601283612408565b8311905080156108a9576040517f979a1d5b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80881660048301526024820185905286166044820152606481018390526084016102a5565b6000836108b7601285612408565b6108c1919061241b565b90506000806108d08989610e3e565b915091506108df828285610fca565b96505050505050505b92915050565b60006108e882604051602001610904919061242e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000084830152603c8085019190915282518085039091018152605c909301909152815191012090565b60006108e860358361101f565b604080516003808252608082019092526060916020820183803683370190505090508373ffffffffffffffffffffffffffffffffffffffff16816000815181106109db576109db61234f565b6020026020010181815250508273ffffffffffffffffffffffffffffffffffffffff1681600181518110610a1157610a1161234f565b6020026020010181815250508173ffffffffffffffffffffffffffffffffffffffff1681600281518110610a4757610a4761234f565b6020026020010181815250509392505050565b610a6583838361104e565b610aa1578282826040517f960c80da0000000000000000000000000000000000000000000000000000000081526004016102a5939291906124e6565b505050565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526034602090815260408083208786168085529083529281902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001695871695861790555193845290927f285223a4171e109a39625d11cc785e338bfe64401273078192ce054455d0c785910160405180910390a3505050565b60408051600280825260608083018452926020830190803683370190505090508273ffffffffffffffffffffffffffffffffffffffff1681600081518110610b8857610b8861234f565b60200260200101818152505081610ba0576000610ba3565b60015b60ff1681600181518110610bb957610bb961234f565b60200260200101818152505092915050565b80610be057610bdb6035836110f1565b610beb565b610beb603583611113565b508173ffffffffffffffffffffffffffffffffffffffff167ffc4acb499491cd850a8a21ab98c7f128850c0f0e5f1a875a62b7fa055c2ecf1982604051610c36911515815260200190565b60405180910390a25050565b6060600061056183611135565b6060610c5a82611191565b610ccd576040805160008082526020820190925290610cc6565b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610c745790505b5092915050565b60008083806020019051810190610ce491906125ab565b91509150600080610cfd610cf7856108ee565b84611332565b9092509050600080826004811115610d1757610d176126b2565b148015610d285750610d2883610982565b905080610d79576040517f9a74fc4800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016102a5565b509295945050505050565b600054610100900460ff16610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b610e23611392565b610e2c84611433565b610e38848484846114d6565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152603460209081526040808320858516845290915281205490918291168015610e9057610e8681611638565b9250925050610fc3565b73ffffffffffffffffffffffffffffffffffffffff80851660009081526034602090815260408083208985168452909152902054168015610edf57610ed481611737565b935093505050610fc3565b73ffffffffffffffffffffffffffffffffffffffff80871660009081526034602081815260408084206033548616808652908352818520548b871686529383528185209085529091529091205490821691168115801590610f55575073ffffffffffffffffffffffffffffffffffffffff811615155b15610f7157610f6482826117cf565b9550955050505050610fc3565b6040517fcb84d12b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808a166004830152881660248201526044016102a5565b9250929050565b600082821015610ff857610fde828461241b565b610fe990600a612801565b610ff3908561283c565b611017565b611002838361241b565b61100d90600a612801565b6110179085612877565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610561565b600080546040517f285228950000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff16906328522895906110b090879030908890889060040161288e565b602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101791906128f9565b60006105618373ffffffffffffffffffffffffffffffffffffffff8416611876565b60006105618373ffffffffffffffffffffffffffffffffffffffff8416611969565b60608160000180548060200260200160405190810160405280929190818152602001828054801561118557602002820191906000526020600020905b815481526020019060010190808311611171575b50505050509050919050565b60008060e0905080835110156111aa5750600092915050565b60006111b684826119b8565b905080845110156111cb575060009392505050565b60006111d785836119b8565b90506111e4816080612877565b6111ee9084612408565b85511461120057506000949350505050565b600061120d8660206119b8565b905061121a826080612877565b611225906060612408565b81146112375750600095945050505050565b600061124387836119b8565b905080604014158015611257575080604114155b15611269575060009695505050505050565b60005b83811015611324576000611281826080612877565b9050600061129a611293836060612408565b8b906119b8565b905073ffffffffffffffffffffffffffffffffffffffff8111156112c8575060009998505050505050505050565b60006112df6112d8846080612408565b8c906119b8565b905073ffffffffffffffffffffffffffffffffffffffff81111561130e575060009a9950505050505050505050565b505050808061131c906123ad565b91505061126c565b506001979650505050505050565b60008082516041036113685760208301516040840151606085015160001a61135c87828585611a15565b94509450505050610fc3565b82516040036113865760208301516040840151610ed4868383611b2d565b50600090506002610fc3565b600054610100900460ff16611429576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b611431611b7f565b565b600054610100900460ff166114ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b6114d381611c1c565b50565b600054610100900460ff1661156d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b611578836001610bcb565b603380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905560005b81518110156106fb576116268282815181106115d9576115d961234f565b6020026020010151600001518383815181106115f7576115f761234f565b6020026020010151602001518484815181106116155761161561234f565b602002602001015160400151610aa6565b80611630816123ad565b9150506115bb565b6000808273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611686573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116aa91906123e5565b60ff16905060008373ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156116fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117209190612935565b50505091505061172f81611d00565b925050915091565b60008060008061174685611638565b90925090506024811180156117a6576040517f6dd967aa00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87166004820152602481018390526044016102a5565b6117b8670de0b6b3a764000084611d70565b94506117c582602461241b565b9350505050915091565b6000806000806117de86611638565b915091506000806117ee87611638565b90925090506000611800601285612408565b821190508015611846576040517f46cd794e00000000000000000000000000000000000000000000000000000000815260048101839052602481018590526044016102a5565b6118508584611d70565b96508161185e601286612408565b611868919061241b565b955050505050509250929050565b6000818152600183016020526040812054801561195f57600061189a60018361241b565b85549091506000906118ae9060019061241b565b90508181146119135760008660000182815481106118ce576118ce61234f565b90600052602060002001549050808760000184815481106118f1576118f161234f565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061192457611924612985565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108e8565b60009150506108e8565b60008181526001830160205260408120546119b0575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108e8565b5060006108e8565b60006119c5826020612408565b83511015611a0c5782516040517f9b722da70000000000000000000000000000000000000000000000000000000081526102a5918491600401918252602082015260400190565b50016020015190565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611a4c5750600090506003611b24565b8460ff16601b14158015611a6457508460ff16601c14155b15611a755750600090506004611b24565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611ac9573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611b1d57600060019250925050611b24565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831681611b6360ff86901c601b612408565b9050611b7187828885611a15565b935093505050935093915050565b600054610100900460ff16611c16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b60018055565b600054610100900460ff16611cb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102a5565b6000805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff909216919091179055565b600080821215611d6c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53616665436173743a2076616c7565206d75737420626520706f73697469766560448201526064016102a5565b5090565b600081600003611dac576040517fb8a2f92100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82600003611dbc575060006108e8565b670de0b6b3a764000083810290848281611dd857611dd861280d565b0414611e1a576040517fea7b49e600000000000000000000000000000000000000000000000000000000815260048101859052602481018290526044016102a5565b828181611e2957611e2961280d565b04949350505050565b73ffffffffffffffffffffffffffffffffffffffff811681146114d357600080fd5b600080600060608486031215611e6957600080fd5b8335611e7481611e32565b92506020840135611e8481611e32565b91506040840135611e9481611e32565b809150509250925092565b80151581146114d357600080fd5b60008060408385031215611ec057600080fd5b8235611ecb81611e32565b91506020830135611edb81611e9f565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015611f3457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611f02565b50909695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715611f9257611f92611f40565b60405290565b6040516080810167ffffffffffffffff81118282101715611f9257611f92611f40565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561200257612002611f40565b604052919050565b600067ffffffffffffffff82111561202457612024611f40565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60008060006060848603121561206557600080fd5b833561207081611e32565b9250602084013561208081611e32565b9150604084013567ffffffffffffffff81111561209c57600080fd5b8401601f810186136120ad57600080fd5b80356120c06120bb8261200a565b611fbb565b8181528760208385010111156120d557600080fd5b816020840160208301376000602083830101528093505050509250925092565b600067ffffffffffffffff82111561210f5761210f611f40565b5060051b60200190565b6000806000806080858703121561212f57600080fd5b843561213a81611e32565b935060208581013561214b81611e32565b935060408681013561215c81611e32565b935060608781013567ffffffffffffffff81111561217957600080fd5b8801601f81018a1361218a57600080fd5b80356121986120bb826120f5565b8181529083028201850190858101908c8311156121b457600080fd5b928601925b828410156122175784848e0312156121d15760008081fd5b6121d9611f6f565b84356121e481611e32565b8152848801356121f381611e32565b818901528487013561220481611e32565b81880152825292840192908601906121b9565b999c989b5096995050505050505050565b6000806040838503121561223b57600080fd5b823561224681611e32565b91506020830135611edb81611e32565b6000602080838503121561226957600080fd5b823567ffffffffffffffff81111561228057600080fd5b8301601f8101851361229157600080fd5b803561229f6120bb826120f5565b81815260079190911b820183019083810190878311156122be57600080fd5b928401925b8284101561232757608084890312156122dc5760008081fd5b6122e4611f98565b84356122ef81611e32565b8152848601356122fe81611e32565b8187015260408581013590820152606080860135908201528252608090930192908401906122c3565b979650505050505050565b60006020828403121561234457600080fd5b813561056181611e32565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036123de576123de61237e565b5060010190565b6000602082840312156123f757600080fd5b815160ff8116811461056157600080fd5b808201808211156108e8576108e861237e565b818103818111156108e8576108e861237e565b602080825282518282018190526000919060409081850190868401855b8281101561249e578151805173ffffffffffffffffffffffffffffffffffffffff90811686528782015116878601528581015186860152606090810151908501526080909301929085019060010161244b565b5091979650505050505050565b600081518084526020808501945080840160005b838110156124db578151875295820195908201906001016124bf565b509495945050505050565b73ffffffffffffffffffffffffffffffffffffffff841681527fffffffff000000000000000000000000000000000000000000000000000000008316602082015260606040820152600061253d60608301846124ab565b95945050505050565b600082601f83011261255757600080fd5b81516125656120bb8261200a565b8181526020858184870101111561257b57600080fd5b60005b8381101561259957858101820151838201830152810161257e565b50600092820101919091529392505050565b60008060408084860312156125bf57600080fd5b835167ffffffffffffffff808211156125d757600080fd5b818601915086601f8301126125eb57600080fd5b815160206125fb6120bb836120f5565b82815260079290921b8401810191818101908a84111561261a57600080fd5b948201945b83861015612681576080868c0312156126385760008081fd5b612640611f98565b865161264b81611e32565b81528684015161265a81611e32565b8185015286880151888201526060808801519082015282526080909501949082019061261f565b9189015191975090945050508083111561269a57600080fd5b50506126a885828601612546565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600181815b8085111561273a57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156127205761272061237e565b8085161561272d57918102915b93841c93908002906126e6565b509250929050565b600082612751575060016108e8565b8161275e575060006108e8565b8160018114612774576002811461277e5761279a565b60019150506108e8565b60ff84111561278f5761278f61237e565b50506001821b6108e8565b5060208310610133831016604e8410600b84101617156127bd575081810a6108e8565b6127c783836126e1565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156127f9576127f961237e565b029392505050565b60006105618383612742565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082612872577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176108e8576108e861237e565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152507fffffffff0000000000000000000000000000000000000000000000000000000084166040830152608060608301526128ef60808301846124ab565b9695505050505050565b60006020828403121561290b57600080fd5b815161056181611e9f565b805169ffffffffffffffffffff8116811461293057600080fd5b919050565b600080600080600060a0868803121561294d57600080fd5b61295686612916565b945060208601519350604086015192506060860151915061297960808701612916565b90509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212206fd140288d566ac8b266c3854581bb432f513c9e005d3ad8915c02d0edc9988964736f6c63430008110033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.