Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
Treasury
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 999999 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import "@openzeppelin/contracts/utils/math/Math.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./lib/Babylonian.sol"; import "./owner/Operator.sol"; import "./utils/ContractGuard.sol"; import "./interfaces/ITreasury.sol"; import "./interfaces/IBasisAsset.sol"; import "./interfaces/IOracle.sol"; import "./interfaces/ICollateralPool.sol"; import "./interfaces/IBoardroom.sol"; import "./interfaces/IRegulationStats.sol"; import "./interfaces/IRewardPool.sol"; /** * @title Treasury * @dev This contract manages seigniorage allocation and expansion for a multi-peg system. * It supports multiple peg tokens (e.g., GREEN and BLUE) using oracle price feeds. * During each epoch, it mints new tokens based on the peg token price and distributes them * among the boardroom, DAO Fund, Collateral Pool, and Development Fund. * The contract is upgradeable via OwnableUpgradeable. */ contract Treasury is ITreasury, ContractGuard, ReentrancyGuard, OwnableUpgradeable { using SafeERC20 for IERC20; /* ========== STATE VARIABLES ========== */ // Epoch management uint256 public startTime; uint256 public lastEpochTime; uint256 private epoch_ = 0; uint256 private epochLength_ = 0; // Core token components address public green; address public blue; address public red; address public redOracle; address public override boardroom; // Price parameters uint256 public priceOne; uint256 public priceCeiling; // Bootstrap parameters: first bootstrapEpochs have fixed expansion percent uint256 public bootstrapEpochs; uint256 public bootstrapSupplyExpansionPercent; // Last epoch's GREEN price uint256 public override previousEpochGreenPrice; // Seigniorage salaries (amount minted during expansion epochs) uint256 public allocateSeigniorageSalaryGreen; uint256 public allocateSeigniorageSalaryBlue; // Fund addresses and their shared percentages address public override daoFund; uint256 public override daoFundSharedPercent; // e.g., 2000 = 20% address public override collateralPool; uint256 public override collateralPoolSharedPercent; // e.g., 2000 = 20% address public override devFund; uint256 public override devFundSharedPercent; // e.g., 1000 = 10% // Multi-Peg configuration address[] public pegTokens; // e.g., [green, blue] mapping(address => address) public pegTokenOracle; // Oracle for each peg token mapping(address => address[]) public pegTokenLockedAccounts; // Accounts whose balances are locked mapping(address => uint256) public pegTokenEpochStart; // Epoch start for each peg token mapping(address => uint256) public pegTokenSupplyTarget; // Supply target for expansion mapping(address => uint256) public pegTokenMaxSupplyExpansionPercent; // Max expansion percent (1% = 10000) mapping(uint256 => mapping(address => bool)) public hasAllocatedPegToken; // Allocation flag per epoch per peg token // Access control for share printing mapping(address => bool) public sharePrinters; mapping(address => bool) public strategist; // Regulation statistics contract address public regulationStats; /* =================== Added variables =================== */ // Reserved for future variables added for proxy to work /* ========== EVENTS ========== */ /** * @dev Emitted when seigniorage funding is added. * @param pegToken The peg token address (e.g., GREEN or BLUE). * @param epoch The epoch number at which funding was allocated. * @param timestamp The block timestamp. * @param price The peg token TWAP price. * @param expanded The total amount minted (expanded supply). * @param boardroomFunded Amount allocated to boardroom. * @param daoFunded Amount allocated to DAO Fund. * @param collateralPooled Amount allocated to Collateral Pool. * @param devFund Amount allocated to Dev Fund. */ event FundingAdded( address indexed pegToken, uint256 indexed epoch, uint256 timestamp, uint256 price, uint256 expanded, uint256 boardroomFunded, uint256 daoFunded, uint256 collateralPooled, uint256 devFund ); /* ========== MODIFIERS ========== */ /** * @dev Restricts function execution to strategist or owner. */ modifier onlyStrategist() { require(strategist[msg.sender] || owner() == msg.sender, "Treasury: not strategist"); _; } /** * @dev Checks that the next epoch has started. */ modifier checkEpoch() { uint256 _nextEpochPoint = nextEpochPoint(); require(block.timestamp >= _nextEpochPoint, "Treasury: not opened"); _; lastEpochTime = _nextEpochPoint; epoch_ += 1; } /** * @dev Ensures Treasury has proper operator permissions on GREEN and BLUE tokens. */ modifier checkOperator() { require( IBasisAsset(green).operator() == address(this) && IBasisAsset(blue).operator() == address(this), "Treasury: need more permission" ); _; } /* ========== VIEW FUNCTIONS ========== */ /// @notice Returns the current epoch. function epoch() public override view returns (uint256) { return epoch_; } /// @notice Returns the timestamp for the next epoch. function nextEpochPoint() public override view returns (uint256) { return lastEpochTime + nextEpochLength(); } /// @notice Returns the length (in seconds) of the next epoch. function nextEpochLength() public override view returns (uint256) { return epochLength_; } /** * @notice Gets the peg token price by consulting its oracle. * @param _token The peg token address. * @return The peg token price scaled by 1e18. */ function getPegTokenPrice(address _token) public override view returns (uint256) { try IOracle(pegTokenOracle[_token]).consult(_token, 1e18) returns (uint144 price) { return uint256(price); } catch { revert("Treasury: oracle failed"); } } /** * @notice Gets the peg token TWAP price from its oracle. * @param _token The peg token address. * @return The updated peg token price scaled by 1e18. */ function getPegTokenUpdatedPrice(address _token) public override view returns (uint256) { try IOracle(pegTokenOracle[_token]).twap(_token, 1e18) returns (uint144 price) { return uint256(price); } catch { revert("Treasury: oracle failed"); } } /** * @notice Returns the boardroom's share percentage (remaining after DAO, Collateral, and Dev funds). */ function boardroomSharedPercent() external override view returns (uint256) { return 10000 - daoFundSharedPercent - collateralPoolSharedPercent - devFundSharedPercent; } /** * @notice Checks if an account is allowed to print shares. * @param _account The account address. * @return True if allowed. */ function isSharePrinter(address _account) external override view returns (bool) { return sharePrinters[_account]; } /** * @notice Returns the number of peg tokens. * @return The count of peg tokens. */ function pegTokenLength() external view returns (uint256) { return pegTokens.length; } /** * @notice Returns the total locked balance of a peg token (excluded from circulating supply). * @param _token The peg token address. * @return The locked balance. */ function getPegTokenLockedBalance(address _token) public override view returns (uint256) { uint256 len = pegTokenLockedAccounts[_token].length; uint256 lockedBalance = 0; for (uint256 i = 0; i < len; i++) { lockedBalance += IERC20(_token).balanceOf(pegTokenLockedAccounts[_token][i]); } return lockedBalance; } /** * @notice Returns the circulating supply of a peg token. * @param _token The peg token address. * @return The circulating supply. */ function getPegTokenCirculatingSupply(address _token) public override view returns (uint256) { return IERC20(_token).totalSupply() - getPegTokenLockedBalance(_token); } /** * @notice Calculates the expansion rate for a peg token. * @param _pegToken The peg token address. * @return The expansion rate (in basis points, where 1% = 1e16). */ function getPegTokenExpansionRate(address _pegToken) public override view returns (uint256) { uint256 startEpoch = pegTokenEpochStart[_pegToken]; if (startEpoch > epoch_ + 1) return 0; if (epoch_ < bootstrapEpochs) { return bootstrapSupplyExpansionPercent; } uint256 twap = getPegTokenUpdatedPrice(_pegToken); if (twap > priceCeiling) { uint256 percentage = twap - priceOne; // 1% = 1e16 uint256 maxExpansion = pegTokenMaxSupplyExpansionPercent[_pegToken] * 1e12; if (percentage > maxExpansion) { percentage = maxExpansion; } return percentage / 1e12; } return 0; } /** * @notice Returns the amount of expansion for a peg token. * @param _pegToken The peg token address. * @return The expansion amount. */ function getPegTokenExpansionAmount(address _pegToken) external override view returns (uint256) { uint256 rate = getPegTokenExpansionRate(_pegToken); return (getPegTokenCirculatingSupply(_pegToken) * rate) / 1e6; } /* ========== GOVERNANCE FUNCTIONS ========== */ /** * @notice Initializes the Treasury. * @param _tokens Array containing addresses for [GREEN, BLUE, RED]. * @param _oracles Array containing oracle addresses for GREEN, BLUE and RED. * @param _farmingPool The farming pool address (for locked accounts). * @param _epochLength Epoch length in seconds. * @param _startTime Timestamp when vesting starts. * @param _boardroom The boardroom contract address. * @param _allocatedPools Array with addresses for extra funds: [DAO Fund, Collateral Pool, Dev Fund]. */ function initialize( address[] memory _tokens, address[] memory _oracles, address _farmingPool, uint256 _epochLength, uint256 _startTime, address _boardroom, address[] memory _allocatedPools ) external initializer { OwnableUpgradeable.__Ownable_init(msg.sender); // Set token addresses. address _green = green = _tokens[0]; address _blue = blue = _tokens[1]; red = _tokens[2]; // Configure peg token for GREEN. pegTokens.push(_green); pegTokenOracle[_green] = _oracles[0]; pegTokenEpochStart[_green] = 0; pegTokenSupplyTarget[_green] = 1000000 ether; pegTokenMaxSupplyExpansionPercent[_green] = 15000; // 1.5% // Configure peg token for BLUE. pegTokens.push(_blue); pegTokenOracle[_blue] = _oracles[1]; pegTokenEpochStart[_blue] = 0; pegTokenSupplyTarget[_blue] = 1000000 ether; pegTokenMaxSupplyExpansionPercent[_blue] = 15000; // 1.5% // Set locked accounts for GREEN and BLUE: farming pool, DAO Fund, and Collateral Pool. pegTokenLockedAccounts[_green] = pegTokenLockedAccounts[_blue] = [_farmingPool, _allocatedPools[0], _allocatedPools[1]]; // Set oracle for RED. redOracle = _oracles[2]; boardroom = _boardroom; startTime = _startTime; epochLength_ = _epochLength; // e.g., 8 hours. lastEpochTime = _startTime - _epochLength; // Price parameters (PEG = 1 GREEN per USDC.e). priceOne = 1e18; priceCeiling = (priceOne * 10001) / 10000; // 1.0001 // Bootstrap: first 21 epochs with 1% expansion. bootstrapEpochs = 21; bootstrapSupplyExpansionPercent = 10000; // 1% // Seigniorage salaries. allocateSeigniorageSalaryGreen = 1 ether; allocateSeigniorageSalaryBlue = 1 ether; // Extra funds allocation. daoFund = _allocatedPools[0]; daoFundSharedPercent = 2000; // 20% collateralPool = _allocatedPools[1]; collateralPoolSharedPercent = 2000; // 20% devFund = _allocatedPools[2]; devFundSharedPercent = 1000; // 10% } /// @notice Sets the boardroom address. function setBoardroom(address _boardroom) external onlyOwner { require(_boardroom != address(0), "Treasury: zero address"); boardroom = _boardroom; } /// @notice Sets the RED oracle address. function setRedOracle(address _redOracle) external onlyOwner { redOracle = _redOracle; } /// @notice Sets the regulation statistics contract address. function setRegulationStats(address _regulationStats) external onlyOwner { regulationStats = _regulationStats; } /** * @notice Sets a new price ceiling. * @param _priceCeiling The new price ceiling; must be between priceOne and 1.2 * priceOne. */ function setPriceCeiling(uint256 _priceCeiling) external onlyOwner { require(_priceCeiling >= priceOne && _priceCeiling <= (priceOne * 12000) / 10000, "Treasury: out of range"); priceCeiling = _priceCeiling; } /// @notice Toggles the share printer status for an account. function toggleSharePrinter(address _account) external onlyOwner { sharePrinters[_account] = !sharePrinters[_account]; } /// @notice Sets bootstrap parameters. function setBootstrap(uint256 _bootstrapEpochs, uint256 _bootstrapSupplyExpansionPercent) external onlyOwner { require(_bootstrapEpochs <= 90, "Treasury: _bootstrapEpochs out of range"); // <= 1 month require(_bootstrapSupplyExpansionPercent >= 1000 && _bootstrapSupplyExpansionPercent <= 50000, "Treasury: _bootstrapSupplyExpansionPercent out of range"); // [0.1%, 5%] bootstrapEpochs = _bootstrapEpochs; bootstrapSupplyExpansionPercent = _bootstrapSupplyExpansionPercent; } /** * @notice Sets extra funds and their shared percentages. */ function setExtraFunds( address _daoFund, uint256 _daoFundSharedPercent, address _collateralPool, uint256 _collateralPoolSharedPercent, address _devFund, uint256 _devFundSharedPercent ) external onlyOwner { require(_daoFundSharedPercent == 0 || _daoFund != address(0), "Treasury: zero"); require(_daoFundSharedPercent <= 3000, "Treasury: out of range"); require(_collateralPoolSharedPercent == 0 || _collateralPool != address(0), "Treasury: zero"); require(_collateralPoolSharedPercent <= 3000, "Treasury: out of range"); require(_devFundSharedPercent == 0 || _devFund != address(0), "Treasury: zero"); require(_devFundSharedPercent <= 1500, "Treasury: out of range"); daoFund = _daoFund; daoFundSharedPercent = _daoFundSharedPercent; collateralPool = _collateralPool; collateralPoolSharedPercent = _collateralPoolSharedPercent; devFund = _devFund; devFundSharedPercent = _devFundSharedPercent; } /** * @notice Sets the seigniorage salaries for GREEN and BLUE. */ function setAllocateSeigniorageSalaries(uint256 _allocateSeigniorageSalaryGreen, uint256 _allocateSeigniorageSalaryBlue) external onlyOwner { require(_allocateSeigniorageSalaryGreen <= 10 ether && _allocateSeigniorageSalaryBlue <= 10 ether, "Treasury: too much"); allocateSeigniorageSalaryGreen = _allocateSeigniorageSalaryGreen; allocateSeigniorageSalaryBlue = _allocateSeigniorageSalaryBlue; } /// @notice Adds a new peg token. function addPegToken(address _token) external onlyOwner { require(IERC20(_token).totalSupply() > 0, "Treasury: invalid token"); pegTokens.push(_token); } /** * @notice Sets configuration parameters for a peg token. * @param _token The peg token address. * @param _oracle The oracle address for the peg token. * @param _epochStart The starting epoch for the peg token. * @param _supplyTarget The supply target for expansion. * @param _expansionPercent The maximum expansion percentage (in basis points, where 1% = 10000). */ function setPegTokenConfig(address _token, address _oracle, uint256 _epochStart, uint256 _supplyTarget, uint256 _expansionPercent) external onlyOwner { pegTokenOracle[_token] = _oracle; pegTokenEpochStart[_token] = _epochStart; pegTokenSupplyTarget[_token] = _supplyTarget; pegTokenMaxSupplyExpansionPercent[_token] = _expansionPercent; } /** * @notice Adds an account to the locked accounts for a peg token. * @param _token The peg token address. * @param _account The account to add. */ function addPegTokenLockedAccount(address _token, address _account) external onlyOwner { require(_account != address(0), "Treasury: invalid address"); uint256 len = pegTokenLockedAccounts[_token].length; for (uint256 i = 0; i < len; i++) { if (pegTokenLockedAccounts[_token][i] == _account) return; // already exists } pegTokenLockedAccounts[_token].push(_account); } /// @notice Sets the strategist status for an account. function setStrategistStatus(address _account, bool _status) external onlyOwner { strategist[_account] = _status; } /* ========== MUTABLE FUNCTIONS ========== */ /** * @dev Internal function to update a peg token's price using its oracle. * Any errors are swallowed. * @param _token The peg token address. */ function _updatePegTokenPrice(address _token) internal { try IOracle(pegTokenOracle[_token]).update() {} catch {} } /** * @notice Allocates seigniorage for the current epoch. * Mints new tokens based on peg token price and distributes them among boardroom, DAO Fund, Collateral Pool, and Dev Fund. * Can only be called once per epoch. */ function allocateSeigniorage() external onlyOneBlock checkEpoch checkOperator nonReentrant { // Update previous epoch GREEN price. previousEpochGreenPrice = getPegTokenPrice(green); uint256 ptLength = pegTokens.length; for (uint256 i = 0; i < ptLength; ++i) { address pegToken = pegTokens[i]; uint256 tokenEpochStart = pegTokenEpochStart[pegToken]; if (tokenEpochStart <= epoch_ + 1) { _updatePegTokenPrice(pegToken); _allocateSeignioragePegToken(epoch_, pegToken); } } // Update the RED oracle as well. if (redOracle != address(0)) { try IOracle(redOracle).update() {} catch {} } if (collateralPool != address(0) && collateralPool.code.length > 0) { try ICollateralPool(collateralPool).update() {} catch {} } // Mint seigniorage salaries. if (allocateSeigniorageSalaryGreen > 0) { IBasisAsset(green).mint(msg.sender, allocateSeigniorageSalaryGreen); } if (allocateSeigniorageSalaryBlue > 0) { IBasisAsset(blue).mint(msg.sender, allocateSeigniorageSalaryBlue); } } /** * @dev Internal function that allocates seigniorage for a specific peg token. * Calculates the expansion amount and distributes minted tokens among funds. * @param _epoch The current epoch. * @param _pegToken The peg token address. */ function _allocateSeignioragePegToken(uint256 _epoch, address _pegToken) internal { if (hasAllocatedPegToken[_epoch + 1][_pegToken]) return; hasAllocatedPegToken[_epoch + 1][_pegToken] = true; uint256 supply = getPegTokenCirculatingSupply(_pegToken); if (supply >= pegTokenSupplyTarget[_pegToken]) { pegTokenSupplyTarget[_pegToken] = (pegTokenSupplyTarget[_pegToken] * 12000) / 10000; // Increase target by 20% pegTokenMaxSupplyExpansionPercent[_pegToken] = (pegTokenMaxSupplyExpansionPercent[_pegToken] * 9000) / 10000; // Decrease expansion by 10% if (pegTokenMaxSupplyExpansionPercent[_pegToken] < 2500) { pegTokenMaxSupplyExpansionPercent[_pegToken] = 2500; // Minimum 0.25% } } uint256 percentage = 0; uint256 pegTokenTwap = getPegTokenPrice(_pegToken); if (epoch_ < bootstrapEpochs) { percentage = bootstrapSupplyExpansionPercent * 1e12; } else if (pegTokenTwap > priceCeiling) { percentage = pegTokenTwap - priceOne; uint256 mse = pegTokenMaxSupplyExpansionPercent[_pegToken] * 1e12; if (percentage > mse) { percentage = mse; } } if (percentage > 0) { uint256 expanded = (supply * percentage) / 1e18; uint256 daoFundAmount = 0; uint256 collateralPoolAmount = 0; uint256 devFundAmount = 0; uint256 boardroomAmount = 0; if (expanded > 0) { IBasisAsset(_pegToken).mint(address(this), expanded); if (daoFundSharedPercent > 0) { daoFundAmount = (expanded * daoFundSharedPercent) / 10000; IERC20(_pegToken).transfer(daoFund, daoFundAmount); } if (collateralPoolSharedPercent > 0) { collateralPoolAmount = (expanded * collateralPoolSharedPercent) / 10000; IERC20(_pegToken).transfer(collateralPool, collateralPoolAmount); } if (devFundSharedPercent > 0) { devFundAmount = (expanded * devFundSharedPercent) / 10000; IERC20(_pegToken).transfer(devFund, devFundAmount); } boardroomAmount = expanded - daoFundAmount - collateralPoolAmount - devFundAmount; IERC20(_pegToken).safeIncreaseAllowance(boardroom, boardroomAmount); IBoardroom(boardroom).allocateSeignioragePegToken(_pegToken, boardroomAmount); } if (regulationStats != address(0)) { IRegulationStats(regulationStats).addPegTokenEpochInfo(_pegToken, _epoch + 1, pegTokenTwap, expanded, boardroomAmount, daoFundAmount, collateralPoolAmount, devFundAmount); } emit FundingAdded(_pegToken, _epoch + 1, block.timestamp, pegTokenTwap, expanded, boardroomAmount, daoFundAmount, collateralPoolAmount, devFundAmount); } } /** * @notice Allows the owner to recover unsupported tokens (except core tokens). * @param _token The token to recover. * @param _amount The amount to recover. * @param _to The recipient address. */ function governanceRecoverUnsupported(IERC20 _token, uint256 _amount, address _to) external onlyOwner { require(_to != address(0), "Treasury: Cannot transfer to zero address"); require(address(_token) != green, "Treasury: cannot recover green"); require(address(_token) != blue, "Treasury: cannot recover blue"); _token.safeTransfer(_to, _amount); } /** * @notice Transfers operator role of a contract (e.g., token or oracle). * @param _contract The contract address. * @param _operator The new operator. */ function transferContractOperator(address _contract, address _operator) external onlyOwner { IBasisAsset(_contract).transferOperator(_operator); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @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] * ```solidity * 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 Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._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() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC165} from "./IERC165.sol"; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol) pragma solidity ^0.8.20; import {Panic} from "../Panic.sol"; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an success flag (no overflow). */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow). */ function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow). */ function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a success flag (no division by zero). */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). */ function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * SafeCast.toUint(condition)); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a < b, a, b); } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. Panic.panic(Panic.DIVISION_BY_ZERO); } // The following calculation ensures accurate ceiling division without overflow. // Since a is non-zero, (a - 1) / b will not overflow. // The largest possible result occurs when (a - 1) / b is type(uint256).max, // but the largest value we can obtain is type(uint256).max - 1, which happens // when a = type(uint256).max and b = 1. unchecked { return SafeCast.toUint(a > 0) * ((a - 1) / b + 1); } } /** * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2²⁵⁶ + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0. if (denominator <= prod1) { Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW)); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv ≡ 1 mod 2⁴. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2⁸ inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶ inverse *= 2 - denominator * inverse; // inverse mod 2³² inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴ inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸ inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶ // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @dev Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); } /** * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. * * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0. * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible. * * If the input value is not inversible, 0 is returned. * * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}. */ function invMod(uint256 a, uint256 n) internal pure returns (uint256) { unchecked { if (n == 0) return 0; // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version) // Used to compute integers x and y such that: ax + ny = gcd(a, n). // When the gcd is 1, then the inverse of a modulo n exists and it's x. // ax + ny = 1 // ax = 1 + (-y)n // ax ≡ 1 (mod n) # x is the inverse of a modulo n // If the remainder is 0 the gcd is n right away. uint256 remainder = a % n; uint256 gcd = n; // Therefore the initial coefficients are: // ax + ny = gcd(a, n) = n // 0a + 1n = n int256 x = 0; int256 y = 1; while (remainder != 0) { uint256 quotient = gcd / remainder; (gcd, remainder) = ( // The old remainder is the next gcd to try. remainder, // Compute the next remainder. // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd // where gcd is at most n (capped to type(uint256).max) gcd - remainder * quotient ); (x, y) = ( // Increment the coefficient of a. y, // Decrement the coefficient of n. // Can overflow, but the result is casted to uint256 so that the // next value of y is "wrapped around" to a value between 0 and n - 1. x - y * int256(quotient) ); } if (gcd != 1) return 0; // No inverse exists. return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative. } } /** * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`. * * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that * `a**(p-2)` is the modular multiplicative inverse of a in Fp. * * NOTE: this function does NOT check that `p` is a prime greater than `2`. */ function invModPrime(uint256 a, uint256 p) internal view returns (uint256) { unchecked { return Math.modExp(a, p - 2, p); } } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m) * * Requirements: * - modulus can't be zero * - underlying staticcall to precompile must succeed * * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make * sure the chain you're using it on supports the precompiled contract for modular exponentiation * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, * the underlying function will succeed given the lack of a revert, but the result may be incorrectly * interpreted as 0. */ function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) { (bool success, uint256 result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m). * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying * to operate modulo 0 or if the underlying precompile reverted. * * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack * of a revert, but the result may be incorrectly interpreted as 0. */ function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) { if (m == 0) return (false, 0); assembly ("memory-safe") { let ptr := mload(0x40) // | Offset | Content | Content (Hex) | // |-----------|------------|--------------------------------------------------------------------| // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x60:0x7f | value of b | 0x<.............................................................b> | // | 0x80:0x9f | value of e | 0x<.............................................................e> | // | 0xa0:0xbf | value of m | 0x<.............................................................m> | mstore(ptr, 0x20) mstore(add(ptr, 0x20), 0x20) mstore(add(ptr, 0x40), 0x20) mstore(add(ptr, 0x60), b) mstore(add(ptr, 0x80), e) mstore(add(ptr, 0xa0), m) // Given the result < m, it's guaranteed to fit in 32 bytes, // so we can use the memory scratch space located at offset 0. success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20) result := mload(0x00) } } /** * @dev Variant of {modExp} that supports inputs of arbitrary length. */ function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) { (bool success, bytes memory result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Variant of {tryModExp} that supports inputs of arbitrary length. */ function tryModExp( bytes memory b, bytes memory e, bytes memory m ) internal view returns (bool success, bytes memory result) { if (_zeroBytes(m)) return (false, new bytes(0)); uint256 mLen = m.length; // Encode call args in result and move the free memory pointer result = abi.encodePacked(b.length, e.length, mLen, b, e, m); assembly ("memory-safe") { let dataPtr := add(result, 0x20) // Write result on top of args to avoid allocating extra memory. success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen) // Overwrite the length. // result.length > returndatasize() is guaranteed because returndatasize() == m.length mstore(result, mLen) // Set the memory pointer after the returned data. mstore(0x40, add(dataPtr, mLen)) } } /** * @dev Returns whether the provided byte array is zero. */ function _zeroBytes(bytes memory byteArray) private pure returns (bool) { for (uint256 i = 0; i < byteArray.length; ++i) { if (byteArray[i] != 0) { return false; } } return true; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * This method is based on Newton's method for computing square roots; the algorithm is restricted to only * using integer operations. */ function sqrt(uint256 a) internal pure returns (uint256) { unchecked { // Take care of easy edge cases when a == 0 or a == 1 if (a <= 1) { return a; } // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between // the current value as `ε_n = | x_n - sqrt(a) |`. // // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is // bigger than any uint256. // // By noticing that // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)` // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar // to the msb function. uint256 aa = a; uint256 xn = 1; if (aa >= (1 << 128)) { aa >>= 128; xn <<= 64; } if (aa >= (1 << 64)) { aa >>= 64; xn <<= 32; } if (aa >= (1 << 32)) { aa >>= 32; xn <<= 16; } if (aa >= (1 << 16)) { aa >>= 16; xn <<= 8; } if (aa >= (1 << 8)) { aa >>= 8; xn <<= 4; } if (aa >= (1 << 4)) { aa >>= 4; xn <<= 2; } if (aa >= (1 << 2)) { xn <<= 1; } // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1). // // We can refine our estimation by noticing that the middle of that interval minimizes the error. // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2). // This is going to be our x_0 (and ε_0) xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2) // From here, Newton's method give us: // x_{n+1} = (x_n + a / x_n) / 2 // // One should note that: // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a // = ((x_n² + a) / (2 * x_n))² - a // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²) // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²) // = (x_n² - a)² / (2 * x_n)² // = ((x_n² - a) / (2 * x_n))² // ≥ 0 // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n // // This gives us the proof of quadratic convergence of the sequence: // ε_{n+1} = | x_{n+1} - sqrt(a) | // = | (x_n + a / x_n) / 2 - sqrt(a) | // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) | // = | (x_n - sqrt(a))² / (2 * x_n) | // = | ε_n² / (2 * x_n) | // = ε_n² / | (2 * x_n) | // // For the first iteration, we have a special case where x_0 is known: // ε_1 = ε_0² / | (2 * x_0) | // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2))) // ≤ 2**(2*e-4) / (3 * 2**(e-1)) // ≤ 2**(e-3) / 3 // ≤ 2**(e-3-log2(3)) // ≤ 2**(e-4.5) // // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n: // ε_{n+1} = ε_n² / | (2 * x_n) | // ≤ (2**(e-k))² / (2 * 2**(e-1)) // ≤ 2**(2*e-2*k) / 2**e // ≤ 2**(e-2*k) xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5 xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9 xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18 xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36 xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72 // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either // sqrt(a) or sqrt(a) + 1. return xn - SafeCast.toUint(xn > a / xn); } } /** * @dev Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 exp; unchecked { exp = 128 * SafeCast.toUint(value > (1 << 128) - 1); value >>= exp; result += exp; exp = 64 * SafeCast.toUint(value > (1 << 64) - 1); value >>= exp; result += exp; exp = 32 * SafeCast.toUint(value > (1 << 32) - 1); value >>= exp; result += exp; exp = 16 * SafeCast.toUint(value > (1 << 16) - 1); value >>= exp; result += exp; exp = 8 * SafeCast.toUint(value > (1 << 8) - 1); value >>= exp; result += exp; exp = 4 * SafeCast.toUint(value > (1 << 4) - 1); value >>= exp; result += exp; exp = 2 * SafeCast.toUint(value > (1 << 2) - 1); value >>= exp; result += exp; result += SafeCast.toUint(value > 1); } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 isGt; unchecked { isGt = SafeCast.toUint(value > (1 << 128) - 1); value >>= isGt * 128; result += isGt * 16; isGt = SafeCast.toUint(value > (1 << 64) - 1); value >>= isGt * 64; result += isGt * 8; isGt = SafeCast.toUint(value > (1 << 32) - 1); value >>= isGt * 32; result += isGt * 4; isGt = SafeCast.toUint(value > (1 << 16) - 1); value >>= isGt * 16; result += isGt * 2; result += SafeCast.toUint(value > (1 << 8) - 1); } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool 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. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @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 */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } 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 */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } 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 */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } 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 */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } 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 */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } 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 */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } 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 */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } 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 */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } 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 */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } 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 */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } 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 */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } 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 */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } 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 */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } 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 */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } 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 */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } 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 */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } 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 */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } 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 */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } 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 */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } 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 */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } 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 */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } 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 */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } 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 */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } 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 */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } 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 */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } 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 */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } 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 */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } 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 */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } 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 */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } 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 */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } 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 */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } 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 */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, 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 */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, 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 */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, 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 */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, 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 */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, 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 */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, 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 */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, 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 */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, 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 */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, 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 */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, 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 */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, 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 */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, 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 */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, 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 */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, 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 */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, 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 */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, 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 */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, 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 */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, 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 */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, 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 */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, 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 */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, 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 */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, 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 */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, 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 */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, 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 */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, 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 */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, 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 */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, 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 */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, 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 */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, 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 */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, 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 */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol) pragma solidity ^0.8.20; /** * @dev Helper library for emitting standardized panic codes. * * ```solidity * contract Example { * using Panic for uint256; * * // Use any of the declared internal constants * function foo() { Panic.GENERIC.panic(); } * * // Alternatively * function foo() { Panic.panic(Panic.GENERIC); } * } * ``` * * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil]. * * _Available since v5.1._ */ // slither-disable-next-line unused-state library Panic { /// @dev generic / unspecified error uint256 internal constant GENERIC = 0x00; /// @dev used by the assert() builtin uint256 internal constant ASSERT = 0x01; /// @dev arithmetic underflow or overflow uint256 internal constant UNDER_OVERFLOW = 0x11; /// @dev division or modulo by zero uint256 internal constant DIVISION_BY_ZERO = 0x12; /// @dev enum conversion error uint256 internal constant ENUM_CONVERSION_ERROR = 0x21; /// @dev invalid encoding in storage uint256 internal constant STORAGE_ENCODING_ERROR = 0x22; /// @dev empty array pop uint256 internal constant EMPTY_ARRAY_POP = 0x31; /// @dev array out of bounds access uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32; /// @dev resource error (too large allocation or too large array) uint256 internal constant RESOURCE_ERROR = 0x41; /// @dev calling invalid internal function uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51; /// @dev Reverts with a panic code. Recommended to use with /// the internal constants with predefined codes. function panic(uint256 code) internal pure { assembly ("memory-safe") { mstore(0x00, 0x4e487b71) mstore(0x20, code) revert(0x1c, 0x24) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @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 EIP-1153 (transient storage) is available on the chain you're deploying at, * consider using {ReentrancyGuardTransient} instead. * * 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 ReentrancyGuard { // 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; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _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() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface IBasisAsset { function mint(address recipient, uint256 amount) external returns (bool); function burn(uint256 amount) external; function burnFrom(address from, uint256 amount) external; function isOperator() external returns (bool); function operator() external view returns (address); function transferOperator(address newOperator_) external; function transferOwnership(address newOwner_) external; function totalBurned() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface IBoardroom { function allocateSeignioragePegToken(address _token, uint256 _amount) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface ICollateralPool { function update() external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface IEpoch { function epoch() external view returns (uint256); function nextEpochPoint() external view returns (uint256); function nextEpochLength() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface IOracle { function update() external; function consult(address _token, uint256 _amountIn) external view returns (uint144 amountOut); function twap(address _token, uint256 _amountIn) external view returns (uint144 _amountOut); function getPegPrice() external view returns (uint256); function getPegPriceUpdated() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface IRegulationStats { function addPegTokenEpochInfo(address _pegToken, uint256 epochNumber, uint256 twap, uint256 expanded, uint256 boardroomFunding, uint256 daoFunding, uint256 collateralFunding, uint256 devFunding) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; interface IRewardPool { function reward() external view returns (address); function deposit(uint256 _pid, uint256 _amount) external; function withdraw(uint256 _pid, uint256 _amount) external; function withdrawAll(uint256 _pid) external; function harvestAllRewards() external; function pendingReward(uint256 _pid, address _user) external view returns (uint256); function pendingAllRewards(address _user) external view returns (uint256); function totalAllocPoint() external view returns (uint256); function poolLength() external view returns (uint256); function getPoolInfo(uint256 _pid) external view returns (address _lp, uint256 _allocPoint); function getRewardPerSecond() external view returns (uint256); function updateRewardRate(uint256 _newRate) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import "./IEpoch.sol"; interface ITreasury is IEpoch { function getPegTokenPrice(address _token) external view returns (uint256); function getPegTokenUpdatedPrice(address _token) external view returns (uint256); function getPegTokenLockedBalance(address _token) external view returns (uint256); function getPegTokenCirculatingSupply(address _token) external view returns (uint256); function getPegTokenExpansionRate(address _token) external view returns (uint256); function getPegTokenExpansionAmount(address _token) external view returns (uint256); function previousEpochGreenPrice() external view returns (uint256); function boardroom() external view returns (address); function boardroomSharedPercent() external view returns (uint256); function daoFund() external view returns (address); function daoFundSharedPercent() external view returns (uint256); function collateralPool() external view returns (address); function collateralPoolSharedPercent() external view returns (uint256); function devFund() external view returns (address); function devFundSharedPercent() external view returns (uint256); function isSharePrinter(address account) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; library Babylonian { function sqrt(uint256 y) internal pure returns (uint256 z) { if (y > 3) { z = y; uint256 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } // else z = 0 } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; abstract contract Operator is Context, Ownable { address private _operator; event OperatorTransferred(address indexed previousOperator, address indexed newOperator); constructor() Ownable(_msgSender()) { _operator = _msgSender(); emit OperatorTransferred(address(0), _operator); } function operator() public view returns (address) { return _operator; } modifier onlyOperator() { require(_operator == msg.sender, "operator: caller is not the operator"); _; } function isOperator() public view returns (bool) { return _msgSender() == _operator; } function transferOperator(address newOperator_) public onlyOwner { _transferOperator(newOperator_); } function _transferOperator(address newOperator_) internal { require(newOperator_ != address(0), "operator: zero address given for new operator"); emit OperatorTransferred(_operator, newOperator_); _operator = newOperator_; } function _renounceOperator() public onlyOwner { emit OperatorTransferred(_operator, address(0)); _operator = address(0); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; contract ContractGuard { mapping(uint256 => mapping(address => bool)) private _status; function checkSameOriginReentranted() internal view returns (bool) { return _status[block.number][tx.origin]; } function checkSameSenderReentranted() internal view returns (bool) { return _status[block.number][msg.sender]; } modifier onlyOneBlock() { require(!checkSameOriginReentranted(), "ContractGuard: one block, one function"); require(!checkSameSenderReentranted(), "ContractGuard: one block, one function"); _; _status[block.number][tx.origin] = true; _status[block.number][msg.sender] = true; } }
{ "optimizer": { "enabled": true, "runs": 999999 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pegToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expanded","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"boardroomFunded","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"daoFunded","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralPooled","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"devFund","type":"uint256"}],"name":"FundingAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"addPegToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"}],"name":"addPegTokenLockedAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allocateSeigniorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allocateSeigniorageSalaryBlue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allocateSeigniorageSalaryGreen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blue","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boardroom","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boardroomSharedPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bootstrapEpochs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bootstrapSupplyExpansionPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralPoolSharedPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"daoFund","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"daoFundSharedPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"devFund","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"devFundSharedPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getPegTokenCirculatingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pegToken","type":"address"}],"name":"getPegTokenExpansionAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pegToken","type":"address"}],"name":"getPegTokenExpansionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getPegTokenLockedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getPegTokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getPegTokenUpdatedPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"governanceRecoverUnsupported","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"green","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"hasAllocatedPegToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"address[]","name":"_oracles","type":"address[]"},{"internalType":"address","name":"_farmingPool","type":"address"},{"internalType":"uint256","name":"_epochLength","type":"uint256"},{"internalType":"uint256","name":"_startTime","type":"uint256"},{"internalType":"address","name":"_boardroom","type":"address"},{"internalType":"address[]","name":"_allocatedPools","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isSharePrinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastEpochTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextEpochLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextEpochPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pegTokenEpochStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pegTokenLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pegTokenLockedAccounts","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pegTokenMaxSupplyExpansionPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pegTokenOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pegTokenSupplyTarget","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pegTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"previousEpochGreenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceCeiling","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceOne","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"red","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"regulationStats","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_allocateSeigniorageSalaryGreen","type":"uint256"},{"internalType":"uint256","name":"_allocateSeigniorageSalaryBlue","type":"uint256"}],"name":"setAllocateSeigniorageSalaries","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_boardroom","type":"address"}],"name":"setBoardroom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bootstrapEpochs","type":"uint256"},{"internalType":"uint256","name":"_bootstrapSupplyExpansionPercent","type":"uint256"}],"name":"setBootstrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_daoFund","type":"address"},{"internalType":"uint256","name":"_daoFundSharedPercent","type":"uint256"},{"internalType":"address","name":"_collateralPool","type":"address"},{"internalType":"uint256","name":"_collateralPoolSharedPercent","type":"uint256"},{"internalType":"address","name":"_devFund","type":"address"},{"internalType":"uint256","name":"_devFundSharedPercent","type":"uint256"}],"name":"setExtraFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"uint256","name":"_epochStart","type":"uint256"},{"internalType":"uint256","name":"_supplyTarget","type":"uint256"},{"internalType":"uint256","name":"_expansionPercent","type":"uint256"}],"name":"setPegTokenConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_priceCeiling","type":"uint256"}],"name":"setPriceCeiling","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_redOracle","type":"address"}],"name":"setRedOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_regulationStats","type":"address"}],"name":"setRegulationStats","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"setStrategistStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"sharePrinters","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"strategist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"toggleSharePrinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"transferContractOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405260006004556000600555348015601957600080fd5b5060018055613f288061002d6000396000f3fe608060405234801561001057600080fd5b50600436106103af5760003560e01c806389c614b8116101f4578063c1a008151161011a578063f20c4a26116100ad578063f9412c901161007c578063f9412c90146108ae578063fa339bd6146108c1578063fd3a7239146108c9578063ff0eccf6146108e957600080fd5b8063f20c4a261461082f578063f2f1e13214610842578063f2fde38b14610862578063f5385bc41461087557600080fd5b8063dc3727ff116100e9578063dc3727ff146107e0578063e7be71a7146107f3578063ed18f0a714610806578063f14698de1461082657600080fd5b8063c1a008151461079c578063c5967c26146107af578063c9b5bc6d146107b7578063d70613d6146107c057600080fd5b80639107f86611610192578063a5655e7811610161578063a5655e781461072d578063a8cca20614610740578063a9fa7ccc14610776578063b3ffc7771461078957600080fd5b80639107f866146106d457806391bbfed5146106e7578063929d7ac5146106fa578063a4dcf0431461071a57600080fd5b80638d934f74116101ce5780638d934f74146106665780638da5cb5b14610686578063900cf0cf146106c35780639075a3bf146106cb57600080fd5b806389c614b81461064c5780638b007ece146106555780638d2309b81461065e57600080fd5b8063574c689a116102d9578063715018a6116102775780637d4d49bb116102465780637d4d49bb146105fd57806382753b141461061d578063828b315c14610630578063874106cc1461064357600080fd5b8063715018a6146105b757806373a1e23f146105bf57806374292e25146105d257806378e97925146105f457600080fd5b80635fbaf094116102b35780635fbaf0941461057f578063608784fb146105885780636a599c001461059b5780636dcb60ee146105ae57600080fd5b8063574c689a146105445780635b756179146105575780635e02c51e1461055f57600080fd5b8063419484f4116103515780634d64161f116103205780634d64161f146104e757806354575af414610515578063546f33a81461052857806355ebdeef1461053b57600080fd5b8063419484f41461046e57806343191f59146104815780634390d2a8146104b45780634a0131fb146104d457600080fd5b80632930cf241161038d5780632930cf24146103ed5780632bf5a7a5146104325780632c2a65e8146104455780632d3b5a861461046557600080fd5b806303be7e76146103b457806307284ce9146103d05780631b0fb35f146103d8575b600080fd5b6103bd60175481565b6040519081526020015b60405180910390f35b6005546103bd565b6103eb6103e63660046139bf565b610909565b005b60085461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103c7565b6103eb610440366004613a26565b610c66565b60095461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103bd600c5481565b6103eb61047c366004613a26565b610dbd565b6104a461048f366004613a26565b601f6020526000908152604090205460ff1681565b60405190151581526020016103c7565b60165461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103eb6104e2366004613b36565b610e0c565b6104a46104f5366004613c01565b601e60209081526000928352604080842090915290825290205460ff1681565b6103eb610523366004613c31565b61154c565b6103bd610536366004613a26565b611727565b6103bd60135481565b61040d610552366004613c73565b61175e565b6103eb611795565b600a5461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103bd600f5481565b6103eb610596366004613c8c565b611f0a565b6103bd6105a9366004613a26565b611fa3565b6103bd60105481565b6103eb6120f0565b6103bd6105cd366004613a26565b612104565b6104a46105e0366004613a26565b602080526000908152604090205460ff1681565b6103bd60025481565b6103bd61060b366004613a26565b601b6020526000908152604090205481565b6103bd61062b366004613a26565b61218e565b6103eb61063e366004613cae565b612203565b6103bd600e5481565b6103bd60035481565b6103bd60155481565b6103bd61238e565b60125461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1661040d565b6004546103bd565b6103bd600b5481565b6103bd6106e2366004613a26565b6123bf565b6103eb6106f5366004613c8c565b6124aa565b6103bd610708366004613a26565b601c6020526000908152604090205481565b6103bd610728366004613a26565b6125ee565b6103eb61073b366004613a26565b612712565b61040d61074e366004613a26565b60196020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6103eb610784366004613cea565b612761565b6103eb610797366004613a26565b6127be565b6103eb6107aa366004613a26565b61288a565b6103bd6128e6565b6103bd60115481565b60215461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b61040d6107ee366004613d18565b6128fe565b6103eb610801366004613c73565b612943565b60075461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103bd600d5481565b6103eb61083d366004613cae565b6129e4565b60065461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103eb610870366004613a26565b612a71565b6104a4610883366004613a26565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f602052604090205460ff1690565b6103eb6108bc366004613d44565b612ad5565b6018546103bd565b6103bd6108d7366004613a26565b601d6020526000908152604090205481565b60145461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b610911612b54565b841580610933575073ffffffffffffffffffffffffffffffffffffffff861615155b61099e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f54726561737572793a207a65726f00000000000000000000000000000000000060448201526064015b60405180910390fd5b610bb8851115610a0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f54726561737572793a206f7574206f662072616e6765000000000000000000006044820152606401610995565b821580610a2c575073ffffffffffffffffffffffffffffffffffffffff841615155b610a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f54726561737572793a207a65726f0000000000000000000000000000000000006044820152606401610995565b610bb8831115610afe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f54726561737572793a206f7574206f662072616e6765000000000000000000006044820152606401610995565b801580610b20575073ffffffffffffffffffffffffffffffffffffffff821615155b610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f54726561737572793a207a65726f0000000000000000000000000000000000006044820152606401610995565b6105dc811115610bf2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f54726561737572793a206f7574206f662072616e6765000000000000000000006044820152606401610995565b601280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9889161790915560139590955560148054861694871694909417909355601591909155601680549093169316929092179055601755565b610c6e612b54565b60008173ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cdf9190613d95565b11610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f54726561737572793a20696e76616c696420746f6b656e0000000000000000006044820152606401610995565b601880546001810182556000919091527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e0180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610dc5612b54565b602180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610e575750825b905060008267ffffffffffffffff166001148015610e745750303b155b905081158015610e82575080155b15610eb9576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610f1a5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b610f2333612be2565b60008c600081518110610f3857610f38613dae565b6020026020010151600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055905060008d600181518110610f9657610f96613dae565b6020026020010151600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905590508d600281518110610ff257610ff2613dae565b6020908102919091010151600880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff938416179091556018805460018101825560009182527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e0180549092169285169290921790558d518e919061109157611091613dae565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff808516600090815260198452604080822080549484167fffffffffffffffffffffffff0000000000000000000000000000000000000000958616179055601b8552808220829055601c855280822069d3c21bcecceda10000009055601d909452928320613a9890556018805460018181018355919094527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e9093018054918516919092161790558d518e9190811061116c5761116c613dae565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff838116600090815260198452604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001694841694909417909355601b8452828120819055601c845282812069d3c21bcecceda10000009055601d8452828120613a989055825160608101909352908f1682528a5191928301918b919061121a5761121a613dae565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018960018151811061126657611266613dae565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff9081169092529083166000908152601a909152604090206112a99160036138b3565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601a6020526040902081546112da929061393d565b508c6002815181106112ee576112ee613dae565b6020908102919091010151600980547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155600a8054909116918b1691909117905560028a905560058b90556113618b8b613e0c565b600355670de0b6b3a7640000600b8190556127109061138290612711613e1f565b61138c9190613e36565b600c556015600d55612710600e55670de0b6b3a76400006010819055601155875188906000906113be576113be613dae565b6020026020010151601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506107d06013819055508760018151811061142257611422613dae565b6020026020010151601460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506107d06015819055508760028151811061148657611486613dae565b6020908102919091010151601680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905550506103e8601755831561153e5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b611554612b54565b73ffffffffffffffffffffffffffffffffffffffff81166115f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f54726561737572793a2043616e6e6f74207472616e7366657220746f207a657260448201527f6f206164647265737300000000000000000000000000000000000000000000006064820152608401610995565b60065473ffffffffffffffffffffffffffffffffffffffff9081169084160361167c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f54726561737572793a2063616e6e6f74207265636f76657220677265656e00006044820152606401610995565b60075473ffffffffffffffffffffffffffffffffffffffff90811690841603611701576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f54726561737572793a2063616e6e6f74207265636f76657220626c75650000006044820152606401610995565b61172273ffffffffffffffffffffffffffffffffffffffff84168284612bf3565b505050565b600080611733836123bf565b9050620f42408161174385612104565b61174d9190613e1f565b6117579190613e36565b9392505050565b6018818154811061176e57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b4360009081526020818152604080832032845290915290205460ff161561183e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610995565b4360009081526020818152604080832033845290915290205460ff16156118e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610995565b60006118f16128e6565b90508042101561195d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f54726561737572793a206e6f74206f70656e65640000000000000000000000006044820152606401610995565b600654604080517f570ca7350000000000000000000000000000000000000000000000000000000081529051309273ffffffffffffffffffffffffffffffffffffffff169163570ca7359160048083019260209291908290030181865afa1580156119cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f09190613e71565b73ffffffffffffffffffffffffffffffffffffffff16148015611ab95750600754604080517f570ca7350000000000000000000000000000000000000000000000000000000081529051309273ffffffffffffffffffffffffffffffffffffffff169163570ca7359160048083019260209291908290030181865afa158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613e71565b73ffffffffffffffffffffffffffffffffffffffff16145b611b1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f54726561737572793a206e656564206d6f7265207065726d697373696f6e00006044820152606401610995565b611b27612c74565b600654611b499073ffffffffffffffffffffffffffffffffffffffff16611fa3565b600f5560185460005b81811015611bd857600060188281548110611b6f57611b6f613dae565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16808352601b90915260409091205460045491925090611bb3906001613e8e565b8111611bce57611bc282612cb7565b611bce60045483612d46565b5050600101611b52565b5060095473ffffffffffffffffffffffffffffffffffffffff1615611c7457600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611c6157600080fd5b505af1925050508015611c72575060015b505b60145473ffffffffffffffffffffffffffffffffffffffff1615801590611cb3575060145473ffffffffffffffffffffffffffffffffffffffff163b15155b15611d3557601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611d2257600080fd5b505af1925050508015611d33575060015b505b60105415611dde576006546010546040517f40c10f19000000000000000000000000000000000000000000000000000000008152336004820152602481019190915273ffffffffffffffffffffffffffffffffffffffff909116906340c10f19906044016020604051808303816000875af1158015611db8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ddc9190613ea1565b505b60115415611e87576007546011546040517f40c10f19000000000000000000000000000000000000000000000000000000008152336004820152602481019190915273ffffffffffffffffffffffffffffffffffffffff909116906340c10f19906044016020604051808303816000875af1158015611e61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e859190613ea1565b505b50611e9160018055565b80600381905550600160046000828254611eab9190613e8e565b909155505043600090815260208181526040808320328452909152808220805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009182168117909255338452919092208054909116909117905550565b611f12612b54565b678ac7230489e800008211158015611f325750678ac7230489e800008111155b611f98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f54726561737572793a20746f6f206d75636800000000000000000000000000006044820152606401610995565b601091909155601155565b73ffffffffffffffffffffffffffffffffffffffff8181166000818152601960205260408082205490517f3ddac9530000000000000000000000000000000000000000000000000000000081526004810193909352670de0b6b3a7640000602484015290921690633ddac953906044015b602060405180830381865afa92505050801561206b575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261206891810190613ebe565b60015b6120d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f54726561737572793a206f7261636c65206661696c65640000000000000000006044820152606401610995565b71ffffffffffffffffffffffffffffffffffff1692915050565b919050565b6120f8612b54565b612102600061352a565b565b600061210f826125ee565b8273ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561215a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217e9190613d95565b6121889190613e0c565b92915050565b73ffffffffffffffffffffffffffffffffffffffff8181166000818152601960205260408082205490517f6808a1280000000000000000000000000000000000000000000000000000000081526004810193909352670de0b6b3a7640000602484015290921690636808a12890604401612014565b61220b612b54565b73ffffffffffffffffffffffffffffffffffffffff8116612288576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f54726561737572793a20696e76616c69642061646472657373000000000000006044820152606401610995565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601a6020526040812054905b818110156123295773ffffffffffffffffffffffffffffffffffffffff8481166000908152601a60205260409020805491851691839081106122f4576122f4613dae565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16036123215750505050565b6001016122b0565b505073ffffffffffffffffffffffffffffffffffffffff9182166000908152601a602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60006017546015546013546127106123a69190613e0c565b6123b09190613e0c565b6123ba9190613e0c565b905090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601b60205260408120546004546123f3906001613e8e565b8111156124035750600092915050565b600d546004541015612419575050600e54919050565b60006124248461218e565b9050600c548111156124a0576000600b54826124409190613e0c565b73ffffffffffffffffffffffffffffffffffffffff86166000908152601d6020526040812054919250906124799064e8d4a51000613e1f565b905080821115612487578091505b61249664e8d4a5100083613e36565b9695505050505050565b5060009392505050565b6124b2612b54565b605a821115612543576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f54726561737572793a205f626f6f74737472617045706f636873206f7574206f60448201527f662072616e6765000000000000000000000000000000000000000000000000006064820152608401610995565b6103e88110158015612557575061c3508111155b6125e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f54726561737572793a205f626f6f747374726170537570706c79457870616e7360448201527f696f6e50657263656e74206f7574206f662072616e67650000000000000000006064820152608401610995565b600d91909155600e55565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601a602052604081205481805b8281101561270a5773ffffffffffffffffffffffffffffffffffffffff85166000818152601a6020526040902080546370a0823191908490811061265d5761265d613dae565b60009182526020909120015460405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa1580156126d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f69190613d95565b6127009083613e8e565b9150600101612617565b509392505050565b61271a612b54565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b612769612b54565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152602080526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6127c6612b54565b73ffffffffffffffffffffffffffffffffffffffff8116612843576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f54726561737572793a207a65726f2061646472657373000000000000000000006044820152606401610995565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b612892612b54565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60006128f160055490565b6003546123ba9190613e8e565b601a602052816000526040600020818154811061291a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b61294b612b54565b600b5481101580156129795750612710600b54612ee061296b9190613e1f565b6129759190613e36565b8111155b6129df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f54726561737572793a206f7574206f662072616e6765000000000000000000006044820152606401610995565b600c55565b6129ec612b54565b6040517f29605e7700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301528316906329605e7790602401600060405180830381600087803b158015612a5557600080fd5b505af1158015612a69573d6000803e3d6000fd5b505050505050565b612a79612b54565b73ffffffffffffffffffffffffffffffffffffffff8116612ac9576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610995565b612ad28161352a565b50565b612add612b54565b73ffffffffffffffffffffffffffffffffffffffff948516600090815260196020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169790981696909617909655601b865284812093909355601c855283832091909155601d9093522055565b33612b937f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614612102576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610995565b612bea6135c0565b612ad281613627565b60405173ffffffffffffffffffffffffffffffffffffffff83811660248301526044820183905261172291859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061362f565b600260015403612cb0576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b73ffffffffffffffffffffffffffffffffffffffff8082166000908152601960205260408082205481517fa2e62045000000000000000000000000000000000000000000000000000000008152915193169263a2e620459260048084019391929182900301818387803b158015612d2d57600080fd5b505af1925050508015612d3e575060015b15612ad25750565b601e6000612d55846001613e8e565b81526020808201929092526040908101600090812073ffffffffffffffffffffffffffffffffffffffff8516825290925290205460ff1615612d95575050565b6001601e6000612da58584613e8e565b81526020808201929092526040908101600090812073ffffffffffffffffffffffffffffffffffffffff86168252909252812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001692151592909217909155612e0f82612104565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601c60205260409020549091508110612f265773ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205461271090612e7490612ee0613e1f565b612e7e9190613e36565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601c6020908152604080832093909355601d9052205461271090612ec090612328613e1f565b612eca9190613e36565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601d602052604090208190556109c41115612f265773ffffffffffffffffffffffffffffffffffffffff82166000908152601d602052604090206109c490555b600080612f3284611fa3565b9050600d546004541015612f5957600e54612f529064e8d4a51000613e1f565b9150612fb9565b600c54811115612fb957600b54612f709082613e0c565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601d602052604081205491935090612fa99064e8d4a51000613e1f565b905080831115612fb7578092505b505b8115613523576000670de0b6b3a7640000612fd48486613e1f565b612fde9190613e36565b9050600080808084156133a6576040517f40c10f190000000000000000000000000000000000000000000000000000000081523060048201526024810186905273ffffffffffffffffffffffffffffffffffffffff8a16906340c10f19906044016020604051808303816000875af115801561305e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130829190613ea1565b5060135415613147576127106013548661309c9190613e1f565b6130a69190613e36565b6012546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018390529195508a169063a9059cbb906044016020604051808303816000875af1158015613121573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131459190613ea1565b505b6015541561320b57612710601554866131609190613e1f565b61316a9190613e36565b6014546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018390529194508a169063a9059cbb906044016020604051808303816000875af11580156131e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132099190613ea1565b505b601754156132cf57612710601754866132249190613e1f565b61322e9190613e36565b6016546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018390529193508a169063a9059cbb906044016020604051808303816000875af11580156132a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132cd9190613ea1565b505b81836132db8688613e0c565b6132e59190613e0c565b6132ef9190613e0c565b600a549091506133199073ffffffffffffffffffffffffffffffffffffffff8b81169116836136d9565b600a546040517f79fbd8e000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015260248201849052909116906379fbd8e090604401600060405180830381600087803b15801561338d57600080fd5b505af11580156133a1573d6000803e3d6000fd5b505050505b60215473ffffffffffffffffffffffffffffffffffffffff161561349d5760215473ffffffffffffffffffffffffffffffffffffffff1663b4c289298a6133ee8d6001613e8e565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260448101899052606481018890526084810184905260a4810187905260c4810186905260e4810185905261010401600060405180830381600087803b15801561348457600080fd5b505af1158015613498573d6000803e3d6000fd5b505050505b6134a88a6001613e8e565b6040805142815260208101899052908101879052606081018390526080810186905260a0810185905260c0810184905273ffffffffffffffffffffffffffffffffffffffff8b16907fcb4b18bb7f2324dc8a73136fbc59cc5f6c578f05b9798c32a87b011922e319b29060e00160405180910390a350505050505b5050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16612102576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612a796135c0565b600080602060008451602086016000885af180613652576040513d6000823e3d81fd5b50506000513d9150811561366a578060011415613684565b73ffffffffffffffffffffffffffffffffffffffff84163b155b156136d3576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610995565b50505050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301526000919085169063dd62ed3e90604401602060405180830381865afa15801561374f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137739190613d95565b90506136d384846137848585613e8e565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052613810848261385c565b6136d35760405173ffffffffffffffffffffffffffffffffffffffff84811660248301526000604483015261385291869182169063095ea7b390606401612c2d565b6136d3848261362f565b6000806000806020600086516020880160008a5af192503d91506000519050828015612496575081156138925780600114612496565b505050505073ffffffffffffffffffffffffffffffffffffffff163b151590565b82805482825590600052602060002090810192821561392d579160200282015b8281111561392d57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906138d3565b5061393992915061397d565b5090565b82805482825590600052602060002090810192821561392d5760005260206000209182015b8281111561392d578254825591600101919060010190613962565b5b80821115613939576000815560010161397e565b73ffffffffffffffffffffffffffffffffffffffff81168114612ad257600080fd5b80356120eb81613992565b60008060008060008060c087890312156139d857600080fd5b86356139e381613992565b95506020870135945060408701356139fa81613992565b9350606087013592506080870135613a1181613992565b9598949750929591949360a090920135925050565b600060208284031215613a3857600080fd5b813561175781613992565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112613a8357600080fd5b813567ffffffffffffffff811115613a9d57613a9d613a43565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811067ffffffffffffffff82111715613ae857613ae8613a43565b604052918252602081850181019290810186841115613b0657600080fd5b6020860192505b83831015613b2c57613b1e836139b4565b815260209283019201613b0d565b5095945050505050565b600080600080600080600060e0888a031215613b5157600080fd5b873567ffffffffffffffff811115613b6857600080fd5b613b748a828b01613a72565b975050602088013567ffffffffffffffff811115613b9157600080fd5b613b9d8a828b01613a72565b9650506040880135613bae81613992565b94506060880135935060808801359250613bca60a089016139b4565b915060c088013567ffffffffffffffff811115613be657600080fd5b613bf28a828b01613a72565b91505092959891949750929550565b60008060408385031215613c1457600080fd5b823591506020830135613c2681613992565b809150509250929050565b600080600060608486031215613c4657600080fd5b8335613c5181613992565b9250602084013591506040840135613c6881613992565b809150509250925092565b600060208284031215613c8557600080fd5b5035919050565b60008060408385031215613c9f57600080fd5b50508035926020909101359150565b60008060408385031215613cc157600080fd5b8235613ccc81613992565b91506020830135613c2681613992565b8015158114612ad257600080fd5b60008060408385031215613cfd57600080fd5b8235613d0881613992565b91506020830135613c2681613cdc565b60008060408385031215613d2b57600080fd5b8235613d3681613992565b946020939093013593505050565b600080600080600060a08688031215613d5c57600080fd5b8535613d6781613992565b94506020860135613d7781613992565b94979496505050506040830135926060810135926080909101359150565b600060208284031215613da757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561218857612188613ddd565b808202811582820484141761218857612188613ddd565b600082613e6c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613e8357600080fd5b815161175781613992565b8082018082111561218857612188613ddd565b600060208284031215613eb357600080fd5b815161175781613cdc565b600060208284031215613ed057600080fd5b815171ffffffffffffffffffffffffffffffffffff8116811461175757600080fdfea2646970667358221220f743c40b93c9dea52a4935274ce3b2d45eee33a3c2c46d248a91c3413f7b490564736f6c634300081c0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103af5760003560e01c806389c614b8116101f4578063c1a008151161011a578063f20c4a26116100ad578063f9412c901161007c578063f9412c90146108ae578063fa339bd6146108c1578063fd3a7239146108c9578063ff0eccf6146108e957600080fd5b8063f20c4a261461082f578063f2f1e13214610842578063f2fde38b14610862578063f5385bc41461087557600080fd5b8063dc3727ff116100e9578063dc3727ff146107e0578063e7be71a7146107f3578063ed18f0a714610806578063f14698de1461082657600080fd5b8063c1a008151461079c578063c5967c26146107af578063c9b5bc6d146107b7578063d70613d6146107c057600080fd5b80639107f86611610192578063a5655e7811610161578063a5655e781461072d578063a8cca20614610740578063a9fa7ccc14610776578063b3ffc7771461078957600080fd5b80639107f866146106d457806391bbfed5146106e7578063929d7ac5146106fa578063a4dcf0431461071a57600080fd5b80638d934f74116101ce5780638d934f74146106665780638da5cb5b14610686578063900cf0cf146106c35780639075a3bf146106cb57600080fd5b806389c614b81461064c5780638b007ece146106555780638d2309b81461065e57600080fd5b8063574c689a116102d9578063715018a6116102775780637d4d49bb116102465780637d4d49bb146105fd57806382753b141461061d578063828b315c14610630578063874106cc1461064357600080fd5b8063715018a6146105b757806373a1e23f146105bf57806374292e25146105d257806378e97925146105f457600080fd5b80635fbaf094116102b35780635fbaf0941461057f578063608784fb146105885780636a599c001461059b5780636dcb60ee146105ae57600080fd5b8063574c689a146105445780635b756179146105575780635e02c51e1461055f57600080fd5b8063419484f4116103515780634d64161f116103205780634d64161f146104e757806354575af414610515578063546f33a81461052857806355ebdeef1461053b57600080fd5b8063419484f41461046e57806343191f59146104815780634390d2a8146104b45780634a0131fb146104d457600080fd5b80632930cf241161038d5780632930cf24146103ed5780632bf5a7a5146104325780632c2a65e8146104455780632d3b5a861461046557600080fd5b806303be7e76146103b457806307284ce9146103d05780631b0fb35f146103d8575b600080fd5b6103bd60175481565b6040519081526020015b60405180910390f35b6005546103bd565b6103eb6103e63660046139bf565b610909565b005b60085461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103c7565b6103eb610440366004613a26565b610c66565b60095461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103bd600c5481565b6103eb61047c366004613a26565b610dbd565b6104a461048f366004613a26565b601f6020526000908152604090205460ff1681565b60405190151581526020016103c7565b60165461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103eb6104e2366004613b36565b610e0c565b6104a46104f5366004613c01565b601e60209081526000928352604080842090915290825290205460ff1681565b6103eb610523366004613c31565b61154c565b6103bd610536366004613a26565b611727565b6103bd60135481565b61040d610552366004613c73565b61175e565b6103eb611795565b600a5461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103bd600f5481565b6103eb610596366004613c8c565b611f0a565b6103bd6105a9366004613a26565b611fa3565b6103bd60105481565b6103eb6120f0565b6103bd6105cd366004613a26565b612104565b6104a46105e0366004613a26565b602080526000908152604090205460ff1681565b6103bd60025481565b6103bd61060b366004613a26565b601b6020526000908152604090205481565b6103bd61062b366004613a26565b61218e565b6103eb61063e366004613cae565b612203565b6103bd600e5481565b6103bd60035481565b6103bd60155481565b6103bd61238e565b60125461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1661040d565b6004546103bd565b6103bd600b5481565b6103bd6106e2366004613a26565b6123bf565b6103eb6106f5366004613c8c565b6124aa565b6103bd610708366004613a26565b601c6020526000908152604090205481565b6103bd610728366004613a26565b6125ee565b6103eb61073b366004613a26565b612712565b61040d61074e366004613a26565b60196020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6103eb610784366004613cea565b612761565b6103eb610797366004613a26565b6127be565b6103eb6107aa366004613a26565b61288a565b6103bd6128e6565b6103bd60115481565b60215461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b61040d6107ee366004613d18565b6128fe565b6103eb610801366004613c73565b612943565b60075461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103bd600d5481565b6103eb61083d366004613cae565b6129e4565b60065461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103eb610870366004613a26565b612a71565b6104a4610883366004613a26565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f602052604090205460ff1690565b6103eb6108bc366004613d44565b612ad5565b6018546103bd565b6103bd6108d7366004613a26565b601d6020526000908152604090205481565b60145461040d9073ffffffffffffffffffffffffffffffffffffffff1681565b610911612b54565b841580610933575073ffffffffffffffffffffffffffffffffffffffff861615155b61099e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f54726561737572793a207a65726f00000000000000000000000000000000000060448201526064015b60405180910390fd5b610bb8851115610a0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f54726561737572793a206f7574206f662072616e6765000000000000000000006044820152606401610995565b821580610a2c575073ffffffffffffffffffffffffffffffffffffffff841615155b610a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f54726561737572793a207a65726f0000000000000000000000000000000000006044820152606401610995565b610bb8831115610afe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f54726561737572793a206f7574206f662072616e6765000000000000000000006044820152606401610995565b801580610b20575073ffffffffffffffffffffffffffffffffffffffff821615155b610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f54726561737572793a207a65726f0000000000000000000000000000000000006044820152606401610995565b6105dc811115610bf2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f54726561737572793a206f7574206f662072616e6765000000000000000000006044820152606401610995565b601280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9889161790915560139590955560148054861694871694909417909355601591909155601680549093169316929092179055601755565b610c6e612b54565b60008173ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cdf9190613d95565b11610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f54726561737572793a20696e76616c696420746f6b656e0000000000000000006044820152606401610995565b601880546001810182556000919091527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e0180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610dc5612b54565b602180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610e575750825b905060008267ffffffffffffffff166001148015610e745750303b155b905081158015610e82575080155b15610eb9576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610f1a5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b610f2333612be2565b60008c600081518110610f3857610f38613dae565b6020026020010151600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055905060008d600181518110610f9657610f96613dae565b6020026020010151600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905590508d600281518110610ff257610ff2613dae565b6020908102919091010151600880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff938416179091556018805460018101825560009182527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e0180549092169285169290921790558d518e919061109157611091613dae565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff808516600090815260198452604080822080549484167fffffffffffffffffffffffff0000000000000000000000000000000000000000958616179055601b8552808220829055601c855280822069d3c21bcecceda10000009055601d909452928320613a9890556018805460018181018355919094527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e9093018054918516919092161790558d518e9190811061116c5761116c613dae565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff838116600090815260198452604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001694841694909417909355601b8452828120819055601c845282812069d3c21bcecceda10000009055601d8452828120613a989055825160608101909352908f1682528a5191928301918b919061121a5761121a613dae565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018960018151811061126657611266613dae565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff9081169092529083166000908152601a909152604090206112a99160036138b3565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601a6020526040902081546112da929061393d565b508c6002815181106112ee576112ee613dae565b6020908102919091010151600980547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155600a8054909116918b1691909117905560028a905560058b90556113618b8b613e0c565b600355670de0b6b3a7640000600b8190556127109061138290612711613e1f565b61138c9190613e36565b600c556015600d55612710600e55670de0b6b3a76400006010819055601155875188906000906113be576113be613dae565b6020026020010151601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506107d06013819055508760018151811061142257611422613dae565b6020026020010151601460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506107d06015819055508760028151811061148657611486613dae565b6020908102919091010151601680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905550506103e8601755831561153e5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b611554612b54565b73ffffffffffffffffffffffffffffffffffffffff81166115f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f54726561737572793a2043616e6e6f74207472616e7366657220746f207a657260448201527f6f206164647265737300000000000000000000000000000000000000000000006064820152608401610995565b60065473ffffffffffffffffffffffffffffffffffffffff9081169084160361167c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f54726561737572793a2063616e6e6f74207265636f76657220677265656e00006044820152606401610995565b60075473ffffffffffffffffffffffffffffffffffffffff90811690841603611701576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f54726561737572793a2063616e6e6f74207265636f76657220626c75650000006044820152606401610995565b61172273ffffffffffffffffffffffffffffffffffffffff84168284612bf3565b505050565b600080611733836123bf565b9050620f42408161174385612104565b61174d9190613e1f565b6117579190613e36565b9392505050565b6018818154811061176e57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b4360009081526020818152604080832032845290915290205460ff161561183e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610995565b4360009081526020818152604080832033845290915290205460ff16156118e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f436f6e747261637447756172643a206f6e6520626c6f636b2c206f6e6520667560448201527f6e6374696f6e00000000000000000000000000000000000000000000000000006064820152608401610995565b60006118f16128e6565b90508042101561195d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f54726561737572793a206e6f74206f70656e65640000000000000000000000006044820152606401610995565b600654604080517f570ca7350000000000000000000000000000000000000000000000000000000081529051309273ffffffffffffffffffffffffffffffffffffffff169163570ca7359160048083019260209291908290030181865afa1580156119cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f09190613e71565b73ffffffffffffffffffffffffffffffffffffffff16148015611ab95750600754604080517f570ca7350000000000000000000000000000000000000000000000000000000081529051309273ffffffffffffffffffffffffffffffffffffffff169163570ca7359160048083019260209291908290030181865afa158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613e71565b73ffffffffffffffffffffffffffffffffffffffff16145b611b1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f54726561737572793a206e656564206d6f7265207065726d697373696f6e00006044820152606401610995565b611b27612c74565b600654611b499073ffffffffffffffffffffffffffffffffffffffff16611fa3565b600f5560185460005b81811015611bd857600060188281548110611b6f57611b6f613dae565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16808352601b90915260409091205460045491925090611bb3906001613e8e565b8111611bce57611bc282612cb7565b611bce60045483612d46565b5050600101611b52565b5060095473ffffffffffffffffffffffffffffffffffffffff1615611c7457600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611c6157600080fd5b505af1925050508015611c72575060015b505b60145473ffffffffffffffffffffffffffffffffffffffff1615801590611cb3575060145473ffffffffffffffffffffffffffffffffffffffff163b15155b15611d3557601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a2e620456040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611d2257600080fd5b505af1925050508015611d33575060015b505b60105415611dde576006546010546040517f40c10f19000000000000000000000000000000000000000000000000000000008152336004820152602481019190915273ffffffffffffffffffffffffffffffffffffffff909116906340c10f19906044016020604051808303816000875af1158015611db8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ddc9190613ea1565b505b60115415611e87576007546011546040517f40c10f19000000000000000000000000000000000000000000000000000000008152336004820152602481019190915273ffffffffffffffffffffffffffffffffffffffff909116906340c10f19906044016020604051808303816000875af1158015611e61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e859190613ea1565b505b50611e9160018055565b80600381905550600160046000828254611eab9190613e8e565b909155505043600090815260208181526040808320328452909152808220805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009182168117909255338452919092208054909116909117905550565b611f12612b54565b678ac7230489e800008211158015611f325750678ac7230489e800008111155b611f98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f54726561737572793a20746f6f206d75636800000000000000000000000000006044820152606401610995565b601091909155601155565b73ffffffffffffffffffffffffffffffffffffffff8181166000818152601960205260408082205490517f3ddac9530000000000000000000000000000000000000000000000000000000081526004810193909352670de0b6b3a7640000602484015290921690633ddac953906044015b602060405180830381865afa92505050801561206b575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261206891810190613ebe565b60015b6120d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f54726561737572793a206f7261636c65206661696c65640000000000000000006044820152606401610995565b71ffffffffffffffffffffffffffffffffffff1692915050565b919050565b6120f8612b54565b612102600061352a565b565b600061210f826125ee565b8273ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561215a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217e9190613d95565b6121889190613e0c565b92915050565b73ffffffffffffffffffffffffffffffffffffffff8181166000818152601960205260408082205490517f6808a1280000000000000000000000000000000000000000000000000000000081526004810193909352670de0b6b3a7640000602484015290921690636808a12890604401612014565b61220b612b54565b73ffffffffffffffffffffffffffffffffffffffff8116612288576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f54726561737572793a20696e76616c69642061646472657373000000000000006044820152606401610995565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601a6020526040812054905b818110156123295773ffffffffffffffffffffffffffffffffffffffff8481166000908152601a60205260409020805491851691839081106122f4576122f4613dae565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16036123215750505050565b6001016122b0565b505073ffffffffffffffffffffffffffffffffffffffff9182166000908152601a602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909216179055565b60006017546015546013546127106123a69190613e0c565b6123b09190613e0c565b6123ba9190613e0c565b905090565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601b60205260408120546004546123f3906001613e8e565b8111156124035750600092915050565b600d546004541015612419575050600e54919050565b60006124248461218e565b9050600c548111156124a0576000600b54826124409190613e0c565b73ffffffffffffffffffffffffffffffffffffffff86166000908152601d6020526040812054919250906124799064e8d4a51000613e1f565b905080821115612487578091505b61249664e8d4a5100083613e36565b9695505050505050565b5060009392505050565b6124b2612b54565b605a821115612543576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f54726561737572793a205f626f6f74737472617045706f636873206f7574206f60448201527f662072616e6765000000000000000000000000000000000000000000000000006064820152608401610995565b6103e88110158015612557575061c3508111155b6125e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f54726561737572793a205f626f6f747374726170537570706c79457870616e7360448201527f696f6e50657263656e74206f7574206f662072616e67650000000000000000006064820152608401610995565b600d91909155600e55565b73ffffffffffffffffffffffffffffffffffffffff81166000908152601a602052604081205481805b8281101561270a5773ffffffffffffffffffffffffffffffffffffffff85166000818152601a6020526040902080546370a0823191908490811061265d5761265d613dae565b60009182526020909120015460405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa1580156126d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f69190613d95565b6127009083613e8e565b9150600101612617565b509392505050565b61271a612b54565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b612769612b54565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152602080526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6127c6612b54565b73ffffffffffffffffffffffffffffffffffffffff8116612843576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f54726561737572793a207a65726f2061646472657373000000000000000000006044820152606401610995565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b612892612b54565b73ffffffffffffffffffffffffffffffffffffffff166000908152601f6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b60006128f160055490565b6003546123ba9190613e8e565b601a602052816000526040600020818154811061291a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b61294b612b54565b600b5481101580156129795750612710600b54612ee061296b9190613e1f565b6129759190613e36565b8111155b6129df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f54726561737572793a206f7574206f662072616e6765000000000000000000006044820152606401610995565b600c55565b6129ec612b54565b6040517f29605e7700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301528316906329605e7790602401600060405180830381600087803b158015612a5557600080fd5b505af1158015612a69573d6000803e3d6000fd5b505050505050565b612a79612b54565b73ffffffffffffffffffffffffffffffffffffffff8116612ac9576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610995565b612ad28161352a565b50565b612add612b54565b73ffffffffffffffffffffffffffffffffffffffff948516600090815260196020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169790981696909617909655601b865284812093909355601c855283832091909155601d9093522055565b33612b937f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614612102576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610995565b612bea6135c0565b612ad281613627565b60405173ffffffffffffffffffffffffffffffffffffffff83811660248301526044820183905261172291859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061362f565b600260015403612cb0576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b73ffffffffffffffffffffffffffffffffffffffff8082166000908152601960205260408082205481517fa2e62045000000000000000000000000000000000000000000000000000000008152915193169263a2e620459260048084019391929182900301818387803b158015612d2d57600080fd5b505af1925050508015612d3e575060015b15612ad25750565b601e6000612d55846001613e8e565b81526020808201929092526040908101600090812073ffffffffffffffffffffffffffffffffffffffff8516825290925290205460ff1615612d95575050565b6001601e6000612da58584613e8e565b81526020808201929092526040908101600090812073ffffffffffffffffffffffffffffffffffffffff86168252909252812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001692151592909217909155612e0f82612104565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601c60205260409020549091508110612f265773ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205461271090612e7490612ee0613e1f565b612e7e9190613e36565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601c6020908152604080832093909355601d9052205461271090612ec090612328613e1f565b612eca9190613e36565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601d602052604090208190556109c41115612f265773ffffffffffffffffffffffffffffffffffffffff82166000908152601d602052604090206109c490555b600080612f3284611fa3565b9050600d546004541015612f5957600e54612f529064e8d4a51000613e1f565b9150612fb9565b600c54811115612fb957600b54612f709082613e0c565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601d602052604081205491935090612fa99064e8d4a51000613e1f565b905080831115612fb7578092505b505b8115613523576000670de0b6b3a7640000612fd48486613e1f565b612fde9190613e36565b9050600080808084156133a6576040517f40c10f190000000000000000000000000000000000000000000000000000000081523060048201526024810186905273ffffffffffffffffffffffffffffffffffffffff8a16906340c10f19906044016020604051808303816000875af115801561305e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130829190613ea1565b5060135415613147576127106013548661309c9190613e1f565b6130a69190613e36565b6012546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018390529195508a169063a9059cbb906044016020604051808303816000875af1158015613121573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131459190613ea1565b505b6015541561320b57612710601554866131609190613e1f565b61316a9190613e36565b6014546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018390529194508a169063a9059cbb906044016020604051808303816000875af11580156131e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132099190613ea1565b505b601754156132cf57612710601754866132249190613e1f565b61322e9190613e36565b6016546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018390529193508a169063a9059cbb906044016020604051808303816000875af11580156132a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132cd9190613ea1565b505b81836132db8688613e0c565b6132e59190613e0c565b6132ef9190613e0c565b600a549091506133199073ffffffffffffffffffffffffffffffffffffffff8b81169116836136d9565b600a546040517f79fbd8e000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015260248201849052909116906379fbd8e090604401600060405180830381600087803b15801561338d57600080fd5b505af11580156133a1573d6000803e3d6000fd5b505050505b60215473ffffffffffffffffffffffffffffffffffffffff161561349d5760215473ffffffffffffffffffffffffffffffffffffffff1663b4c289298a6133ee8d6001613e8e565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260448101899052606481018890526084810184905260a4810187905260c4810186905260e4810185905261010401600060405180830381600087803b15801561348457600080fd5b505af1158015613498573d6000803e3d6000fd5b505050505b6134a88a6001613e8e565b6040805142815260208101899052908101879052606081018390526080810186905260a0810185905260c0810184905273ffffffffffffffffffffffffffffffffffffffff8b16907fcb4b18bb7f2324dc8a73136fbc59cc5f6c578f05b9798c32a87b011922e319b29060e00160405180910390a350505050505b5050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16612102576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612a796135c0565b600080602060008451602086016000885af180613652576040513d6000823e3d81fd5b50506000513d9150811561366a578060011415613684565b73ffffffffffffffffffffffffffffffffffffffff84163b155b156136d3576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610995565b50505050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301526000919085169063dd62ed3e90604401602060405180830381865afa15801561374f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137739190613d95565b90506136d384846137848585613e8e565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052613810848261385c565b6136d35760405173ffffffffffffffffffffffffffffffffffffffff84811660248301526000604483015261385291869182169063095ea7b390606401612c2d565b6136d3848261362f565b6000806000806020600086516020880160008a5af192503d91506000519050828015612496575081156138925780600114612496565b505050505073ffffffffffffffffffffffffffffffffffffffff163b151590565b82805482825590600052602060002090810192821561392d579160200282015b8281111561392d57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906138d3565b5061393992915061397d565b5090565b82805482825590600052602060002090810192821561392d5760005260206000209182015b8281111561392d578254825591600101919060010190613962565b5b80821115613939576000815560010161397e565b73ffffffffffffffffffffffffffffffffffffffff81168114612ad257600080fd5b80356120eb81613992565b60008060008060008060c087890312156139d857600080fd5b86356139e381613992565b95506020870135945060408701356139fa81613992565b9350606087013592506080870135613a1181613992565b9598949750929591949360a090920135925050565b600060208284031215613a3857600080fd5b813561175781613992565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112613a8357600080fd5b813567ffffffffffffffff811115613a9d57613a9d613a43565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811067ffffffffffffffff82111715613ae857613ae8613a43565b604052918252602081850181019290810186841115613b0657600080fd5b6020860192505b83831015613b2c57613b1e836139b4565b815260209283019201613b0d565b5095945050505050565b600080600080600080600060e0888a031215613b5157600080fd5b873567ffffffffffffffff811115613b6857600080fd5b613b748a828b01613a72565b975050602088013567ffffffffffffffff811115613b9157600080fd5b613b9d8a828b01613a72565b9650506040880135613bae81613992565b94506060880135935060808801359250613bca60a089016139b4565b915060c088013567ffffffffffffffff811115613be657600080fd5b613bf28a828b01613a72565b91505092959891949750929550565b60008060408385031215613c1457600080fd5b823591506020830135613c2681613992565b809150509250929050565b600080600060608486031215613c4657600080fd5b8335613c5181613992565b9250602084013591506040840135613c6881613992565b809150509250925092565b600060208284031215613c8557600080fd5b5035919050565b60008060408385031215613c9f57600080fd5b50508035926020909101359150565b60008060408385031215613cc157600080fd5b8235613ccc81613992565b91506020830135613c2681613992565b8015158114612ad257600080fd5b60008060408385031215613cfd57600080fd5b8235613d0881613992565b91506020830135613c2681613cdc565b60008060408385031215613d2b57600080fd5b8235613d3681613992565b946020939093013593505050565b600080600080600060a08688031215613d5c57600080fd5b8535613d6781613992565b94506020860135613d7781613992565b94979496505050506040830135926060810135926080909101359150565b600060208284031215613da757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561218857612188613ddd565b808202811582820484141761218857612188613ddd565b600082613e6c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215613e8357600080fd5b815161175781613992565b8082018082111561218857612188613ddd565b600060208284031215613eb357600080fd5b815161175781613cdc565b600060208284031215613ed057600080fd5b815171ffffffffffffffffffffffffffffffffffff8116811461175757600080fdfea2646970667358221220f743c40b93c9dea52a4935274ce3b2d45eee33a3c2c46d248a91c3413f7b490564736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.