More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 4,419 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim Batch | 59127301 | 19 mins ago | IN | 0 AVAX | 0.0004845 | ||||
Claim Batch | 59126218 | 53 mins ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59124257 | 1 hr ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59122372 | 2 hrs ago | IN | 0 AVAX | 0.00028148 | ||||
Claim Batch | 59120560 | 3 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59118782 | 4 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59117011 | 5 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59115234 | 6 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59113477 | 7 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59111718 | 8 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59109970 | 9 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59108191 | 10 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59106243 | 11 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59104336 | 12 hrs ago | IN | 0 AVAX | 0.00029675 | ||||
Claim Batch | 59102532 | 13 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59100740 | 14 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59098972 | 15 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59097149 | 16 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59095976 | 17 hrs ago | IN | 0 AVAX | 0.00109595 | ||||
Claim Batch | 59095334 | 17 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59093459 | 18 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59091671 | 19 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59089871 | 20 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59087996 | 21 hrs ago | IN | 0 AVAX | 0.00027965 | ||||
Claim Batch | 59086127 | 22 hrs ago | IN | 0 AVAX | 0.00027965 |
Loading...
Loading
Contract Name:
MoeTreasury
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion, Audited
Contract Source Code (Solidity Standard Json-Input format)Audit Report
// SPDX-License-Identifier: GPL-3.0 // solhint-disable not-rely-on-time // solhint-disable reason-string pragma solidity 0.8.20; import {APower} from "./APower.sol"; import {XPower} from "./XPower.sol"; import {XPowerPpt} from "./XPowerPpt.sol"; import {Array} from "./libs/Array.sol"; import {Constants} from "./libs/Constants.sol"; import {Integrator} from "./libs/Integrator.sol"; import {Polynomial, Polynomials} from "./libs/Polynomials.sol"; import {Power} from "./libs/Power.sol"; import {Rpp} from "./libs/Rpp.sol"; import {MoeTreasurySupervised} from "./base/Supervised.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; /** * Treasury to mint (SoV) tokens for staked XPowerNft(s). */ contract MoeTreasury is MoeTreasurySupervised, Ownable { using Integrator for Integrator.Item[]; using Polynomials for Polynomial; /** (burnable) proof-of-work tokens */ XPower private _moe; /** (burnable) *aged* XPower tokens */ APower private _sov; /** staked proof-of-work NFTs */ XPowerPpt private _ppt; /** map of rewards claimed: account => nft-id => amount */ mapping(address => mapping(uint256 => uint256)) private _claimed; /** map of rewards minted: account => nft-id => amount */ mapping(address => mapping(uint256 => uint256)) private _minted; /** @param moeLink address of contract for XPower tokens */ /** @param sovLink address of contract for APower tokens */ /** @param pptLink address of contract for staked NFTs */ constructor(address moeLink, address sovLink, address pptLink) { _moe = XPower(moeLink); _sov = APower(sovLink); _ppt = XPowerPpt(pptLink); transferOwnership(pptLink); _ppt.init(address(this)); } /** refresh claimed (by rescaling) */ function refreshClaimed( address account, uint256 nftId, uint256 balanceOld, uint256 balanceNew ) public onlyOwner { _claimed[account][nftId] = Math.mulDiv( _claimed[account][nftId], balanceNew, balanceOld ); } /** @return minted amount */ function minted( address account, uint256 nftId ) public view returns (uint256) { return _minted[account][nftId]; } /** @return minted amounts */ function mintedBatch( address account, uint256[] memory nftIds ) public view returns (uint256[] memory) { uint256[] memory mintedRewards = new uint256[](nftIds.length); for (uint256 i = 0; i < nftIds.length; i++) { mintedRewards[i] = minted(account, nftIds[i]); } return mintedRewards; } /** @return mintable amount */ function mintable( address account, uint256 nftId ) public view returns (uint256) { return _sov.mintable(claimable(account, nftId)); } /** @return mintable amounts */ function mintableBatch( address account, uint256[] memory nftIds ) public view returns (uint256[] memory) { return _sov.mintableBatch(claimableBatch(account, nftIds)); } /** emitted on claiming NFT reward */ event Claim(address account, uint256 nftId, uint256 amount); /** claim APower tokens */ function claim(address account, uint256 nftId) external { uint256 amount = claimable(account, nftId); require(amount > 0, "invalid claimable"); _claimed[account][nftId] += amount; _minted[account][nftId] += _sov.mintable(amount); _moe.increaseAllowance(address(_sov), _sov.wrappable(amount)); _sov.mint(account, amount); emit Claim(account, nftId, amount); } /** emitted on claiming NFT rewards */ event ClaimBatch(address account, uint256[] nftIds, uint256[] amounts); /** claim APower tokens */ function claimBatch(address account, uint256[] memory nftIds) external { require(Array.unique(nftIds), "unsorted or duplicate ids"); uint256[] memory amounts = claimableBatch(account, nftIds); for (uint256 i = 0; i < nftIds.length; i++) { require(amounts[i] > 0, "invalid claimables"); } for (uint256 i = 0; i < nftIds.length; i++) { _claimed[account][nftIds[i]] += amounts[i]; _minted[account][nftIds[i]] += _sov.mintable(amounts[i]); _moe.increaseAllowance(address(_sov), _sov.wrappable(amounts[i])); _sov.mint(account, amounts[i]); } emit ClaimBatch(account, nftIds, amounts); } /** @return claimed amount */ function claimed( address account, uint256 nftId ) public view returns (uint256) { return _claimed[account][nftId]; } /** @return claimed amounts */ function claimedBatch( address account, uint256[] memory nftIds ) public view returns (uint256[] memory) { uint256[] memory claimedRewards = new uint256[](nftIds.length); for (uint256 i = 0; i < nftIds.length; i++) { claimedRewards[i] = claimed(account, nftIds[i]); } return claimedRewards; } /** @return claimable amount */ function claimable( address account, uint256 nftId ) public view returns (uint256) { uint256 claimedReward = claimed(account, nftId); uint256 generalReward = rewardOf(account, nftId); if (generalReward > claimedReward) { return generalReward - claimedReward; } return 0; } /** @return claimable amounts */ function claimableBatch( address account, uint256[] memory nftIds ) public view returns (uint256[] memory) { uint256[] memory claimedRewards = claimedBatch(account, nftIds); uint256[] memory generalRewards = rewardOfBatch(account, nftIds); uint256[] memory pendingRewards = new uint256[](nftIds.length); for (uint256 i = 0; i < nftIds.length; i++) { if (generalRewards[i] > claimedRewards[i]) { pendingRewards[i] = generalRewards[i] - claimedRewards[i]; } } return pendingRewards; } /** @return reward amount */ function rewardOf( address account, uint256 nftId ) public view returns (uint256) { uint256 age = _ppt.ageOf(account, nftId); uint256 rate = aprOf(nftId) + apbOf(nftId); uint256 denomination = _ppt.denominationOf(_ppt.levelOf(nftId)); return Math.mulDiv( rate * age * 10 ** _moe.decimals(), denomination, 1e6 * Constants.CENTURY ); } /** @return reward amounts */ function rewardOfBatch( address account, uint256[] memory nftIds ) public view returns (uint256[] memory) { uint256[] memory rewards = new uint256[](nftIds.length); for (uint256 i = 0; i < nftIds.length; i++) { rewards[i] = rewardOf(account, nftIds[i]); } return rewards; } /** integrator for APRs: nft-id => [(stamp, value)] */ mapping(uint256 => Integrator.Item[]) public aprs; /** parametrization of APR: nft-id => coefficients */ mapping(uint256 => uint256[]) private _apr; /** @return length of APRs */ function aprsLength(uint256 nftId) external view returns (uint256) { uint256 id = _aprId(nftId); return aprs[id].length; } /** @return duration weighted mean of APRs */ function aprOf(uint256 nftId) public view returns (uint256) { uint256 rate = aprTargetOf(nftId); uint256 id = _aprId(nftId); if (aprs[id].length > 0) { return aprs[id].meanOf(block.timestamp, rate); } return rate; } /** @return target for annualized percentage rate */ function aprTargetOf(uint256 nftId) public view returns (uint256) { return aprTargetOf(nftId, getAPR(nftId)); } /** @return target for annualized percentage rate */ function aprTargetOf( uint256 nftId, uint256[] memory array ) private view returns (uint256) { uint256 rate = Polynomial(array).eval3(_ppt.levelOf(nftId)); uint256 base = Power.raise(1e6, array[array.length - 1]); return Math.mulDiv(rate, 1e6, base); } /** annual percentage rate: 3.375000[%] (per nft.level) */ uint256 public constant APR_MUL = 3_375_000; uint256 private constant APR_DIV = 3; uint256 private constant APR_EXP = 256; /** @return APR parameters */ function getAPR(uint256 nftId) public view returns (uint256[] memory) { uint256 id = _aprId(nftId); if (_apr[id].length > 0) { return _apr[id]; } uint256[] memory array = new uint256[](4); array[1] = APR_DIV; array[2] = APR_MUL; array[3] = APR_EXP; return array; } /** set APR parameters */ function setAPR( uint256 nftId, uint256[] memory array ) public onlyRole(APR_ROLE) { Rpp.checkArray(array); // fixed nft-id as anchor uint256 id = _aprId(nftId); // check APR reparametrization of value (rate) uint256 nextRate = aprTargetOf(id, array); uint256 currRate = aprTargetOf(id); Rpp.checkValue(nextRate, currRate, 1e6); // check APR reparametrization of value (mean) uint256 nextMean = _aprMeanOf(array); uint256 currMean = _aprMeanOf(_apr[id]); Rpp.checkValue(nextMean, currMean, APR_MUL); // check APR reparametrization of stamp Integrator.Item memory last = aprs[id].lastOf("S"); Rpp.checkStamp(block.timestamp, last.stamp); // append (stamp, apr-of[nft-id]) to integrator aprs[id].append(block.timestamp, currRate, "S"); // all requirements satisfied: use array _apr[id] = array; emit SetAPR(nftId, array); } event SetAPR(uint256 nftId, uint256[] array); /** @return mean of annualized percentage rate */ function _aprMeanOf(uint256[] memory array) private pure returns (uint256) { return array.length > 2 ? array[2] : APR_MUL; } /** batch-set APR parameters */ function setAPRBatch( uint256[] memory nftIds, uint256[] memory array ) external onlyRole(APR_ROLE) { for (uint256 i = 0; i < nftIds.length; i++) { setAPR(nftIds[i], array); } } /** emitted on refreshing APR parameters */ event RefreshRates(bool allLevels); /** refresh APR parameters */ function refreshRates(bool allLevels) external { int256[34] memory shares = _ppt.shares(); (uint256 bins, uint256 sum, uint256 max) = _moments(shares); uint256 maxLength = allLevels ? shares.length : max; for (uint256 i = 0; i < maxLength; i++) { uint256 id = _ppt.idBy(2021, 3 * i); Integrator.Item memory item = aprs[id].lastOf(); uint256 target = aprTargetOf(id); if (item.stamp == 0) { aprs[id].append(block.timestamp - Constants.MONTH, target); aprs[id].append(block.timestamp, target); // laggy init } else if (item.value != target) { aprs[id].append(block.timestamp, target); } if (shares[i] > 0) { if (_apr[id].length == 0) { _apr[id] = new uint256[](4); // [add, div, mul, exp] _apr[id][0] = _scalar(APR_MUL, sum, bins, shares[i]); _apr[id][1] = type(uint256).max; // div-by-infinity _apr[id][2] = APR_MUL; _apr[id][3] = APR_EXP; } else { _apr[id][0] = _scalar(_apr[id][2], sum, bins, shares[i]); _apr[id][1] = type(uint256).max; // div-by-infinity } } else if (_apr[id].length > 0) { _apr[id][0] = 0; // clear _apr[id][1] = APR_DIV; } } emit RefreshRates(allLevels); } /** @return refreshable flag */ function refreshable() external view returns (bool) { int256[34] memory shares = _ppt.shares(); (uint256 bins, uint256 sum, ) = _moments(shares); for (uint256 i = 0; i < shares.length; i++) { uint256 id = _ppt.idBy(2021, 3 * i); Integrator.Item memory item = aprs[id].lastOf(); if (item.stamp == 0) { return true; } if (shares[i] > 0) { if (_apr[id].length == 0) { return true; } if (_apr[id][0] != _scalar(_apr[id][2], sum, bins, shares[i])) { return true; } if (_apr[id][1] != type(uint256).max) { return true; } } else if (_apr[id].length > 0) { if (_apr[id][0] != 0) { return true; } if (_apr[id][1] != APR_DIV) { return true; } } } return false; } /** @return moments of (bins, sum, max) */ function _moments( int256[34] memory shares ) private pure returns (uint256, uint256, uint256) { (uint256 bins, uint256 sum, uint256 max) = (0, 0, 0); for (uint256 i = 0; i < shares.length; i++) { if (shares[i] > 0) { sum += uint256(shares[i]); max = i + 1; bins++; } } return (bins, sum, max); } /** @return additive scalar */ function _scalar( uint256 mul, uint256 sum, uint256 bins, int256 share ) private pure returns (uint256) { assert(bins > 0 && share > 0); // no div-by-zero return Math.mulDiv(mul, sum, bins * uint256(share)); } /** @return apr-id */ function _aprId(uint256 nftId) private view returns (uint256) { return _ppt.idBy(2021, _ppt.levelOf(nftId)); } /** integrator for APBs: nft-id => [(stamp, value)] */ mapping(uint256 => Integrator.Item[]) public apbs; /** parametrization of APB: nft-id => coefficients */ mapping(uint256 => uint256[]) private _apb; /** @return length fo APBs (for nft-id) */ function apbsLength(uint256 nftId) external view returns (uint256) { uint256 id = _apbId(nftId); return apbs[id].length; } /** @return duration weighted mean of APBs (per nft.level) */ function apbOf(uint256 nftId) public view returns (uint256) { uint256 rate = apbTargetOf(nftId); uint256 id = _apbId(nftId); if (apbs[id].length > 0) { return apbs[id].meanOf(block.timestamp, rate); } return rate; } /** @return target for annualized percentage rate bonus */ function apbTargetOf(uint256 nftId) public view returns (uint256) { return apbTargetOf(nftId, getAPB(nftId)); } /** @return target for annualized percentage rate bonus */ function apbTargetOf( uint256 nftId, uint256[] memory array ) private view returns (uint256) { uint256 nowYear = _ppt.year(); uint256 nftYear = _ppt.yearOf(nftId); if (nowYear > nftYear || nowYear == nftYear) { uint256 rate = Polynomial(array).eval3(nowYear - nftYear); uint256 base = Power.raise(1e6, array[array.length - 1]); return Math.mulDiv(rate, 1e6, base); } return 0; } /** annual percentage bonus: 1.0000[‱] (per nft.year) */ uint256 private constant APB_MUL = 10_000; uint256 private constant APB_DIV = 1; uint256 private constant APB_EXP = 256; /** @return APB parameters */ function getAPB(uint256 nftId) public view returns (uint256[] memory) { uint256 id = _apbId(nftId); if (_apb[id].length > 0) { return _apb[id]; } uint256[] memory array = new uint256[](4); array[1] = APB_DIV; array[2] = APB_MUL; array[3] = APB_EXP; return array; } /** set APB parameters */ function setAPB( uint256 nftId, uint256[] memory array ) public onlyRole(APB_ROLE) { Rpp.checkArray(array); // fixed nft-id as anchor uint256 id = _apbId(nftId); // check APB reparametrization of value uint256 nextRate = apbTargetOf(id, array); uint256 currRate = apbTargetOf(id); Rpp.checkValue(nextRate, currRate, 1e6); // check APB reparametrization of stamp Integrator.Item memory last = apbs[id].lastOf(); Rpp.checkStamp(block.timestamp, last.stamp); // append (stamp, apb-of[nft-id]) to integrator apbs[id].append(block.timestamp, currRate); // all requirements satisfied: use array _apb[id] = array; emit SetAPB(nftId, array); } event SetAPB(uint256 nftId, uint256[] array); /** batch-set APB parameters */ function setAPBBatch( uint256[] memory nftIds, uint256[] memory array ) external onlyRole(APB_ROLE) { for (uint256 i = 0; i < nftIds.length; i++) { setAPB(nftIds[i], array); } } /** @return apb-id */ function _apbId(uint256) private view returns (uint256) { return _ppt.idBy(2021, 3); } }
// SPDX-License-Identifier: GPL-3.0 // solhint-disable no-empty-blocks pragma solidity 0.8.20; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {XPower} from "./XPower.sol"; import {SovMigratable} from "./base/Migratable.sol"; /** * Class for the APOW tokens, where only the owner of the contract i.e. the * MoeTreasury is entitled to mint them -- with a supply rate of on average * one token per minute. */ contract APower is ERC20, ERC20Burnable, SovMigratable, Ownable { /** timestamp of contract deployment (absolute) */ uint256 private _timestamp = block.timestamp; /** timestamp of last mean (relative) */ uint256 private _time; /** last mean of claims */ uint256 private _mean; /** (burnable) XPower */ XPower private _moe; /** @param moeLink address of XPower tokens */ /** @param sovBase address of old contract */ /** @param deadlineIn seconds to end-of-migration */ constructor( address moeLink, address[] memory sovBase, uint256 deadlineIn ) // ERC20 constructor: name, symbol ERC20("APower", "APOW") // Migratable: XPower, old APower & rel. deadline [seconds] SovMigratable(moeLink, sovBase, deadlineIn) { _moe = XPower(moeLink); } /** @return number of decimals of representation */ function decimals() public view virtual override returns (uint8) { return _moe.decimals(); } /** mint on average one APower/min (after wrapping XPower) */ function mint(address to, uint256 claim) external onlyOwner { assert(_moe.transferFrom(owner(), address(this), wrappable(claim))); (uint256 a, uint256 m, uint256 t) = _mintable(claim, _mean, _time); (_mean, _time) = (m, t); _mint(to, a); } /** @return wrappable XPower targeting a ratio of 1:1 (at most) */ function wrappable(uint256 claim) public view returns (uint256) { uint256 treasury = _moe.balanceOf(owner()); return Math.min(claim, treasury); } /** @return mintable APower w.r.t. long-term mean of claims */ function mintable(uint256 claim) external view returns (uint256) { (uint256 a, , ) = _mintable(claim, _mean, _time); return a; } /** @return mintable APower w.r.t. long-term mean of claims */ function mintableBatch( uint256[] memory claims ) external view returns (uint256[] memory) { (uint256 mean, uint256 time) = (_mean, _time); uint256[] memory mintables = new uint256[](claims.length); for (uint256 i = 0; i < claims.length; i++) { (uint256 a, uint256 m, uint256 t) = _mintable( claims[i], mean, time ); (mean, time) = (m, t); mintables[i] = a; } return mintables; } function _mintable( uint256 claim, uint256 mean, uint256 time ) private view returns (uint256, uint256, uint256) { if (claim > 0) { uint256 t = block.timestamp - _timestamp; uint256 m = Math.mulDiv(mean, time, t) + claim / t; uint256 a = Math.mulDiv(claim, 10 ** decimals() / 60, m); return (a, m, t); } return (0, mean, time); } /** burn amount of tokens from caller (and then unwrap XPower) */ function burn(uint256 amount) public override { super.burn(amount); _moe.transfer(msg.sender, unwrappable(amount)); } /** * burn amount of tokens from account, deducting from the caller's * allowance (and then unwrap XPower) */ function burnFrom(address account, uint256 amount) public override { super.burnFrom(account, amount); _moe.transfer(account, unwrappable(amount)); } /** @return unwrappable XPower proportional to burned APower amount */ function unwrappable(uint256 amount) public view returns (uint256) { uint256 balance = _moe.balanceOf(address(this)); uint256 supply = amount + totalSupply(); if (supply > 0) { return Math.mulDiv(balance, amount, supply); } return 0; } /** @return APOW to XPOW conversion: 1e18 ~ 100% */ function metric() external view returns (uint256) { uint256 balance = _moe.balanceOf(address(this)); uint256 supply = totalSupply(); if (supply > 0) { return Math.mulDiv(10 ** decimals(), balance, supply); } return 0; } }
// SPDX-License-Identifier: GPL-3.0 // solhint-disable not-rely-on-time // solhint-disable no-empty-blocks pragma solidity 0.8.20; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import {Constants} from "./libs/Constants.sol"; import {FeeTracker} from "./base/FeeTracker.sol"; import {MoeMigratable} from "./base/Migratable.sol"; /** * Class for the XPOW proof-of-work tokens: It verifies, that the nonce and the * block-hash result in a positive amount. After a successful verification, the * corresponding amount is minted for the beneficiary (plus the MoE treasury). */ contract XPower is ERC20, ERC20Burnable, FeeTracker, MoeMigratable, Ownable { /** set of nonce-hashes already minted for */ mapping(bytes32 => bool) private _hashes; /** map from block-hashes to timestamps */ mapping(bytes32 => uint256) private _timestamps; /** map from intervals to block-hashes */ mapping(uint256 => bytes32) private _blockHashes; /** @param moeBase addresses of old contracts */ /** @param deadlineIn seconds to end-of-migration */ constructor( address[] memory moeBase, uint256 deadlineIn ) // ERC20 constructor: name, symbol ERC20("XPower", "XPOW") // MoeMigratable: old contract, rel. deadline [seconds] MoeMigratable(moeBase, deadlineIn) {} /** @return number of decimals of representation */ function decimals() public view virtual override returns (uint8) { return Constants.DECIMALS; } /** emitted on caching most recent block-hash */ event Init(bytes32 blockHash, uint256 timestamp); /** cache most recent block-hash */ function init() external { uint256 interval = currentInterval(); if (uint256(_blockHashes[interval]) == 0) { bytes32 blockHash = blockhash(block.number - 1); uint256 timestamp = block.timestamp; _blockHashes[interval] = blockHash; _timestamps[blockHash] = timestamp; emit Init(blockHash, timestamp); } else { bytes32 blockHash = _blockHashes[interval]; uint256 timestamp = _timestamps[blockHash]; emit Init(blockHash, timestamp); } } /** mint tokens for to-beneficiary, block-hash & data (incl. nonce) */ function mint( address to, bytes32 blockHash, bytes calldata data ) external tracked { // check block-hash to be in current interval require(_recent(blockHash), "expired block-hash"); // calculate nonce-hash & pair-index for to, block-hash & data (bytes32 nonceHash, bytes32 pairIndex) = _hashOf(to, blockHash, data); require(_unique(pairIndex), "duplicate nonce-hash"); // calculate number of zeros of nonce-hash uint256 zeros = _zerosOf(nonceHash); require(zeros > 0, "empty nonce-hash"); // calculate amount of tokens of zeros uint256 amount = _amountOf(zeros); // ensure unique (nonce-hash, block-hash) _hashes[pairIndex] = true; // mint for contract owner _mint(owner(), amount >> 3); // mint for beneficiary _mint(to, amount); } /** @return block-hash */ function blockHashOf(uint256 interval) external view returns (bytes32) { return _blockHashes[interval]; } /** @return current interval's timestamp */ function currentInterval() public view returns (uint256) { return block.timestamp / (1 hours); } /** check whether block-hash has recently been cached */ function _recent(bytes32 blockHash) private view returns (bool) { return _timestamps[blockHash] >= currentInterval() * (1 hours); } /** @return hash of contract, to-beneficiary, block-hash & data (incl. nonce) */ function _hashOf( address to, bytes32 blockHash, bytes calldata data ) internal view returns (bytes32, bytes32) { bytes32 nonceHash = keccak256( bytes.concat( bytes20(uint160(address(this)) ^ uint160(to)), blockHash, data ) ); return (nonceHash, nonceHash ^ blockHash); } /** check whether (nonce-hash, block-hash) pair is unique */ function _unique(bytes32 pairIndex) private view returns (bool) { return !_hashes[pairIndex]; } /** @return number of leading-zeros */ function _zerosOf(bytes32 nonceHash) internal pure returns (uint8) { if (nonceHash > 0) { return uint8(63 - (Math.log2(uint256(nonceHash)) >> 2)); } return 64; } /** @return amount (for level) */ function _amountOf(uint256 level) internal view returns (uint256) { return (2 ** level - 1) * 10 ** decimals(); } /** @return true if this contract implements the interface defined by interface-id */ function supportsInterface( bytes4 interfaceId ) public view virtual override(MoeMigratable) returns (bool) { return super.supportsInterface(interfaceId); } /** @return fee-estimate plus averages over gas and gas-price */ function fees() external view returns (uint256[] memory) { return _fees(FEE_ADD, FEE_MUL, FEE_DIV); } /** fee-tracker estimate: 21_000+700+1360+1088+68*8 */ uint256 private constant FEE_ADD = 24_692_000_000_000; uint256 private constant FEE_MUL = 1_6168707436776024; uint256 private constant FEE_DIV = 1_0000000000000000; }
// SPDX-License-Identifier: GPL-3.0 // solhint-disable not-rely-on-time // solhint-disable no-empty-blocks // solhint-disable reason-string pragma solidity 0.8.20; import {NftBase} from "./base/NftBase.sol"; import {MoeTreasury} from "./MoeTreasury.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; /** * Abstract base class for staked XPowerNft(s): Only the contract owner * i.e. the NftTreasury is allowed to mint and burn XPowerPpt tokens. */ contract XPowerPpt is NftBase { /** map of age: account => nft-id => accumulator [seconds] */ mapping(address => mapping(uint256 => uint256)) private _age; /** map of levels: nft-level => accumulator */ int256[34] private _shares; /** @param pptUri meta-data URI */ /** @param pptBase addresses of old contracts */ /** @param deadlineIn seconds to end-of-migration */ constructor( string memory pptUri, address[] memory pptBase, uint256 deadlineIn ) NftBase("XPower PPTs", "XPOWPPT", pptUri, pptBase, deadlineIn) {} /** MOE treasury */ MoeTreasury private _mty; /** post-constructor init (once) */ function init(address mty) external { require(address(_mty) == address(0), "already initialized"); _mty = MoeTreasury(mty); emit Init(mty); } event Init(address mty); /** transfer tokens (and reset age) */ function safeTransferFrom( address account, address to, uint256 nftId, uint256 amount, bytes memory data ) public override { _pushBurn(account, nftId, amount); _pushMint(to, nftId, amount); super.safeTransferFrom(account, to, nftId, amount, data); } /** batch transfer tokens (and reset age) */ function safeBatchTransferFrom( address account, address to, uint256[] memory nftIds, uint256[] memory amounts, bytes memory data ) public override { _pushBurnBatch(account, nftIds, amounts); _pushMintBatch(to, nftIds, amounts); super.safeBatchTransferFrom(account, to, nftIds, amounts, data); } /** mint particular amount of staked NFTs */ function mint( address account, uint256 nftId, uint256 amount ) external onlyOwner { _memoMint(account, nftId, amount); _mint(account, nftId, amount, ""); } /** mint particular amounts of staked NFTs */ function mintBatch( address account, uint256[] memory nftIds, uint256[] memory amounts ) external onlyOwner { require(nftIds.length > 0, "empty ids"); require(amounts.length > 0, "empty amounts"); _memoMintBatch(account, nftIds, amounts); _mintBatch(account, nftIds, amounts, ""); } /** burn particular amount of staked NFTs */ function burn( address account, uint256 nftId, uint256 amount ) public override onlyOwner { _memoBurn(account, nftId, amount); _burn(account, nftId, amount); } /** burn particular amounts of staked NFTs */ function burnBatch( address account, uint256[] memory nftIds, uint256[] memory amounts ) public override onlyOwner { require(nftIds.length > 0, "empty ids"); require(amounts.length > 0, "empty amounts"); _memoBurnBatch(account, nftIds, amounts); _burnBatch(account, nftIds, amounts); } /** @return age seconds over all stakes */ function ageOf( address account, uint256 nftId ) external view returns (uint256) { uint256 age = _age[account][nftId]; if (age > 0) { uint256 balance = balanceOf(account, nftId); return balance * block.timestamp - age; } return 0; } /** @return share accumulators */ function shares() external view returns (int256[34] memory) { return _shares; } /** remember mint action */ function _pushMint(address account, uint256 nftId, uint256 amount) private { _age[account][nftId] += amount * block.timestamp; } /** remember mint actions */ function _pushMintBatch( address account, uint256[] memory nftIds, uint256[] memory amounts ) private { require( nftIds.length == amounts.length, "ERC1155: ids and amounts length mismatch" ); for (uint256 i = 0; i < nftIds.length; i++) { _pushMint(account, nftIds[i], amounts[i]); } } /** remember burn action (and refresh claimed) */ function _pushBurn(address account, uint256 nftId, uint256 amount) private { require( amount > 0 && balanceOf(account, nftId) >= amount, "ERC1155: invalid amount or insufficient balance for transfer" ); _mty.refreshClaimed( account, nftId, balanceOf(account, nftId), balanceOf(account, nftId) - amount ); _age[account][nftId] -= Math.mulDiv( _age[account][nftId], amount, balanceOf(account, nftId) ); } /** remember burn actions */ function _pushBurnBatch( address account, uint256[] memory nftIds, uint256[] memory amounts ) private { require( nftIds.length == amounts.length, "ERC1155: ids and amounts length mismatch" ); for (uint256 i = 0; i < nftIds.length; i++) { _pushBurn(account, nftIds[i], amounts[i]); } } /** remember mint action (incl. accumulators) */ function _memoMint(address to, uint256 nftId, uint256 amount) private { _pushMint(to, nftId, amount); uint256 level = levelOf(nftId); _shares[level / 3] += int256(amount * 10 ** level); } /** remember mint actions (incl. accumulators) */ function _memoMintBatch( address account, uint256[] memory nftIds, uint256[] memory amounts ) private { require( nftIds.length == amounts.length, "ERC1155: ids and amounts length mismatch" ); for (uint256 i = 0; i < nftIds.length; i++) { _memoMint(account, nftIds[i], amounts[i]); } } /** remember burn action (incl. accumulators) */ function _memoBurn(address account, uint256 nftId, uint256 amount) private { _pushBurn(account, nftId, amount); uint256 level = levelOf(nftId); _shares[level / 3] -= int256(amount * 10 ** level); } /** remember burn actions (incl. accumulators) */ function _memoBurnBatch( address account, uint256[] memory nftIds, uint256[] memory amounts ) private { require( nftIds.length == amounts.length, "ERC1155: ids and amounts length mismatch" ); for (uint256 i = 0; i < nftIds.length; i++) { _memoBurn(account, nftIds[i], amounts[i]); } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; library Array { /** @return true if array is sorted */ function sorted(uint256[] memory array) internal pure returns (bool) { for (uint256 i = 1; i < array.length; i++) { if (array[i - 1] <= array[i]) { continue; } return false; } return true; } /** @return true if array is sorted and free of duplicates */ function unique(uint256[] memory array) internal pure returns (bool) { for (uint256 i = 1; i < array.length; i++) { if (array[i - 1] < array[i]) { continue; } return false; } return true; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; library Constants { /** a century in [seconds] (approximation) */ uint256 internal constant CENTURY = 365_25 days; /** a year in [seconds] (approximation) */ uint256 internal constant YEAR = CENTURY / 100; /** a month [seconds] (approximation) */ uint256 internal constant MONTH = YEAR / 12; /** number of decimals of representation */ uint8 internal constant DECIMALS = 18; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; /** * Allows to integrate over an array of (stamp, value) tuples, and to take * the duration i.e. Δ-stamp weighted arithmetic mean of those values. */ library Integrator { struct Item { /** stamp of value */ uint256 stamp; /** value of interest */ uint256 value; /** cumulative sum over Δ-stamps × values */ uint256 area; /** previous index w.r.t. meta */ uint256 prev; } /** @return head item */ function headOf(Item[] storage items) internal view returns (Item memory) { return items.length > 0 ? items[0] : Item(0, 0, 0, 0); } /** @return last item */ function lastOf(Item[] storage items) internal view returns (Item memory) { return lastOf(items, ""); } /** @return last item (for meta) */ function lastOf( Item[] storage items, bytes1 meta ) internal view returns (Item memory) { if (items.length > 0) { Item memory last = items[items.length - 1]; if (meta != "") return items[last.prev]; return last; } return Item(0, 0, 0, 0); } /** append (stamp, value) to items (with stamp >= last?.stamp) */ function append( Item[] storage items, uint256 stamp, uint256 value ) internal { return append(items, stamp, value, ""); } /** append (stamp, value, meta) to items (with stamp >= last?.stamp) */ function append( Item[] storage items, uint256 stamp, uint256 value, bytes1 meta ) internal { items.push(_nextOf(items, stamp, value, meta)); } /** @return Δ-stamp weighted arithmetic mean of values (incl. next stamp & value) */ function meanOf( Item[] storage items, uint256 stamp, uint256 value ) internal view returns (uint256) { uint256 area = areaOf(items, stamp, value); Item memory head = headOf(items); if (stamp > head.stamp) { return area / (stamp - head.stamp); } return head.value; } /** @return area of Δ-stamps × values (incl. next stamp & value) */ function areaOf( Item[] storage items, uint256 stamp, uint256 value ) internal view returns (uint256) { if (items.length > 0) { Item memory last = items[items.length - 1]; require(stamp >= last.stamp, "invalid stamp"); uint256 area = value * (stamp - last.stamp); return last.area + area; } return 0; } /** @return next item (for stamp, value & meta) */ function _nextOf( Item[] storage items, uint256 stamp, uint256 value, bytes1 meta ) private view returns (Item memory) { if (items.length > 0) { Item memory last = items[items.length - 1]; require(stamp >= last.stamp, "invalid stamp"); uint256 area = value * (stamp - last.stamp); if (meta != "") last.prev = items.length; return Item(stamp, value, last.area + area, last.prev); } return Item(stamp, value, 0, 0); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {Power} from "./Power.sol"; struct Polynomial { uint256[] array; } library Polynomials { /** * @return value evaluated with {(value+[5-4])*[3/2]+[1-0]}^{[6]/256} * * Evaluates a `value` using a linear function -- defined by * the provided polynomial coefficients. */ function eval6(Polynomial memory p, uint256 value) internal pure returns (uint256) { uint256 delta = value + p.array[5] - p.array[4]; uint256 ratio = Math.mulDiv(delta, p.array[3], p.array[2]); uint256 shift = ratio + p.array[1] - p.array[0]; return Power.raise(shift, p.array[6]); } /** * @return value evaluated with {(value+[4-3])*[2/1]+[0]}^{[5]/256} * * Evaluates a `value` using a linear function -- defined by * the provided polynomial coefficients. */ function eval5(Polynomial memory p, uint256 value) internal pure returns (uint256) { uint256 delta = value + p.array[4] - p.array[3]; uint256 ratio = Math.mulDiv(delta, p.array[2], p.array[1]); return Power.raise(ratio + p.array[0], p.array[5]); } /** * @return value evaluated with {(value)*[3/2]+[1-0]}^{[4]/256} * * Evaluates a `value` using a linear function -- defined by * the provided polynomial coefficients. */ function eval4(Polynomial memory p, uint256 value) internal pure returns (uint256) { uint256 ratio = Math.mulDiv(value, p.array[3], p.array[2]); uint256 shift = ratio + p.array[1] - p.array[0]; return Power.raise(shift, p.array[4]); } /** * @return value evaluated with {(value)*[2/1]+[0]}^{[3]/256} * * Evaluates a `value` using a linear function -- defined by * the provided polynomial coefficients. */ function eval3(Polynomial memory p, uint256 value) internal pure returns (uint256) { uint256 ratio = Math.mulDiv(value, p.array[2], p.array[1]); return Power.raise(ratio + p.array[0], p.array[3]); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; import {UD60x18, ud, pow} from "@prb/math/src/UD60x18.sol"; library Power { /** * @return n raised to the power of (exp/[root=256]) */ function raise(uint256 n, uint256 exp) internal pure returns (uint256) { require(exp >= 128, "invalid exponent: too small"); require(exp <= 512, "invalid exponent: too large"); UD60x18 p = pow(ud(n * 1e18), ud(exp * 3906250e9)); return p.intoUint256() / 1e18; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; import {Constants} from "../libs/Constants.sol"; /** * @title Rug pull protection */ library Rpp { /** validate params: w.r.t. Polynomial.eval3 */ function checkArray(uint256[] memory array) internal pure { require(array.length == 4, "invalid array.length"); // eliminate possibility of division-by-zero require(array[1] > 0, "invalid array[1] == 0"); // eliminate possibility of all-zero values require(array[2] > 0, "invalid array[2] == 0"); } /** validate change: 0.5 <= next / last <= 2.0 or next <= unit */ function checkValue(uint256 next, uint256 last, uint256 unit) internal pure { if (next < last) { require(last <= 2 * next, "invalid change: too small"); } if (next > last && last > 0) { require(next <= 2 * last, "invalid change: too large"); } if (next > last && last == 0) { require(next <= unit, "invalid change: too large"); } } /** validate change: invocation frequency at most once per month */ function checkStamp(uint256 next, uint256 last) internal pure { if (last > 0) { require(next > Constants.MONTH + last, "invalid change: too frequent"); } } }
// SPDX-License-Identifier: GPL-3.0 // solhint-disable one-contract-per-file pragma solidity 0.8.20; import {AccessControlEnumerable} from "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; abstract contract Supervised is AccessControlEnumerable { constructor() { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); } /** @return true if this contract implements the interface defined by interface-id */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return super.supportsInterface(interfaceId); } } abstract contract MoeTreasurySupervised is Supervised { /** role grants right to change APR parametrization */ bytes32 public constant APR_ROLE = keccak256("APR_ROLE"); bytes32 public constant APR_ADMIN_ROLE = keccak256("APR_ADMIN_ROLE"); /** role grants right to change APB parametrization */ bytes32 public constant APB_ROLE = keccak256("APB_ROLE"); bytes32 public constant APB_ADMIN_ROLE = keccak256("APB_ADMIN_ROLE"); constructor() { _setRoleAdmin(APR_ROLE, APR_ADMIN_ROLE); _grantRole(APR_ADMIN_ROLE, msg.sender); _setRoleAdmin(APB_ROLE, APB_ADMIN_ROLE); _grantRole(APB_ADMIN_ROLE, msg.sender); } } abstract contract MoeMigratableSupervised is Supervised { /** role grants right to seal MOE immigration */ bytes32 public constant MOE_SEAL_ROLE = keccak256("MOE_SEAL_ROLE"); bytes32 public constant MOE_SEAL_ADMIN_ROLE = keccak256("MOE_SEAL_ADMIN_ROLE"); constructor() { _setRoleAdmin(MOE_SEAL_ROLE, MOE_SEAL_ADMIN_ROLE); _grantRole(MOE_SEAL_ADMIN_ROLE, msg.sender); } } abstract contract SovMigratableSupervised is Supervised { /** role grants right to seal SOV immigration */ bytes32 public constant SOV_SEAL_ROLE = keccak256("SOV_SEAL_ROLE"); bytes32 public constant SOV_SEAL_ADMIN_ROLE = keccak256("SOV_SEAL_ADMIN_ROLE"); constructor() { _setRoleAdmin(SOV_SEAL_ROLE, SOV_SEAL_ADMIN_ROLE); _grantRole(SOV_SEAL_ADMIN_ROLE, msg.sender); } } abstract contract NftMigratableSupervised is Supervised { /** role grants right to seal NFT immigration */ bytes32 public constant NFT_SEAL_ROLE = keccak256("NFT_SEAL_ROLE"); bytes32 public constant NFT_SEAL_ADMIN_ROLE = keccak256("NFT_SEAL_ADMIN_ROLE"); /** role grants right to open NFT emigration */ bytes32 public constant NFT_OPEN_ROLE = keccak256("NFT_OPEN_ROLE"); bytes32 public constant NFT_OPEN_ADMIN_ROLE = keccak256("NFT_OPEN_ADMIN_ROLE"); constructor() { _setRoleAdmin(NFT_SEAL_ROLE, NFT_SEAL_ADMIN_ROLE); _grantRole(NFT_SEAL_ADMIN_ROLE, msg.sender); _setRoleAdmin(NFT_OPEN_ROLE, NFT_OPEN_ADMIN_ROLE); _grantRole(NFT_OPEN_ADMIN_ROLE, msg.sender); } } abstract contract NftRoyaltySupervised is Supervised { /** role grants right to set the NFT's default royalty beneficiary */ bytes32 public constant NFT_ROYAL_ROLE = keccak256("NFT_ROYAL_ROLE"); bytes32 public constant NFT_ROYAL_ADMIN_ROLE = keccak256("NFT_ROYAL_ADMIN_ROLE"); constructor() { _setRoleAdmin(NFT_ROYAL_ROLE, NFT_ROYAL_ADMIN_ROLE); _grantRole(NFT_ROYAL_ADMIN_ROLE, msg.sender); } } abstract contract URIMalleableSupervised is Supervised { /** role grants right to change metadata URIs */ bytes32 public constant URI_DATA_ROLE = keccak256("URI_DATA_ROLE"); bytes32 public constant URI_DATA_ADMIN_ROLE = keccak256("URI_DATA_ADMIN_ROLE"); constructor() { _setRoleAdmin(URI_DATA_ROLE, URI_DATA_ADMIN_ROLE); _grantRole(URI_DATA_ADMIN_ROLE, msg.sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // 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^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv 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. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../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. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. 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 { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer(address from, address to, uint256 amount) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol) pragma solidity ^0.8.0; import "../ERC20.sol"; import "../../../utils/Context.sol"; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public virtual { _burn(_msgSender(), amount); } /** * @dev Destroys `amount` tokens from `account`, deducting from the caller's * allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { _spendAllowance(account, _msgSender(), amount); _burn(account, amount); } }
// SPDX-License-Identifier: GPL-3.0 // solhint-disable not-rely-on-time // solhint-disable one-contract-per-file // solhint-disable reason-string pragma solidity 0.8.20; import {ERC20, IERC20, IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import {Supervised, MoeMigratableSupervised, SovMigratableSupervised} from "./Supervised.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; /** * Allows migration of tokens from an old contract upto a certain deadline. * Further, it is possible to close down the migration window earlier than * the specified deadline. */ abstract contract Migratable is ERC20, ERC20Burnable, Supervised { /** burnable ERC20 tokens */ ERC20Burnable[] private _base; /** base address to index map */ mapping(address => uint256) private _index; /** timestamp of immigration deadline */ uint256 private _deadlineBy; /** flag to seal immigration */ bool[] private _sealed; /** number of immigrated tokens */ uint256 private _migrated; /** * @param base addresses of old contracts * @param deadlineIn seconds to end-of-migration */ constructor(address[] memory base, uint256 deadlineIn) { _deadlineBy = block.timestamp + deadlineIn; _base = new ERC20Burnable[](base.length); _sealed = new bool[](base.length); for (uint256 i = 0; i < base.length; i++) { _base[i] = ERC20Burnable(base[i]); _index[base[i]] = i; } } /** * @param base address of old contract * @return index of base address */ function oldIndexOf(address base) external view returns (uint256) { return _index[base]; } /** * migrate amount of ERC20 tokens * * @param amount of ERC20s to migrate * @param index single of base contract */ function migrate( uint256 amount, uint256[] memory index ) external returns (uint256) { return _migrateFrom(msg.sender, amount, index); } /** * migrate amount of ERC20 tokens * * @param account to migrate from * @param amount of ERC20s to migrate * @param index single of base contract */ function migrateFrom( address account, uint256 amount, uint256[] memory index ) external returns (uint256) { require( account == msg.sender || approvedMigrate(account, msg.sender), "caller is not token owner or approved" ); return _migrateFrom(account, amount, index); } /** approve migrate by `operator` */ function approveMigrate(address operator, bool approved) external { require(msg.sender != operator, "approving migrate for self"); _migrateApprovals[msg.sender][operator] = approved; emit ApproveMigrate(msg.sender, operator, approved); } /** @return true if `account` approved migrate by `operator` */ function approvedMigrate( address account, address operator ) public view returns (bool) { return _migrateApprovals[account][operator]; } /** migrate approvals: account => operator */ mapping(address => mapping(address => bool)) private _migrateApprovals; /** * emitted when `account` grants or revokes permission to * `operator` to migrate their tokens according to `approved` */ event ApproveMigrate( address indexed account, address indexed operator, bool approved ); /** migrate amount of ERC20 tokens */ function _migrateFrom( address account, uint256 amount, uint256[] memory index ) internal virtual returns (uint256) { uint256 minAmount = Math.min( amount, _base[index[0]].balanceOf(account) ); uint256 newAmount = _premigrate(account, minAmount, index[0]); _mint(account, newAmount); return newAmount; } /** migrate amount of ERC20 tokens */ function _premigrate( address account, uint256 amount, uint256 index ) internal returns (uint256) { require(!_sealed[index], "migration sealed"); uint256 timestamp = block.timestamp; require(_deadlineBy >= timestamp, "deadline passed"); _base[index].burnFrom(account, amount); assert(amount > 0 || amount == 0); uint256 newAmount = newUnits(amount, index); _migrated += newAmount; return newAmount; } /** * @param oldAmount to convert from * @param index of base contract * @return forward converted new amount w.r.t. decimals */ function newUnits( uint256 oldAmount, uint256 index ) public view returns (uint256) { if (decimals() >= _base[index].decimals()) { return oldAmount * (10 ** (decimals() - _base[index].decimals())); } else { return oldAmount / (10 ** (_base[index].decimals() - decimals())); } } /** * @param newAmount to convert from * @param index of base contract * @return backward converted old amount w.r.t. decimals */ function oldUnits( uint256 newAmount, uint256 index ) public view returns (uint256) { if (decimals() >= _base[index].decimals()) { return newAmount / (10 ** (decimals() - _base[index].decimals())); } else { return newAmount * (10 ** (_base[index].decimals() - decimals())); } } /** @return number of migrated tokens */ function migrated() public view returns (uint256) { return _migrated; } /** * seal immigration * * @param index of base contract */ function _seal(uint256 index) internal { _sealed[index] = true; emit Seal(index); } event Seal(uint256 index); /** seal-all immigration */ function _sealAll() internal { for (uint256 i = 0; i < _sealed.length; i++) { _sealed[i] = true; } emit SealAll(); } event SealAll(); /** @return seal flags (of all bases) */ function seals() public view returns (bool[] memory) { return _sealed; } /** @return true if this contract implements the interface defined by interface-id */ function supportsInterface( bytes4 interfaceId ) public view virtual override returns (bool) { return interfaceId == type(IERC20).interfaceId || interfaceId == type(IERC20Metadata).interfaceId || super.supportsInterface(interfaceId); } } /** * Allows migration of MOE tokens from an old contract upto a certain deadline. */ abstract contract MoeMigratable is Migratable, MoeMigratableSupervised { /** @param base addresses of old contracts */ /** @param deadlineIn seconds to end-of-migration */ constructor( address[] memory base, uint256 deadlineIn ) Migratable(base, deadlineIn) {} /** seal migration */ function seal(uint256 index) external onlyRole(MOE_SEAL_ROLE) { _seal(index); } /** seal-all migration */ function sealAll() external onlyRole(MOE_SEAL_ROLE) { _sealAll(); } /** @return true if this contract implements the interface defined by interface-id */ function supportsInterface( bytes4 interfaceId ) public view virtual override(Migratable, Supervised) returns (bool) { return super.supportsInterface(interfaceId); } } /** * Allows migration of SOV tokens from an old contract upto a certain deadline. */ abstract contract SovMigratable is Migratable, SovMigratableSupervised { /** migratable MOE tokens */ MoeMigratable private _moeMigratable; /** @param moe address of MOE tokens */ /** @param base addresses of old contracts */ /** @param deadlineIn seconds to end-of-migration */ constructor( address moe, address[] memory base, uint256 deadlineIn ) Migratable(base, deadlineIn) { _moeMigratable = MoeMigratable(moe); } /** * migrate amount of SOV tokens * * @param account to migrate from * @param amount of ERC20s to migrate * @param index pair of [sov_index, moe_index] */ /// /// @dev assumes old (XPower:APower) == new (XPower:APower) w.r.t. decimals /// function _migrateFrom( address account, uint256 amount, uint256[] memory index ) internal override returns (uint256) { uint256[] memory moeIndex = new uint256[](1); moeIndex[0] = index[1]; // drop sov-index uint256 newAmountSov = newUnits(amount, index[0]); uint256 migAmountSov = _premigrate(account, amount, index[0]); assert(migAmountSov == newAmountSov); uint256 newAmountMoe = moeUnits(newAmountSov); uint256 oldAmountMoe = _moeMigratable.oldUnits(newAmountMoe, moeIndex[0]); uint256 migAmountMoe = _moeMigratable.migrateFrom(account, oldAmountMoe, moeIndex); assert(_moeMigratable.transferFrom(account, (address)(this), migAmountMoe)); _mint(account, newAmountSov); return newAmountSov; } /** * @param sovAmount to convert from * @return cross-converted MOE amount w.r.t. decimals */ function moeUnits(uint256 sovAmount) public view returns (uint256) { if (decimals() >= _moeMigratable.decimals()) { return sovAmount / (10 ** (decimals() - _moeMigratable.decimals())); } else { return sovAmount * (10 ** (_moeMigratable.decimals() - decimals())); } } /** * @param moeAmount to convert from * @return cross-converted SOV amount w.r.t. decimals */ function sovUnits(uint256 moeAmount) public view returns (uint256) { if (decimals() >= _moeMigratable.decimals()) { return moeAmount * (10 ** (decimals() - _moeMigratable.decimals())); } else { return moeAmount / (10 ** (_moeMigratable.decimals() - decimals())); } } /** seal migration */ function seal(uint256 index) external onlyRole(SOV_SEAL_ROLE) { _seal(index); } /** seal-all migration */ function sealAll() external onlyRole(SOV_SEAL_ROLE) { _sealAll(); } /** @return true if this contract implements the interface defined by interface-id */ function supportsInterface( bytes4 interfaceId ) public view virtual override(Migratable, Supervised) returns (bool) { return super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; /** * Allows tracking of fees using cumulative moving-averages: * > * > avg[n+1] = (fee[n+1] + n*avg[n]) / (n+1) * > */ abstract contract FeeTracker { /** cumulative moving-averages: gas & gas-price */ uint256[2] private _average; /** gas & gas-price tracker */ modifier tracked() { uint256 gas = gasleft(); _; _update(gas - gasleft(), tx.gasprice); } /** update averages over gas & gas-price */ function _update(uint256 gasValue, uint256 gasPrice) private { uint256 value = _average[0]; if (value > 0) { _average[0] = (gasValue + value * 0xf) >> 4; } else { _average[0] = (gasValue); } uint256 price = _average[1]; if (price > 0) { _average[1] = (gasPrice + price * 0xf) >> 4; } else { _average[1] = (gasPrice); } } /** @return fee-estimate and averages over gas & gas-price */ function _fees(uint256 add, uint256 mul, uint256 div) internal view returns (uint256[] memory) { uint256[] memory array = new uint256[](3); uint256 gasPrice = _average[1]; array[2] = gasPrice; uint256 gasValue = _average[0]; array[1] = gasValue; uint256 feeValue = gasPrice * gasValue; array[0] = ((feeValue + add) * mul) / div; return array; } }
// SPDX-License-Identifier: GPL-3.0 // solhint-disable no-empty-blocks pragma solidity 0.8.20; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import {ERC1155Supply} from "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol"; import {ERC1155Burnable} from "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol"; import {Nft} from "../libs/Nft.sol"; import {NftMigratable} from "./NftMigratable.sol"; import {NftRoyalty} from "./NftRoyalty.sol"; import {URIMalleable} from "./URIMalleable.sol"; /** * Abstract base NFT class: publicly *not* minteable (nor burnable). */ abstract contract NftBase is ERC1155, ERC1155Supply, ERC1155Burnable, URIMalleable, NftRoyalty, NftMigratable, Ownable { /** contract name */ string public name; /** contract symbol */ string public symbol; /** @param nftBase address of old contract */ /** @param uri meta-data URI */ /** @param deadlineIn seconds to end-of-migration */ constructor( string memory nftName, string memory nftSymbol, string memory nftUri, address[] memory nftBase, uint256 deadlineIn ) // ERC1155 constructor: meta-data URI ERC1155(nftUri) // MigratableNft: old contract, rel. deadline [seconds] NftMigratable(nftBase, deadlineIn) { name = nftName; symbol = nftSymbol; } /** @return nft-id composed of (year, level) */ function idBy(uint256 anno, uint256 level) public pure returns (uint256) { return Nft.idBy(anno, level); } /** @return nft-ids composed of [(year, level) for level in levels] */ function idsBy( uint256 anno, uint256[] memory levels ) public pure returns (uint256[] memory) { return Nft.idsBy(anno, levels); } /** @return denomination of level (1, 1'000, 1'000'000, ...) */ function denominationOf(uint256 level) public pure returns (uint256) { return Nft.denominationOf(level); } /** @return level of nft-id (0, 3, 6, ...) */ function levelOf(uint256 nftId) public pure returns (uint256) { return Nft.levelOf(nftId); } /** @return year of nft-id (2021, 2022, ...) */ function yearOf(uint256 nftId) public pure returns (uint256) { return Nft.yearOf(nftId); } /** @return current number of years since anno domini */ function year() public view returns (uint256) { return Nft.year(); } /** called before any token transfer; includes (batched) minting and burning */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory nftIds, uint256[] memory amounts, bytes memory data ) internal override(ERC1155, ERC1155Supply) { ERC1155Supply._beforeTokenTransfer( operator, from, to, nftIds, amounts, data ); } /** @return URI of nft-id */ function uri( uint256 nftId ) public view virtual override(ERC1155, URIMalleable) returns (string memory) { return super.uri(nftId); } /** @return true if this contract implements the interface defined by interface-id */ function supportsInterface( bytes4 interfaceId ) public view virtual override(ERC1155, URIMalleable, NftRoyalty, NftMigratable) returns (bool) { return super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; /* ██████╗ ██████╗ ██████╗ ███╗ ███╗ █████╗ ████████╗██╗ ██╗ ██╔══██╗██╔══██╗██╔══██╗████╗ ████║██╔══██╗╚══██╔══╝██║ ██║ ██████╔╝██████╔╝██████╔╝██╔████╔██║███████║ ██║ ███████║ ██╔═══╝ ██╔══██╗██╔══██╗██║╚██╔╝██║██╔══██║ ██║ ██╔══██║ ██║ ██║ ██║██████╔╝██║ ╚═╝ ██║██║ ██║ ██║ ██║ ██║ ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ ██╗ ██╗ █████╗ ██║ ██║██╔══██╗██╔════╝ ██╔═████╗╚██╗██╔╝███║██╔══██╗ ██║ ██║██║ ██║███████╗ ██║██╔██║ ╚███╔╝ ╚██║╚█████╔╝ ██║ ██║██║ ██║██╔═══██╗████╔╝██║ ██╔██╗ ██║██╔══██╗ ╚██████╔╝██████╔╝╚██████╔╝╚██████╔╝██╔╝ ██╗ ██║╚█████╔╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚════╝ */ import "./ud60x18/Casting.sol"; import "./ud60x18/Constants.sol"; import "./ud60x18/Conversions.sol"; import "./ud60x18/Errors.sol"; import "./ud60x18/Helpers.sol"; import "./ud60x18/Math.sol"; import "./ud60x18/ValueType.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControlEnumerable.sol"; import "./AccessControl.sol"; import "../utils/structs/EnumerableSet.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { using EnumerableSet for EnumerableSet.AddressSet; mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { return _roleMembers[role].at(index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { return _roleMembers[role].length(); } /** * @dev Overload {_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override { super._grantRole(role, account); _roleMembers[role].add(account); } /** * @dev Overload {_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override { super._revokeRole(role, account); _roleMembers[role].remove(account); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.0; import "./IERC1155.sol"; import "./IERC1155Receiver.sol"; import "./extensions/IERC1155MetadataURI.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 * * _Available since v3.1._ */ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { using Address for address; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ constructor(string memory uri_) { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155MetadataURI).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: address zero is not a valid owner"); return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] memory accounts, uint256[] memory ids ) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts[i], ids[i]); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeTransferFrom(from, to, id, amount, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, to, ids, amounts, data); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); _balances[id][to] += amount; emit TransferSingle(operator, address(0), to, id, amount); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { _balances[ids[i]][to] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } /** * @dev Destroys `amount` tokens of token type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `amount` tokens of token type `id`. */ function _burn(address from, uint256 id, uint256 amount) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } emit TransferSingle(operator, from, address(0), id, amount); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch(address from, uint256[] memory ids, uint256[] memory amounts) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); for (uint256 i = 0; i < ids.length; i++) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } } emit TransferBatch(operator, from, address(0), ids, amounts); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { require(owner != operator, "ERC1155: setting approval status for self"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `ids` and `amounts` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol) pragma solidity ^0.8.0; import "../ERC1155.sol"; /** * @dev Extension of ERC1155 that adds tracking of total supply per id. * * Useful for scenarios where Fungible and Non-fungible tokens have to be * clearly identified. Note: While a totalSupply of 1 might mean the * corresponding is an NFT, there is no guarantees that no other token with the * same id are not going to be minted. */ abstract contract ERC1155Supply is ERC1155 { mapping(uint256 => uint256) private _totalSupply; /** * @dev Total amount of tokens in with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { return _totalSupply[id]; } /** * @dev Indicates whether any token exist with a given id, or not. */ function exists(uint256 id) public view virtual returns (bool) { return ERC1155Supply.totalSupply(id) > 0; } /** * @dev See {ERC1155-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); if (from == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { _totalSupply[ids[i]] += amounts[i]; } } if (to == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 supply = _totalSupply[id]; require(supply >= amount, "ERC1155: burn amount exceeds totalSupply"); unchecked { _totalSupply[id] = supply - amount; } } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/extensions/ERC1155Burnable.sol) pragma solidity ^0.8.0; import "../ERC1155.sol"; /** * @dev Extension of {ERC1155} that allows token holders to destroy both their * own tokens and those that they have been approved to use. * * _Available since v3.1._ */ abstract contract ERC1155Burnable is ERC1155 { function burn(address account, uint256 id, uint256 value) public virtual { require( account == _msgSender() || isApprovedForAll(account, _msgSender()), "ERC1155: caller is not token owner or approved" ); _burn(account, id, value); } function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public virtual { require( account == _msgSender() || isApprovedForAll(account, _msgSender()), "ERC1155: caller is not token owner or approved" ); _burnBatch(account, ids, values); } }
// SPDX-License-Identifier: GPL-3.0 // solhint-disable not-rely-on-time pragma solidity 0.8.20; import {Constants} from "./Constants.sol"; library Nft { /** @return nft-id composed of (year, level) */ function idBy(uint256 anno, uint256 level) internal pure returns (uint256) { require(level % 3 == 0, "non-ternary level"); require(level < 100, "invalid level"); require(anno > 2020, "invalid year"); return 100 * anno + level; } /** @return nft-ids composed of [(year, level) for level in levels] */ function idsBy( uint256 anno, uint256[] memory levels ) internal pure returns (uint256[] memory) { uint256[] memory ids = new uint256[](levels.length); for (uint256 i = 0; i < levels.length; i++) { ids[i] = idBy(anno, levels[i]); } return ids; } /** @return denomination of level (1, 1'000, 1'000'000, ...) */ function denominationOf(uint256 level) internal pure returns (uint256) { require(level % 3 == 0, "non-ternary level"); require(level < 100, "invalid level"); return 10 ** level; } /** @return level of nft-id (0, 3, 6, ...) */ function levelOf(uint256 nftId) internal pure returns (uint256) { uint256 level = nftId % 100; require(level % 3 == 0, "non-ternary level"); require(level < 100, "invalid level"); return level; } /** @return year of nft-id (2021, 2022, ...) */ function yearOf(uint256 nftId) internal pure returns (uint256) { uint256 anno = nftId / 100; require(anno > 2020, "invalid year"); return anno; } /** @return current number of years since anno domini */ function year() internal view returns (uint256) { uint256 anno = 1970 + (100 * block.timestamp) / Constants.CENTURY; require(anno > 2020, "invalid year"); return anno; } }
// SPDX-License-Identifier: GPL-3.0 // solhint-disable not-rely-on-time // solhint-disable reason-string pragma solidity 0.8.20; import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import {ERC1155Burnable} from "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol"; import {Supervised, NftMigratableSupervised} from "./Supervised.sol"; /** * Allows migration of NFTs from an old contract; batch migration is also * possible. Further, manually sealing the migration is possible too. */ abstract contract NftMigratable is ERC1155, ERC1155Burnable, NftMigratableSupervised { /** burnable ERC1155 tokens */ ERC1155Burnable[] private _base; /** base address to index map */ mapping(address => uint256) private _index; /** timestamp of immigration deadline */ uint256 private _deadlineBy; /** flag to seal immigration */ bool[] private _sealed; /** flag to open emigration */ uint256 private _migratable; /** * @param base addresses of old contracts * @param deadlineIn seconds to end-of-migration */ constructor(address[] memory base, uint256 deadlineIn) { _deadlineBy = block.timestamp + deadlineIn; _base = new ERC1155Burnable[](base.length); _sealed = new bool[](base.length); for (uint256 i = 0; i < base.length; i++) { _base[i] = ERC1155Burnable(base[i]); _index[base[i]] = i; } } /** * @param base address of old contract * @return index of base address */ function oldIndexOf(address base) external view returns (uint256) { return _index[base]; } /** * migrate amount of ERC1155 * * @param nftId matching (<prefix>2?)(<year>[0-9]{4,})(<level>[0-9]{2}) * @param amount of ERC1155s to migrate * @param index pair of [nft_index, moe_index] */ function migrate(uint256 nftId, uint256 amount, uint256[] memory index) external { _migrateFrom(msg.sender, nftId, amount, index); } /** * migrate amount of ERC1155 * * @param account to migrate from * @param nftId matching (<prefix>2?)(<year>[0-9]{4,})(<level>[0-9]{2}) * @param amount of ERC1155s to migrate * @param index pair of [nft_index, moe_index] */ function migrateFrom(address account, uint256 nftId, uint256 amount, uint256[] memory index) external { require( account == msg.sender || approvedMigrate(account, msg.sender), "caller is not token owner or approved" ); _migrateFrom(account, nftId, amount, index); } /** approve migrate by `operator` */ function approveMigrate(address operator, bool approved) external { require(msg.sender != operator, "approving migrate for self"); _migrateApprovals[msg.sender][operator] = approved; emit ApproveMigrate(msg.sender, operator, approved); } /** @return true if `account` approved migrate by `operator` */ function approvedMigrate( address account, address operator ) public view returns (bool) { return _migrateApprovals[account][operator]; } /** migrate approvals: account => operator */ mapping(address => mapping(address => bool)) private _migrateApprovals; /** * emitted when `account` grants or revokes permission to * `operator` to migrate their tokens according to `approved` */ event ApproveMigrate( address indexed account, address indexed operator, bool approved ); /** migrate amount of ERC1155 */ function _migrateFrom(address account, uint256 nftId, uint256 amount, uint256[] memory index) internal { require(_deadlineBy >= block.timestamp, "deadline passed"); _burnFrom(account, nftId, amount, index); _mint(account, nftId, amount, ""); } /** burn amount of ERC1155 */ function _burnFrom(address account, uint256 nftId, uint256 amount, uint256[] memory index) internal virtual { require(!_sealed[index[0]], "migration sealed"); uint256 tryId = nftId + 2_000_000; // older ID format uint256 tryBalance = _base[index[0]].balanceOf(account, tryId); _base[index[0]].burn(account, tryBalance > 0 ? tryId : nftId, amount); } /** * batch-migrate amounts of ERC1155 * * @param nftIds matching (<prefix>2?)(<year>[0-9]{4,})(<level>[0-9]{2}) * @param amounts of ERC1155s to migrate * @param index pair of [nft_index, moe_index] */ function migrateBatch(uint256[] memory nftIds, uint256[] memory amounts, uint256[] memory index) external { _migrateFromBatch(msg.sender, nftIds, amounts, index); } /** * batch-migrate amounts of ERC1155 * * @param account to migrate from * @param nftIds matching (<prefix>2?)(<year>[0-9]{4,})(<level>[0-9]{2}) * @param amounts of ERC1155s to migrate * @param index pair of [nft_index, moe_index] */ function migrateFromBatch( address account, uint256[] memory nftIds, uint256[] memory amounts, uint256[] memory index ) external { require( account == msg.sender || approvedMigrate(account, msg.sender), "caller is not token owner or approved" ); _migrateFromBatch(account, nftIds, amounts, index); } /** batch-migrate amounts of ERC1155 */ function _migrateFromBatch( address account, uint256[] memory nftIds, uint256[] memory amounts, uint256[] memory index ) internal { require(_deadlineBy >= block.timestamp, "deadline passed"); for (uint256 i = 0; i < nftIds.length; i++) { _burnFrom(account, nftIds[i], amounts[i], index); } _mintBatch(account, nftIds, amounts, ""); } /** * seal immigration * * @param index of base contract */ function seal(uint256 index) external onlyRole(NFT_SEAL_ROLE) { _sealed[index] = true; emit Seal(index); } event Seal(uint256 index); /** seal-all immigration */ function sealAll() external onlyRole(NFT_SEAL_ROLE) { for (uint256 i = 0; i < _sealed.length; i++) { _sealed[i] = true; } emit SealAll(); } event SealAll(); /** @return seal flags (of all bases) */ function seals() external view returns (bool[] memory) { return _sealed; } /** emitted on opening emigration */ event Migratable(uint256 timestamp); /** * open emigration for *all* nft-years (deferred by a week) * @param flag value to set to (only `true` has an effect) */ function migratable(bool flag) external onlyRole(NFT_OPEN_ROLE) { require(_deadlineBy >= block.timestamp, "deadline passed"); if (flag && _migratable == 0) { _migratable = block.timestamp + 7 days; emit Migratable(_migratable); } } /** @return emigration flag */ function migratable() public view returns (bool) { if (_migratable > 0) { return block.timestamp >= _migratable; } return false; } /** @return true if this contract implements the interface defined by interface-id */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC1155, Supervised) returns (bool) { return super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: GPL-3.0 // solhint-disable not-rely-on-time pragma solidity 0.8.20; import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol"; import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol"; import {Supervised, NftRoyaltySupervised} from "./Supervised.sol"; /** * Allows changing of the NFT's beneficiary (by the NFT_ROYAL_ROLE) while * the default royalty fraction is set to a flat value of 0.5%. */ abstract contract NftRoyalty is IERC2981, NftRoyaltySupervised { /** address of beneficiary */ address private _royal; constructor() { _royal = msg.sender; // fallback beneficiary } /** @return royalty beneficiary and amount (for nft-id & price) */ function royaltyInfo(uint256, uint256 price) external view override returns (address, uint256) { return (_royal, price / 200); } /** @return default royalty beneficiary */ function getRoyal() external view returns (address) { return _royal; } /** set default royalty beneficiary */ function setRoyal(address beneficiary) external onlyRole(NFT_ROYAL_ROLE) { _royal = beneficiary; emit SetRoyal(beneficiary); } event SetRoyal(address beneficiary); /** @return true if this contract implements the interface defined by interface-id */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, Supervised) returns (bool) { return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.20; import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import {Supervised, URIMalleableSupervised} from "./Supervised.sol"; import {Nft} from "../libs/Nft.sol"; /** * Allows changing of the NFT's URI (by the URI_DATA_ROLE), where the URI * should e.g. redirect permanently (301) to a corresponding IPFS address. * A URI for a particular year becomes permanent after a decade, but only * if set (i.e. non-empty) before *or* after the cut-off year. * * Further, specifies a contract-level metadata URI to support Opensea.io, * including a setter (guarded by the same URI_DATA_ROLE). */ abstract contract URIMalleable is ERC1155, URIMalleableSupervised { /** metadata URI: year-of(nft-id) => value */ mapping(uint256 => string) private _uris; /** metadata URI: malleability duration */ uint256 private constant DECADE = 10; /** metadata URI: contract-level */ string private _uriContract; /** get contract-level metadata URI */ function contractURI() external view returns (string memory) { return _uriContract; } /** set contract-level metadata URI */ function setContractURI( string memory newuri ) external onlyRole(URI_DATA_ROLE) { _uriContract = newuri; } /** set default metadata URI */ function setURI(string memory newuri) external onlyRole(URI_DATA_ROLE) { _setURI(newuri); } /** set metadata URI (for year) */ function setURI( string memory newuri, uint256 year ) external onlyRole(URI_DATA_ROLE) { if (!_empty(_uris[year])) { require(year + DECADE > Nft.year(), "immalleable year"); } require(year > 2020, "invalid year"); _uris[year] = newuri; } /** @return URI of nft-id */ function uri( uint256 nftId ) public view virtual override returns (string memory) { string memory value = _uris[Nft.yearOf(nftId)]; return !_empty(value) ? value : super.uri(nftId); } /** @return true if URI of nft-id is permanent */ function fixedURI(uint256 nftId) external view returns (bool) { uint256 year = Nft.yearOf(nftId); if (_empty(_uris[year])) { return false; } if (year + DECADE > Nft.year()) { return false; } return true; } function _empty(string memory value) private pure returns (bool) { return bytes(value).length == 0; } /** @return true if this contract implements the interface defined by interface-id */ function supportsInterface( bytes4 interfaceId ) public view virtual override(ERC1155, Supervised) returns (bool) { return super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Errors.sol" as CastingErrors; import { MAX_UINT128, MAX_UINT40 } from "../Common.sol"; import { uMAX_SD1x18 } from "../sd1x18/Constants.sol"; import { SD1x18 } from "../sd1x18/ValueType.sol"; import { uMAX_SD59x18 } from "../sd59x18/Constants.sol"; import { SD59x18 } from "../sd59x18/ValueType.sol"; import { uMAX_UD2x18 } from "../ud2x18/Constants.sol"; import { UD2x18 } from "../ud2x18/ValueType.sol"; import { UD60x18 } from "./ValueType.sol"; /// @notice Casts a UD60x18 number into SD1x18. /// @dev Requirements: /// - x must be less than or equal to `uMAX_SD1x18`. function intoSD1x18(UD60x18 x) pure returns (SD1x18 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > uint256(int256(uMAX_SD1x18))) { revert CastingErrors.PRBMath_UD60x18_IntoSD1x18_Overflow(x); } result = SD1x18.wrap(int64(uint64(xUint))); } /// @notice Casts a UD60x18 number into UD2x18. /// @dev Requirements: /// - x must be less than or equal to `uMAX_UD2x18`. function intoUD2x18(UD60x18 x) pure returns (UD2x18 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > uMAX_UD2x18) { revert CastingErrors.PRBMath_UD60x18_IntoUD2x18_Overflow(x); } result = UD2x18.wrap(uint64(xUint)); } /// @notice Casts a UD60x18 number into SD59x18. /// @dev Requirements: /// - x must be less than or equal to `uMAX_SD59x18`. function intoSD59x18(UD60x18 x) pure returns (SD59x18 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > uint256(uMAX_SD59x18)) { revert CastingErrors.PRBMath_UD60x18_IntoSD59x18_Overflow(x); } result = SD59x18.wrap(int256(xUint)); } /// @notice Casts a UD60x18 number into uint128. /// @dev This is basically an alias for {unwrap}. function intoUint256(UD60x18 x) pure returns (uint256 result) { result = UD60x18.unwrap(x); } /// @notice Casts a UD60x18 number into uint128. /// @dev Requirements: /// - x must be less than or equal to `MAX_UINT128`. function intoUint128(UD60x18 x) pure returns (uint128 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > MAX_UINT128) { revert CastingErrors.PRBMath_UD60x18_IntoUint128_Overflow(x); } result = uint128(xUint); } /// @notice Casts a UD60x18 number into uint40. /// @dev Requirements: /// - x must be less than or equal to `MAX_UINT40`. function intoUint40(UD60x18 x) pure returns (uint40 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > MAX_UINT40) { revert CastingErrors.PRBMath_UD60x18_IntoUint40_Overflow(x); } result = uint40(xUint); } /// @notice Alias for {wrap}. function ud(uint256 x) pure returns (UD60x18 result) { result = UD60x18.wrap(x); } /// @notice Alias for {wrap}. function ud60x18(uint256 x) pure returns (UD60x18 result) { result = UD60x18.wrap(x); } /// @notice Unwraps a UD60x18 number into uint256. function unwrap(UD60x18 x) pure returns (uint256 result) { result = UD60x18.unwrap(x); } /// @notice Wraps a uint256 number into the UD60x18 value type. function wrap(uint256 x) pure returns (UD60x18 result) { result = UD60x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { UD60x18 } from "./ValueType.sol"; // NOTICE: the "u" prefix stands for "unwrapped". /// @dev Euler's number as a UD60x18 number. UD60x18 constant E = UD60x18.wrap(2_718281828459045235); /// @dev The maximum input permitted in {exp}. uint256 constant uEXP_MAX_INPUT = 133_084258667509499440; UD60x18 constant EXP_MAX_INPUT = UD60x18.wrap(uEXP_MAX_INPUT); /// @dev The maximum input permitted in {exp2}. uint256 constant uEXP2_MAX_INPUT = 192e18 - 1; UD60x18 constant EXP2_MAX_INPUT = UD60x18.wrap(uEXP2_MAX_INPUT); /// @dev Half the UNIT number. uint256 constant uHALF_UNIT = 0.5e18; UD60x18 constant HALF_UNIT = UD60x18.wrap(uHALF_UNIT); /// @dev $log_2(10)$ as a UD60x18 number. uint256 constant uLOG2_10 = 3_321928094887362347; UD60x18 constant LOG2_10 = UD60x18.wrap(uLOG2_10); /// @dev $log_2(e)$ as a UD60x18 number. uint256 constant uLOG2_E = 1_442695040888963407; UD60x18 constant LOG2_E = UD60x18.wrap(uLOG2_E); /// @dev The maximum value a UD60x18 number can have. uint256 constant uMAX_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_584007913129639935; UD60x18 constant MAX_UD60x18 = UD60x18.wrap(uMAX_UD60x18); /// @dev The maximum whole value a UD60x18 number can have. uint256 constant uMAX_WHOLE_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_000000000000000000; UD60x18 constant MAX_WHOLE_UD60x18 = UD60x18.wrap(uMAX_WHOLE_UD60x18); /// @dev PI as a UD60x18 number. UD60x18 constant PI = UD60x18.wrap(3_141592653589793238); /// @dev The unit number, which gives the decimal precision of UD60x18. uint256 constant uUNIT = 1e18; UD60x18 constant UNIT = UD60x18.wrap(uUNIT); /// @dev The unit number squared. uint256 constant uUNIT_SQUARED = 1e36; UD60x18 constant UNIT_SQUARED = UD60x18.wrap(uUNIT_SQUARED); /// @dev Zero as a UD60x18 number. UD60x18 constant ZERO = UD60x18.wrap(0);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { uMAX_UD60x18, uUNIT } from "./Constants.sol"; import { PRBMath_UD60x18_Convert_Overflow } from "./Errors.sol"; import { UD60x18 } from "./ValueType.sol"; /// @notice Converts a UD60x18 number to a simple integer by dividing it by `UNIT`. /// @dev The result is rounded toward zero. /// @param x The UD60x18 number to convert. /// @return result The same number in basic integer form. function convert(UD60x18 x) pure returns (uint256 result) { result = UD60x18.unwrap(x) / uUNIT; } /// @notice Converts a simple integer to UD60x18 by multiplying it by `UNIT`. /// /// @dev Requirements: /// - x must be less than or equal to `MAX_UD60x18 / UNIT`. /// /// @param x The basic integer to convert. /// @param result The same number converted to UD60x18. function convert(uint256 x) pure returns (UD60x18 result) { if (x > uMAX_UD60x18 / uUNIT) { revert PRBMath_UD60x18_Convert_Overflow(x); } unchecked { result = UD60x18.wrap(x * uUNIT); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { UD60x18 } from "./ValueType.sol"; /// @notice Thrown when ceiling a number overflows UD60x18. error PRBMath_UD60x18_Ceil_Overflow(UD60x18 x); /// @notice Thrown when converting a basic integer to the fixed-point format overflows UD60x18. error PRBMath_UD60x18_Convert_Overflow(uint256 x); /// @notice Thrown when taking the natural exponent of a base greater than 133_084258667509499441. error PRBMath_UD60x18_Exp_InputTooBig(UD60x18 x); /// @notice Thrown when taking the binary exponent of a base greater than 192e18. error PRBMath_UD60x18_Exp2_InputTooBig(UD60x18 x); /// @notice Thrown when taking the geometric mean of two numbers and multiplying them overflows UD60x18. error PRBMath_UD60x18_Gm_Overflow(UD60x18 x, UD60x18 y); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD1x18. error PRBMath_UD60x18_IntoSD1x18_Overflow(UD60x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD59x18. error PRBMath_UD60x18_IntoSD59x18_Overflow(UD60x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD2x18. error PRBMath_UD60x18_IntoUD2x18_Overflow(UD60x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint128. error PRBMath_UD60x18_IntoUint128_Overflow(UD60x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint40. error PRBMath_UD60x18_IntoUint40_Overflow(UD60x18 x); /// @notice Thrown when taking the logarithm of a number less than 1. error PRBMath_UD60x18_Log_InputTooSmall(UD60x18 x); /// @notice Thrown when calculating the square root overflows UD60x18. error PRBMath_UD60x18_Sqrt_Overflow(UD60x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { wrap } from "./Casting.sol"; import { UD60x18 } from "./ValueType.sol"; /// @notice Implements the checked addition operation (+) in the UD60x18 type. function add(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() + y.unwrap()); } /// @notice Implements the AND (&) bitwise operation in the UD60x18 type. function and(UD60x18 x, uint256 bits) pure returns (UD60x18 result) { result = wrap(x.unwrap() & bits); } /// @notice Implements the AND (&) bitwise operation in the UD60x18 type. function and2(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() & y.unwrap()); } /// @notice Implements the equal operation (==) in the UD60x18 type. function eq(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() == y.unwrap(); } /// @notice Implements the greater than operation (>) in the UD60x18 type. function gt(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() > y.unwrap(); } /// @notice Implements the greater than or equal to operation (>=) in the UD60x18 type. function gte(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() >= y.unwrap(); } /// @notice Implements a zero comparison check function in the UD60x18 type. function isZero(UD60x18 x) pure returns (bool result) { // This wouldn't work if x could be negative. result = x.unwrap() == 0; } /// @notice Implements the left shift operation (<<) in the UD60x18 type. function lshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) { result = wrap(x.unwrap() << bits); } /// @notice Implements the lower than operation (<) in the UD60x18 type. function lt(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() < y.unwrap(); } /// @notice Implements the lower than or equal to operation (<=) in the UD60x18 type. function lte(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() <= y.unwrap(); } /// @notice Implements the checked modulo operation (%) in the UD60x18 type. function mod(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() % y.unwrap()); } /// @notice Implements the not equal operation (!=) in the UD60x18 type. function neq(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() != y.unwrap(); } /// @notice Implements the NOT (~) bitwise operation in the UD60x18 type. function not(UD60x18 x) pure returns (UD60x18 result) { result = wrap(~x.unwrap()); } /// @notice Implements the OR (|) bitwise operation in the UD60x18 type. function or(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() | y.unwrap()); } /// @notice Implements the right shift operation (>>) in the UD60x18 type. function rshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) { result = wrap(x.unwrap() >> bits); } /// @notice Implements the checked subtraction operation (-) in the UD60x18 type. function sub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() - y.unwrap()); } /// @notice Implements the unchecked addition operation (+) in the UD60x18 type. function uncheckedAdd(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { unchecked { result = wrap(x.unwrap() + y.unwrap()); } } /// @notice Implements the unchecked subtraction operation (-) in the UD60x18 type. function uncheckedSub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { unchecked { result = wrap(x.unwrap() - y.unwrap()); } } /// @notice Implements the XOR (^) bitwise operation in the UD60x18 type. function xor(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() ^ y.unwrap()); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "../Common.sol" as Common; import "./Errors.sol" as Errors; import { wrap } from "./Casting.sol"; import { uEXP_MAX_INPUT, uEXP2_MAX_INPUT, uHALF_UNIT, uLOG2_10, uLOG2_E, uMAX_UD60x18, uMAX_WHOLE_UD60x18, UNIT, uUNIT, uUNIT_SQUARED, ZERO } from "./Constants.sol"; import { UD60x18 } from "./ValueType.sol"; /*////////////////////////////////////////////////////////////////////////// MATHEMATICAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice Calculates the arithmetic average of x and y using the following formula: /// /// $$ /// avg(x, y) = (x & y) + ((xUint ^ yUint) / 2) /// $$ /// /// In English, this is what this formula does: /// /// 1. AND x and y. /// 2. Calculate half of XOR x and y. /// 3. Add the two results together. /// /// This technique is known as SWAR, which stands for "SIMD within a register". You can read more about it here: /// https://devblogs.microsoft.com/oldnewthing/20220207-00/?p=106223 /// /// @dev Notes: /// - The result is rounded toward zero. /// /// @param x The first operand as a UD60x18 number. /// @param y The second operand as a UD60x18 number. /// @return result The arithmetic average as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function avg(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); uint256 yUint = y.unwrap(); unchecked { result = wrap((xUint & yUint) + ((xUint ^ yUint) >> 1)); } } /// @notice Yields the smallest whole number greater than or equal to x. /// /// @dev This is optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional /// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// /// Requirements: /// - x must be less than or equal to `MAX_WHOLE_UD60x18`. /// /// @param x The UD60x18 number to ceil. /// @param result The smallest whole number greater than or equal to x, as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function ceil(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); if (xUint > uMAX_WHOLE_UD60x18) { revert Errors.PRBMath_UD60x18_Ceil_Overflow(x); } assembly ("memory-safe") { // Equivalent to `x % UNIT`. let remainder := mod(x, uUNIT) // Equivalent to `UNIT - remainder`. let delta := sub(uUNIT, remainder) // Equivalent to `x + remainder > 0 ? delta : 0`. result := add(x, mul(delta, gt(remainder, 0))) } } /// @notice Divides two UD60x18 numbers, returning a new UD60x18 number. /// /// @dev Uses {Common.mulDiv} to enable overflow-safe multiplication and division. /// /// Notes: /// - Refer to the notes in {Common.mulDiv}. /// /// Requirements: /// - Refer to the requirements in {Common.mulDiv}. /// /// @param x The numerator as a UD60x18 number. /// @param y The denominator as a UD60x18 number. /// @param result The quotient as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function div(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(Common.mulDiv(x.unwrap(), uUNIT, y.unwrap())); } /// @notice Calculates the natural exponent of x using the following formula: /// /// $$ /// e^x = 2^{x * log_2{e}} /// $$ /// /// @dev Requirements: /// - x must be less than 133_084258667509499441. /// /// @param x The exponent as a UD60x18 number. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function exp(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); // This check prevents values greater than 192e18 from being passed to {exp2}. if (xUint > uEXP_MAX_INPUT) { revert Errors.PRBMath_UD60x18_Exp_InputTooBig(x); } unchecked { // Inline the fixed-point multiplication to save gas. uint256 doubleUnitProduct = xUint * uLOG2_E; result = exp2(wrap(doubleUnitProduct / uUNIT)); } } /// @notice Calculates the binary exponent of x using the binary fraction method. /// /// @dev See https://ethereum.stackexchange.com/q/79903/24693 /// /// Requirements: /// - x must be less than 192e18. /// - The result must fit in UD60x18. /// /// @param x The exponent as a UD60x18 number. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function exp2(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); // Numbers greater than or equal to 192e18 don't fit in the 192.64-bit format. if (xUint > uEXP2_MAX_INPUT) { revert Errors.PRBMath_UD60x18_Exp2_InputTooBig(x); } // Convert x to the 192.64-bit fixed-point format. uint256 x_192x64 = (xUint << 64) / uUNIT; // Pass x to the {Common.exp2} function, which uses the 192.64-bit fixed-point number representation. result = wrap(Common.exp2(x_192x64)); } /// @notice Yields the greatest whole number less than or equal to x. /// @dev Optimized for fractional value inputs, because every whole value has (1e18 - 1) fractional counterparts. /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// @param x The UD60x18 number to floor. /// @param result The greatest whole number less than or equal to x, as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function floor(UD60x18 x) pure returns (UD60x18 result) { assembly ("memory-safe") { // Equivalent to `x % UNIT`. let remainder := mod(x, uUNIT) // Equivalent to `x - remainder > 0 ? remainder : 0)`. result := sub(x, mul(remainder, gt(remainder, 0))) } } /// @notice Yields the excess beyond the floor of x using the odd function definition. /// @dev See https://en.wikipedia.org/wiki/Fractional_part. /// @param x The UD60x18 number to get the fractional part of. /// @param result The fractional part of x as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function frac(UD60x18 x) pure returns (UD60x18 result) { assembly ("memory-safe") { result := mod(x, uUNIT) } } /// @notice Calculates the geometric mean of x and y, i.e. $\sqrt{x * y}$, rounding down. /// /// @dev Requirements: /// - x * y must fit in UD60x18. /// /// @param x The first operand as a UD60x18 number. /// @param y The second operand as a UD60x18 number. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function gm(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); uint256 yUint = y.unwrap(); if (xUint == 0 || yUint == 0) { return ZERO; } unchecked { // Checking for overflow this way is faster than letting Solidity do it. uint256 xyUint = xUint * yUint; if (xyUint / xUint != yUint) { revert Errors.PRBMath_UD60x18_Gm_Overflow(x, y); } // We don't need to multiply the result by `UNIT` here because the x*y product picked up a factor of `UNIT` // during multiplication. See the comments in {Common.sqrt}. result = wrap(Common.sqrt(xyUint)); } } /// @notice Calculates the inverse of x. /// /// @dev Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - x must not be zero. /// /// @param x The UD60x18 number for which to calculate the inverse. /// @return result The inverse as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function inv(UD60x18 x) pure returns (UD60x18 result) { unchecked { result = wrap(uUNIT_SQUARED / x.unwrap()); } } /// @notice Calculates the natural logarithm of x using the following formula: /// /// $$ /// ln{x} = log_2{x} / log_2{e} /// $$ /// /// @dev Notes: /// - Refer to the notes in {log2}. /// - The precision isn't sufficiently fine-grained to return exactly `UNIT` when the input is `E`. /// /// Requirements: /// - Refer to the requirements in {log2}. /// /// @param x The UD60x18 number for which to calculate the natural logarithm. /// @return result The natural logarithm as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function ln(UD60x18 x) pure returns (UD60x18 result) { unchecked { // Inline the fixed-point multiplication to save gas. This is overflow-safe because the maximum value that // {log2} can return is ~196_205294292027477728. result = wrap(log2(x).unwrap() * uUNIT / uLOG2_E); } } /// @notice Calculates the common logarithm of x using the following formula: /// /// $$ /// log_{10}{x} = log_2{x} / log_2{10} /// $$ /// /// However, if x is an exact power of ten, a hard coded value is returned. /// /// @dev Notes: /// - Refer to the notes in {log2}. /// /// Requirements: /// - Refer to the requirements in {log2}. /// /// @param x The UD60x18 number for which to calculate the common logarithm. /// @return result The common logarithm as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function log10(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); if (xUint < uUNIT) { revert Errors.PRBMath_UD60x18_Log_InputTooSmall(x); } // Note that the `mul` in this assembly block is the standard multiplication operation, not {UD60x18.mul}. // prettier-ignore assembly ("memory-safe") { switch x case 1 { result := mul(uUNIT, sub(0, 18)) } case 10 { result := mul(uUNIT, sub(1, 18)) } case 100 { result := mul(uUNIT, sub(2, 18)) } case 1000 { result := mul(uUNIT, sub(3, 18)) } case 10000 { result := mul(uUNIT, sub(4, 18)) } case 100000 { result := mul(uUNIT, sub(5, 18)) } case 1000000 { result := mul(uUNIT, sub(6, 18)) } case 10000000 { result := mul(uUNIT, sub(7, 18)) } case 100000000 { result := mul(uUNIT, sub(8, 18)) } case 1000000000 { result := mul(uUNIT, sub(9, 18)) } case 10000000000 { result := mul(uUNIT, sub(10, 18)) } case 100000000000 { result := mul(uUNIT, sub(11, 18)) } case 1000000000000 { result := mul(uUNIT, sub(12, 18)) } case 10000000000000 { result := mul(uUNIT, sub(13, 18)) } case 100000000000000 { result := mul(uUNIT, sub(14, 18)) } case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) } case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) } case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) } case 1000000000000000000 { result := 0 } case 10000000000000000000 { result := uUNIT } case 100000000000000000000 { result := mul(uUNIT, 2) } case 1000000000000000000000 { result := mul(uUNIT, 3) } case 10000000000000000000000 { result := mul(uUNIT, 4) } case 100000000000000000000000 { result := mul(uUNIT, 5) } case 1000000000000000000000000 { result := mul(uUNIT, 6) } case 10000000000000000000000000 { result := mul(uUNIT, 7) } case 100000000000000000000000000 { result := mul(uUNIT, 8) } case 1000000000000000000000000000 { result := mul(uUNIT, 9) } case 10000000000000000000000000000 { result := mul(uUNIT, 10) } case 100000000000000000000000000000 { result := mul(uUNIT, 11) } case 1000000000000000000000000000000 { result := mul(uUNIT, 12) } case 10000000000000000000000000000000 { result := mul(uUNIT, 13) } case 100000000000000000000000000000000 { result := mul(uUNIT, 14) } case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) } case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) } case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) } case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) } case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) } case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) } case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) } case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) } case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) } case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) } case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) } case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) } case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) } case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) } case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) } case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) } case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) } case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) } case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) } case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) } case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) } case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) } case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) } case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) } case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) } case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) } case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) } case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) } case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) } case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) } case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) } case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) } case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) } case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) } case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) } case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) } case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) } case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) } case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) } case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) } case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) } case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) } case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) } case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) } case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 59) } default { result := uMAX_UD60x18 } } if (result.unwrap() == uMAX_UD60x18) { unchecked { // Inline the fixed-point division to save gas. result = wrap(log2(x).unwrap() * uUNIT / uLOG2_10); } } } /// @notice Calculates the binary logarithm of x using the iterative approximation algorithm: /// /// $$ /// log_2{x} = n + log_2{y}, \text{ where } y = x*2^{-n}, \ y \in [1, 2) /// $$ /// /// For $0 \leq x \lt 1$, the input is inverted: /// /// $$ /// log_2{x} = -log_2{\frac{1}{x}} /// $$ /// /// @dev See https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation /// /// Notes: /// - Due to the lossy precision of the iterative approximation, the results are not perfectly accurate to the last decimal. /// /// Requirements: /// - x must be greater than zero. /// /// @param x The UD60x18 number for which to calculate the binary logarithm. /// @return result The binary logarithm as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function log2(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); if (xUint < uUNIT) { revert Errors.PRBMath_UD60x18_Log_InputTooSmall(x); } unchecked { // Calculate the integer part of the logarithm. uint256 n = Common.msb(xUint / uUNIT); // This is the integer part of the logarithm as a UD60x18 number. The operation can't overflow because n // n is at most 255 and UNIT is 1e18. uint256 resultUint = n * uUNIT; // Calculate $y = x * 2^{-n}$. uint256 y = xUint >> n; // If y is the unit number, the fractional part is zero. if (y == uUNIT) { return wrap(resultUint); } // Calculate the fractional part via the iterative approximation. // The `delta >>= 1` part is equivalent to `delta /= 2`, but shifting bits is more gas efficient. uint256 DOUBLE_UNIT = 2e18; for (uint256 delta = uHALF_UNIT; delta > 0; delta >>= 1) { y = (y * y) / uUNIT; // Is y^2 >= 2e18 and so in the range [2e18, 4e18)? if (y >= DOUBLE_UNIT) { // Add the 2^{-m} factor to the logarithm. resultUint += delta; // Halve y, which corresponds to z/2 in the Wikipedia article. y >>= 1; } } result = wrap(resultUint); } } /// @notice Multiplies two UD60x18 numbers together, returning a new UD60x18 number. /// /// @dev Uses {Common.mulDiv} to enable overflow-safe multiplication and division. /// /// Notes: /// - Refer to the notes in {Common.mulDiv}. /// /// Requirements: /// - Refer to the requirements in {Common.mulDiv}. /// /// @dev See the documentation in {Common.mulDiv18}. /// @param x The multiplicand as a UD60x18 number. /// @param y The multiplier as a UD60x18 number. /// @return result The product as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function mul(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(Common.mulDiv18(x.unwrap(), y.unwrap())); } /// @notice Raises x to the power of y. /// /// For $1 \leq x \leq \infty$, the following standard formula is used: /// /// $$ /// x^y = 2^{log_2{x} * y} /// $$ /// /// For $0 \leq x \lt 1$, since the unsigned {log2} is undefined, an equivalent formula is used: /// /// $$ /// i = \frac{1}{x} /// w = 2^{log_2{i} * y} /// x^y = \frac{1}{w} /// $$ /// /// @dev Notes: /// - Refer to the notes in {log2} and {mul}. /// - Returns `UNIT` for 0^0. /// - It may not perform well with very small values of x. Consider using SD59x18 as an alternative. /// /// Requirements: /// - Refer to the requirements in {exp2}, {log2}, and {mul}. /// /// @param x The base as a UD60x18 number. /// @param y The exponent as a UD60x18 number. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function pow(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); uint256 yUint = y.unwrap(); // If both x and y are zero, the result is `UNIT`. If just x is zero, the result is always zero. if (xUint == 0) { return yUint == 0 ? UNIT : ZERO; } // If x is `UNIT`, the result is always `UNIT`. else if (xUint == uUNIT) { return UNIT; } // If y is zero, the result is always `UNIT`. if (yUint == 0) { return UNIT; } // If y is `UNIT`, the result is always x. else if (yUint == uUNIT) { return x; } // If x is greater than `UNIT`, use the standard formula. if (xUint > uUNIT) { result = exp2(mul(log2(x), y)); } // Conversely, if x is less than `UNIT`, use the equivalent formula. else { UD60x18 i = wrap(uUNIT_SQUARED / xUint); UD60x18 w = exp2(mul(log2(i), y)); result = wrap(uUNIT_SQUARED / w.unwrap()); } } /// @notice Raises x (a UD60x18 number) to the power y (an unsigned basic integer) using the well-known /// algorithm "exponentiation by squaring". /// /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring. /// /// Notes: /// - Refer to the notes in {Common.mulDiv18}. /// - Returns `UNIT` for 0^0. /// /// Requirements: /// - The result must fit in UD60x18. /// /// @param x The base as a UD60x18 number. /// @param y The exponent as a uint256. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function powu(UD60x18 x, uint256 y) pure returns (UD60x18 result) { // Calculate the first iteration of the loop in advance. uint256 xUint = x.unwrap(); uint256 resultUint = y & 1 > 0 ? xUint : uUNIT; // Equivalent to `for(y /= 2; y > 0; y /= 2)`. for (y >>= 1; y > 0; y >>= 1) { xUint = Common.mulDiv18(xUint, xUint); // Equivalent to `y % 2 == 1`. if (y & 1 > 0) { resultUint = Common.mulDiv18(resultUint, xUint); } } result = wrap(resultUint); } /// @notice Calculates the square root of x using the Babylonian method. /// /// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. /// /// Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - x must be less than `MAX_UD60x18 / UNIT`. /// /// @param x The UD60x18 number for which to calculate the square root. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function sqrt(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); unchecked { if (xUint > uMAX_UD60x18 / uUNIT) { revert Errors.PRBMath_UD60x18_Sqrt_Overflow(x); } // Multiply x by `UNIT` to account for the factor of `UNIT` picked up when multiplying two UD60x18 numbers. // In this case, the two numbers are both the square root. result = wrap(Common.sqrt(xUint * uUNIT)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Casting.sol" as Casting; import "./Helpers.sol" as Helpers; import "./Math.sol" as Math; /// @notice The unsigned 60.18-decimal fixed-point number representation, which can have up to 60 digits and up to 18 /// decimals. The values of this are bound by the minimum and the maximum values permitted by the Solidity type uint256. /// @dev The value type is defined here so it can be imported in all other files. type UD60x18 is uint256; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { Casting.intoSD1x18, Casting.intoUD2x18, Casting.intoSD59x18, Casting.intoUint128, Casting.intoUint256, Casting.intoUint40, Casting.unwrap } for UD60x18 global; /*////////////////////////////////////////////////////////////////////////// MATHEMATICAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ // The global "using for" directive makes the functions in this library callable on the UD60x18 type. using { Math.avg, Math.ceil, Math.div, Math.exp, Math.exp2, Math.floor, Math.frac, Math.gm, Math.inv, Math.ln, Math.log10, Math.log2, Math.mul, Math.pow, Math.powu, Math.sqrt } for UD60x18 global; /*////////////////////////////////////////////////////////////////////////// HELPER FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ // The global "using for" directive makes the functions in this library callable on the UD60x18 type. using { Helpers.add, Helpers.and, Helpers.eq, Helpers.gt, Helpers.gte, Helpers.isZero, Helpers.lshift, Helpers.lt, Helpers.lte, Helpers.mod, Helpers.neq, Helpers.not, Helpers.or, Helpers.rshift, Helpers.sub, Helpers.uncheckedAdd, Helpers.uncheckedSub, Helpers.xor } for UD60x18 global; /*////////////////////////////////////////////////////////////////////////// OPERATORS //////////////////////////////////////////////////////////////////////////*/ // The global "using for" directive makes it possible to use these operators on the UD60x18 type. using { Helpers.add as +, Helpers.and2 as &, Math.div as /, Helpers.eq as ==, Helpers.gt as >, Helpers.gte as >=, Helpers.lt as <, Helpers.lte as <=, Helpers.or as |, Helpers.mod as %, Math.mul as *, Helpers.neq as !=, Helpers.not as ~, Helpers.sub as -, Helpers.xor as ^ } for UD60x18 global;
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(account), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] calldata accounts, uint256[] calldata ids ) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "../IERC1155.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo( uint256 tokenId, uint256 salePrice ) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; // Common.sol // // Common mathematical functions used in both SD59x18 and UD60x18. Note that these global functions do not // always operate with SD59x18 and UD60x18 numbers. /*////////////////////////////////////////////////////////////////////////// CUSTOM ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when the resultant value in {mulDiv} overflows uint256. error PRBMath_MulDiv_Overflow(uint256 x, uint256 y, uint256 denominator); /// @notice Thrown when the resultant value in {mulDiv18} overflows uint256. error PRBMath_MulDiv18_Overflow(uint256 x, uint256 y); /// @notice Thrown when one of the inputs passed to {mulDivSigned} is `type(int256).min`. error PRBMath_MulDivSigned_InputTooSmall(); /// @notice Thrown when the resultant value in {mulDivSigned} overflows int256. error PRBMath_MulDivSigned_Overflow(int256 x, int256 y); /*////////////////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////////////////*/ /// @dev The maximum value a uint128 number can have. uint128 constant MAX_UINT128 = type(uint128).max; /// @dev The maximum value a uint40 number can have. uint40 constant MAX_UINT40 = type(uint40).max; /// @dev The unit number, which the decimal precision of the fixed-point types. uint256 constant UNIT = 1e18; /// @dev The unit number inverted mod 2^256. uint256 constant UNIT_INVERSE = 78156646155174841979727994598816262306175212592076161876661_508869554232690281; /// @dev The the largest power of two that divides the decimal value of `UNIT`. The logarithm of this value is the least significant /// bit in the binary representation of `UNIT`. uint256 constant UNIT_LPOTD = 262144; /*////////////////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice Calculates the binary exponent of x using the binary fraction method. /// @dev Has to use 192.64-bit fixed-point numbers. See https://ethereum.stackexchange.com/a/96594/24693. /// @param x The exponent as an unsigned 192.64-bit fixed-point number. /// @return result The result as an unsigned 60.18-decimal fixed-point number. /// @custom:smtchecker abstract-function-nondet function exp2(uint256 x) pure returns (uint256 result) { unchecked { // Start from 0.5 in the 192.64-bit fixed-point format. result = 0x800000000000000000000000000000000000000000000000; // The following logic multiplies the result by $\sqrt{2^{-i}}$ when the bit at position i is 1. Key points: // // 1. Intermediate results will not overflow, as the starting point is 2^191 and all magic factors are under 2^65. // 2. The rationale for organizing the if statements into groups of 8 is gas savings. If the result of performing // a bitwise AND operation between x and any value in the array [0x80; 0x40; 0x20; 0x10; 0x08; 0x04; 0x02; 0x01] is 1, // we know that `x & 0xFF` is also 1. if (x & 0xFF00000000000000 > 0) { if (x & 0x8000000000000000 > 0) { result = (result * 0x16A09E667F3BCC909) >> 64; } if (x & 0x4000000000000000 > 0) { result = (result * 0x1306FE0A31B7152DF) >> 64; } if (x & 0x2000000000000000 > 0) { result = (result * 0x1172B83C7D517ADCE) >> 64; } if (x & 0x1000000000000000 > 0) { result = (result * 0x10B5586CF9890F62A) >> 64; } if (x & 0x800000000000000 > 0) { result = (result * 0x1059B0D31585743AE) >> 64; } if (x & 0x400000000000000 > 0) { result = (result * 0x102C9A3E778060EE7) >> 64; } if (x & 0x200000000000000 > 0) { result = (result * 0x10163DA9FB33356D8) >> 64; } if (x & 0x100000000000000 > 0) { result = (result * 0x100B1AFA5ABCBED61) >> 64; } } if (x & 0xFF000000000000 > 0) { if (x & 0x80000000000000 > 0) { result = (result * 0x10058C86DA1C09EA2) >> 64; } if (x & 0x40000000000000 > 0) { result = (result * 0x1002C605E2E8CEC50) >> 64; } if (x & 0x20000000000000 > 0) { result = (result * 0x100162F3904051FA1) >> 64; } if (x & 0x10000000000000 > 0) { result = (result * 0x1000B175EFFDC76BA) >> 64; } if (x & 0x8000000000000 > 0) { result = (result * 0x100058BA01FB9F96D) >> 64; } if (x & 0x4000000000000 > 0) { result = (result * 0x10002C5CC37DA9492) >> 64; } if (x & 0x2000000000000 > 0) { result = (result * 0x1000162E525EE0547) >> 64; } if (x & 0x1000000000000 > 0) { result = (result * 0x10000B17255775C04) >> 64; } } if (x & 0xFF0000000000 > 0) { if (x & 0x800000000000 > 0) { result = (result * 0x1000058B91B5BC9AE) >> 64; } if (x & 0x400000000000 > 0) { result = (result * 0x100002C5C89D5EC6D) >> 64; } if (x & 0x200000000000 > 0) { result = (result * 0x10000162E43F4F831) >> 64; } if (x & 0x100000000000 > 0) { result = (result * 0x100000B1721BCFC9A) >> 64; } if (x & 0x80000000000 > 0) { result = (result * 0x10000058B90CF1E6E) >> 64; } if (x & 0x40000000000 > 0) { result = (result * 0x1000002C5C863B73F) >> 64; } if (x & 0x20000000000 > 0) { result = (result * 0x100000162E430E5A2) >> 64; } if (x & 0x10000000000 > 0) { result = (result * 0x1000000B172183551) >> 64; } } if (x & 0xFF00000000 > 0) { if (x & 0x8000000000 > 0) { result = (result * 0x100000058B90C0B49) >> 64; } if (x & 0x4000000000 > 0) { result = (result * 0x10000002C5C8601CC) >> 64; } if (x & 0x2000000000 > 0) { result = (result * 0x1000000162E42FFF0) >> 64; } if (x & 0x1000000000 > 0) { result = (result * 0x10000000B17217FBB) >> 64; } if (x & 0x800000000 > 0) { result = (result * 0x1000000058B90BFCE) >> 64; } if (x & 0x400000000 > 0) { result = (result * 0x100000002C5C85FE3) >> 64; } if (x & 0x200000000 > 0) { result = (result * 0x10000000162E42FF1) >> 64; } if (x & 0x100000000 > 0) { result = (result * 0x100000000B17217F8) >> 64; } } if (x & 0xFF000000 > 0) { if (x & 0x80000000 > 0) { result = (result * 0x10000000058B90BFC) >> 64; } if (x & 0x40000000 > 0) { result = (result * 0x1000000002C5C85FE) >> 64; } if (x & 0x20000000 > 0) { result = (result * 0x100000000162E42FF) >> 64; } if (x & 0x10000000 > 0) { result = (result * 0x1000000000B17217F) >> 64; } if (x & 0x8000000 > 0) { result = (result * 0x100000000058B90C0) >> 64; } if (x & 0x4000000 > 0) { result = (result * 0x10000000002C5C860) >> 64; } if (x & 0x2000000 > 0) { result = (result * 0x1000000000162E430) >> 64; } if (x & 0x1000000 > 0) { result = (result * 0x10000000000B17218) >> 64; } } if (x & 0xFF0000 > 0) { if (x & 0x800000 > 0) { result = (result * 0x1000000000058B90C) >> 64; } if (x & 0x400000 > 0) { result = (result * 0x100000000002C5C86) >> 64; } if (x & 0x200000 > 0) { result = (result * 0x10000000000162E43) >> 64; } if (x & 0x100000 > 0) { result = (result * 0x100000000000B1721) >> 64; } if (x & 0x80000 > 0) { result = (result * 0x10000000000058B91) >> 64; } if (x & 0x40000 > 0) { result = (result * 0x1000000000002C5C8) >> 64; } if (x & 0x20000 > 0) { result = (result * 0x100000000000162E4) >> 64; } if (x & 0x10000 > 0) { result = (result * 0x1000000000000B172) >> 64; } } if (x & 0xFF00 > 0) { if (x & 0x8000 > 0) { result = (result * 0x100000000000058B9) >> 64; } if (x & 0x4000 > 0) { result = (result * 0x10000000000002C5D) >> 64; } if (x & 0x2000 > 0) { result = (result * 0x1000000000000162E) >> 64; } if (x & 0x1000 > 0) { result = (result * 0x10000000000000B17) >> 64; } if (x & 0x800 > 0) { result = (result * 0x1000000000000058C) >> 64; } if (x & 0x400 > 0) { result = (result * 0x100000000000002C6) >> 64; } if (x & 0x200 > 0) { result = (result * 0x10000000000000163) >> 64; } if (x & 0x100 > 0) { result = (result * 0x100000000000000B1) >> 64; } } if (x & 0xFF > 0) { if (x & 0x80 > 0) { result = (result * 0x10000000000000059) >> 64; } if (x & 0x40 > 0) { result = (result * 0x1000000000000002C) >> 64; } if (x & 0x20 > 0) { result = (result * 0x10000000000000016) >> 64; } if (x & 0x10 > 0) { result = (result * 0x1000000000000000B) >> 64; } if (x & 0x8 > 0) { result = (result * 0x10000000000000006) >> 64; } if (x & 0x4 > 0) { result = (result * 0x10000000000000003) >> 64; } if (x & 0x2 > 0) { result = (result * 0x10000000000000001) >> 64; } if (x & 0x1 > 0) { result = (result * 0x10000000000000001) >> 64; } } // In the code snippet below, two operations are executed simultaneously: // // 1. The result is multiplied by $(2^n + 1)$, where $2^n$ represents the integer part, and the additional 1 // accounts for the initial guess of 0.5. This is achieved by subtracting from 191 instead of 192. // 2. The result is then converted to an unsigned 60.18-decimal fixed-point format. // // The underlying logic is based on the relationship $2^{191-ip} = 2^{ip} / 2^{191}$, where $ip$ denotes the, // integer part, $2^n$. result *= UNIT; result >>= (191 - (x >> 64)); } } /// @notice Finds the zero-based index of the first 1 in the binary representation of x. /// /// @dev See the note on "msb" in this Wikipedia article: https://en.wikipedia.org/wiki/Find_first_set /// /// Each step in this implementation is equivalent to this high-level code: /// /// ```solidity /// if (x >= 2 ** 128) { /// x >>= 128; /// result += 128; /// } /// ``` /// /// Where 128 is replaced with each respective power of two factor. See the full high-level implementation here: /// https://gist.github.com/PaulRBerg/f932f8693f2733e30c4d479e8e980948 /// /// The Yul instructions used below are: /// /// - "gt" is "greater than" /// - "or" is the OR bitwise operator /// - "shl" is "shift left" /// - "shr" is "shift right" /// /// @param x The uint256 number for which to find the index of the most significant bit. /// @return result The index of the most significant bit as a uint256. /// @custom:smtchecker abstract-function-nondet function msb(uint256 x) pure returns (uint256 result) { // 2^128 assembly ("memory-safe") { let factor := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^64 assembly ("memory-safe") { let factor := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^32 assembly ("memory-safe") { let factor := shl(5, gt(x, 0xFFFFFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^16 assembly ("memory-safe") { let factor := shl(4, gt(x, 0xFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^8 assembly ("memory-safe") { let factor := shl(3, gt(x, 0xFF)) x := shr(factor, x) result := or(result, factor) } // 2^4 assembly ("memory-safe") { let factor := shl(2, gt(x, 0xF)) x := shr(factor, x) result := or(result, factor) } // 2^2 assembly ("memory-safe") { let factor := shl(1, gt(x, 0x3)) x := shr(factor, x) result := or(result, factor) } // 2^1 // No need to shift x any more. assembly ("memory-safe") { let factor := gt(x, 0x1) result := or(result, factor) } } /// @notice Calculates x*y÷denominator with 512-bit precision. /// /// @dev Credits to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv. /// /// Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - The denominator must not be zero. /// - The result must fit in uint256. /// /// @param x The multiplicand as a uint256. /// @param y The multiplier as a uint256. /// @param denominator The divisor as a uint256. /// @return result The result as a uint256. /// @custom:smtchecker abstract-function-nondet function mulDiv(uint256 x, uint256 y, uint256 denominator) pure returns (uint256 result) { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512-bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly ("memory-safe") { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { unchecked { return prod0 / denominator; } } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (prod1 >= denominator) { revert PRBMath_MulDiv_Overflow(x, y, denominator); } //////////////////////////////////////////////////////////////////////////// // 512 by 256 division //////////////////////////////////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly ("memory-safe") { // Compute remainder using the mulmod Yul instruction. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512-bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } unchecked { // Calculate the largest power of two divisor of the denominator using the unary operator ~. This operation cannot overflow // because the denominator cannot be zero at this point in the function execution. The result is always >= 1. // For more detail, see https://cs.stackexchange.com/q/138556/92363. uint256 lpotdod = denominator & (~denominator + 1); uint256 flippedLpotdod; assembly ("memory-safe") { // Factor powers of two out of denominator. denominator := div(denominator, lpotdod) // Divide [prod1 prod0] by lpotdod. prod0 := div(prod0, lpotdod) // Get the flipped value `2^256 / lpotdod`. If the `lpotdod` is zero, the flipped value is one. // `sub(0, lpotdod)` produces the two's complement version of `lpotdod`, which is equivalent to flipping all the bits. // However, `div` interprets this value as an unsigned value: https://ethereum.stackexchange.com/q/147168/24693 flippedLpotdod := add(div(sub(0, lpotdod), lpotdod), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * flippedLpotdod; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; } } /// @notice Calculates x*y÷1e18 with 512-bit precision. /// /// @dev A variant of {mulDiv} with constant folding, i.e. in which the denominator is hard coded to 1e18. /// /// Notes: /// - The body is purposely left uncommented; to understand how this works, see the documentation in {mulDiv}. /// - The result is rounded toward zero. /// - We take as an axiom that the result cannot be `MAX_UINT256` when x and y solve the following system of equations: /// /// $$ /// \begin{cases} /// x * y = MAX\_UINT256 * UNIT \\ /// (x * y) \% UNIT \geq \frac{UNIT}{2} /// \end{cases} /// $$ /// /// Requirements: /// - Refer to the requirements in {mulDiv}. /// - The result must fit in uint256. /// /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number. /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number. /// @return result The result as an unsigned 60.18-decimal fixed-point number. /// @custom:smtchecker abstract-function-nondet function mulDiv18(uint256 x, uint256 y) pure returns (uint256 result) { uint256 prod0; uint256 prod1; assembly ("memory-safe") { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } if (prod1 == 0) { unchecked { return prod0 / UNIT; } } if (prod1 >= UNIT) { revert PRBMath_MulDiv18_Overflow(x, y); } uint256 remainder; assembly ("memory-safe") { remainder := mulmod(x, y, UNIT) result := mul( or( div(sub(prod0, remainder), UNIT_LPOTD), mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1)) ), UNIT_INVERSE ) } } /// @notice Calculates x*y÷denominator with 512-bit precision. /// /// @dev This is an extension of {mulDiv} for signed numbers, which works by computing the signs and the absolute values separately. /// /// Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - Refer to the requirements in {mulDiv}. /// - None of the inputs can be `type(int256).min`. /// - The result must fit in int256. /// /// @param x The multiplicand as an int256. /// @param y The multiplier as an int256. /// @param denominator The divisor as an int256. /// @return result The result as an int256. /// @custom:smtchecker abstract-function-nondet function mulDivSigned(int256 x, int256 y, int256 denominator) pure returns (int256 result) { if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) { revert PRBMath_MulDivSigned_InputTooSmall(); } // Get hold of the absolute values of x, y and the denominator. uint256 xAbs; uint256 yAbs; uint256 dAbs; unchecked { xAbs = x < 0 ? uint256(-x) : uint256(x); yAbs = y < 0 ? uint256(-y) : uint256(y); dAbs = denominator < 0 ? uint256(-denominator) : uint256(denominator); } // Compute the absolute value of x*y÷denominator. The result must fit in int256. uint256 resultAbs = mulDiv(xAbs, yAbs, dAbs); if (resultAbs > uint256(type(int256).max)) { revert PRBMath_MulDivSigned_Overflow(x, y); } // Get the signs of x, y and the denominator. uint256 sx; uint256 sy; uint256 sd; assembly ("memory-safe") { // "sgt" is the "signed greater than" assembly instruction and "sub(0,1)" is -1 in two's complement. sx := sgt(x, sub(0, 1)) sy := sgt(y, sub(0, 1)) sd := sgt(denominator, sub(0, 1)) } // XOR over sx, sy and sd. What this does is to check whether there are 1 or 3 negative signs in the inputs. // If there are, the result should be negative. Otherwise, it should be positive. unchecked { result = sx ^ sy ^ sd == 0 ? -int256(resultAbs) : int256(resultAbs); } } /// @notice Calculates the square root of x using the Babylonian method. /// /// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. /// /// Notes: /// - If x is not a perfect square, the result is rounded down. /// - Credits to OpenZeppelin for the explanations in comments below. /// /// @param x The uint256 number for which to calculate the square root. /// @return result The result as a uint256. /// @custom:smtchecker abstract-function-nondet function sqrt(uint256 x) pure returns (uint256 result) { if (x == 0) { return 0; } // For our first guess, we calculate the biggest power of 2 which is smaller than the square root of x. // // We know that the "msb" (most significant bit) of x is a power of 2 such that we have: // // $$ // msb(x) <= x <= 2*msb(x)$ // $$ // // We write $msb(x)$ as $2^k$, and we get: // // $$ // k = log_2(x) // $$ // // Thus, we can write the initial inequality as: // // $$ // 2^{log_2(x)} <= x <= 2*2^{log_2(x)+1} \\ // sqrt(2^k) <= sqrt(x) < sqrt(2^{k+1}) \\ // 2^{k/2} <= sqrt(x) < 2^{(k+1)/2} <= 2^{(k/2)+1} // $$ // // Consequently, $2^{log_2(x) /2} is a good first approximation of sqrt(x) with at least one correct bit. uint256 xAux = uint256(x); result = 1; if (xAux >= 2 ** 128) { xAux >>= 128; result <<= 64; } if (xAux >= 2 ** 64) { xAux >>= 64; result <<= 32; } if (xAux >= 2 ** 32) { xAux >>= 32; result <<= 16; } if (xAux >= 2 ** 16) { xAux >>= 16; result <<= 8; } if (xAux >= 2 ** 8) { xAux >>= 8; result <<= 4; } if (xAux >= 2 ** 4) { xAux >>= 4; result <<= 2; } if (xAux >= 2 ** 2) { result <<= 1; } // At this point, `result` is an estimation with at least one bit of precision. We know the true value has at // most 128 bits, since it is the square root of a uint256. Newton's method converges quadratically (precision // doubles at every iteration). We thus need at most 7 iteration to turn our partial result with one bit of // precision into the expected uint128 result. unchecked { result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; // If x is not a perfect square, round the result toward zero. uint256 roundedResult = x / result; if (result >= roundedResult) { result = roundedResult; } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { SD1x18 } from "./ValueType.sol"; /// @dev Euler's number as an SD1x18 number. SD1x18 constant E = SD1x18.wrap(2_718281828459045235); /// @dev The maximum value an SD1x18 number can have. int64 constant uMAX_SD1x18 = 9_223372036854775807; SD1x18 constant MAX_SD1x18 = SD1x18.wrap(uMAX_SD1x18); /// @dev The maximum value an SD1x18 number can have. int64 constant uMIN_SD1x18 = -9_223372036854775808; SD1x18 constant MIN_SD1x18 = SD1x18.wrap(uMIN_SD1x18); /// @dev PI as an SD1x18 number. SD1x18 constant PI = SD1x18.wrap(3_141592653589793238); /// @dev The unit number, which gives the decimal precision of SD1x18. SD1x18 constant UNIT = SD1x18.wrap(1e18); int256 constant uUNIT = 1e18;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Casting.sol" as Casting; /// @notice The signed 1.18-decimal fixed-point number representation, which can have up to 1 digit and up to 18 /// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity /// type int64. This is useful when end users want to use int64 to save gas, e.g. with tight variable packing in contract /// storage. type SD1x18 is int64; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { Casting.intoSD59x18, Casting.intoUD2x18, Casting.intoUD60x18, Casting.intoUint256, Casting.intoUint128, Casting.intoUint40, Casting.unwrap } for SD1x18 global;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { SD59x18 } from "./ValueType.sol"; // NOTICE: the "u" prefix stands for "unwrapped". /// @dev Euler's number as an SD59x18 number. SD59x18 constant E = SD59x18.wrap(2_718281828459045235); /// @dev The maximum input permitted in {exp}. int256 constant uEXP_MAX_INPUT = 133_084258667509499440; SD59x18 constant EXP_MAX_INPUT = SD59x18.wrap(uEXP_MAX_INPUT); /// @dev The maximum input permitted in {exp2}. int256 constant uEXP2_MAX_INPUT = 192e18 - 1; SD59x18 constant EXP2_MAX_INPUT = SD59x18.wrap(uEXP2_MAX_INPUT); /// @dev Half the UNIT number. int256 constant uHALF_UNIT = 0.5e18; SD59x18 constant HALF_UNIT = SD59x18.wrap(uHALF_UNIT); /// @dev $log_2(10)$ as an SD59x18 number. int256 constant uLOG2_10 = 3_321928094887362347; SD59x18 constant LOG2_10 = SD59x18.wrap(uLOG2_10); /// @dev $log_2(e)$ as an SD59x18 number. int256 constant uLOG2_E = 1_442695040888963407; SD59x18 constant LOG2_E = SD59x18.wrap(uLOG2_E); /// @dev The maximum value an SD59x18 number can have. int256 constant uMAX_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_792003956564819967; SD59x18 constant MAX_SD59x18 = SD59x18.wrap(uMAX_SD59x18); /// @dev The maximum whole value an SD59x18 number can have. int256 constant uMAX_WHOLE_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_000000000000000000; SD59x18 constant MAX_WHOLE_SD59x18 = SD59x18.wrap(uMAX_WHOLE_SD59x18); /// @dev The minimum value an SD59x18 number can have. int256 constant uMIN_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_792003956564819968; SD59x18 constant MIN_SD59x18 = SD59x18.wrap(uMIN_SD59x18); /// @dev The minimum whole value an SD59x18 number can have. int256 constant uMIN_WHOLE_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_000000000000000000; SD59x18 constant MIN_WHOLE_SD59x18 = SD59x18.wrap(uMIN_WHOLE_SD59x18); /// @dev PI as an SD59x18 number. SD59x18 constant PI = SD59x18.wrap(3_141592653589793238); /// @dev The unit number, which gives the decimal precision of SD59x18. int256 constant uUNIT = 1e18; SD59x18 constant UNIT = SD59x18.wrap(1e18); /// @dev The unit number squared. int256 constant uUNIT_SQUARED = 1e36; SD59x18 constant UNIT_SQUARED = SD59x18.wrap(uUNIT_SQUARED); /// @dev Zero as an SD59x18 number. SD59x18 constant ZERO = SD59x18.wrap(0);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Casting.sol" as Casting; import "./Helpers.sol" as Helpers; import "./Math.sol" as Math; /// @notice The signed 59.18-decimal fixed-point number representation, which can have up to 59 digits and up to 18 /// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity /// type int256. type SD59x18 is int256; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { Casting.intoInt256, Casting.intoSD1x18, Casting.intoUD2x18, Casting.intoUD60x18, Casting.intoUint256, Casting.intoUint128, Casting.intoUint40, Casting.unwrap } for SD59x18 global; /*////////////////////////////////////////////////////////////////////////// MATHEMATICAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ using { Math.abs, Math.avg, Math.ceil, Math.div, Math.exp, Math.exp2, Math.floor, Math.frac, Math.gm, Math.inv, Math.log10, Math.log2, Math.ln, Math.mul, Math.pow, Math.powu, Math.sqrt } for SD59x18 global; /*////////////////////////////////////////////////////////////////////////// HELPER FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ using { Helpers.add, Helpers.and, Helpers.eq, Helpers.gt, Helpers.gte, Helpers.isZero, Helpers.lshift, Helpers.lt, Helpers.lte, Helpers.mod, Helpers.neq, Helpers.not, Helpers.or, Helpers.rshift, Helpers.sub, Helpers.uncheckedAdd, Helpers.uncheckedSub, Helpers.uncheckedUnary, Helpers.xor } for SD59x18 global; /*////////////////////////////////////////////////////////////////////////// OPERATORS //////////////////////////////////////////////////////////////////////////*/ // The global "using for" directive makes it possible to use these operators on the SD59x18 type. using { Helpers.add as +, Helpers.and2 as &, Math.div as /, Helpers.eq as ==, Helpers.gt as >, Helpers.gte as >=, Helpers.lt as <, Helpers.lte as <=, Helpers.mod as %, Math.mul as *, Helpers.neq as !=, Helpers.not as ~, Helpers.or as |, Helpers.sub as -, Helpers.unary as -, Helpers.xor as ^ } for SD59x18 global;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { UD2x18 } from "./ValueType.sol"; /// @dev Euler's number as a UD2x18 number. UD2x18 constant E = UD2x18.wrap(2_718281828459045235); /// @dev The maximum value a UD2x18 number can have. uint64 constant uMAX_UD2x18 = 18_446744073709551615; UD2x18 constant MAX_UD2x18 = UD2x18.wrap(uMAX_UD2x18); /// @dev PI as a UD2x18 number. UD2x18 constant PI = UD2x18.wrap(3_141592653589793238); /// @dev The unit number, which gives the decimal precision of UD2x18. uint256 constant uUNIT = 1e18; UD2x18 constant UNIT = UD2x18.wrap(1e18);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Casting.sol" as Casting; /// @notice The unsigned 2.18-decimal fixed-point number representation, which can have up to 2 digits and up to 18 /// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity /// type uint64. This is useful when end users want to use uint64 to save gas, e.g. with tight variable packing in contract /// storage. type UD2x18 is uint64; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { Casting.intoSD1x18, Casting.intoSD59x18, Casting.intoUD60x18, Casting.intoUint256, Casting.intoUint128, Casting.intoUint40, Casting.unwrap } for UD2x18 global;
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface 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[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "../Common.sol" as Common; import "./Errors.sol" as CastingErrors; import { SD59x18 } from "../sd59x18/ValueType.sol"; import { UD2x18 } from "../ud2x18/ValueType.sol"; import { UD60x18 } from "../ud60x18/ValueType.sol"; import { SD1x18 } from "./ValueType.sol"; /// @notice Casts an SD1x18 number into SD59x18. /// @dev There is no overflow check because the domain of SD1x18 is a subset of SD59x18. function intoSD59x18(SD1x18 x) pure returns (SD59x18 result) { result = SD59x18.wrap(int256(SD1x18.unwrap(x))); } /// @notice Casts an SD1x18 number into UD2x18. /// - x must be positive. function intoUD2x18(SD1x18 x) pure returns (UD2x18 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD1x18_ToUD2x18_Underflow(x); } result = UD2x18.wrap(uint64(xInt)); } /// @notice Casts an SD1x18 number into UD60x18. /// @dev Requirements: /// - x must be positive. function intoUD60x18(SD1x18 x) pure returns (UD60x18 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD1x18_ToUD60x18_Underflow(x); } result = UD60x18.wrap(uint64(xInt)); } /// @notice Casts an SD1x18 number into uint256. /// @dev Requirements: /// - x must be positive. function intoUint256(SD1x18 x) pure returns (uint256 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD1x18_ToUint256_Underflow(x); } result = uint256(uint64(xInt)); } /// @notice Casts an SD1x18 number into uint128. /// @dev Requirements: /// - x must be positive. function intoUint128(SD1x18 x) pure returns (uint128 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD1x18_ToUint128_Underflow(x); } result = uint128(uint64(xInt)); } /// @notice Casts an SD1x18 number into uint40. /// @dev Requirements: /// - x must be positive. /// - x must be less than or equal to `MAX_UINT40`. function intoUint40(SD1x18 x) pure returns (uint40 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD1x18_ToUint40_Underflow(x); } if (xInt > int64(uint64(Common.MAX_UINT40))) { revert CastingErrors.PRBMath_SD1x18_ToUint40_Overflow(x); } result = uint40(uint64(xInt)); } /// @notice Alias for {wrap}. function sd1x18(int64 x) pure returns (SD1x18 result) { result = SD1x18.wrap(x); } /// @notice Unwraps an SD1x18 number into int64. function unwrap(SD1x18 x) pure returns (int64 result) { result = SD1x18.unwrap(x); } /// @notice Wraps an int64 number into SD1x18. function wrap(int64 x) pure returns (SD1x18 result) { result = SD1x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Errors.sol" as CastingErrors; import { MAX_UINT128, MAX_UINT40 } from "../Common.sol"; import { uMAX_SD1x18, uMIN_SD1x18 } from "../sd1x18/Constants.sol"; import { SD1x18 } from "../sd1x18/ValueType.sol"; import { uMAX_UD2x18 } from "../ud2x18/Constants.sol"; import { UD2x18 } from "../ud2x18/ValueType.sol"; import { UD60x18 } from "../ud60x18/ValueType.sol"; import { SD59x18 } from "./ValueType.sol"; /// @notice Casts an SD59x18 number into int256. /// @dev This is basically a functional alias for {unwrap}. function intoInt256(SD59x18 x) pure returns (int256 result) { result = SD59x18.unwrap(x); } /// @notice Casts an SD59x18 number into SD1x18. /// @dev Requirements: /// - x must be greater than or equal to `uMIN_SD1x18`. /// - x must be less than or equal to `uMAX_SD1x18`. function intoSD1x18(SD59x18 x) pure returns (SD1x18 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < uMIN_SD1x18) { revert CastingErrors.PRBMath_SD59x18_IntoSD1x18_Underflow(x); } if (xInt > uMAX_SD1x18) { revert CastingErrors.PRBMath_SD59x18_IntoSD1x18_Overflow(x); } result = SD1x18.wrap(int64(xInt)); } /// @notice Casts an SD59x18 number into UD2x18. /// @dev Requirements: /// - x must be positive. /// - x must be less than or equal to `uMAX_UD2x18`. function intoUD2x18(SD59x18 x) pure returns (UD2x18 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD59x18_IntoUD2x18_Underflow(x); } if (xInt > int256(uint256(uMAX_UD2x18))) { revert CastingErrors.PRBMath_SD59x18_IntoUD2x18_Overflow(x); } result = UD2x18.wrap(uint64(uint256(xInt))); } /// @notice Casts an SD59x18 number into UD60x18. /// @dev Requirements: /// - x must be positive. function intoUD60x18(SD59x18 x) pure returns (UD60x18 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD59x18_IntoUD60x18_Underflow(x); } result = UD60x18.wrap(uint256(xInt)); } /// @notice Casts an SD59x18 number into uint256. /// @dev Requirements: /// - x must be positive. function intoUint256(SD59x18 x) pure returns (uint256 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD59x18_IntoUint256_Underflow(x); } result = uint256(xInt); } /// @notice Casts an SD59x18 number into uint128. /// @dev Requirements: /// - x must be positive. /// - x must be less than or equal to `uMAX_UINT128`. function intoUint128(SD59x18 x) pure returns (uint128 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD59x18_IntoUint128_Underflow(x); } if (xInt > int256(uint256(MAX_UINT128))) { revert CastingErrors.PRBMath_SD59x18_IntoUint128_Overflow(x); } result = uint128(uint256(xInt)); } /// @notice Casts an SD59x18 number into uint40. /// @dev Requirements: /// - x must be positive. /// - x must be less than or equal to `MAX_UINT40`. function intoUint40(SD59x18 x) pure returns (uint40 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD59x18_IntoUint40_Underflow(x); } if (xInt > int256(uint256(MAX_UINT40))) { revert CastingErrors.PRBMath_SD59x18_IntoUint40_Overflow(x); } result = uint40(uint256(xInt)); } /// @notice Alias for {wrap}. function sd(int256 x) pure returns (SD59x18 result) { result = SD59x18.wrap(x); } /// @notice Alias for {wrap}. function sd59x18(int256 x) pure returns (SD59x18 result) { result = SD59x18.wrap(x); } /// @notice Unwraps an SD59x18 number into int256. function unwrap(SD59x18 x) pure returns (int256 result) { result = SD59x18.unwrap(x); } /// @notice Wraps an int256 number into SD59x18. function wrap(int256 x) pure returns (SD59x18 result) { result = SD59x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { wrap } from "./Casting.sol"; import { SD59x18 } from "./ValueType.sol"; /// @notice Implements the checked addition operation (+) in the SD59x18 type. function add(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { return wrap(x.unwrap() + y.unwrap()); } /// @notice Implements the AND (&) bitwise operation in the SD59x18 type. function and(SD59x18 x, int256 bits) pure returns (SD59x18 result) { return wrap(x.unwrap() & bits); } /// @notice Implements the AND (&) bitwise operation in the SD59x18 type. function and2(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { return wrap(x.unwrap() & y.unwrap()); } /// @notice Implements the equal (=) operation in the SD59x18 type. function eq(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() == y.unwrap(); } /// @notice Implements the greater than operation (>) in the SD59x18 type. function gt(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() > y.unwrap(); } /// @notice Implements the greater than or equal to operation (>=) in the SD59x18 type. function gte(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() >= y.unwrap(); } /// @notice Implements a zero comparison check function in the SD59x18 type. function isZero(SD59x18 x) pure returns (bool result) { result = x.unwrap() == 0; } /// @notice Implements the left shift operation (<<) in the SD59x18 type. function lshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) { result = wrap(x.unwrap() << bits); } /// @notice Implements the lower than operation (<) in the SD59x18 type. function lt(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() < y.unwrap(); } /// @notice Implements the lower than or equal to operation (<=) in the SD59x18 type. function lte(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() <= y.unwrap(); } /// @notice Implements the unchecked modulo operation (%) in the SD59x18 type. function mod(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(x.unwrap() % y.unwrap()); } /// @notice Implements the not equal operation (!=) in the SD59x18 type. function neq(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() != y.unwrap(); } /// @notice Implements the NOT (~) bitwise operation in the SD59x18 type. function not(SD59x18 x) pure returns (SD59x18 result) { result = wrap(~x.unwrap()); } /// @notice Implements the OR (|) bitwise operation in the SD59x18 type. function or(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(x.unwrap() | y.unwrap()); } /// @notice Implements the right shift operation (>>) in the SD59x18 type. function rshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) { result = wrap(x.unwrap() >> bits); } /// @notice Implements the checked subtraction operation (-) in the SD59x18 type. function sub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(x.unwrap() - y.unwrap()); } /// @notice Implements the checked unary minus operation (-) in the SD59x18 type. function unary(SD59x18 x) pure returns (SD59x18 result) { result = wrap(-x.unwrap()); } /// @notice Implements the unchecked addition operation (+) in the SD59x18 type. function uncheckedAdd(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { unchecked { result = wrap(x.unwrap() + y.unwrap()); } } /// @notice Implements the unchecked subtraction operation (-) in the SD59x18 type. function uncheckedSub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { unchecked { result = wrap(x.unwrap() - y.unwrap()); } } /// @notice Implements the unchecked unary minus operation (-) in the SD59x18 type. function uncheckedUnary(SD59x18 x) pure returns (SD59x18 result) { unchecked { result = wrap(-x.unwrap()); } } /// @notice Implements the XOR (^) bitwise operation in the SD59x18 type. function xor(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(x.unwrap() ^ y.unwrap()); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "../Common.sol" as Common; import "./Errors.sol" as Errors; import { uEXP_MAX_INPUT, uEXP2_MAX_INPUT, uHALF_UNIT, uLOG2_10, uLOG2_E, uMAX_SD59x18, uMAX_WHOLE_SD59x18, uMIN_SD59x18, uMIN_WHOLE_SD59x18, UNIT, uUNIT, uUNIT_SQUARED, ZERO } from "./Constants.sol"; import { wrap } from "./Helpers.sol"; import { SD59x18 } from "./ValueType.sol"; /// @notice Calculates the absolute value of x. /// /// @dev Requirements: /// - x must be greater than `MIN_SD59x18`. /// /// @param x The SD59x18 number for which to calculate the absolute value. /// @param result The absolute value of x as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function abs(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt == uMIN_SD59x18) { revert Errors.PRBMath_SD59x18_Abs_MinSD59x18(); } result = xInt < 0 ? wrap(-xInt) : x; } /// @notice Calculates the arithmetic average of x and y. /// /// @dev Notes: /// - The result is rounded toward zero. /// /// @param x The first operand as an SD59x18 number. /// @param y The second operand as an SD59x18 number. /// @return result The arithmetic average as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function avg(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); int256 yInt = y.unwrap(); unchecked { // This operation is equivalent to `x / 2 + y / 2`, and it can never overflow. int256 sum = (xInt >> 1) + (yInt >> 1); if (sum < 0) { // If at least one of x and y is odd, add 1 to the result, because shifting negative numbers to the right // rounds toward negative infinity. The right part is equivalent to `sum + (x % 2 == 1 || y % 2 == 1)`. assembly ("memory-safe") { result := add(sum, and(or(xInt, yInt), 1)) } } else { // Add 1 if both x and y are odd to account for the double 0.5 remainder truncated after shifting. result = wrap(sum + (xInt & yInt & 1)); } } } /// @notice Yields the smallest whole number greater than or equal to x. /// /// @dev Optimized for fractional value inputs, because every whole value has (1e18 - 1) fractional counterparts. /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// /// Requirements: /// - x must be less than or equal to `MAX_WHOLE_SD59x18`. /// /// @param x The SD59x18 number to ceil. /// @param result The smallest whole number greater than or equal to x, as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function ceil(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt > uMAX_WHOLE_SD59x18) { revert Errors.PRBMath_SD59x18_Ceil_Overflow(x); } int256 remainder = xInt % uUNIT; if (remainder == 0) { result = x; } else { unchecked { // Solidity uses C fmod style, which returns a modulus with the same sign as x. int256 resultInt = xInt - remainder; if (xInt > 0) { resultInt += uUNIT; } result = wrap(resultInt); } } } /// @notice Divides two SD59x18 numbers, returning a new SD59x18 number. /// /// @dev This is an extension of {Common.mulDiv} for signed numbers, which works by computing the signs and the absolute /// values separately. /// /// Notes: /// - Refer to the notes in {Common.mulDiv}. /// - The result is rounded toward zero. /// /// Requirements: /// - Refer to the requirements in {Common.mulDiv}. /// - None of the inputs can be `MIN_SD59x18`. /// - The denominator must not be zero. /// - The result must fit in SD59x18. /// /// @param x The numerator as an SD59x18 number. /// @param y The denominator as an SD59x18 number. /// @param result The quotient as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function div(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); int256 yInt = y.unwrap(); if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) { revert Errors.PRBMath_SD59x18_Div_InputTooSmall(); } // Get hold of the absolute values of x and y. uint256 xAbs; uint256 yAbs; unchecked { xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt); yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt); } // Compute the absolute value (x*UNIT÷y). The resulting value must fit in SD59x18. uint256 resultAbs = Common.mulDiv(xAbs, uint256(uUNIT), yAbs); if (resultAbs > uint256(uMAX_SD59x18)) { revert Errors.PRBMath_SD59x18_Div_Overflow(x, y); } // Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for // negative, 0 for positive or zero). bool sameSign = (xInt ^ yInt) > -1; // If the inputs have the same sign, the result should be positive. Otherwise, it should be negative. unchecked { result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs)); } } /// @notice Calculates the natural exponent of x using the following formula: /// /// $$ /// e^x = 2^{x * log_2{e}} /// $$ /// /// @dev Notes: /// - Refer to the notes in {exp2}. /// /// Requirements: /// - Refer to the requirements in {exp2}. /// - x must be less than 133_084258667509499441. /// /// @param x The exponent as an SD59x18 number. /// @return result The result as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function exp(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); // This check prevents values greater than 192e18 from being passed to {exp2}. if (xInt > uEXP_MAX_INPUT) { revert Errors.PRBMath_SD59x18_Exp_InputTooBig(x); } unchecked { // Inline the fixed-point multiplication to save gas. int256 doubleUnitProduct = xInt * uLOG2_E; result = exp2(wrap(doubleUnitProduct / uUNIT)); } } /// @notice Calculates the binary exponent of x using the binary fraction method using the following formula: /// /// $$ /// 2^{-x} = \frac{1}{2^x} /// $$ /// /// @dev See https://ethereum.stackexchange.com/q/79903/24693. /// /// Notes: /// - If x is less than -59_794705707972522261, the result is zero. /// /// Requirements: /// - x must be less than 192e18. /// - The result must fit in SD59x18. /// /// @param x The exponent as an SD59x18 number. /// @return result The result as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function exp2(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt < 0) { // The inverse of any number less than this is truncated to zero. if (xInt < -59_794705707972522261) { return ZERO; } unchecked { // Inline the fixed-point inversion to save gas. result = wrap(uUNIT_SQUARED / exp2(wrap(-xInt)).unwrap()); } } else { // Numbers greater than or equal to 192e18 don't fit in the 192.64-bit format. if (xInt > uEXP2_MAX_INPUT) { revert Errors.PRBMath_SD59x18_Exp2_InputTooBig(x); } unchecked { // Convert x to the 192.64-bit fixed-point format. uint256 x_192x64 = uint256((xInt << 64) / uUNIT); // It is safe to cast the result to int256 due to the checks above. result = wrap(int256(Common.exp2(x_192x64))); } } } /// @notice Yields the greatest whole number less than or equal to x. /// /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional /// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// /// Requirements: /// - x must be greater than or equal to `MIN_WHOLE_SD59x18`. /// /// @param x The SD59x18 number to floor. /// @param result The greatest whole number less than or equal to x, as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function floor(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt < uMIN_WHOLE_SD59x18) { revert Errors.PRBMath_SD59x18_Floor_Underflow(x); } int256 remainder = xInt % uUNIT; if (remainder == 0) { result = x; } else { unchecked { // Solidity uses C fmod style, which returns a modulus with the same sign as x. int256 resultInt = xInt - remainder; if (xInt < 0) { resultInt -= uUNIT; } result = wrap(resultInt); } } } /// @notice Yields the excess beyond the floor of x for positive numbers and the part of the number to the right. /// of the radix point for negative numbers. /// @dev Based on the odd function definition. https://en.wikipedia.org/wiki/Fractional_part /// @param x The SD59x18 number to get the fractional part of. /// @param result The fractional part of x as an SD59x18 number. function frac(SD59x18 x) pure returns (SD59x18 result) { result = wrap(x.unwrap() % uUNIT); } /// @notice Calculates the geometric mean of x and y, i.e. $\sqrt{x * y}$. /// /// @dev Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - x * y must fit in SD59x18. /// - x * y must not be negative, since complex numbers are not supported. /// /// @param x The first operand as an SD59x18 number. /// @param y The second operand as an SD59x18 number. /// @return result The result as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function gm(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); int256 yInt = y.unwrap(); if (xInt == 0 || yInt == 0) { return ZERO; } unchecked { // Equivalent to `xy / x != y`. Checking for overflow this way is faster than letting Solidity do it. int256 xyInt = xInt * yInt; if (xyInt / xInt != yInt) { revert Errors.PRBMath_SD59x18_Gm_Overflow(x, y); } // The product must not be negative, since complex numbers are not supported. if (xyInt < 0) { revert Errors.PRBMath_SD59x18_Gm_NegativeProduct(x, y); } // We don't need to multiply the result by `UNIT` here because the x*y product picked up a factor of `UNIT` // during multiplication. See the comments in {Common.sqrt}. uint256 resultUint = Common.sqrt(uint256(xyInt)); result = wrap(int256(resultUint)); } } /// @notice Calculates the inverse of x. /// /// @dev Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - x must not be zero. /// /// @param x The SD59x18 number for which to calculate the inverse. /// @return result The inverse as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function inv(SD59x18 x) pure returns (SD59x18 result) { result = wrap(uUNIT_SQUARED / x.unwrap()); } /// @notice Calculates the natural logarithm of x using the following formula: /// /// $$ /// ln{x} = log_2{x} / log_2{e} /// $$ /// /// @dev Notes: /// - Refer to the notes in {log2}. /// - The precision isn't sufficiently fine-grained to return exactly `UNIT` when the input is `E`. /// /// Requirements: /// - Refer to the requirements in {log2}. /// /// @param x The SD59x18 number for which to calculate the natural logarithm. /// @return result The natural logarithm as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function ln(SD59x18 x) pure returns (SD59x18 result) { // Inline the fixed-point multiplication to save gas. This is overflow-safe because the maximum value that // {log2} can return is ~195_205294292027477728. result = wrap(log2(x).unwrap() * uUNIT / uLOG2_E); } /// @notice Calculates the common logarithm of x using the following formula: /// /// $$ /// log_{10}{x} = log_2{x} / log_2{10} /// $$ /// /// However, if x is an exact power of ten, a hard coded value is returned. /// /// @dev Notes: /// - Refer to the notes in {log2}. /// /// Requirements: /// - Refer to the requirements in {log2}. /// /// @param x The SD59x18 number for which to calculate the common logarithm. /// @return result The common logarithm as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function log10(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt < 0) { revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x); } // Note that the `mul` in this block is the standard multiplication operation, not {SD59x18.mul}. // prettier-ignore assembly ("memory-safe") { switch x case 1 { result := mul(uUNIT, sub(0, 18)) } case 10 { result := mul(uUNIT, sub(1, 18)) } case 100 { result := mul(uUNIT, sub(2, 18)) } case 1000 { result := mul(uUNIT, sub(3, 18)) } case 10000 { result := mul(uUNIT, sub(4, 18)) } case 100000 { result := mul(uUNIT, sub(5, 18)) } case 1000000 { result := mul(uUNIT, sub(6, 18)) } case 10000000 { result := mul(uUNIT, sub(7, 18)) } case 100000000 { result := mul(uUNIT, sub(8, 18)) } case 1000000000 { result := mul(uUNIT, sub(9, 18)) } case 10000000000 { result := mul(uUNIT, sub(10, 18)) } case 100000000000 { result := mul(uUNIT, sub(11, 18)) } case 1000000000000 { result := mul(uUNIT, sub(12, 18)) } case 10000000000000 { result := mul(uUNIT, sub(13, 18)) } case 100000000000000 { result := mul(uUNIT, sub(14, 18)) } case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) } case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) } case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) } case 1000000000000000000 { result := 0 } case 10000000000000000000 { result := uUNIT } case 100000000000000000000 { result := mul(uUNIT, 2) } case 1000000000000000000000 { result := mul(uUNIT, 3) } case 10000000000000000000000 { result := mul(uUNIT, 4) } case 100000000000000000000000 { result := mul(uUNIT, 5) } case 1000000000000000000000000 { result := mul(uUNIT, 6) } case 10000000000000000000000000 { result := mul(uUNIT, 7) } case 100000000000000000000000000 { result := mul(uUNIT, 8) } case 1000000000000000000000000000 { result := mul(uUNIT, 9) } case 10000000000000000000000000000 { result := mul(uUNIT, 10) } case 100000000000000000000000000000 { result := mul(uUNIT, 11) } case 1000000000000000000000000000000 { result := mul(uUNIT, 12) } case 10000000000000000000000000000000 { result := mul(uUNIT, 13) } case 100000000000000000000000000000000 { result := mul(uUNIT, 14) } case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) } case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) } case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) } case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) } case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) } case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) } case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) } case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) } case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) } case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) } case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) } case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) } case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) } case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) } case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) } case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) } case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) } case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) } case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) } case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) } case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) } case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) } case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) } case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) } case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) } case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) } case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) } case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) } case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) } case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) } case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) } case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) } case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) } case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) } case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) } case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) } case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) } case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) } case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) } case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) } case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) } case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) } case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) } case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) } default { result := uMAX_SD59x18 } } if (result.unwrap() == uMAX_SD59x18) { unchecked { // Inline the fixed-point division to save gas. result = wrap(log2(x).unwrap() * uUNIT / uLOG2_10); } } } /// @notice Calculates the binary logarithm of x using the iterative approximation algorithm: /// /// $$ /// log_2{x} = n + log_2{y}, \text{ where } y = x*2^{-n}, \ y \in [1, 2) /// $$ /// /// For $0 \leq x \lt 1$, the input is inverted: /// /// $$ /// log_2{x} = -log_2{\frac{1}{x}} /// $$ /// /// @dev See https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation. /// /// Notes: /// - Due to the lossy precision of the iterative approximation, the results are not perfectly accurate to the last decimal. /// /// Requirements: /// - x must be greater than zero. /// /// @param x The SD59x18 number for which to calculate the binary logarithm. /// @return result The binary logarithm as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function log2(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt <= 0) { revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x); } unchecked { int256 sign; if (xInt >= uUNIT) { sign = 1; } else { sign = -1; // Inline the fixed-point inversion to save gas. xInt = uUNIT_SQUARED / xInt; } // Calculate the integer part of the logarithm. uint256 n = Common.msb(uint256(xInt / uUNIT)); // This is the integer part of the logarithm as an SD59x18 number. The operation can't overflow // because n is at most 255, `UNIT` is 1e18, and the sign is either 1 or -1. int256 resultInt = int256(n) * uUNIT; // Calculate $y = x * 2^{-n}$. int256 y = xInt >> n; // If y is the unit number, the fractional part is zero. if (y == uUNIT) { return wrap(resultInt * sign); } // Calculate the fractional part via the iterative approximation. // The `delta >>= 1` part is equivalent to `delta /= 2`, but shifting bits is more gas efficient. int256 DOUBLE_UNIT = 2e18; for (int256 delta = uHALF_UNIT; delta > 0; delta >>= 1) { y = (y * y) / uUNIT; // Is y^2 >= 2e18 and so in the range [2e18, 4e18)? if (y >= DOUBLE_UNIT) { // Add the 2^{-m} factor to the logarithm. resultInt = resultInt + delta; // Halve y, which corresponds to z/2 in the Wikipedia article. y >>= 1; } } resultInt *= sign; result = wrap(resultInt); } } /// @notice Multiplies two SD59x18 numbers together, returning a new SD59x18 number. /// /// @dev Notes: /// - Refer to the notes in {Common.mulDiv18}. /// /// Requirements: /// - Refer to the requirements in {Common.mulDiv18}. /// - None of the inputs can be `MIN_SD59x18`. /// - The result must fit in SD59x18. /// /// @param x The multiplicand as an SD59x18 number. /// @param y The multiplier as an SD59x18 number. /// @return result The product as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function mul(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); int256 yInt = y.unwrap(); if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) { revert Errors.PRBMath_SD59x18_Mul_InputTooSmall(); } // Get hold of the absolute values of x and y. uint256 xAbs; uint256 yAbs; unchecked { xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt); yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt); } // Compute the absolute value (x*y÷UNIT). The resulting value must fit in SD59x18. uint256 resultAbs = Common.mulDiv18(xAbs, yAbs); if (resultAbs > uint256(uMAX_SD59x18)) { revert Errors.PRBMath_SD59x18_Mul_Overflow(x, y); } // Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for // negative, 0 for positive or zero). bool sameSign = (xInt ^ yInt) > -1; // If the inputs have the same sign, the result should be positive. Otherwise, it should be negative. unchecked { result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs)); } } /// @notice Raises x to the power of y using the following formula: /// /// $$ /// x^y = 2^{log_2{x} * y} /// $$ /// /// @dev Notes: /// - Refer to the notes in {exp2}, {log2}, and {mul}. /// - Returns `UNIT` for 0^0. /// /// Requirements: /// - Refer to the requirements in {exp2}, {log2}, and {mul}. /// /// @param x The base as an SD59x18 number. /// @param y Exponent to raise x to, as an SD59x18 number /// @return result x raised to power y, as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function pow(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); int256 yInt = y.unwrap(); // If both x and y are zero, the result is `UNIT`. If just x is zero, the result is always zero. if (xInt == 0) { return yInt == 0 ? UNIT : ZERO; } // If x is `UNIT`, the result is always `UNIT`. else if (xInt == uUNIT) { return UNIT; } // If y is zero, the result is always `UNIT`. if (yInt == 0) { return UNIT; } // If y is `UNIT`, the result is always x. else if (yInt == uUNIT) { return x; } // Calculate the result using the formula. result = exp2(mul(log2(x), y)); } /// @notice Raises x (an SD59x18 number) to the power y (an unsigned basic integer) using the well-known /// algorithm "exponentiation by squaring". /// /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring. /// /// Notes: /// - Refer to the notes in {Common.mulDiv18}. /// - Returns `UNIT` for 0^0. /// /// Requirements: /// - Refer to the requirements in {abs} and {Common.mulDiv18}. /// - The result must fit in SD59x18. /// /// @param x The base as an SD59x18 number. /// @param y The exponent as a uint256. /// @return result The result as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function powu(SD59x18 x, uint256 y) pure returns (SD59x18 result) { uint256 xAbs = uint256(abs(x).unwrap()); // Calculate the first iteration of the loop in advance. uint256 resultAbs = y & 1 > 0 ? xAbs : uint256(uUNIT); // Equivalent to `for(y /= 2; y > 0; y /= 2)`. uint256 yAux = y; for (yAux >>= 1; yAux > 0; yAux >>= 1) { xAbs = Common.mulDiv18(xAbs, xAbs); // Equivalent to `y % 2 == 1`. if (yAux & 1 > 0) { resultAbs = Common.mulDiv18(resultAbs, xAbs); } } // The result must fit in SD59x18. if (resultAbs > uint256(uMAX_SD59x18)) { revert Errors.PRBMath_SD59x18_Powu_Overflow(x, y); } unchecked { // Is the base negative and the exponent odd? If yes, the result should be negative. int256 resultInt = int256(resultAbs); bool isNegative = x.unwrap() < 0 && y & 1 == 1; if (isNegative) { resultInt = -resultInt; } result = wrap(resultInt); } } /// @notice Calculates the square root of x using the Babylonian method. /// /// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. /// /// Notes: /// - Only the positive root is returned. /// - The result is rounded toward zero. /// /// Requirements: /// - x cannot be negative, since complex numbers are not supported. /// - x must be less than `MAX_SD59x18 / UNIT`. /// /// @param x The SD59x18 number for which to calculate the square root. /// @return result The result as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function sqrt(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt < 0) { revert Errors.PRBMath_SD59x18_Sqrt_NegativeInput(x); } if (xInt > uMAX_SD59x18 / uUNIT) { revert Errors.PRBMath_SD59x18_Sqrt_Overflow(x); } unchecked { // Multiply x by `UNIT` to account for the factor of `UNIT` picked up when multiplying two SD59x18 numbers. // In this case, the two numbers are both the square root. uint256 resultUint = Common.sqrt(uint256(xInt * uUNIT)); result = wrap(int256(resultUint)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "../Common.sol" as Common; import "./Errors.sol" as Errors; import { uMAX_SD1x18 } from "../sd1x18/Constants.sol"; import { SD1x18 } from "../sd1x18/ValueType.sol"; import { SD59x18 } from "../sd59x18/ValueType.sol"; import { UD60x18 } from "../ud60x18/ValueType.sol"; import { UD2x18 } from "./ValueType.sol"; /// @notice Casts a UD2x18 number into SD1x18. /// - x must be less than or equal to `uMAX_SD1x18`. function intoSD1x18(UD2x18 x) pure returns (SD1x18 result) { uint64 xUint = UD2x18.unwrap(x); if (xUint > uint64(uMAX_SD1x18)) { revert Errors.PRBMath_UD2x18_IntoSD1x18_Overflow(x); } result = SD1x18.wrap(int64(xUint)); } /// @notice Casts a UD2x18 number into SD59x18. /// @dev There is no overflow check because the domain of UD2x18 is a subset of SD59x18. function intoSD59x18(UD2x18 x) pure returns (SD59x18 result) { result = SD59x18.wrap(int256(uint256(UD2x18.unwrap(x)))); } /// @notice Casts a UD2x18 number into UD60x18. /// @dev There is no overflow check because the domain of UD2x18 is a subset of UD60x18. function intoUD60x18(UD2x18 x) pure returns (UD60x18 result) { result = UD60x18.wrap(UD2x18.unwrap(x)); } /// @notice Casts a UD2x18 number into uint128. /// @dev There is no overflow check because the domain of UD2x18 is a subset of uint128. function intoUint128(UD2x18 x) pure returns (uint128 result) { result = uint128(UD2x18.unwrap(x)); } /// @notice Casts a UD2x18 number into uint256. /// @dev There is no overflow check because the domain of UD2x18 is a subset of uint256. function intoUint256(UD2x18 x) pure returns (uint256 result) { result = uint256(UD2x18.unwrap(x)); } /// @notice Casts a UD2x18 number into uint40. /// @dev Requirements: /// - x must be less than or equal to `MAX_UINT40`. function intoUint40(UD2x18 x) pure returns (uint40 result) { uint64 xUint = UD2x18.unwrap(x); if (xUint > uint64(Common.MAX_UINT40)) { revert Errors.PRBMath_UD2x18_IntoUint40_Overflow(x); } result = uint40(xUint); } /// @notice Alias for {wrap}. function ud2x18(uint64 x) pure returns (UD2x18 result) { result = UD2x18.wrap(x); } /// @notice Unwrap a UD2x18 number into uint64. function unwrap(UD2x18 x) pure returns (uint64 result) { result = UD2x18.unwrap(x); } /// @notice Wraps a uint64 number into UD2x18. function wrap(uint64 x) pure returns (UD2x18 result) { result = UD2x18.wrap(x); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { SD1x18 } from "./ValueType.sol"; /// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in UD2x18. error PRBMath_SD1x18_ToUD2x18_Underflow(SD1x18 x); /// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in UD60x18. error PRBMath_SD1x18_ToUD60x18_Underflow(SD1x18 x); /// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint128. error PRBMath_SD1x18_ToUint128_Underflow(SD1x18 x); /// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint256. error PRBMath_SD1x18_ToUint256_Underflow(SD1x18 x); /// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint40. error PRBMath_SD1x18_ToUint40_Overflow(SD1x18 x); /// @notice Thrown when trying to cast a SD1x18 number that doesn't fit in uint40. error PRBMath_SD1x18_ToUint40_Underflow(SD1x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { SD59x18 } from "./ValueType.sol"; /// @notice Thrown when taking the absolute value of `MIN_SD59x18`. error PRBMath_SD59x18_Abs_MinSD59x18(); /// @notice Thrown when ceiling a number overflows SD59x18. error PRBMath_SD59x18_Ceil_Overflow(SD59x18 x); /// @notice Thrown when converting a basic integer to the fixed-point format overflows SD59x18. error PRBMath_SD59x18_Convert_Overflow(int256 x); /// @notice Thrown when converting a basic integer to the fixed-point format underflows SD59x18. error PRBMath_SD59x18_Convert_Underflow(int256 x); /// @notice Thrown when dividing two numbers and one of them is `MIN_SD59x18`. error PRBMath_SD59x18_Div_InputTooSmall(); /// @notice Thrown when dividing two numbers and one of the intermediary unsigned results overflows SD59x18. error PRBMath_SD59x18_Div_Overflow(SD59x18 x, SD59x18 y); /// @notice Thrown when taking the natural exponent of a base greater than 133_084258667509499441. error PRBMath_SD59x18_Exp_InputTooBig(SD59x18 x); /// @notice Thrown when taking the binary exponent of a base greater than 192e18. error PRBMath_SD59x18_Exp2_InputTooBig(SD59x18 x); /// @notice Thrown when flooring a number underflows SD59x18. error PRBMath_SD59x18_Floor_Underflow(SD59x18 x); /// @notice Thrown when taking the geometric mean of two numbers and their product is negative. error PRBMath_SD59x18_Gm_NegativeProduct(SD59x18 x, SD59x18 y); /// @notice Thrown when taking the geometric mean of two numbers and multiplying them overflows SD59x18. error PRBMath_SD59x18_Gm_Overflow(SD59x18 x, SD59x18 y); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD1x18. error PRBMath_SD59x18_IntoSD1x18_Overflow(SD59x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD1x18. error PRBMath_SD59x18_IntoSD1x18_Underflow(SD59x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD2x18. error PRBMath_SD59x18_IntoUD2x18_Overflow(SD59x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD2x18. error PRBMath_SD59x18_IntoUD2x18_Underflow(SD59x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD60x18. error PRBMath_SD59x18_IntoUD60x18_Underflow(SD59x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint128. error PRBMath_SD59x18_IntoUint128_Overflow(SD59x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint128. error PRBMath_SD59x18_IntoUint128_Underflow(SD59x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint256. error PRBMath_SD59x18_IntoUint256_Underflow(SD59x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint40. error PRBMath_SD59x18_IntoUint40_Overflow(SD59x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint40. error PRBMath_SD59x18_IntoUint40_Underflow(SD59x18 x); /// @notice Thrown when taking the logarithm of a number less than or equal to zero. error PRBMath_SD59x18_Log_InputTooSmall(SD59x18 x); /// @notice Thrown when multiplying two numbers and one of the inputs is `MIN_SD59x18`. error PRBMath_SD59x18_Mul_InputTooSmall(); /// @notice Thrown when multiplying two numbers and the intermediary absolute result overflows SD59x18. error PRBMath_SD59x18_Mul_Overflow(SD59x18 x, SD59x18 y); /// @notice Thrown when raising a number to a power and the intermediary absolute result overflows SD59x18. error PRBMath_SD59x18_Powu_Overflow(SD59x18 x, uint256 y); /// @notice Thrown when taking the square root of a negative number. error PRBMath_SD59x18_Sqrt_NegativeInput(SD59x18 x); /// @notice Thrown when the calculating the square root overflows SD59x18. error PRBMath_SD59x18_Sqrt_Overflow(SD59x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { UD2x18 } from "./ValueType.sol"; /// @notice Thrown when trying to cast a UD2x18 number that doesn't fit in SD1x18. error PRBMath_UD2x18_IntoSD1x18_Overflow(UD2x18 x); /// @notice Thrown when trying to cast a UD2x18 number that doesn't fit in uint40. error PRBMath_UD2x18_IntoUint40_Overflow(UD2x18 x);
{ "remappings": [ "@openzeppelin/contracts/=lib/@openzeppelin/contracts/", "@prb/math/=lib/@prb/math/", "forge-std/=lib/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
Contract Security Audit
- Hacken - Jan 10th, 2024 - Security Audit Report
Contract ABI
API[{"inputs":[{"internalType":"address","name":"moeLink","type":"address"},{"internalType":"address","name":"sovLink","type":"address"},{"internalType":"address","name":"pptLink","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"PRBMath_MulDiv18_Overflow","type":"error"},{"inputs":[{"internalType":"UD60x18","name":"x","type":"uint256"}],"name":"PRBMath_UD60x18_Exp2_InputTooBig","type":"error"},{"inputs":[{"internalType":"UD60x18","name":"x","type":"uint256"}],"name":"PRBMath_UD60x18_Log_InputTooSmall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"nftId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"nftIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"ClaimBatch","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"allLevels","type":"bool"}],"name":"RefreshRates","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nftId","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"array","type":"uint256[]"}],"name":"SetAPB","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nftId","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"array","type":"uint256[]"}],"name":"SetAPR","type":"event"},{"inputs":[],"name":"APB_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"APB_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"APR_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"APR_MUL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"APR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"apbOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"apbTargetOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"apbs","outputs":[{"internalType":"uint256","name":"stamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"area","type":"uint256"},{"internalType":"uint256","name":"prev","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"apbsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"aprOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"aprTargetOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"aprs","outputs":[{"internalType":"uint256","name":"stamp","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"area","type":"uint256"},{"internalType":"uint256","name":"prev","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"aprsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"name":"claimBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"name":"claimableBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"claimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"name":"claimedBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"getAPB","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"getAPR","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"mintable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"name":"mintableBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"minted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"name":"mintedBatch","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":"account","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint256","name":"balanceOld","type":"uint256"},{"internalType":"uint256","name":"balanceNew","type":"uint256"}],"name":"refreshClaimed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"allLevels","type":"bool"}],"name":"refreshRates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refreshable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"rewardOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"name":"rewardOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint256[]","name":"array","type":"uint256[]"}],"name":"setAPB","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"},{"internalType":"uint256[]","name":"array","type":"uint256[]"}],"name":"setAPBBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint256[]","name":"array","type":"uint256[]"}],"name":"setAPR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"},{"internalType":"uint256[]","name":"array","type":"uint256[]"}],"name":"setAPRBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506040516200528738038062005287833981016040819052620000349162000481565b62000041600033620001a8565b6200007c7f38a1e363a5fc827cc1f19eefcb90a6754e498f53da57f75398e199d1045ef06c60008051602062005267833981519152620001d3565b620000976000805160206200526783398151915233620001a8565b620000d27f8cadeb9575c1633adcbd52ff88944ca1b8e912ca14a96c78420898c01e30346760008051602062005247833981519152620001d3565b620000ed6000805160206200524783398151915233620001a8565b620000f8336200021e565b600380546001600160a01b038086166001600160a01b031992831617909255600480548584169083161790556005805492841692909116919091179055620001408162000270565b60055460405163066ad14f60e21b81523060048201526001600160a01b03909116906319ab453c90602401600060405180830381600087803b1580156200018657600080fd5b505af11580156200019b573d6000803e3d6000fd5b50505050505050620004cb565b620001b48282620002f3565b6000828152600160205260409020620001ce908262000394565b505050565b600082815260208190526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6200027a620003b4565b6001600160a01b038116620002e55760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b620002f0816200021e565b50565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1662000390576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556200034f3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6000620003ab836001600160a01b03841662000412565b90505b92915050565b6002546001600160a01b03163314620004105760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620002dc565b565b60008181526001830160205260408120546200045b57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003ae565b506000620003ae565b80516001600160a01b03811681146200047c57600080fd5b919050565b6000806000606084860312156200049757600080fd5b620004a28462000464565b9250620004b26020850162000464565b9150620004c26040850162000464565b90509250925092565b614d6c80620004db6000396000f3fe608060405234801561001057600080fd5b506004361061028a5760003560e01c8063715018a61161015c578063a217fddf116100ce578063cc046ae411610087578063cc046ae41461064d578063cc1bf6cc14610657578063d547741f1461066a578063e0b335231461067d578063e899fd2614610690578063f2fde38b146106a357600080fd5b8063a217fddf146105af578063aa21c1eb146105b7578063aad3ec96146105de578063ae190514146105f1578063b765680814610604578063ca15c8731461063a57600080fd5b80638da5cb5b116101205780638da5cb5b1461052b5780639010d07c1461055057806391d14854146105635780639c38c548146105765780639eb82fc414610589578063a1b7adef1461059c57600080fd5b8063715018a6146104d757806371ec7450146104df5780637a2d42f8146104f25780637c04c80a146105055780637e640c2f1461051857600080fd5b80632f2ff15d116102005780634dd6c8de116101b95780634dd6c8de1461044857806354f35d211461045b57806360efe3341461048257806365c54f0f1461049557806366236b6f146104bc5780636cf82206146104c457600080fd5b80632f2ff15d146103d657806330f1ee58146103e957806336568abe146103fc5780633b4938611461040f5780634a022eea146104225780634d7291e61461043557600080fd5b806313dcff0d1161025257806313dcff0d146103325780631fc0381214610367578063248a9ca31461037a5780632b37ce221461039d5780632c482250146103b05780632d807b2d146103c357600080fd5b806301ffc9a71461028f57806306a190ef146102b75780630791438d146102cc5780630db424b8146102df57806311f8ec1514610312575b600080fd5b6102a261029d366004614581565b6106b6565b60405190151581526020015b60405180910390f35b6102ca6102c53660046145b9565b6106c7565b005b6102ca6102da3660046145f2565b610b73565b6102f26102ed36600461462b565b610bd8565b6040805194855260208501939093529183015260608201526080016102ae565b610325610320366004614721565b610c1e565b6040516102ae91906147a9565b6103597f38a1e363a5fc827cc1f19eefcb90a6754e498f53da57f75398e199d1045ef06c81565b6040519081526020016102ae565b6103256103753660046147bc565b610d42565b6103596103883660046147bc565b60009081526020819052604090206001015490565b6103596103ab3660046147bc565b610e56565b6102ca6103be3660046147d5565b610e6a565b6102ca6103d1366004614805565b610f75565b6102ca6103e436600461485e565b610fe6565b6103596103f73660046147bc565b611010565b6102ca61040a36600461485e565b611068565b61032561041d3660046147bc565b6110eb565b6103596104303660046147bc565b6111c8565b6103596104433660046147bc565b611211565b61035961045636600461488a565b611233565b6103597fb03495d45a9e4413acab9f875676fbec46185ad404ccaa8085beaf8df1ad275281565b61035961049036600461488a565b61125b565b6103597f50b36571f3d13a5d9b68f1821be5b7ebf7ed496f52cbd5580a50a4268d9de83481565b6102a261129e565b6103256104d2366004614721565b6115b1565b6102ca611660565b6102ca6104ed366004614805565b611674565b610325610500366004614721565b6116df565b6102ca610513366004614721565b6117a9565b6103596105263660046147bc565b611bf2565b6002546001600160a01b03165b6040516001600160a01b0390911681526020016102ae565b61053861055e36600461462b565b611c06565b6102a261057136600461485e565b611c25565b61035961058436600461488a565b611c4e565b610325610597366004614721565b611ccb565b6102f26105aa36600461462b565b611d72565b610359600081565b6103597f8cadeb9575c1633adcbd52ff88944ca1b8e912ca14a96c78420898c01e30346781565b6102ca6105ec36600461488a565b611d8e565b6103596105ff3660046147bc565b612056565b61035961061236600461488a565b6001600160a01b03919091166000908152600760209081526040808320938352929052205490565b6103596106483660046147bc565b612078565b61035962337f9881565b61035961066536600461488a565b61208f565b6102ca61067836600461485e565b6122be565b6102ca61068b3660046147d5565b6122e3565b61032561069e366004614721565b61247b565b6102ca6106b13660046148b4565b6124fa565b60006106c182612573565b92915050565b60055460408051630198a77d60e11b815290516000926001600160a01b0316916303314efa916004808301926104409291908290030181865afa158015610712573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073691906148cf565b9050600080600061074684612598565b925092509250600085610759578161075c565b60225b905060005b81811015610b35576005546000906001600160a01b0316636252e4e76107e561078b856003614963565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa1580156107cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f0919061497a565b60008181526008602052604081209192509061080b90612627565b9050600061081883610e56565b825190915060000361087f57610861600c610838606463bc1913806149a9565b61084291906149a9565b61084c90426149cb565b6000858152600860205260409020908361265d565b600083815260086020526040902061087a90428361265d565b6108a3565b808260200151146108a35760008381526008602052604090206108a390428361265d565b60008985602281106108b7576108b76149de565b60200201511315610aab576000838152600960205260408120549003610a115760408051600480825260a082019092529060208201608080368337505050600084815260096020908152604090912082516109189391929190910190614521565b5061093e62337f98888a8c8860228110610934576109346149de565b602002015161266a565b6000848152600960205260408120805490919061095d5761095d6149de565b906000526020600020018190555060001960096000858152602001908152602001600020600181548110610993576109936149de565b906000526020600020018190555062337f98600960008581526020019081526020016000206002815481106109ca576109ca6149de565b906000526020600020018190555061010060096000858152602001908152602001600020600381548110610a0057610a006149de565b600091825260209091200155610b1f565b60008381526009602052604090208054610a5691906002908110610a3757610a376149de565b9060005260206000200154888a8c8860228110610934576109346149de565b60008481526009602052604081208054909190610a7557610a756149de565b906000526020600020018190555060001960096000858152602001908152602001600020600181548110610a0057610a006149de565b60008381526009602052604090205415610b1f57600083815260096020526040812080548290610add57610add6149de565b9060005260206000200181905550600360096000858152602001908152602001600020600181548110610b1257610b126149de565b6000918252602090912001555b5050508080610b2d906149f4565b915050610761565b5060405186151581527f5467dbee4b7072f6b5874b2eefaa0b951577f0729dfbb60e7b1993e1e7b338029060200160405180910390a1505050505050565b610b7b61269f565b6001600160a01b0384166000908152600660209081526040808320868452909152902054610baa9082846126f9565b6001600160a01b03909416600090815260066020908152604080832095835294905292909220929092555050565b60086020528160005260406000208181548110610bf457600080fd5b60009182526020909120600490910201805460018201546002830154600390930154919450925084565b60606000610c2c8484611ccb565b90506000610c3a85856115b1565b9050600084516001600160401b03811115610c5757610c5761464d565b604051908082528060200260200182016040528015610c80578160200160208202803683370190505b50905060005b8551811015610d3857838181518110610ca157610ca16149de565b6020026020010151838281518110610cbb57610cbb6149de565b60200260200101511115610d2657838181518110610cdb57610cdb6149de565b6020026020010151838281518110610cf557610cf56149de565b6020026020010151610d0791906149cb565b828281518110610d1957610d196149de565b6020026020010181815250505b80610d30816149f4565b915050610c86565b5095945050505050565b60606000610d4f836127e2565b60008181526009602052604090205490915015610dc75760008181526009602090815260409182902080548351818402810184019094528084529091830182828015610dba57602002820191906000526020600020905b815481526020019060010190808311610da6575b5050505050915050919050565b60408051600480825260a0820190925260009160208201608080368337019050509050600381600181518110610dff57610dff6149de565b60200260200101818152505062337f9881600281518110610e2257610e226149de565b60200260200101818152505061010081600381518110610e4457610e446149de565b60209081029190910101529392505050565b60006106c182610e6584610d42565b6128c2565b7f8cadeb9575c1633adcbd52ff88944ca1b8e912ca14a96c78420898c01e303467610e9481612991565b610e9d8261299b565b6000610ea884612aa7565b90506000610eb68285612ae1565b90506000610ec383611bf2565b9050610ed38282620f4240612c3a565b6000838152600a60205260408120610eea90612627565b9050610efa428260000151612d64565b6000848152600a60205260409020610f1390428461265d565b6000848152600b602090815260409091208751610f3292890190614521565b507f260a641f8f87e9560df74b9a49c7aa11f245b937f2c8bf6b2f44958113ff66bc8787604051610f64929190614a0d565b60405180910390a150505050505050565b7f38a1e363a5fc827cc1f19eefcb90a6754e498f53da57f75398e199d1045ef06c610f9f81612991565b60005b8351811015610fe057610fce848281518110610fc057610fc06149de565b6020026020010151846122e3565b80610fd8816149f4565b915050610fa2565b50505050565b60008281526020819052604090206001015461100181612991565b61100b8383612dde565b505050565b60008061101c83611bf2565b9050600061102984612aa7565b6000818152600a602052604090205490915015611061576000818152600a60205260409020611059904284612e00565b949350505050565b5092915050565b6001600160a01b03811633146110dd5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6110e78282612e53565b5050565b606060006110f883612aa7565b6000818152600b60205260409020549091501561116e576000818152600b602090815260409182902080548351818402810184019094528084529091830182828015610dba5760200282019190600052602060002090815481526020019060010190808311610da6575050505050915050919050565b60408051600480825260a08201909252600091602082016080803683370190505090506001816001815181106111a6576111a66149de565b60200260200101818152505061271081600281518110610e2257610e226149de565b6000806111d483610e56565b905060006111e1846127e2565b60008181526008602052604090205490915015611061576000818152600860205260409020611059904284612e00565b60008061121d836127e2565b6000908152600860205260409020549392505050565b6001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6000806112688484611233565b90506000611276858561208f565b9050818111156112935761128a82826149cb565b925050506106c1565b506000949350505050565b600080600560009054906101000a90046001600160a01b03166001600160a01b03166303314efa6040518163ffffffff1660e01b815260040161044060405180830381865afa1580156112f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131991906148cf565b905060008061132783612598565b509150915060005b60228110156115a6576005546000906001600160a01b0316636252e4e76107e561135a856003614963565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa15801561139b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bf919061497a565b6000818152600860205260408120919250906113da90612627565b80519091506000036113f3576001965050505050505090565b6000868460228110611407576114076149de565b602002015113156114fd576000828152600960205260408120549003611434576001965050505050505090565b600082815260096020526040902080546114799190600290811061145a5761145a6149de565b90600052602060002001548587898760228110610934576109346149de565b60008381526009602052604081208054909190611498576114986149de565b9060005260206000200154146114b5576001965050505050505090565b60008281526009602052604090208054600019919060019081106114db576114db6149de565b9060005260206000200154146114f8576001965050505050505090565b611591565b600082815260096020526040902054156115915760008281526009602052604081208054909190611530576115306149de565b906000526020600020015460001461154f576001965050505050505090565b60008281526009602052604090208054600391906001908110611574576115746149de565b906000526020600020015414611591576001965050505050505090565b5050808061159e906149f4565b91505061132f565b506000935050505090565b6060600082516001600160401b038111156115ce576115ce61464d565b6040519080825280602002602001820160405280156115f7578160200160208202803683370190505b50905060005b8351811015611658576116298585838151811061161c5761161c6149de565b602002602001015161208f565b82828151811061163b5761163b6149de565b602090810291909101015280611650816149f4565b9150506115fd565b509392505050565b61166861269f565b6116726000612e75565b565b7f8cadeb9575c1633adcbd52ff88944ca1b8e912ca14a96c78420898c01e30346761169e81612991565b60005b8351811015610fe0576116cd8482815181106116bf576116bf6149de565b602002602001015184610e6a565b806116d7816149f4565b9150506116a1565b6060600082516001600160401b038111156116fc576116fc61464d565b604051908082528060200260200182016040528015611725578160200160208202803683370190505b50905060005b83518110156116585761177a8585838151811061174a5761174a6149de565b60200260200101516001600160a01b03919091166000908152600760209081526040808320938352929052205490565b82828151811061178c5761178c6149de565b6020908102919091010152806117a1816149f4565b91505061172b565b6117b281612ec7565b6117fe5760405162461bcd60e51b815260206004820152601960248201527f756e736f72746564206f72206475706c6963617465206964730000000000000060448201526064016110d4565b600061180a8383610c1e565b905060005b825181101561188857600082828151811061182c5761182c6149de565b6020026020010151116118765760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420636c61696d61626c657360701b60448201526064016110d4565b80611880816149f4565b91505061180f565b5060005b8251811015611bb1578181815181106118a7576118a76149de565b602002602001015160066000866001600160a01b03166001600160a01b0316815260200190815260200160002060008584815181106118e8576118e86149de565b60200260200101518152602001908152602001600020600082825461190d9190614a26565b909155505060045482516001600160a01b0390911690630f7849439084908490811061193b5761193b6149de565b60200260200101516040518263ffffffff1660e01b815260040161196191815260200190565b602060405180830381865afa15801561197e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a2919061497a565b6001600160a01b038516600090815260076020526040812085519091908690859081106119d1576119d16149de565b6020026020010151815260200190815260200160002060008282546119f69190614a26565b909155505060035460045483516001600160a01b039283169263395093519216908190635205332990879087908110611a3157611a316149de565b60200260200101516040518263ffffffff1660e01b8152600401611a5791815260200190565b602060405180830381865afa158015611a74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a98919061497a565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b079190614a39565b5060045482516001600160a01b03909116906340c10f19908690859085908110611b3357611b336149de565b60200260200101516040518363ffffffff1660e01b8152600401611b6c9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015611b8657600080fd5b505af1158015611b9a573d6000803e3d6000fd5b505050508080611ba9906149f4565b91505061188c565b507fcd6b542d20d27ca1f4e7d7a0ee6e7c8719b0f413323169dca8cfe49df665f58a838383604051611be593929190614a56565b60405180910390a1505050565b60006106c182611c01846110eb565b612ae1565b6000828152600160205260408120611c1e9083612f3e565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6004546000906001600160a01b0316630f784943611c6c858561125b565b6040518263ffffffff1660e01b8152600401611c8a91815260200190565b602060405180830381865afa158015611ca7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1e919061497a565b6060600082516001600160401b03811115611ce857611ce861464d565b604051908082528060200260200182016040528015611d11578160200160208202803683370190505b50905060005b835181101561165857611d4385858381518110611d3657611d366149de565b6020026020010151611233565b828281518110611d5557611d556149de565b602090810291909101015280611d6a816149f4565b915050611d17565b600a6020528160005260406000208181548110610bf457600080fd5b6000611d9a838361125b565b905060008111611de05760405162461bcd60e51b8152602060048201526011602482015270696e76616c696420636c61696d61626c6560781b60448201526064016110d4565b6001600160a01b038316600090815260066020908152604080832085845290915281208054839290611e13908490614a26565b909155505060048054604051630f78494360e01b81529182018390526001600160a01b031690630f78494390602401602060405180830381865afa158015611e5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e83919061497a565b6001600160a01b038416600090815260076020908152604080832086845290915281208054909190611eb6908490614a26565b909155505060035460048054604051635205332960e01b81529182018490526001600160a01b03928316926339509351929116908190635205332990602401602060405180830381865afa158015611f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f36919061497a565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa59190614a39565b50600480546040516340c10f1960e01b81526001600160a01b0386811693820193909352602481018490529116906340c10f1990604401600060405180830381600087803b158015611ff657600080fd5b505af115801561200a573d6000803e3d6000fd5b5050604080516001600160a01b0387168152602081018690529081018490527f34fcbac0073d7c3d388e51312faf357774904998eeb8fca628b9e6f65ee1cbf792506060019050611be5565b60008061206283612aa7565b6000908152600a60205260409020549392505050565b60008181526001602052604081206106c190612f4a565b60055460405163a62c779960e01b81526001600160a01b03848116600483015260248201849052600092839291169063a62c779990604401602060405180830381865afa1580156120e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612108919061497a565b9050600061211584611010565b61211e856111c8565b6121289190614a26565b6005546040516336af181960e11b8152600481018790529192506000916001600160a01b03909116906329cd827d908290636d5e303290602401602060405180830381865afa15801561217f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a3919061497a565b6040518263ffffffff1660e01b81526004016121c191815260200190565b602060405180830381865afa1580156121de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612202919061497a565b90506122b4600360009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561225a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227e9190614a8c565b61228990600a614b93565b6122938585614963565b61229d9190614963565b826122af63bc191380620f4240614963565b6126f9565b9695505050505050565b6000828152602081905260409020600101546122d981612991565b61100b8383612e53565b7f38a1e363a5fc827cc1f19eefcb90a6754e498f53da57f75398e199d1045ef06c61230d81612991565b6123168261299b565b6000612321846127e2565b9050600061232f82856128c2565b9050600061233c83610e56565b905061234c8282620f4240612c3a565b600061235786612f54565b6000858152600960209081526040808320805482518185028101850190935280835294955092936123bd9391928301828280156123b357602002820191906000526020600020905b81548152602001906001019080831161239f575b5050505050612f54565b90506123cd828262337f98612c3a565b60008581526008602052604081206123e990605360f81b612f89565b90506123f9428260000151612d64565b6000868152600860205260409020612417904286605360f81b6130c6565b60008681526009602090815260409091208951612436928b0190614521565b507fb9a40ddb8ff9724738fa6518011b9b259a2caba4f31aaeb43da2d9df6215cb808989604051612468929190614a0d565b60405180910390a1505050505050505050565b6004546060906001600160a01b03166391c9ce386124998585610c1e565b6040518263ffffffff1660e01b81526004016124b591906147a9565b600060405180830381865afa1580156124d2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c1e9190810190614ba2565b61250261269f565b6001600160a01b0381166125675760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016110d4565b61257081612e75565b50565b60006001600160e01b03198216635a05180f60e01b14806106c157506106c182613117565b60008080808080805b60228110156126195760008882602281106125be576125be6149de565b60200201511315612607578781602281106125db576125db6149de565b60200201516125ea9084614a26565b92506125f7816001614a26565b915083612603816149f4565b9450505b80612611816149f4565b9150506125a1565b509196909550909350915050565b6126526040518060800160405280600081526020016000815260200160008152602001600081525090565b6106c1826000612f89565b61100b83838360006130c6565b6000808311801561267b5750600082135b61268757612687614c27565b61269685856122af8587614963565b95945050505050565b6002546001600160a01b031633146116725760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016110d4565b60008080600019858709858702925082811083820303915050806000036127335783828161272957612729614993565b0492505050611c1e565b80841161277a5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016110d4565b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b6005546040516336af181960e11b8152600481018390526000916001600160a01b031690636252e4e7906107e5908390636d5e303290602401602060405180830381865afa158015612838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285c919061497a565b6040516001600160e01b031960e085901b168152600481019290925260248201526044015b602060405180830381865afa15801561289e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c1919061497a565b6005546040516336af181960e11b815260048101849052600091829161294a916001600160a01b031690636d5e303290602401602060405180830381865afa158015612912573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612936919061497a565b60408051602081019091528581529061314c565b90506000612981620f4240856001875161296491906149cb565b81518110612974576129746149de565b60200260200101516131da565b905061269682620f4240836126f9565b61257081336132c9565b80516004146129e35760405162461bcd60e51b81526020600482015260146024820152730d2dcecc2d8d2c840c2e4e4c2f25cd8cadccee8d60631b60448201526064016110d4565b6000816001815181106129f8576129f86149de565b602002602001015111612a455760405162461bcd60e51b81526020600482015260156024820152740696e76616c69642061727261795b315d203d3d203605c1b60448201526064016110d4565b600081600281518110612a5a57612a5a6149de565b6020026020010151116125705760405162461bcd60e51b81526020600482015260156024820152740696e76616c69642061727261795b325d203d3d203605c1b60448201526064016110d4565b600554604051636252e4e760e01b81526107e56004820152600360248201526000916001600160a01b031690636252e4e790604401612881565b600080600560009054906101000a90046001600160a01b03166001600160a01b031663f32697166040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b5b919061497a565b600554604051632a84ade960e11b8152600481018790529192506000916001600160a01b03909116906355095bd290602401602060405180830381865afa158015612baa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bce919061497a565b905080821180612bdd57508082145b15611293576000612c05612bf183856149cb565b60408051602081019091528781529061314c565b90506000612c1f620f4240876001895161296491906149cb565b9050612c2f82620f4240836126f9565b9450505050506106c1565b81831015612c9c57612c4d836002614963565b821115612c9c5760405162461bcd60e51b815260206004820152601960248201527f696e76616c6964206368616e67653a20746f6f20736d616c6c0000000000000060448201526064016110d4565b8183118015612cab5750600082115b15612d0657612cbb826002614963565b831115612d065760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206368616e67653a20746f6f206c6172676560381b60448201526064016110d4565b8183118015612d13575081155b1561100b578083111561100b5760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206368616e67653a20746f6f206c6172676560381b60448201526064016110d4565b80156110e75780600c612d7c606463bc1913806149a9565b612d8691906149a9565b612d909190614a26565b82116110e75760405162461bcd60e51b815260206004820152601c60248201527f696e76616c6964206368616e67653a20746f6f206672657175656e740000000060448201526064016110d4565b612de88282613322565b600082815260016020526040902061100b90826133a6565b600080612e0e8585856133bb565b90506000612e1b866134a4565b8051909150851115612e46578051612e3390866149cb565b612e3d90836149a9565b92505050611c1e565b6020015195945050505050565b612e5d8282613559565b600082815260016020526040902061100b90826135be565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600060015b8251811015612f3557828181518110612ee757612ee76149de565b602002602001015183600183612efd91906149cb565b81518110612f0d57612f0d6149de565b602002602001015110612f235750600092915050565b80612f2d816149f4565b915050612ecc565b50600192915050565b6000611c1e83836135d3565b60006106c1825490565b60006002825111612f685762337f986106c1565b81600281518110612f7b57612f7b6149de565b602002602001015192915050565b612fb46040518060800160405280600081526020016000815260200160008152602001600081525090565b8254156130995782546000908490612fce906001906149cb565b81548110612fde57612fde6149de565b90600052602060002090600402016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509050826001600160f81b0319166000146130925783816060015181548110613049576130496149de565b90600052602060002090600402016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509150506106c1565b90506106c1565b60405180608001604052806000815260200160008152602001600081526020016000815250905092915050565b836130d3858585856135fd565b815460018181018455600093845260209384902083516004909302019182559282015192810192909255604081015160028301556060015160039091015550505050565b60006001600160e01b03198216637965db0b60e01b14806106c157506301ffc9a760e01b6001600160e01b03198316146106c1565b60008061319683856000015160028151811061316a5761316a6149de565b60200260200101518660000151600181518110613189576131896149de565b60200260200101516126f9565b905061105984600001516000815181106131b2576131b26149de565b6020026020010151826131c59190614a26565b855180516003908110612974576129746149de565b6000608082101561322d5760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206578706f6e656e743a20746f6f20736d616c6c000000000060448201526064016110d4565b61020082111561327f5760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206578706f6e656e743a20746f6f206c61726765000000000060448201526064016110d4565b60006132b561329c61329986670de0b6b3a7640000614963565b90565b6132b061329986660de0b6b3a76400614963565b613772565b9050611059670de0b6b3a7640000826149a9565b6132d38282611c25565b6110e7576132e081613883565b6132eb836020613895565b6040516020016132fc929190614c61565b60408051601f198184030181529082905262461bcd60e51b82526110d491600401614cd6565b61332c8282611c25565b6110e7576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556133623390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000611c1e836001600160a01b038416613a30565b82546000901561349a57835460009085906133d8906001906149cb565b815481106133e8576133e86149de565b90600052602060002090600402016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509050806000015184101561346f5760405162461bcd60e51b815260206004820152600d60248201526c0696e76616c6964207374616d7609c1b60448201526064016110d4565b805160009061347e90866149cb565b6134889085614963565b9050808260400151612e3d9190614a26565b5060009392505050565b6134cf6040518060800160405280600081526020016000815260200160008152602001600081525090565b81546134ff57604051806080016040528060008152602001600081526020016000815260200160008152506106c1565b81600081548110613512576135126149de565b906000526020600020906004020160405180608001604052908160008201548152602001600182015481526020016002820154815260200160038201548152505092915050565b6135638282611c25565b156110e7576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000611c1e836001600160a01b038416613a7f565b60008260000182815481106135ea576135ea6149de565b9060005260206000200154905092915050565b6136286040518060800160405280600081526020016000815260200160008152602001600081525090565b8454156137495784546000908690613642906001906149cb565b81548110613652576136526149de565b9060005260206000209060040201604051806080016040529081600082015481526020016001820154815260200160028201548152602001600382015481525050905080600001518510156136d95760405162461bcd60e51b815260206004820152600d60248201526c0696e76616c6964207374616d7609c1b60448201526064016110d4565b80516000906136e890876149cb565b6136f29086614963565b90506001600160f81b031984161561370c57865460608301525b60405180608001604052808781526020018681526020018284604001516137339190614a26565b8152602001836060015181525092505050611059565b505060408051608081018252928352602083019190915260009082018190526060820152919050565b6000828281830361379c57801561378a57600061128a565b670de0b6b3a7640000925050506106c1565b670de0b6b3a764000082036137bd57670de0b6b3a7640000925050506106c1565b806000036137d757670de0b6b3a7640000925050506106c1565b670de0b6b3a764000081036137f05784925050506106c1565b670de0b6b3a76400008211156138215761381a61381561380f87613b72565b86613ca6565b613cb5565b925061387b565b600061383f613299846ec097ce7bc90715b34b9f10000000006149a9565b9050600061385861381561385284613b72565b88613ca6565b9050613876613299826ec097ce7bc90715b34b9f10000000006149a9565b945050505b505092915050565b60606106c16001600160a01b03831660145b606060006138a4836002614963565b6138af906002614a26565b6001600160401b038111156138c6576138c661464d565b6040519080825280601f01601f1916602001820160405280156138f0576020820181803683370190505b509050600360fc1b8160008151811061390b5761390b6149de565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061393a5761393a6149de565b60200101906001600160f81b031916908160001a905350600061395e846002614963565b613969906001614a26565b90505b60018111156139e1576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061399d5761399d6149de565b1a60f81b8282815181106139b3576139b36149de565b60200101906001600160f81b031916908160001a90535060049490941c936139da81614d09565b905061396c565b508315611c1e5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016110d4565b6000818152600183016020526040812054613a77575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106c1565b5060006106c1565b60008181526001830160205260408120548015613b68576000613aa36001836149cb565b8554909150600090613ab7906001906149cb565b9050818114613b1c576000866000018281548110613ad757613ad76149de565b9060005260206000200154905080876000018481548110613afa57613afa6149de565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613b2d57613b2d614d20565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106c1565b60009150506106c1565b600081670de0b6b3a7640000811015613ba15760405163036d32ef60e41b8152600481018490526024016110d4565b6000613c2c670de0b6b3a7640000830460016fffffffffffffffffffffffffffffffff821160071b91821c6001600160401b03811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211871b91821c969096119490961792909217171791909117919091171790565b9050670de0b6b3a7640000810282821c670de0b6b3a763ffff198101613c555750949350505050565b671bc16d674ec800006706f05b59d3b200005b8015613c9857670de0b6b3a7640000838002049250818310613c90579283019260019290921c915b60011c613c68565b50825b979650505050505050565b6000611c1e6132998484613d0b565b600081680a688906bd8affffff811115613ce55760405163b3b6ba1f60e01b8152600481018490526024016110d4565b6000613cfd670de0b6b3a7640000604084901b6149a9565b905061105961329982613dc1565b6000808060001984860984860292508281108382030391505080600003613d3f5750670de0b6b3a7640000900490506106c1565b670de0b6b3a76400008110613d7157604051635173648d60e01b815260048101869052602481018590526044016110d4565b6000670de0b6b3a764000085870962040000818503049310909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690291505092915050565b600160bf1b67ff00000000000000821615613ece57678000000000000000821615613df55768016a09e667f3bcc9090260401c5b674000000000000000821615613e14576801306fe0a31b7152df0260401c5b672000000000000000821615613e33576801172b83c7d517adce0260401c5b671000000000000000821615613e525768010b5586cf9890f62a0260401c5b670800000000000000821615613e71576801059b0d31585743ae0260401c5b670400000000000000821615613e9057680102c9a3e778060ee70260401c5b670200000000000000821615613eaf5768010163da9fb33356d80260401c5b670100000000000000821615613ece57680100b1afa5abcbed610260401c5b66ff000000000000821615613fcd576680000000000000821615613efb5768010058c86da1c09ea20260401c5b6640000000000000821615613f19576801002c605e2e8cec500260401c5b6620000000000000821615613f3757680100162f3904051fa10260401c5b6610000000000000821615613f55576801000b175effdc76ba0260401c5b6608000000000000821615613f7357680100058ba01fb9f96d0260401c5b6604000000000000821615613f915768010002c5cc37da94920260401c5b6602000000000000821615613faf576801000162e525ee05470260401c5b6601000000000000821615613fcd5768010000b17255775c040260401c5b65ff00000000008216156140c35765800000000000821615613ff8576801000058b91b5bc9ae0260401c5b6540000000000082161561401557680100002c5c89d5ec6d0260401c5b652000000000008216156140325768010000162e43f4f8310260401c5b6510000000000082161561404f57680100000b1721bcfc9a0260401c5b6508000000000082161561406c5768010000058b90cf1e6e0260401c5b65040000000000821615614089576801000002c5c863b73f0260401c5b650200000000008216156140a657680100000162e430e5a20260401c5b650100000000008216156140c3576801000000b1721835510260401c5b64ff000000008216156141b0576480000000008216156140ec57680100000058b90c0b490260401c5b6440000000008216156141085768010000002c5c8601cc0260401c5b642000000000821615614124576801000000162e42fff00260401c5b6410000000008216156141405768010000000b17217fbb0260401c5b64080000000082161561415c576801000000058b90bfce0260401c5b64040000000082161561417857680100000002c5c85fe30260401c5b6402000000008216156141945768010000000162e42ff10260401c5b6401000000008216156141b057680100000000b17217f80260401c5b63ff0000008216156142945763800000008216156141d75768010000000058b90bfc0260401c5b63400000008216156141f2576801000000002c5c85fe0260401c5b632000000082161561420d57680100000000162e42ff0260401c5b6310000000821615614228576801000000000b17217f0260401c5b630800000082161561424357680100000000058b90c00260401c5b630400000082161561425e5768010000000002c5c8600260401c5b6302000000821615614279576801000000000162e4300260401c5b63010000008216156142945768010000000000b172180260401c5b62ff000082161561436f57628000008216156142b9576801000000000058b90c0260401c5b624000008216156142d357680100000000002c5c860260401c5b622000008216156142ed5768010000000000162e430260401c5b6210000082161561430757680100000000000b17210260401c5b620800008216156143215768010000000000058b910260401c5b6204000082161561433b576801000000000002c5c80260401c5b6202000082161561435557680100000000000162e40260401c5b6201000082161561436f576801000000000000b1720260401c5b61ff008216156144415761800082161561439257680100000000000058b90260401c5b6140008216156143ab5768010000000000002c5d0260401c5b6120008216156143c4576801000000000000162e0260401c5b6110008216156143dd5768010000000000000b170260401c5b6108008216156143f6576801000000000000058c0260401c5b61040082161561440f57680100000000000002c60260401c5b61020082161561442857680100000000000001630260401c5b61010082161561444157680100000000000000b10260401c5b60ff82161561450a57608082161561446257680100000000000000590260401c5b604082161561447a576801000000000000002c0260401c5b602082161561449257680100000000000000160260401c5b60108216156144aa576801000000000000000b0260401c5b60088216156144c257680100000000000000060260401c5b60048216156144da57680100000000000000030260401c5b60028216156144f257680100000000000000010260401c5b600182161561450a57680100000000000000010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b82805482825590600052602060002090810192821561455c579160200282015b8281111561455c578251825591602001919060010190614541565b5061456892915061456c565b5090565b5b80821115614568576000815560010161456d565b60006020828403121561459357600080fd5b81356001600160e01b031981168114611c1e57600080fd5b801515811461257057600080fd5b6000602082840312156145cb57600080fd5b8135611c1e816145ab565b80356001600160a01b03811681146145ed57600080fd5b919050565b6000806000806080858703121561460857600080fd5b614611856145d6565b966020860135965060408601359560600135945092505050565b6000806040838503121561463e57600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561468b5761468b61464d565b604052919050565b60006001600160401b038211156146ac576146ac61464d565b5060051b60200190565b600082601f8301126146c757600080fd5b813560206146dc6146d783614693565b614663565b82815260059290921b840181019181810190868411156146fb57600080fd5b8286015b8481101561471657803583529183019183016146ff565b509695505050505050565b6000806040838503121561473457600080fd5b61473d836145d6565b915060208301356001600160401b0381111561475857600080fd5b614764858286016146b6565b9150509250929050565b600081518084526020808501945080840160005b8381101561479e57815187529582019590820190600101614782565b509495945050505050565b602081526000611c1e602083018461476e565b6000602082840312156147ce57600080fd5b5035919050565b600080604083850312156147e857600080fd5b8235915060208301356001600160401b0381111561475857600080fd5b6000806040838503121561481857600080fd5b82356001600160401b038082111561482f57600080fd5b61483b868387016146b6565b9350602085013591508082111561485157600080fd5b50614764858286016146b6565b6000806040838503121561487157600080fd5b82359150614881602084016145d6565b90509250929050565b6000806040838503121561489d57600080fd5b6148a6836145d6565b946020939093013593505050565b6000602082840312156148c657600080fd5b611c1e826145d6565b60006104408083850312156148e357600080fd5b83601f8401126148f257600080fd5b6040518181018181106001600160401b03821117156149135761491361464d565b60405290830190808583111561492857600080fd5b845b8381101561494257805182526020918201910161492a565b509095945050505050565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176106c1576106c161494d565b60006020828403121561498c57600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b6000826149c657634e487b7160e01b600052601260045260246000fd5b500490565b818103818111156106c1576106c161494d565b634e487b7160e01b600052603260045260246000fd5b600060018201614a0657614a0661494d565b5060010190565b828152604060208201526000611059604083018461476e565b808201808211156106c1576106c161494d565b600060208284031215614a4b57600080fd5b8151611c1e816145ab565b6001600160a01b0384168152606060208201819052600090614a7a9083018561476e565b82810360408401526122b4818561476e565b600060208284031215614a9e57600080fd5b815160ff81168114611c1e57600080fd5b600181815b80851115614aea578160001904821115614ad057614ad061494d565b80851615614add57918102915b93841c9390800290614ab4565b509250929050565b600082614b01575060016106c1565b81614b0e575060006106c1565b8160018114614b245760028114614b2e57614b4a565b60019150506106c1565b60ff841115614b3f57614b3f61494d565b50506001821b6106c1565b5060208310610133831016604e8410600b8410161715614b6d575081810a6106c1565b614b778383614aaf565b8060001904821115614b8b57614b8b61494d565b029392505050565b6000611c1e60ff841683614af2565b60006020808385031215614bb557600080fd5b82516001600160401b03811115614bcb57600080fd5b8301601f81018513614bdc57600080fd5b8051614bea6146d782614693565b81815260059190911b82018301908381019087831115614c0957600080fd5b928401925b82841015613c9b57835182529284019290840190614c0e565b634e487b7160e01b600052600160045260246000fd5b60005b83811015614c58578181015183820152602001614c40565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614c99816017850160208801614c3d565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351614cca816028840160208801614c3d565b01602801949350505050565b6020815260008251806020840152614cf5816040850160208701614c3d565b601f01601f19169190910160400192915050565b600081614d1857614d1861494d565b506000190190565b634e487b7160e01b600052603160045260246000fdfea26469706673582212204e59235108acf579764123c51cf17cdf5a80bc25bae407cc1e492c339cb1a75564736f6c63430008140033b03495d45a9e4413acab9f875676fbec46185ad404ccaa8085beaf8df1ad275250b36571f3d13a5d9b68f1821be5b7ebf7ed496f52cbd5580a50a4268d9de834000000000000000000000000735d8f3b6a5d2c96d0405230c50eaf96794fbb880000000000000000000000007f9c841feadddb4bdbb2a161ca40bebc4f215a9a0000000000000000000000000d7b30580a94e293bd29a9d33798617a384fcb0c
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061028a5760003560e01c8063715018a61161015c578063a217fddf116100ce578063cc046ae411610087578063cc046ae41461064d578063cc1bf6cc14610657578063d547741f1461066a578063e0b335231461067d578063e899fd2614610690578063f2fde38b146106a357600080fd5b8063a217fddf146105af578063aa21c1eb146105b7578063aad3ec96146105de578063ae190514146105f1578063b765680814610604578063ca15c8731461063a57600080fd5b80638da5cb5b116101205780638da5cb5b1461052b5780639010d07c1461055057806391d14854146105635780639c38c548146105765780639eb82fc414610589578063a1b7adef1461059c57600080fd5b8063715018a6146104d757806371ec7450146104df5780637a2d42f8146104f25780637c04c80a146105055780637e640c2f1461051857600080fd5b80632f2ff15d116102005780634dd6c8de116101b95780634dd6c8de1461044857806354f35d211461045b57806360efe3341461048257806365c54f0f1461049557806366236b6f146104bc5780636cf82206146104c457600080fd5b80632f2ff15d146103d657806330f1ee58146103e957806336568abe146103fc5780633b4938611461040f5780634a022eea146104225780634d7291e61461043557600080fd5b806313dcff0d1161025257806313dcff0d146103325780631fc0381214610367578063248a9ca31461037a5780632b37ce221461039d5780632c482250146103b05780632d807b2d146103c357600080fd5b806301ffc9a71461028f57806306a190ef146102b75780630791438d146102cc5780630db424b8146102df57806311f8ec1514610312575b600080fd5b6102a261029d366004614581565b6106b6565b60405190151581526020015b60405180910390f35b6102ca6102c53660046145b9565b6106c7565b005b6102ca6102da3660046145f2565b610b73565b6102f26102ed36600461462b565b610bd8565b6040805194855260208501939093529183015260608201526080016102ae565b610325610320366004614721565b610c1e565b6040516102ae91906147a9565b6103597f38a1e363a5fc827cc1f19eefcb90a6754e498f53da57f75398e199d1045ef06c81565b6040519081526020016102ae565b6103256103753660046147bc565b610d42565b6103596103883660046147bc565b60009081526020819052604090206001015490565b6103596103ab3660046147bc565b610e56565b6102ca6103be3660046147d5565b610e6a565b6102ca6103d1366004614805565b610f75565b6102ca6103e436600461485e565b610fe6565b6103596103f73660046147bc565b611010565b6102ca61040a36600461485e565b611068565b61032561041d3660046147bc565b6110eb565b6103596104303660046147bc565b6111c8565b6103596104433660046147bc565b611211565b61035961045636600461488a565b611233565b6103597fb03495d45a9e4413acab9f875676fbec46185ad404ccaa8085beaf8df1ad275281565b61035961049036600461488a565b61125b565b6103597f50b36571f3d13a5d9b68f1821be5b7ebf7ed496f52cbd5580a50a4268d9de83481565b6102a261129e565b6103256104d2366004614721565b6115b1565b6102ca611660565b6102ca6104ed366004614805565b611674565b610325610500366004614721565b6116df565b6102ca610513366004614721565b6117a9565b6103596105263660046147bc565b611bf2565b6002546001600160a01b03165b6040516001600160a01b0390911681526020016102ae565b61053861055e36600461462b565b611c06565b6102a261057136600461485e565b611c25565b61035961058436600461488a565b611c4e565b610325610597366004614721565b611ccb565b6102f26105aa36600461462b565b611d72565b610359600081565b6103597f8cadeb9575c1633adcbd52ff88944ca1b8e912ca14a96c78420898c01e30346781565b6102ca6105ec36600461488a565b611d8e565b6103596105ff3660046147bc565b612056565b61035961061236600461488a565b6001600160a01b03919091166000908152600760209081526040808320938352929052205490565b6103596106483660046147bc565b612078565b61035962337f9881565b61035961066536600461488a565b61208f565b6102ca61067836600461485e565b6122be565b6102ca61068b3660046147d5565b6122e3565b61032561069e366004614721565b61247b565b6102ca6106b13660046148b4565b6124fa565b60006106c182612573565b92915050565b60055460408051630198a77d60e11b815290516000926001600160a01b0316916303314efa916004808301926104409291908290030181865afa158015610712573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073691906148cf565b9050600080600061074684612598565b925092509250600085610759578161075c565b60225b905060005b81811015610b35576005546000906001600160a01b0316636252e4e76107e561078b856003614963565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa1580156107cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f0919061497a565b60008181526008602052604081209192509061080b90612627565b9050600061081883610e56565b825190915060000361087f57610861600c610838606463bc1913806149a9565b61084291906149a9565b61084c90426149cb565b6000858152600860205260409020908361265d565b600083815260086020526040902061087a90428361265d565b6108a3565b808260200151146108a35760008381526008602052604090206108a390428361265d565b60008985602281106108b7576108b76149de565b60200201511315610aab576000838152600960205260408120549003610a115760408051600480825260a082019092529060208201608080368337505050600084815260096020908152604090912082516109189391929190910190614521565b5061093e62337f98888a8c8860228110610934576109346149de565b602002015161266a565b6000848152600960205260408120805490919061095d5761095d6149de565b906000526020600020018190555060001960096000858152602001908152602001600020600181548110610993576109936149de565b906000526020600020018190555062337f98600960008581526020019081526020016000206002815481106109ca576109ca6149de565b906000526020600020018190555061010060096000858152602001908152602001600020600381548110610a0057610a006149de565b600091825260209091200155610b1f565b60008381526009602052604090208054610a5691906002908110610a3757610a376149de565b9060005260206000200154888a8c8860228110610934576109346149de565b60008481526009602052604081208054909190610a7557610a756149de565b906000526020600020018190555060001960096000858152602001908152602001600020600181548110610a0057610a006149de565b60008381526009602052604090205415610b1f57600083815260096020526040812080548290610add57610add6149de565b9060005260206000200181905550600360096000858152602001908152602001600020600181548110610b1257610b126149de565b6000918252602090912001555b5050508080610b2d906149f4565b915050610761565b5060405186151581527f5467dbee4b7072f6b5874b2eefaa0b951577f0729dfbb60e7b1993e1e7b338029060200160405180910390a1505050505050565b610b7b61269f565b6001600160a01b0384166000908152600660209081526040808320868452909152902054610baa9082846126f9565b6001600160a01b03909416600090815260066020908152604080832095835294905292909220929092555050565b60086020528160005260406000208181548110610bf457600080fd5b60009182526020909120600490910201805460018201546002830154600390930154919450925084565b60606000610c2c8484611ccb565b90506000610c3a85856115b1565b9050600084516001600160401b03811115610c5757610c5761464d565b604051908082528060200260200182016040528015610c80578160200160208202803683370190505b50905060005b8551811015610d3857838181518110610ca157610ca16149de565b6020026020010151838281518110610cbb57610cbb6149de565b60200260200101511115610d2657838181518110610cdb57610cdb6149de565b6020026020010151838281518110610cf557610cf56149de565b6020026020010151610d0791906149cb565b828281518110610d1957610d196149de565b6020026020010181815250505b80610d30816149f4565b915050610c86565b5095945050505050565b60606000610d4f836127e2565b60008181526009602052604090205490915015610dc75760008181526009602090815260409182902080548351818402810184019094528084529091830182828015610dba57602002820191906000526020600020905b815481526020019060010190808311610da6575b5050505050915050919050565b60408051600480825260a0820190925260009160208201608080368337019050509050600381600181518110610dff57610dff6149de565b60200260200101818152505062337f9881600281518110610e2257610e226149de565b60200260200101818152505061010081600381518110610e4457610e446149de565b60209081029190910101529392505050565b60006106c182610e6584610d42565b6128c2565b7f8cadeb9575c1633adcbd52ff88944ca1b8e912ca14a96c78420898c01e303467610e9481612991565b610e9d8261299b565b6000610ea884612aa7565b90506000610eb68285612ae1565b90506000610ec383611bf2565b9050610ed38282620f4240612c3a565b6000838152600a60205260408120610eea90612627565b9050610efa428260000151612d64565b6000848152600a60205260409020610f1390428461265d565b6000848152600b602090815260409091208751610f3292890190614521565b507f260a641f8f87e9560df74b9a49c7aa11f245b937f2c8bf6b2f44958113ff66bc8787604051610f64929190614a0d565b60405180910390a150505050505050565b7f38a1e363a5fc827cc1f19eefcb90a6754e498f53da57f75398e199d1045ef06c610f9f81612991565b60005b8351811015610fe057610fce848281518110610fc057610fc06149de565b6020026020010151846122e3565b80610fd8816149f4565b915050610fa2565b50505050565b60008281526020819052604090206001015461100181612991565b61100b8383612dde565b505050565b60008061101c83611bf2565b9050600061102984612aa7565b6000818152600a602052604090205490915015611061576000818152600a60205260409020611059904284612e00565b949350505050565b5092915050565b6001600160a01b03811633146110dd5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6110e78282612e53565b5050565b606060006110f883612aa7565b6000818152600b60205260409020549091501561116e576000818152600b602090815260409182902080548351818402810184019094528084529091830182828015610dba5760200282019190600052602060002090815481526020019060010190808311610da6575050505050915050919050565b60408051600480825260a08201909252600091602082016080803683370190505090506001816001815181106111a6576111a66149de565b60200260200101818152505061271081600281518110610e2257610e226149de565b6000806111d483610e56565b905060006111e1846127e2565b60008181526008602052604090205490915015611061576000818152600860205260409020611059904284612e00565b60008061121d836127e2565b6000908152600860205260409020549392505050565b6001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6000806112688484611233565b90506000611276858561208f565b9050818111156112935761128a82826149cb565b925050506106c1565b506000949350505050565b600080600560009054906101000a90046001600160a01b03166001600160a01b03166303314efa6040518163ffffffff1660e01b815260040161044060405180830381865afa1580156112f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131991906148cf565b905060008061132783612598565b509150915060005b60228110156115a6576005546000906001600160a01b0316636252e4e76107e561135a856003614963565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa15801561139b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bf919061497a565b6000818152600860205260408120919250906113da90612627565b80519091506000036113f3576001965050505050505090565b6000868460228110611407576114076149de565b602002015113156114fd576000828152600960205260408120549003611434576001965050505050505090565b600082815260096020526040902080546114799190600290811061145a5761145a6149de565b90600052602060002001548587898760228110610934576109346149de565b60008381526009602052604081208054909190611498576114986149de565b9060005260206000200154146114b5576001965050505050505090565b60008281526009602052604090208054600019919060019081106114db576114db6149de565b9060005260206000200154146114f8576001965050505050505090565b611591565b600082815260096020526040902054156115915760008281526009602052604081208054909190611530576115306149de565b906000526020600020015460001461154f576001965050505050505090565b60008281526009602052604090208054600391906001908110611574576115746149de565b906000526020600020015414611591576001965050505050505090565b5050808061159e906149f4565b91505061132f565b506000935050505090565b6060600082516001600160401b038111156115ce576115ce61464d565b6040519080825280602002602001820160405280156115f7578160200160208202803683370190505b50905060005b8351811015611658576116298585838151811061161c5761161c6149de565b602002602001015161208f565b82828151811061163b5761163b6149de565b602090810291909101015280611650816149f4565b9150506115fd565b509392505050565b61166861269f565b6116726000612e75565b565b7f8cadeb9575c1633adcbd52ff88944ca1b8e912ca14a96c78420898c01e30346761169e81612991565b60005b8351811015610fe0576116cd8482815181106116bf576116bf6149de565b602002602001015184610e6a565b806116d7816149f4565b9150506116a1565b6060600082516001600160401b038111156116fc576116fc61464d565b604051908082528060200260200182016040528015611725578160200160208202803683370190505b50905060005b83518110156116585761177a8585838151811061174a5761174a6149de565b60200260200101516001600160a01b03919091166000908152600760209081526040808320938352929052205490565b82828151811061178c5761178c6149de565b6020908102919091010152806117a1816149f4565b91505061172b565b6117b281612ec7565b6117fe5760405162461bcd60e51b815260206004820152601960248201527f756e736f72746564206f72206475706c6963617465206964730000000000000060448201526064016110d4565b600061180a8383610c1e565b905060005b825181101561188857600082828151811061182c5761182c6149de565b6020026020010151116118765760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420636c61696d61626c657360701b60448201526064016110d4565b80611880816149f4565b91505061180f565b5060005b8251811015611bb1578181815181106118a7576118a76149de565b602002602001015160066000866001600160a01b03166001600160a01b0316815260200190815260200160002060008584815181106118e8576118e86149de565b60200260200101518152602001908152602001600020600082825461190d9190614a26565b909155505060045482516001600160a01b0390911690630f7849439084908490811061193b5761193b6149de565b60200260200101516040518263ffffffff1660e01b815260040161196191815260200190565b602060405180830381865afa15801561197e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a2919061497a565b6001600160a01b038516600090815260076020526040812085519091908690859081106119d1576119d16149de565b6020026020010151815260200190815260200160002060008282546119f69190614a26565b909155505060035460045483516001600160a01b039283169263395093519216908190635205332990879087908110611a3157611a316149de565b60200260200101516040518263ffffffff1660e01b8152600401611a5791815260200190565b602060405180830381865afa158015611a74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a98919061497a565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b079190614a39565b5060045482516001600160a01b03909116906340c10f19908690859085908110611b3357611b336149de565b60200260200101516040518363ffffffff1660e01b8152600401611b6c9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015611b8657600080fd5b505af1158015611b9a573d6000803e3d6000fd5b505050508080611ba9906149f4565b91505061188c565b507fcd6b542d20d27ca1f4e7d7a0ee6e7c8719b0f413323169dca8cfe49df665f58a838383604051611be593929190614a56565b60405180910390a1505050565b60006106c182611c01846110eb565b612ae1565b6000828152600160205260408120611c1e9083612f3e565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6004546000906001600160a01b0316630f784943611c6c858561125b565b6040518263ffffffff1660e01b8152600401611c8a91815260200190565b602060405180830381865afa158015611ca7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1e919061497a565b6060600082516001600160401b03811115611ce857611ce861464d565b604051908082528060200260200182016040528015611d11578160200160208202803683370190505b50905060005b835181101561165857611d4385858381518110611d3657611d366149de565b6020026020010151611233565b828281518110611d5557611d556149de565b602090810291909101015280611d6a816149f4565b915050611d17565b600a6020528160005260406000208181548110610bf457600080fd5b6000611d9a838361125b565b905060008111611de05760405162461bcd60e51b8152602060048201526011602482015270696e76616c696420636c61696d61626c6560781b60448201526064016110d4565b6001600160a01b038316600090815260066020908152604080832085845290915281208054839290611e13908490614a26565b909155505060048054604051630f78494360e01b81529182018390526001600160a01b031690630f78494390602401602060405180830381865afa158015611e5f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e83919061497a565b6001600160a01b038416600090815260076020908152604080832086845290915281208054909190611eb6908490614a26565b909155505060035460048054604051635205332960e01b81529182018490526001600160a01b03928316926339509351929116908190635205332990602401602060405180830381865afa158015611f12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f36919061497a565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa59190614a39565b50600480546040516340c10f1960e01b81526001600160a01b0386811693820193909352602481018490529116906340c10f1990604401600060405180830381600087803b158015611ff657600080fd5b505af115801561200a573d6000803e3d6000fd5b5050604080516001600160a01b0387168152602081018690529081018490527f34fcbac0073d7c3d388e51312faf357774904998eeb8fca628b9e6f65ee1cbf792506060019050611be5565b60008061206283612aa7565b6000908152600a60205260409020549392505050565b60008181526001602052604081206106c190612f4a565b60055460405163a62c779960e01b81526001600160a01b03848116600483015260248201849052600092839291169063a62c779990604401602060405180830381865afa1580156120e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612108919061497a565b9050600061211584611010565b61211e856111c8565b6121289190614a26565b6005546040516336af181960e11b8152600481018790529192506000916001600160a01b03909116906329cd827d908290636d5e303290602401602060405180830381865afa15801561217f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a3919061497a565b6040518263ffffffff1660e01b81526004016121c191815260200190565b602060405180830381865afa1580156121de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612202919061497a565b90506122b4600360009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561225a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227e9190614a8c565b61228990600a614b93565b6122938585614963565b61229d9190614963565b826122af63bc191380620f4240614963565b6126f9565b9695505050505050565b6000828152602081905260409020600101546122d981612991565b61100b8383612e53565b7f38a1e363a5fc827cc1f19eefcb90a6754e498f53da57f75398e199d1045ef06c61230d81612991565b6123168261299b565b6000612321846127e2565b9050600061232f82856128c2565b9050600061233c83610e56565b905061234c8282620f4240612c3a565b600061235786612f54565b6000858152600960209081526040808320805482518185028101850190935280835294955092936123bd9391928301828280156123b357602002820191906000526020600020905b81548152602001906001019080831161239f575b5050505050612f54565b90506123cd828262337f98612c3a565b60008581526008602052604081206123e990605360f81b612f89565b90506123f9428260000151612d64565b6000868152600860205260409020612417904286605360f81b6130c6565b60008681526009602090815260409091208951612436928b0190614521565b507fb9a40ddb8ff9724738fa6518011b9b259a2caba4f31aaeb43da2d9df6215cb808989604051612468929190614a0d565b60405180910390a1505050505050505050565b6004546060906001600160a01b03166391c9ce386124998585610c1e565b6040518263ffffffff1660e01b81526004016124b591906147a9565b600060405180830381865afa1580156124d2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c1e9190810190614ba2565b61250261269f565b6001600160a01b0381166125675760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016110d4565b61257081612e75565b50565b60006001600160e01b03198216635a05180f60e01b14806106c157506106c182613117565b60008080808080805b60228110156126195760008882602281106125be576125be6149de565b60200201511315612607578781602281106125db576125db6149de565b60200201516125ea9084614a26565b92506125f7816001614a26565b915083612603816149f4565b9450505b80612611816149f4565b9150506125a1565b509196909550909350915050565b6126526040518060800160405280600081526020016000815260200160008152602001600081525090565b6106c1826000612f89565b61100b83838360006130c6565b6000808311801561267b5750600082135b61268757612687614c27565b61269685856122af8587614963565b95945050505050565b6002546001600160a01b031633146116725760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016110d4565b60008080600019858709858702925082811083820303915050806000036127335783828161272957612729614993565b0492505050611c1e565b80841161277a5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016110d4565b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b6005546040516336af181960e11b8152600481018390526000916001600160a01b031690636252e4e7906107e5908390636d5e303290602401602060405180830381865afa158015612838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285c919061497a565b6040516001600160e01b031960e085901b168152600481019290925260248201526044015b602060405180830381865afa15801561289e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c1919061497a565b6005546040516336af181960e11b815260048101849052600091829161294a916001600160a01b031690636d5e303290602401602060405180830381865afa158015612912573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612936919061497a565b60408051602081019091528581529061314c565b90506000612981620f4240856001875161296491906149cb565b81518110612974576129746149de565b60200260200101516131da565b905061269682620f4240836126f9565b61257081336132c9565b80516004146129e35760405162461bcd60e51b81526020600482015260146024820152730d2dcecc2d8d2c840c2e4e4c2f25cd8cadccee8d60631b60448201526064016110d4565b6000816001815181106129f8576129f86149de565b602002602001015111612a455760405162461bcd60e51b81526020600482015260156024820152740696e76616c69642061727261795b315d203d3d203605c1b60448201526064016110d4565b600081600281518110612a5a57612a5a6149de565b6020026020010151116125705760405162461bcd60e51b81526020600482015260156024820152740696e76616c69642061727261795b325d203d3d203605c1b60448201526064016110d4565b600554604051636252e4e760e01b81526107e56004820152600360248201526000916001600160a01b031690636252e4e790604401612881565b600080600560009054906101000a90046001600160a01b03166001600160a01b031663f32697166040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b5b919061497a565b600554604051632a84ade960e11b8152600481018790529192506000916001600160a01b03909116906355095bd290602401602060405180830381865afa158015612baa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bce919061497a565b905080821180612bdd57508082145b15611293576000612c05612bf183856149cb565b60408051602081019091528781529061314c565b90506000612c1f620f4240876001895161296491906149cb565b9050612c2f82620f4240836126f9565b9450505050506106c1565b81831015612c9c57612c4d836002614963565b821115612c9c5760405162461bcd60e51b815260206004820152601960248201527f696e76616c6964206368616e67653a20746f6f20736d616c6c0000000000000060448201526064016110d4565b8183118015612cab5750600082115b15612d0657612cbb826002614963565b831115612d065760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206368616e67653a20746f6f206c6172676560381b60448201526064016110d4565b8183118015612d13575081155b1561100b578083111561100b5760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206368616e67653a20746f6f206c6172676560381b60448201526064016110d4565b80156110e75780600c612d7c606463bc1913806149a9565b612d8691906149a9565b612d909190614a26565b82116110e75760405162461bcd60e51b815260206004820152601c60248201527f696e76616c6964206368616e67653a20746f6f206672657175656e740000000060448201526064016110d4565b612de88282613322565b600082815260016020526040902061100b90826133a6565b600080612e0e8585856133bb565b90506000612e1b866134a4565b8051909150851115612e46578051612e3390866149cb565b612e3d90836149a9565b92505050611c1e565b6020015195945050505050565b612e5d8282613559565b600082815260016020526040902061100b90826135be565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600060015b8251811015612f3557828181518110612ee757612ee76149de565b602002602001015183600183612efd91906149cb565b81518110612f0d57612f0d6149de565b602002602001015110612f235750600092915050565b80612f2d816149f4565b915050612ecc565b50600192915050565b6000611c1e83836135d3565b60006106c1825490565b60006002825111612f685762337f986106c1565b81600281518110612f7b57612f7b6149de565b602002602001015192915050565b612fb46040518060800160405280600081526020016000815260200160008152602001600081525090565b8254156130995782546000908490612fce906001906149cb565b81548110612fde57612fde6149de565b90600052602060002090600402016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509050826001600160f81b0319166000146130925783816060015181548110613049576130496149de565b90600052602060002090600402016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509150506106c1565b90506106c1565b60405180608001604052806000815260200160008152602001600081526020016000815250905092915050565b836130d3858585856135fd565b815460018181018455600093845260209384902083516004909302019182559282015192810192909255604081015160028301556060015160039091015550505050565b60006001600160e01b03198216637965db0b60e01b14806106c157506301ffc9a760e01b6001600160e01b03198316146106c1565b60008061319683856000015160028151811061316a5761316a6149de565b60200260200101518660000151600181518110613189576131896149de565b60200260200101516126f9565b905061105984600001516000815181106131b2576131b26149de565b6020026020010151826131c59190614a26565b855180516003908110612974576129746149de565b6000608082101561322d5760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206578706f6e656e743a20746f6f20736d616c6c000000000060448201526064016110d4565b61020082111561327f5760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206578706f6e656e743a20746f6f206c61726765000000000060448201526064016110d4565b60006132b561329c61329986670de0b6b3a7640000614963565b90565b6132b061329986660de0b6b3a76400614963565b613772565b9050611059670de0b6b3a7640000826149a9565b6132d38282611c25565b6110e7576132e081613883565b6132eb836020613895565b6040516020016132fc929190614c61565b60408051601f198184030181529082905262461bcd60e51b82526110d491600401614cd6565b61332c8282611c25565b6110e7576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556133623390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000611c1e836001600160a01b038416613a30565b82546000901561349a57835460009085906133d8906001906149cb565b815481106133e8576133e86149de565b90600052602060002090600402016040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250509050806000015184101561346f5760405162461bcd60e51b815260206004820152600d60248201526c0696e76616c6964207374616d7609c1b60448201526064016110d4565b805160009061347e90866149cb565b6134889085614963565b9050808260400151612e3d9190614a26565b5060009392505050565b6134cf6040518060800160405280600081526020016000815260200160008152602001600081525090565b81546134ff57604051806080016040528060008152602001600081526020016000815260200160008152506106c1565b81600081548110613512576135126149de565b906000526020600020906004020160405180608001604052908160008201548152602001600182015481526020016002820154815260200160038201548152505092915050565b6135638282611c25565b156110e7576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000611c1e836001600160a01b038416613a7f565b60008260000182815481106135ea576135ea6149de565b9060005260206000200154905092915050565b6136286040518060800160405280600081526020016000815260200160008152602001600081525090565b8454156137495784546000908690613642906001906149cb565b81548110613652576136526149de565b9060005260206000209060040201604051806080016040529081600082015481526020016001820154815260200160028201548152602001600382015481525050905080600001518510156136d95760405162461bcd60e51b815260206004820152600d60248201526c0696e76616c6964207374616d7609c1b60448201526064016110d4565b80516000906136e890876149cb565b6136f29086614963565b90506001600160f81b031984161561370c57865460608301525b60405180608001604052808781526020018681526020018284604001516137339190614a26565b8152602001836060015181525092505050611059565b505060408051608081018252928352602083019190915260009082018190526060820152919050565b6000828281830361379c57801561378a57600061128a565b670de0b6b3a7640000925050506106c1565b670de0b6b3a764000082036137bd57670de0b6b3a7640000925050506106c1565b806000036137d757670de0b6b3a7640000925050506106c1565b670de0b6b3a764000081036137f05784925050506106c1565b670de0b6b3a76400008211156138215761381a61381561380f87613b72565b86613ca6565b613cb5565b925061387b565b600061383f613299846ec097ce7bc90715b34b9f10000000006149a9565b9050600061385861381561385284613b72565b88613ca6565b9050613876613299826ec097ce7bc90715b34b9f10000000006149a9565b945050505b505092915050565b60606106c16001600160a01b03831660145b606060006138a4836002614963565b6138af906002614a26565b6001600160401b038111156138c6576138c661464d565b6040519080825280601f01601f1916602001820160405280156138f0576020820181803683370190505b509050600360fc1b8160008151811061390b5761390b6149de565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061393a5761393a6149de565b60200101906001600160f81b031916908160001a905350600061395e846002614963565b613969906001614a26565b90505b60018111156139e1576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061399d5761399d6149de565b1a60f81b8282815181106139b3576139b36149de565b60200101906001600160f81b031916908160001a90535060049490941c936139da81614d09565b905061396c565b508315611c1e5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016110d4565b6000818152600183016020526040812054613a77575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106c1565b5060006106c1565b60008181526001830160205260408120548015613b68576000613aa36001836149cb565b8554909150600090613ab7906001906149cb565b9050818114613b1c576000866000018281548110613ad757613ad76149de565b9060005260206000200154905080876000018481548110613afa57613afa6149de565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613b2d57613b2d614d20565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106c1565b60009150506106c1565b600081670de0b6b3a7640000811015613ba15760405163036d32ef60e41b8152600481018490526024016110d4565b6000613c2c670de0b6b3a7640000830460016fffffffffffffffffffffffffffffffff821160071b91821c6001600160401b03811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211871b91821c969096119490961792909217171791909117919091171790565b9050670de0b6b3a7640000810282821c670de0b6b3a763ffff198101613c555750949350505050565b671bc16d674ec800006706f05b59d3b200005b8015613c9857670de0b6b3a7640000838002049250818310613c90579283019260019290921c915b60011c613c68565b50825b979650505050505050565b6000611c1e6132998484613d0b565b600081680a688906bd8affffff811115613ce55760405163b3b6ba1f60e01b8152600481018490526024016110d4565b6000613cfd670de0b6b3a7640000604084901b6149a9565b905061105961329982613dc1565b6000808060001984860984860292508281108382030391505080600003613d3f5750670de0b6b3a7640000900490506106c1565b670de0b6b3a76400008110613d7157604051635173648d60e01b815260048101869052602481018590526044016110d4565b6000670de0b6b3a764000085870962040000818503049310909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690291505092915050565b600160bf1b67ff00000000000000821615613ece57678000000000000000821615613df55768016a09e667f3bcc9090260401c5b674000000000000000821615613e14576801306fe0a31b7152df0260401c5b672000000000000000821615613e33576801172b83c7d517adce0260401c5b671000000000000000821615613e525768010b5586cf9890f62a0260401c5b670800000000000000821615613e71576801059b0d31585743ae0260401c5b670400000000000000821615613e9057680102c9a3e778060ee70260401c5b670200000000000000821615613eaf5768010163da9fb33356d80260401c5b670100000000000000821615613ece57680100b1afa5abcbed610260401c5b66ff000000000000821615613fcd576680000000000000821615613efb5768010058c86da1c09ea20260401c5b6640000000000000821615613f19576801002c605e2e8cec500260401c5b6620000000000000821615613f3757680100162f3904051fa10260401c5b6610000000000000821615613f55576801000b175effdc76ba0260401c5b6608000000000000821615613f7357680100058ba01fb9f96d0260401c5b6604000000000000821615613f915768010002c5cc37da94920260401c5b6602000000000000821615613faf576801000162e525ee05470260401c5b6601000000000000821615613fcd5768010000b17255775c040260401c5b65ff00000000008216156140c35765800000000000821615613ff8576801000058b91b5bc9ae0260401c5b6540000000000082161561401557680100002c5c89d5ec6d0260401c5b652000000000008216156140325768010000162e43f4f8310260401c5b6510000000000082161561404f57680100000b1721bcfc9a0260401c5b6508000000000082161561406c5768010000058b90cf1e6e0260401c5b65040000000000821615614089576801000002c5c863b73f0260401c5b650200000000008216156140a657680100000162e430e5a20260401c5b650100000000008216156140c3576801000000b1721835510260401c5b64ff000000008216156141b0576480000000008216156140ec57680100000058b90c0b490260401c5b6440000000008216156141085768010000002c5c8601cc0260401c5b642000000000821615614124576801000000162e42fff00260401c5b6410000000008216156141405768010000000b17217fbb0260401c5b64080000000082161561415c576801000000058b90bfce0260401c5b64040000000082161561417857680100000002c5c85fe30260401c5b6402000000008216156141945768010000000162e42ff10260401c5b6401000000008216156141b057680100000000b17217f80260401c5b63ff0000008216156142945763800000008216156141d75768010000000058b90bfc0260401c5b63400000008216156141f2576801000000002c5c85fe0260401c5b632000000082161561420d57680100000000162e42ff0260401c5b6310000000821615614228576801000000000b17217f0260401c5b630800000082161561424357680100000000058b90c00260401c5b630400000082161561425e5768010000000002c5c8600260401c5b6302000000821615614279576801000000000162e4300260401c5b63010000008216156142945768010000000000b172180260401c5b62ff000082161561436f57628000008216156142b9576801000000000058b90c0260401c5b624000008216156142d357680100000000002c5c860260401c5b622000008216156142ed5768010000000000162e430260401c5b6210000082161561430757680100000000000b17210260401c5b620800008216156143215768010000000000058b910260401c5b6204000082161561433b576801000000000002c5c80260401c5b6202000082161561435557680100000000000162e40260401c5b6201000082161561436f576801000000000000b1720260401c5b61ff008216156144415761800082161561439257680100000000000058b90260401c5b6140008216156143ab5768010000000000002c5d0260401c5b6120008216156143c4576801000000000000162e0260401c5b6110008216156143dd5768010000000000000b170260401c5b6108008216156143f6576801000000000000058c0260401c5b61040082161561440f57680100000000000002c60260401c5b61020082161561442857680100000000000001630260401c5b61010082161561444157680100000000000000b10260401c5b60ff82161561450a57608082161561446257680100000000000000590260401c5b604082161561447a576801000000000000002c0260401c5b602082161561449257680100000000000000160260401c5b60108216156144aa576801000000000000000b0260401c5b60088216156144c257680100000000000000060260401c5b60048216156144da57680100000000000000030260401c5b60028216156144f257680100000000000000010260401c5b600182161561450a57680100000000000000010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b82805482825590600052602060002090810192821561455c579160200282015b8281111561455c578251825591602001919060010190614541565b5061456892915061456c565b5090565b5b80821115614568576000815560010161456d565b60006020828403121561459357600080fd5b81356001600160e01b031981168114611c1e57600080fd5b801515811461257057600080fd5b6000602082840312156145cb57600080fd5b8135611c1e816145ab565b80356001600160a01b03811681146145ed57600080fd5b919050565b6000806000806080858703121561460857600080fd5b614611856145d6565b966020860135965060408601359560600135945092505050565b6000806040838503121561463e57600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561468b5761468b61464d565b604052919050565b60006001600160401b038211156146ac576146ac61464d565b5060051b60200190565b600082601f8301126146c757600080fd5b813560206146dc6146d783614693565b614663565b82815260059290921b840181019181810190868411156146fb57600080fd5b8286015b8481101561471657803583529183019183016146ff565b509695505050505050565b6000806040838503121561473457600080fd5b61473d836145d6565b915060208301356001600160401b0381111561475857600080fd5b614764858286016146b6565b9150509250929050565b600081518084526020808501945080840160005b8381101561479e57815187529582019590820190600101614782565b509495945050505050565b602081526000611c1e602083018461476e565b6000602082840312156147ce57600080fd5b5035919050565b600080604083850312156147e857600080fd5b8235915060208301356001600160401b0381111561475857600080fd5b6000806040838503121561481857600080fd5b82356001600160401b038082111561482f57600080fd5b61483b868387016146b6565b9350602085013591508082111561485157600080fd5b50614764858286016146b6565b6000806040838503121561487157600080fd5b82359150614881602084016145d6565b90509250929050565b6000806040838503121561489d57600080fd5b6148a6836145d6565b946020939093013593505050565b6000602082840312156148c657600080fd5b611c1e826145d6565b60006104408083850312156148e357600080fd5b83601f8401126148f257600080fd5b6040518181018181106001600160401b03821117156149135761491361464d565b60405290830190808583111561492857600080fd5b845b8381101561494257805182526020918201910161492a565b509095945050505050565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176106c1576106c161494d565b60006020828403121561498c57600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b6000826149c657634e487b7160e01b600052601260045260246000fd5b500490565b818103818111156106c1576106c161494d565b634e487b7160e01b600052603260045260246000fd5b600060018201614a0657614a0661494d565b5060010190565b828152604060208201526000611059604083018461476e565b808201808211156106c1576106c161494d565b600060208284031215614a4b57600080fd5b8151611c1e816145ab565b6001600160a01b0384168152606060208201819052600090614a7a9083018561476e565b82810360408401526122b4818561476e565b600060208284031215614a9e57600080fd5b815160ff81168114611c1e57600080fd5b600181815b80851115614aea578160001904821115614ad057614ad061494d565b80851615614add57918102915b93841c9390800290614ab4565b509250929050565b600082614b01575060016106c1565b81614b0e575060006106c1565b8160018114614b245760028114614b2e57614b4a565b60019150506106c1565b60ff841115614b3f57614b3f61494d565b50506001821b6106c1565b5060208310610133831016604e8410600b8410161715614b6d575081810a6106c1565b614b778383614aaf565b8060001904821115614b8b57614b8b61494d565b029392505050565b6000611c1e60ff841683614af2565b60006020808385031215614bb557600080fd5b82516001600160401b03811115614bcb57600080fd5b8301601f81018513614bdc57600080fd5b8051614bea6146d782614693565b81815260059190911b82018301908381019087831115614c0957600080fd5b928401925b82841015613c9b57835182529284019290840190614c0e565b634e487b7160e01b600052600160045260246000fd5b60005b83811015614c58578181015183820152602001614c40565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614c99816017850160208801614c3d565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351614cca816028840160208801614c3d565b01602801949350505050565b6020815260008251806020840152614cf5816040850160208701614c3d565b601f01601f19169190910160400192915050565b600081614d1857614d1861494d565b506000190190565b634e487b7160e01b600052603160045260246000fdfea26469706673582212204e59235108acf579764123c51cf17cdf5a80bc25bae407cc1e492c339cb1a75564736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000735d8f3b6a5d2c96d0405230c50eaf96794fbb880000000000000000000000007f9c841feadddb4bdbb2a161ca40bebc4f215a9a0000000000000000000000000d7b30580a94e293bd29a9d33798617a384fcb0c
-----Decoded View---------------
Arg [0] : moeLink (address): 0x735D8f3B6A5d2c96D0405230c50Eaf96794FbB88
Arg [1] : sovLink (address): 0x7F9C841FEAdDdB4bdBB2A161cA40bEbc4F215a9A
Arg [2] : pptLink (address): 0x0d7b30580A94E293BD29A9d33798617a384fCB0C
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000735d8f3b6a5d2c96d0405230c50eaf96794fbb88
Arg [1] : 0000000000000000000000007f9c841feadddb4bdbb2a161ca40bebc4f215a9a
Arg [2] : 0000000000000000000000000d7b30580a94e293bd29a9d33798617a384fcb0c
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
AVAX | 100.00% | $0.000023 | 60,631,032.273 | $1,383.6 |
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.