Overview
ETH Balance
ETH Value
$0.00
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "../Governance/RebootFlexVotingClientUpgradeable.sol";
import "./SoulboundERC1155Upgradeable.sol";
import "../Utils/ContractRolesUpgradeable.sol";
import "../Utils/DirectoryConsumerUpgradeable.sol";
import "../Interfaces/ITickets.sol";
import "../Interfaces/IGame.sol";
import "../Interfaces/ICommonOFT.sol";
import "../Libraries/PVMath.sol";
import "../Libraries/LzLib.sol";
/**
* @title Tickets Token
*
* @author Jack Chuma, Niftydude
*
* @notice A soulbound ERC1155 wrapper token for Reboot's GG token.
*/
contract Tickets is
SoulboundERC1155Upgradeable,
RebootFlexVotingClientUpgradeable,
DirectoryConsumerUpgradeable,
ContractRolesUpgradeable,
ITickets,
UUPSUpgradeable
{
using PVMath for uint256;
uint16 public novaChainId;
bytes public adapterParams;
mapping(uint256 => uint256) public ticketsPerGG;
function __Tickets_init(
string memory _uri,
address _adminWallet,
IDirectory _directory,
uint256 _ticketsPerGG
) public initializer {
__SoulboundERC1155_init(_uri);
__ContractRoles_init(_adminWallet);
__Directory_Consumer_init(_directory);
__RebootFlexVotingClient_init(_directory.governorContract());
_validateTicketsPerGG(_ticketsPerGG);
ticketsPerGG[0] = _ticketsPerGG;
novaChainId = 175;
_setAdapterParams(1, 2000000);
}
function setNovaChainId(uint16 _novaChainId) external onlyGov {
novaChainId = _novaChainId;
emit NovaChainIdSet(_novaChainId);
}
function setAdapterParams(
uint16 _version,
uint256 _gasForDestination
) external onlyGov {
_setAdapterParams(_version, _gasForDestination);
emit AdapterParamsSet(_version, _gasForDestination);
}
/**
* @notice Governance function to update the uri string.
*
* @param _uri New uri string
*/
function setURI(string memory _uri) external onlyGov {
_setURI(_uri);
emit UriSet(_uri);
}
function setTicketsPerGG(
uint256 _gameId,
uint256 _ticketsPerGG
) external protocolActive {
if (msg.sender != address(directory.factoryController()))
revert InvalidCaller();
if (ticketsPerGG[_gameId] != 0) revert GameValueAlreadySet();
_validateTicketsPerGG(_ticketsPerGG);
ticketsPerGG[_gameId] = _ticketsPerGG;
emit TicketsPerGGSet(_gameId, _ticketsPerGG);
}
/**
* @notice For a trusted protocol contract to mint Ticket tokens.
*
* @dev Any minted Ticket tokens have to be backed by GG tokens that will be stored in this contract.
* @dev The user will receive voting power from those tokens.
*
* @param to Address to send Ticket to
* @param ggFrom Address supplying the GG collateral
* @param amount Amount of tokens to mint
*/
function mint(
address to,
address ggFrom,
uint256 id,
uint256 amount
) external onlyRole(PROTOCOL_ROLE) {
if (amount == 0) revert ZeroTokens();
uint256 _ticketsPerGG = ticketsPerGG[id];
if (_ticketsPerGG == 0) revert InvalidId();
_mint(to, id, amount, "");
uint256 _ggAmount = amount.div(_ticketsPerGG);
increaseRawBalance(to, _ggAmount);
directory.ggt().transferFrom(ggFrom, address(this), _ggAmount);
}
/**
* @notice Extracts locked GG out of tickets by burning tickets and extractors.
*
* @param playerWallet address of player wallet to burn tickets and extractors from
* @param gameId ID of ticket
* @param extractorId ID of extractors to use
* @param amount Amount of tickets to burn
*/
function burnToExtract(
address playerWallet,
uint256 gameId,
uint256 extractorId,
uint256 amount,
uint16 chainId
)
external
payable
protocolActive
onlySelfOrRole(playerWallet, RELAYER_ROLE)
{
if (extractorId == 0) revert MustUseExtractors();
uint256 _ggAmount = _burn(playerWallet, gameId, extractorId, amount);
decreaseRawBalance(playerWallet, _ggAmount);
if (chainId == novaChainId) {
directory.ggt().transfer(playerWallet, _ggAmount);
} else {
directory.ggt().sendFrom{ value: msg.value }(
address(this),
chainId,
LzLib.addressToBytes32(playerWallet),
_ggAmount,
ICommonOFT.LzCallParams(
payable(msg.sender),
address(0x0),
adapterParams
)
);
}
}
/**
* @notice For a trusted protocol contract to burn Ticket and transfer the underlying collateral to a specified address.
*
* @dev For vrgda purchase where collateral is being moved to item contract
*
* @param from Address to burn ticket from
* @param ggTo Address to send the underlying collateral to
* @param amount Amount of tokens to burn
* @param extractorId ID of extractors to burn
*/
function burn(
address from,
address ggTo,
uint256 amount,
uint256 gameId,
uint256 extractorId
) external onlyRole(PROTOCOL_ROLE) {
uint256 _ggAmount = _burn(from, gameId, extractorId, amount);
decreaseRawBalance(from, _ggAmount);
directory.ggt().transfer(ggTo, _ggAmount);
}
/**
* @notice Gas efficient function for token market to distribute Ticket payments to different receivers
*
* @dev For vrgda purchase where collateral is being moved to addresses other than item contract
*
* @param from Address to burn ticket from
* @param shares affiliate share, dev share and protocol share of payment in an array
* @param receivers receiving addresses for affiliate share, dev share, protocol share and collateral
* @param totalAmount total amount of Ticket to burn
*/
function burnAndTransferSaleShares(
address from,
uint256 gameId,
uint256[3] calldata shares,
address[4] calldata receivers,
uint256 totalAmount
) external onlyRole(PROTOCOL_ROLE) returns (uint256) {
uint256 _ggAmount = _burn(from, gameId, 0, totalAmount);
// calculate and distribute affiliate share if neccessary
uint256 _affAmount;
if (shares[0] > 0) {
_affAmount = shares[0].mul(_ggAmount);
directory.ggt().transfer(receivers[0], _affAmount);
}
// calculate and distribute dev share
uint256 _devAmount = shares[1].mul(_ggAmount);
directory.ggt().transfer(receivers[1], _devAmount);
// calculate and distribute protocol fee
uint256 _protocolAmount = shares[2].mul(_ggAmount);
directory.ggt().transfer(receivers[2], _protocolAmount);
uint256 _collateralGG = _ggAmount -
_affAmount -
_devAmount -
_protocolAmount;
directory.ggt().transfer(receivers[3], _collateralGG);
decreaseRawBalance(from, _ggAmount);
return _collateralGG;
}
/**
* @dev Burn tokens and optionally burn extractors
*/
function _burn(
address _from, // Address from which tokens are burned
uint256 _gameId,
uint256 _extractorId, // Extractor ID (optional)
uint256 _amount // Amount of tokens to burn
) private returns (uint256 _ggAmount) {
// Revert if the amount of tokens to burn is zero
if (_amount == 0) revert ZeroTokens();
// Convert the token amount to GG amount
_ggAmount = _amount.div(ticketsPerGG[_gameId]);
// If extractorID 0 is passed in, no extractors will be burned
if (_extractorId > 0) {
if (_gameId > 0) {
address _game = directory.factoryController().gameAddress(
_gameId
);
if (!IGame(_game).isWhitelisted(_extractorId))
revert ExtractorBlockedByGame();
}
// Get the Extractors contract
IExtractors _extractors = directory.extractors();
// Get the GG per extractor value for the extractor ID
uint256 _ggPerExtractor = _extractors.getGGPerExtractor(
_extractorId
);
// Calculate the amount of extractors to burn
uint256 _extractorsAmount = _ggAmount.div(_ggPerExtractor);
// Burn the extractors
_extractors.burn(_from, _extractorId, _extractorsAmount);
}
// Burn the tokens
_burn(_from, _gameId, _amount);
// Return the amount of GG burned
return _ggAmount;
}
/**
* @dev Override required by solidity.
*/
function supportsInterface(
bytes4 interfaceId
)
public
view
override(ERC1155Upgradeable, AccessControlUpgradeable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
function _setAdapterParams(
uint16 _version,
uint256 _gasForDestination
) private {
adapterParams = abi.encodePacked(_version, _gasForDestination);
}
function _validateTicketsPerGG(uint256 _ticketsPerGG) private pure {
if (_ticketsPerGG == 0) revert MustHaveTicketPerGG();
if (_ticketsPerGG > 2.75e50) revert TicketPerGGTooHigh();
}
function _authorizeUpgrade(
address newImplementation
) internal override onlyGov {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControlUpgradeable.sol";
import "../utils/ContextUpgradeable.sol";
import "../utils/StringsUpgradeable.sol";
import "../utils/introspection/ERC165Upgradeable.sol";
import "../proxy/utils/Initializable.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 AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {
function __AccessControl_init() internal onlyInitializing {
}
function __AccessControl_init_unchained() internal onlyInitializing {
}
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(IAccessControlUpgradeable).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 ",
StringsUpgradeable.toHexString(account),
" is missing role ",
StringsUpgradeable.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());
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControlUpgradeable {
/**
* @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.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822ProxiableUpgradeable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
interface IERC1967Upgradeable {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeaconUpgradeable {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeaconUpgradeable.sol";
import "../../interfaces/IERC1967Upgradeable.sol";
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/StorageSlotUpgradeable.sol";
import "../utils/Initializable.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {
function __ERC1967Upgrade_init() internal onlyInitializing {
}
function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
}
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
AddressUpgradeable.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import "./Initializable.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
function __UUPSUpgradeable_init() internal onlyInitializing {
}
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
}
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/ERC1155.sol)
pragma solidity ^0.8.0;
import "./IERC1155Upgradeable.sol";
import "./IERC1155ReceiverUpgradeable.sol";
import "./extensions/IERC1155MetadataURIUpgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/ContextUpgradeable.sol";
import "../../utils/introspection/ERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.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 ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable {
using AddressUpgradeable 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}.
*/
function __ERC1155_init(string memory uri_) internal onlyInitializing {
__ERC1155_init_unchained(uri_);
}
function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing {
_setURI(uri_);
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {
return
interfaceId == type(IERC1155Upgradeable).interfaceId ||
interfaceId == type(IERC1155MetadataURIUpgradeable).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 IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
if (response != IERC1155ReceiverUpgradeable.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 IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
bytes4 response
) {
if (response != IERC1155ReceiverUpgradeable.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;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[47] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol)
pragma solidity ^0.8.0;
import "../ERC1155Upgradeable.sol";
import "../../../proxy/utils/Initializable.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 ERC1155SupplyUpgradeable is Initializable, ERC1155Upgradeable {
function __ERC1155Supply_init() internal onlyInitializing {
}
function __ERC1155Supply_init_unchained() internal onlyInitializing {
}
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 ERC1155SupplyUpgradeable.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;
}
}
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)
pragma solidity ^0.8.0;
import "../IERC1155Upgradeable.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 IERC1155MetadataURIUpgradeable is IERC1155Upgradeable {
/**
* @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.5.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165Upgradeable.sol";
/**
* @dev _Available since v3.1._
*/
interface IERC1155ReceiverUpgradeable is IERC165Upgradeable {
/**
* @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 (last updated v4.9.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165Upgradeable.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 IERC1155Upgradeable is IERC165Upgradeable {
/**
* @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.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* 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/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.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 ERC165Upgradeable is Initializable, IERC165Upgradeable {
function __ERC165_init() internal onlyInitializing {
}
function __ERC165_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165Upgradeable).interfaceId;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165Upgradeable {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathUpgradeable {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// 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.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMathUpgradeable {
/**
* @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
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlotUpgradeable {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/MathUpgradeable.sol";
import "./math/SignedMathUpgradeable.sol";
/**
* @dev String operations.
*/
library StringsUpgradeable {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = MathUpgradeable.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMathUpgradeable.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, MathUpgradeable.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @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 (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) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Checkpoints.sol)
// This file was procedurally generated from scripts/generate/templates/Checkpoints.js.
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SafeCast.sol";
/**
* @dev This library defines the `History` struct, for checkpointing values as they change at different points in
* time, and later looking up past values by block number. See {Votes} as an example.
*
* To create a history of checkpoints define a variable type `Checkpoints.History` in your contract, and store a new
* checkpoint for the current transaction block using the {push} function.
*
* _Available since v4.5._
*/
library Checkpoints {
struct History {
Checkpoint[] _checkpoints;
}
struct Checkpoint {
uint32 _blockNumber;
uint224 _value;
}
/**
* @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
* before it is returned, or zero otherwise. Because the number returned corresponds to that at the end of the
* block, the requested block number must be in the past, excluding the current block.
*/
function getAtBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
require(blockNumber < block.number, "Checkpoints: block not yet mined");
uint32 key = SafeCast.toUint32(blockNumber);
uint256 len = self._checkpoints.length;
uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
* before it is returned, or zero otherwise. Similar to {upperLookup} but optimized for the case when the searched
* checkpoint is probably "recent", defined as being among the last sqrt(N) checkpoints where N is the number of
* checkpoints.
*/
function getAtProbablyRecentBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
require(blockNumber < block.number, "Checkpoints: block not yet mined");
uint32 key = SafeCast.toUint32(blockNumber);
uint256 len = self._checkpoints.length;
uint256 low = 0;
uint256 high = len;
if (len > 5) {
uint256 mid = len - Math.sqrt(len);
if (key < _unsafeAccess(self._checkpoints, mid)._blockNumber) {
high = mid;
} else {
low = mid + 1;
}
}
uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Pushes a value onto a History so that it is stored as the checkpoint for the current block.
*
* Returns previous value and new value.
*/
function push(History storage self, uint256 value) internal returns (uint256, uint256) {
return _insert(self._checkpoints, SafeCast.toUint32(block.number), SafeCast.toUint224(value));
}
/**
* @dev Pushes a value onto a History, by updating the latest value using binary operation `op`. The new value will
* be set to `op(latest, delta)`.
*
* Returns previous value and new value.
*/
function push(
History storage self,
function(uint256, uint256) view returns (uint256) op,
uint256 delta
) internal returns (uint256, uint256) {
return push(self, op(latest(self), delta));
}
/**
* @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
*/
function latest(History storage self) internal view returns (uint224) {
uint256 pos = self._checkpoints.length;
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
* in the most recent checkpoint.
*/
function latestCheckpoint(
History storage self
) internal view returns (bool exists, uint32 _blockNumber, uint224 _value) {
uint256 pos = self._checkpoints.length;
if (pos == 0) {
return (false, 0, 0);
} else {
Checkpoint memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._blockNumber, ckpt._value);
}
}
/**
* @dev Returns the number of checkpoint.
*/
function length(History storage self) internal view returns (uint256) {
return self._checkpoints.length;
}
/**
* @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
* or by updating the last one.
*/
function _insert(Checkpoint[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) {
uint256 pos = self.length;
if (pos > 0) {
// Copying to memory is important here.
Checkpoint memory last = _unsafeAccess(self, pos - 1);
// Checkpoint keys must be non-decreasing.
require(last._blockNumber <= key, "Checkpoint: decreasing keys");
// Update or push new checkpoint
if (last._blockNumber == key) {
_unsafeAccess(self, pos - 1)._value = value;
} else {
self.push(Checkpoint({_blockNumber: key, _value: value}));
}
return (last._value, value);
} else {
self.push(Checkpoint({_blockNumber: key, _value: value}));
return (0, value);
}
}
/**
* @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none.
* `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _upperBinaryLookup(
Checkpoint[] storage self,
uint32 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._blockNumber > key) {
high = mid;
} else {
low = mid + 1;
}
}
return high;
}
/**
* @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none.
* `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _lowerBinaryLookup(
Checkpoint[] storage self,
uint32 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._blockNumber < key) {
low = mid + 1;
} else {
high = mid;
}
}
return high;
}
/**
* @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
*/
function _unsafeAccess(Checkpoint[] storage self, uint256 pos) private pure returns (Checkpoint storage result) {
assembly {
mstore(0, self.slot)
result.slot := add(keccak256(0, 0x20), pos)
}
}
struct Trace224 {
Checkpoint224[] _checkpoints;
}
struct Checkpoint224 {
uint32 _key;
uint224 _value;
}
/**
* @dev Pushes a (`key`, `value`) pair into a Trace224 so that it is stored as the checkpoint.
*
* Returns previous value and new value.
*/
function push(Trace224 storage self, uint32 key, uint224 value) internal returns (uint224, uint224) {
return _insert(self._checkpoints, key, value);
}
/**
* @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if there is none.
*/
function lowerLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {
uint256 len = self._checkpoints.length;
uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);
return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;
}
/**
* @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
*/
function upperLookup(Trace224 storage self, uint32 key) internal view returns (uint224) {
uint256 len = self._checkpoints.length;
uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
*
* NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high keys).
*/
function upperLookupRecent(Trace224 storage self, uint32 key) internal view returns (uint224) {
uint256 len = self._checkpoints.length;
uint256 low = 0;
uint256 high = len;
if (len > 5) {
uint256 mid = len - Math.sqrt(len);
if (key < _unsafeAccess(self._checkpoints, mid)._key) {
high = mid;
} else {
low = mid + 1;
}
}
uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
*/
function latest(Trace224 storage self) internal view returns (uint224) {
uint256 pos = self._checkpoints.length;
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
* in the most recent checkpoint.
*/
function latestCheckpoint(Trace224 storage self) internal view returns (bool exists, uint32 _key, uint224 _value) {
uint256 pos = self._checkpoints.length;
if (pos == 0) {
return (false, 0, 0);
} else {
Checkpoint224 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._key, ckpt._value);
}
}
/**
* @dev Returns the number of checkpoint.
*/
function length(Trace224 storage self) internal view returns (uint256) {
return self._checkpoints.length;
}
/**
* @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
* or by updating the last one.
*/
function _insert(Checkpoint224[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) {
uint256 pos = self.length;
if (pos > 0) {
// Copying to memory is important here.
Checkpoint224 memory last = _unsafeAccess(self, pos - 1);
// Checkpoint keys must be non-decreasing.
require(last._key <= key, "Checkpoint: decreasing keys");
// Update or push new checkpoint
if (last._key == key) {
_unsafeAccess(self, pos - 1)._value = value;
} else {
self.push(Checkpoint224({_key: key, _value: value}));
}
return (last._value, value);
} else {
self.push(Checkpoint224({_key: key, _value: value}));
return (0, value);
}
}
/**
* @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none.
* `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _upperBinaryLookup(
Checkpoint224[] storage self,
uint32 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._key > key) {
high = mid;
} else {
low = mid + 1;
}
}
return high;
}
/**
* @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none.
* `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _lowerBinaryLookup(
Checkpoint224[] storage self,
uint32 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._key < key) {
low = mid + 1;
} else {
high = mid;
}
}
return high;
}
/**
* @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
*/
function _unsafeAccess(
Checkpoint224[] storage self,
uint256 pos
) private pure returns (Checkpoint224 storage result) {
assembly {
mstore(0, self.slot)
result.slot := add(keccak256(0, 0x20), pos)
}
}
struct Trace160 {
Checkpoint160[] _checkpoints;
}
struct Checkpoint160 {
uint96 _key;
uint160 _value;
}
/**
* @dev Pushes a (`key`, `value`) pair into a Trace160 so that it is stored as the checkpoint.
*
* Returns previous value and new value.
*/
function push(Trace160 storage self, uint96 key, uint160 value) internal returns (uint160, uint160) {
return _insert(self._checkpoints, key, value);
}
/**
* @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if there is none.
*/
function lowerLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {
uint256 len = self._checkpoints.length;
uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len);
return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value;
}
/**
* @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
*/
function upperLookup(Trace160 storage self, uint96 key) internal view returns (uint160) {
uint256 len = self._checkpoints.length;
uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none.
*
* NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high keys).
*/
function upperLookupRecent(Trace160 storage self, uint96 key) internal view returns (uint160) {
uint256 len = self._checkpoints.length;
uint256 low = 0;
uint256 high = len;
if (len > 5) {
uint256 mid = len - Math.sqrt(len);
if (key < _unsafeAccess(self._checkpoints, mid)._key) {
high = mid;
} else {
low = mid + 1;
}
}
uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
*/
function latest(Trace160 storage self) internal view returns (uint160) {
uint256 pos = self._checkpoints.length;
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
* in the most recent checkpoint.
*/
function latestCheckpoint(Trace160 storage self) internal view returns (bool exists, uint96 _key, uint160 _value) {
uint256 pos = self._checkpoints.length;
if (pos == 0) {
return (false, 0, 0);
} else {
Checkpoint160 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._key, ckpt._value);
}
}
/**
* @dev Returns the number of checkpoint.
*/
function length(Trace160 storage self) internal view returns (uint256) {
return self._checkpoints.length;
}
/**
* @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
* or by updating the last one.
*/
function _insert(Checkpoint160[] storage self, uint96 key, uint160 value) private returns (uint160, uint160) {
uint256 pos = self.length;
if (pos > 0) {
// Copying to memory is important here.
Checkpoint160 memory last = _unsafeAccess(self, pos - 1);
// Checkpoint keys must be non-decreasing.
require(last._key <= key, "Checkpoint: decreasing keys");
// Update or push new checkpoint
if (last._key == key) {
_unsafeAccess(self, pos - 1)._value = value;
} else {
self.push(Checkpoint160({_key: key, _value: value}));
}
return (last._value, value);
} else {
self.push(Checkpoint160({_key: key, _value: value}));
return (0, value);
}
}
/**
* @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none.
* `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _upperBinaryLookup(
Checkpoint160[] storage self,
uint96 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._key > key) {
high = mid;
} else {
low = mid + 1;
}
}
return high;
}
/**
* @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none.
* `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _lowerBinaryLookup(
Checkpoint160[] storage self,
uint96 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._key < key) {
low = mid + 1;
} else {
high = mid;
}
}
return high;
}
/**
* @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
*/
function _unsafeAccess(
Checkpoint160[] storage self,
uint256 pos
) private pure returns (Checkpoint160 storage result) {
assembly {
mstore(0, self.slot)
result.slot := add(keccak256(0, 0x20), pos)
}
}
}// 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
// 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.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toUint248(uint256 value) internal pure returns (uint248) {
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toUint240(uint256 value) internal pure returns (uint240) {
require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toUint232(uint256 value) internal pure returns (uint232) {
require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.2._
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toUint216(uint256 value) internal pure returns (uint216) {
require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toUint208(uint256 value) internal pure returns (uint208) {
require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toUint200(uint256 value) internal pure returns (uint200) {
require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toUint192(uint256 value) internal pure returns (uint192) {
require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toUint184(uint256 value) internal pure returns (uint184) {
require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toUint176(uint256 value) internal pure returns (uint176) {
require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toUint168(uint256 value) internal pure returns (uint168) {
require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toUint160(uint256 value) internal pure returns (uint160) {
require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toUint152(uint256 value) internal pure returns (uint152) {
require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toUint144(uint256 value) internal pure returns (uint144) {
require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toUint136(uint256 value) internal pure returns (uint136) {
require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v2.5._
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toUint120(uint256 value) internal pure returns (uint120) {
require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toUint112(uint256 value) internal pure returns (uint112) {
require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.2._
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toUint88(uint256 value) internal pure returns (uint88) {
require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toUint80(uint256 value) internal pure returns (uint80) {
require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toUint72(uint256 value) internal pure returns (uint72) {
require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v2.5._
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toUint56(uint256 value) internal pure returns (uint56) {
require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toUint48(uint256 value) internal pure returns (uint48) {
require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toUint40(uint256 value) internal pure returns (uint40) {
require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v2.5._
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toUint24(uint256 value) internal pure returns (uint24) {
require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v2.5._
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v2.5._
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*
* _Available since v3.0._
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.7._
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.7._
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*
* _Available since v3.0._
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.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
// 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
pragma solidity >=0.8.13;
/// Common mathematical functions used in both SD59x18 and UD60x18. Note that these global functions do not
/// always operate with SD59x18 and UD60x18 numbers.
/*//////////////////////////////////////////////////////////////////////////
CUSTOM ERRORS
//////////////////////////////////////////////////////////////////////////*/
/// @notice Emitted when the ending result in the fixed-point version of `mulDiv` would overflow uint256.
error PRBMath_MulDiv18_Overflow(uint256 x, uint256 y);
/// @notice Emitted when the ending result in `mulDiv` would overflow uint256.
error PRBMath_MulDiv_Overflow(uint256 x, uint256 y, uint256 denominator);
/// @notice Emitted when attempting to run `mulDiv` with one of the inputs `type(int256).min`.
error PRBMath_MulDivSigned_InputTooSmall();
/// @notice Emitted when the ending result in the signed version of `mulDiv` would overflow int256.
error PRBMath_MulDivSigned_Overflow(int256 x, int256 y);
/*//////////////////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////////////////*/
/// @dev The maximum value an uint128 number can have.
uint128 constant MAX_UINT128 = type(uint128).max;
/// @dev The maximum value an uint40 number can have.
uint40 constant MAX_UINT40 = type(uint40).max;
/// @dev How many trailing decimals can be represented.
uint256 constant UNIT = 1e18;
/// @dev Largest power of two that is a divisor of `UNIT`.
uint256 constant UNIT_LPOTD = 262144;
/// @dev The `UNIT` number inverted mod 2^256.
uint256 constant UNIT_INVERSE = 78156646155174841979727994598816262306175212592076161876661_508869554232690281;
/*//////////////////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/// @notice Finds the zero-based index of the first one in the binary representation of x.
/// @dev See the note on msb in the "Find First Set" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set
///
/// Each of the steps in this implementation is equivalent to this high-level code:
///
/// ```solidity
/// if (x >= 2 ** 128) {
/// x >>= 128;
/// result += 128;
/// }
/// ```
///
/// Where 128 is swapped with each respective power of two factor. See the full high-level implementation here:
/// https://gist.github.com/PaulRBerg/f932f8693f2733e30c4d479e8e980948
///
/// A list of the Yul instructions used below:
/// - "gt" is "greater than"
/// - "or" is the OR bitwise operator
/// - "shl" is "shift left"
/// - "shr" is "shift right"
///
/// @param x The uint256 number for which to find the index of the most significant bit.
/// @return result The index of the most significant bit as an uint256.
function msb(uint256 x) pure returns (uint256 result) {
// 2^128
assembly ("memory-safe") {
let factor := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^64
assembly ("memory-safe") {
let factor := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^32
assembly ("memory-safe") {
let factor := shl(5, gt(x, 0xFFFFFFFF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^16
assembly ("memory-safe") {
let factor := shl(4, gt(x, 0xFFFF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^8
assembly ("memory-safe") {
let factor := shl(3, gt(x, 0xFF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^4
assembly ("memory-safe") {
let factor := shl(2, gt(x, 0xF))
x := shr(factor, x)
result := or(result, factor)
}
// 2^2
assembly ("memory-safe") {
let factor := shl(1, gt(x, 0x3))
x := shr(factor, x)
result := or(result, factor)
}
// 2^1
// No need to shift x any more.
assembly ("memory-safe") {
let factor := gt(x, 0x1)
result := or(result, factor)
}
}
/// @notice Calculates floor(x*y÷denominator) with full precision.
///
/// @dev Credits to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.
///
/// Requirements:
/// - The denominator cannot be zero.
/// - The result must fit within uint256.
///
/// Caveats:
/// - This function does not work with fixed-point numbers.
///
/// @param x The multiplicand as an uint256.
/// @param y The multiplier as an uint256.
/// @param denominator The divisor as an uint256.
/// @return result The result as an uint256.
function mulDiv(uint256 x, uint256 y, uint256 denominator) pure returns (uint256 result) {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly ("memory-safe") {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
unchecked {
return prod0 / denominator;
}
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (prod1 >= denominator) {
revert PRBMath_MulDiv_Overflow(x, y, denominator);
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using the mulmod Yul instruction.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
unchecked {
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 lpotdod = denominator & (~denominator + 1);
assembly ("memory-safe") {
// Divide denominator by lpotdod.
denominator := div(denominator, lpotdod)
// Divide [prod1 prod0] by lpotdod.
prod0 := div(prod0, lpotdod)
// Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.
lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * lpotdod;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
}
}
/// @notice Calculates floor(x*y÷1e18) with full precision.
///
/// @dev Variant of `mulDiv` with constant folding, i.e. in which the denominator is always 1e18. Before returning the
/// final result, we add 1 if `(x * y) % UNIT >= HALF_UNIT`. Without this adjustment, 6.6e-19 would be truncated to 0
/// instead of being rounded to 1e-18. See "Listing 6" and text above it at https://accu.org/index.php/journals/1717.
///
/// Requirements:
/// - The result must fit within uint256.
///
/// Caveats:
/// - The body is purposely left uncommented; to understand how this works, see the NatSpec comments in `mulDiv`.
/// - It is assumed that the result can never be `type(uint256).max` when x and y solve the following two equations:
/// 1. x * y = type(uint256).max * UNIT
/// 2. (x * y) % UNIT >= UNIT / 2
///
/// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
/// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
/// @return result The result as an unsigned 60.18-decimal fixed-point number.
function mulDiv18(uint256 x, uint256 y) pure returns (uint256 result) {
uint256 prod0;
uint256 prod1;
assembly ("memory-safe") {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 >= UNIT) {
revert PRBMath_MulDiv18_Overflow(x, y);
}
uint256 remainder;
assembly ("memory-safe") {
remainder := mulmod(x, y, UNIT)
}
if (prod1 == 0) {
unchecked {
return prod0 / UNIT;
}
}
assembly ("memory-safe") {
result := mul(
or(
div(sub(prod0, remainder), UNIT_LPOTD),
mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1))
),
UNIT_INVERSE
)
}
}
/// @notice Calculates floor(x*y÷denominator) with full precision.
///
/// @dev An extension of `mulDiv` for signed numbers. Works by computing the signs and the absolute values separately.
///
/// Requirements:
/// - None of the inputs can be `type(int256).min`.
/// - The result must fit within int256.
///
/// @param x The multiplicand as an int256.
/// @param y The multiplier as an int256.
/// @param denominator The divisor as an int256.
/// @return result The result as an int256.
function mulDivSigned(int256 x, int256 y, int256 denominator) pure returns (int256 result) {
if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {
revert PRBMath_MulDivSigned_InputTooSmall();
}
// Get hold of the absolute values of x, y and the denominator.
uint256 absX;
uint256 absY;
uint256 absD;
unchecked {
absX = x < 0 ? uint256(-x) : uint256(x);
absY = y < 0 ? uint256(-y) : uint256(y);
absD = denominator < 0 ? uint256(-denominator) : uint256(denominator);
}
// Compute the absolute value of (x*y)÷denominator. The result must fit within int256.
uint256 rAbs = mulDiv(absX, absY, absD);
if (rAbs > uint256(type(int256).max)) {
revert PRBMath_MulDivSigned_Overflow(x, y);
}
// Get the signs of x, y and the denominator.
uint256 sx;
uint256 sy;
uint256 sd;
assembly ("memory-safe") {
// This works thanks to two's complement.
// "sgt" stands for "signed greater than" and "sub(0,1)" is max uint256.
sx := sgt(x, sub(0, 1))
sy := sgt(y, sub(0, 1))
sd := sgt(denominator, sub(0, 1))
}
// XOR over sx, sy and sd. What this does is to check whether there are 1 or 3 negative signs in the inputs.
// If there are, the result should be negative. Otherwise, it should be positive.
unchecked {
result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);
}
}
/// @notice Calculates the binary exponent of x using the binary fraction method.
/// @dev Has to use 192.64-bit fixed-point numbers.
/// See https://ethereum.stackexchange.com/a/96594/24693.
/// @param x The exponent as an unsigned 192.64-bit fixed-point number.
/// @return result The result as an unsigned 60.18-decimal fixed-point number.
function prbExp2(uint256 x) pure returns (uint256 result) {
unchecked {
// Start from 0.5 in the 192.64-bit fixed-point format.
result = 0x800000000000000000000000000000000000000000000000;
// Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows
// because the initial result is 2^191 and all magic factors are less than 2^65.
if (x & 0xFF00000000000000 > 0) {
if (x & 0x8000000000000000 > 0) {
result = (result * 0x16A09E667F3BCC909) >> 64;
}
if (x & 0x4000000000000000 > 0) {
result = (result * 0x1306FE0A31B7152DF) >> 64;
}
if (x & 0x2000000000000000 > 0) {
result = (result * 0x1172B83C7D517ADCE) >> 64;
}
if (x & 0x1000000000000000 > 0) {
result = (result * 0x10B5586CF9890F62A) >> 64;
}
if (x & 0x800000000000000 > 0) {
result = (result * 0x1059B0D31585743AE) >> 64;
}
if (x & 0x400000000000000 > 0) {
result = (result * 0x102C9A3E778060EE7) >> 64;
}
if (x & 0x200000000000000 > 0) {
result = (result * 0x10163DA9FB33356D8) >> 64;
}
if (x & 0x100000000000000 > 0) {
result = (result * 0x100B1AFA5ABCBED61) >> 64;
}
}
if (x & 0xFF000000000000 > 0) {
if (x & 0x80000000000000 > 0) {
result = (result * 0x10058C86DA1C09EA2) >> 64;
}
if (x & 0x40000000000000 > 0) {
result = (result * 0x1002C605E2E8CEC50) >> 64;
}
if (x & 0x20000000000000 > 0) {
result = (result * 0x100162F3904051FA1) >> 64;
}
if (x & 0x10000000000000 > 0) {
result = (result * 0x1000B175EFFDC76BA) >> 64;
}
if (x & 0x8000000000000 > 0) {
result = (result * 0x100058BA01FB9F96D) >> 64;
}
if (x & 0x4000000000000 > 0) {
result = (result * 0x10002C5CC37DA9492) >> 64;
}
if (x & 0x2000000000000 > 0) {
result = (result * 0x1000162E525EE0547) >> 64;
}
if (x & 0x1000000000000 > 0) {
result = (result * 0x10000B17255775C04) >> 64;
}
}
if (x & 0xFF0000000000 > 0) {
if (x & 0x800000000000 > 0) {
result = (result * 0x1000058B91B5BC9AE) >> 64;
}
if (x & 0x400000000000 > 0) {
result = (result * 0x100002C5C89D5EC6D) >> 64;
}
if (x & 0x200000000000 > 0) {
result = (result * 0x10000162E43F4F831) >> 64;
}
if (x & 0x100000000000 > 0) {
result = (result * 0x100000B1721BCFC9A) >> 64;
}
if (x & 0x80000000000 > 0) {
result = (result * 0x10000058B90CF1E6E) >> 64;
}
if (x & 0x40000000000 > 0) {
result = (result * 0x1000002C5C863B73F) >> 64;
}
if (x & 0x20000000000 > 0) {
result = (result * 0x100000162E430E5A2) >> 64;
}
if (x & 0x10000000000 > 0) {
result = (result * 0x1000000B172183551) >> 64;
}
}
if (x & 0xFF00000000 > 0) {
if (x & 0x8000000000 > 0) {
result = (result * 0x100000058B90C0B49) >> 64;
}
if (x & 0x4000000000 > 0) {
result = (result * 0x10000002C5C8601CC) >> 64;
}
if (x & 0x2000000000 > 0) {
result = (result * 0x1000000162E42FFF0) >> 64;
}
if (x & 0x1000000000 > 0) {
result = (result * 0x10000000B17217FBB) >> 64;
}
if (x & 0x800000000 > 0) {
result = (result * 0x1000000058B90BFCE) >> 64;
}
if (x & 0x400000000 > 0) {
result = (result * 0x100000002C5C85FE3) >> 64;
}
if (x & 0x200000000 > 0) {
result = (result * 0x10000000162E42FF1) >> 64;
}
if (x & 0x100000000 > 0) {
result = (result * 0x100000000B17217F8) >> 64;
}
}
if (x & 0xFF00000000 > 0) {
if (x & 0x80000000 > 0) {
result = (result * 0x10000000058B90BFC) >> 64;
}
if (x & 0x40000000 > 0) {
result = (result * 0x1000000002C5C85FE) >> 64;
}
if (x & 0x20000000 > 0) {
result = (result * 0x100000000162E42FF) >> 64;
}
if (x & 0x10000000 > 0) {
result = (result * 0x1000000000B17217F) >> 64;
}
if (x & 0x8000000 > 0) {
result = (result * 0x100000000058B90C0) >> 64;
}
if (x & 0x4000000 > 0) {
result = (result * 0x10000000002C5C860) >> 64;
}
if (x & 0x2000000 > 0) {
result = (result * 0x1000000000162E430) >> 64;
}
if (x & 0x1000000 > 0) {
result = (result * 0x10000000000B17218) >> 64;
}
}
if (x & 0xFF0000 > 0) {
if (x & 0x800000 > 0) {
result = (result * 0x1000000000058B90C) >> 64;
}
if (x & 0x400000 > 0) {
result = (result * 0x100000000002C5C86) >> 64;
}
if (x & 0x200000 > 0) {
result = (result * 0x10000000000162E43) >> 64;
}
if (x & 0x100000 > 0) {
result = (result * 0x100000000000B1721) >> 64;
}
if (x & 0x80000 > 0) {
result = (result * 0x10000000000058B91) >> 64;
}
if (x & 0x40000 > 0) {
result = (result * 0x1000000000002C5C8) >> 64;
}
if (x & 0x20000 > 0) {
result = (result * 0x100000000000162E4) >> 64;
}
if (x & 0x10000 > 0) {
result = (result * 0x1000000000000B172) >> 64;
}
}
if (x & 0xFF00 > 0) {
if (x & 0x8000 > 0) {
result = (result * 0x100000000000058B9) >> 64;
}
if (x & 0x4000 > 0) {
result = (result * 0x10000000000002C5D) >> 64;
}
if (x & 0x2000 > 0) {
result = (result * 0x1000000000000162E) >> 64;
}
if (x & 0x1000 > 0) {
result = (result * 0x10000000000000B17) >> 64;
}
if (x & 0x800 > 0) {
result = (result * 0x1000000000000058C) >> 64;
}
if (x & 0x400 > 0) {
result = (result * 0x100000000000002C6) >> 64;
}
if (x & 0x200 > 0) {
result = (result * 0x10000000000000163) >> 64;
}
if (x & 0x100 > 0) {
result = (result * 0x100000000000000B1) >> 64;
}
}
if (x & 0xFF > 0) {
if (x & 0x80 > 0) {
result = (result * 0x10000000000000059) >> 64;
}
if (x & 0x40 > 0) {
result = (result * 0x1000000000000002C) >> 64;
}
if (x & 0x20 > 0) {
result = (result * 0x10000000000000016) >> 64;
}
if (x & 0x10 > 0) {
result = (result * 0x1000000000000000B) >> 64;
}
if (x & 0x8 > 0) {
result = (result * 0x10000000000000006) >> 64;
}
if (x & 0x4 > 0) {
result = (result * 0x10000000000000003) >> 64;
}
if (x & 0x2 > 0) {
result = (result * 0x10000000000000001) >> 64;
}
if (x & 0x1 > 0) {
result = (result * 0x10000000000000001) >> 64;
}
}
// We're doing two things at the same time:
//
// 1. Multiply the result by 2^n + 1, where "2^n" is the integer part and the one is added to account for
// the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191
// rather than 192.
// 2. Convert the result to the unsigned 60.18-decimal fixed-point format.
//
// This works because 2^(191-ip) = 2^ip / 2^191, where "ip" is the integer part "2^n".
result *= UNIT;
result >>= (191 - (x >> 64));
}
}
/// @notice Calculates the square root of x, rounding down if x is not a perfect square.
/// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
/// Credits to OpenZeppelin for the explanations in code comments below.
///
/// Caveats:
/// - This function does not work with fixed-point numbers.
///
/// @param x The uint256 number for which to calculate the square root.
/// @return result The result as an uint256.
function prbSqrt(uint256 x) pure returns (uint256 result) {
if (x == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of x.
//
// We know that the "msb" (most significant bit) of x is a power of 2 such that we have:
//
// $$
// msb(x) <= x <= 2*msb(x)$
// $$
//
// We write $msb(x)$ as $2^k$ and we get:
//
// $$
// k = log_2(x)
// $$
//
// Thus we can write the initial inequality as:
//
// $$
// 2^{log_2(x)} <= x <= 2*2^{log_2(x)+1} \\
// sqrt(2^k) <= sqrt(x) < sqrt(2^{k+1}) \\
// 2^{k/2} <= sqrt(x) < 2^{(k+1)/2} <= 2^{(k/2)+1}
// $$
//
// Consequently, $2^{log_2(x) /2}` is a good first approximation of sqrt(x) with at least one correct bit.
uint256 xAux = uint256(x);
result = 1;
if (xAux >= 2 ** 128) {
xAux >>= 128;
result <<= 64;
}
if (xAux >= 2 ** 64) {
xAux >>= 64;
result <<= 32;
}
if (xAux >= 2 ** 32) {
xAux >>= 32;
result <<= 16;
}
if (xAux >= 2 ** 16) {
xAux >>= 16;
result <<= 8;
}
if (xAux >= 2 ** 8) {
xAux >>= 8;
result <<= 4;
}
if (xAux >= 2 ** 4) {
xAux >>= 4;
result <<= 2;
}
if (xAux >= 2 ** 2) {
result <<= 1;
}
// At this point, `result` is an estimation with at least one bit of precision. We know the true value has at
// most 128 bits, since it is the square root of a uint256. Newton's method converges quadratically (precision
// doubles at every iteration). We thus need at most 7 iteration to turn our partial result with one bit of
// precision into the expected uint128 result.
unchecked {
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
// Round down the result in case x is not a perfect square.
uint256 roundedDownResult = x / result;
if (result >= roundedDownResult) {
result = roundedDownResult;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { MAX_UINT40 } from "../Common.sol";
import { SD59x18 } from "../sd59x18/ValueType.sol";
import { UD2x18 } from "../ud2x18/ValueType.sol";
import { UD60x18 } from "../ud60x18/ValueType.sol";
import {
PRBMath_SD1x18_ToUD2x18_Underflow,
PRBMath_SD1x18_ToUD60x18_Underflow,
PRBMath_SD1x18_ToUint128_Underflow,
PRBMath_SD1x18_ToUint256_Underflow,
PRBMath_SD1x18_ToUint40_Overflow,
PRBMath_SD1x18_ToUint40_Underflow
} from "./Errors.sol";
import { SD1x18 } from "./ValueType.sol";
/// @notice Casts an SD1x18 number into SD59x18.
/// @dev There is no overflow check because the domain of SD1x18 is a subset of SD59x18.
function intoSD59x18(SD1x18 x) pure returns (SD59x18 result) {
result = SD59x18.wrap(int256(SD1x18.unwrap(x)));
}
/// @notice Casts an SD1x18 number into UD2x18.
/// - x must be positive.
function intoUD2x18(SD1x18 x) pure returns (UD2x18 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt < 0) {
revert PRBMath_SD1x18_ToUD2x18_Underflow(x);
}
result = UD2x18.wrap(uint64(xInt));
}
/// @notice Casts an SD1x18 number into UD60x18.
/// @dev Requirements:
/// - x must be positive.
function intoUD60x18(SD1x18 x) pure returns (UD60x18 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt < 0) {
revert PRBMath_SD1x18_ToUD60x18_Underflow(x);
}
result = UD60x18.wrap(uint64(xInt));
}
/// @notice Casts an SD1x18 number into uint256.
/// @dev Requirements:
/// - x must be positive.
function intoUint256(SD1x18 x) pure returns (uint256 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt < 0) {
revert PRBMath_SD1x18_ToUint256_Underflow(x);
}
result = uint256(uint64(xInt));
}
/// @notice Casts an SD1x18 number into uint128.
/// @dev Requirements:
/// - x must be positive.
function intoUint128(SD1x18 x) pure returns (uint128 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt < 0) {
revert PRBMath_SD1x18_ToUint128_Underflow(x);
}
result = uint128(uint64(xInt));
}
/// @notice Casts an SD1x18 number into uint40.
/// @dev Requirements:
/// - x must be positive.
/// - x must be less than or equal to `MAX_UINT40`.
function intoUint40(SD1x18 x) pure returns (uint40 result) {
int64 xInt = SD1x18.unwrap(x);
if (xInt < 0) {
revert PRBMath_SD1x18_ToUint40_Underflow(x);
}
if (xInt > int64(uint64(MAX_UINT40))) {
revert PRBMath_SD1x18_ToUint40_Overflow(x);
}
result = uint40(uint64(xInt));
}
/// @notice Alias for the `wrap` function.
function sd1x18(int64 x) pure returns (SD1x18 result) {
result = wrap(x);
}
/// @notice Unwraps an SD1x18 number into int64.
function unwrap(SD1x18 x) pure returns (int64 result) {
result = SD1x18.unwrap(x);
}
/// @notice Wraps an int64 number into the SD1x18 value type.
function wrap(int64 x) pure returns (SD1x18 result) {
result = SD1x18.wrap(x);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { SD1x18 } from "./ValueType.sol";
/// @dev Euler's number as an SD1x18 number.
SD1x18 constant E = SD1x18.wrap(2_718281828459045235);
/// @dev The maximum value an SD1x18 number can have.
int64 constant uMAX_SD1x18 = 9_223372036854775807;
SD1x18 constant MAX_SD1x18 = SD1x18.wrap(uMAX_SD1x18);
/// @dev The maximum value an SD1x18 number can have.
int64 constant uMIN_SD1x18 = -9_223372036854775808;
SD1x18 constant MIN_SD1x18 = SD1x18.wrap(uMIN_SD1x18);
/// @dev PI as an SD1x18 number.
SD1x18 constant PI = SD1x18.wrap(3_141592653589793238);
/// @dev The unit amount that implies how many trailing decimals can be represented.
SD1x18 constant UNIT = SD1x18.wrap(1e18);
int256 constant uUNIT = 1e18;// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { SD1x18 } from "./ValueType.sol";
/// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in UD2x18.
error PRBMath_SD1x18_ToUD2x18_Underflow(SD1x18 x);
/// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in UD60x18.
error PRBMath_SD1x18_ToUD60x18_Underflow(SD1x18 x);
/// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in uint128.
error PRBMath_SD1x18_ToUint128_Underflow(SD1x18 x);
/// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in uint256.
error PRBMath_SD1x18_ToUint256_Underflow(SD1x18 x);
/// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in uint40.
error PRBMath_SD1x18_ToUint40_Overflow(SD1x18 x);
/// @notice Emitted when trying to cast a SD1x18 number that doesn't fit in uint40.
error PRBMath_SD1x18_ToUint40_Underflow(SD1x18 x);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import "./Casting.sol" as C;
/// @notice The signed 1.18-decimal fixed-point number representation, which can have up to 1 digit and up to 18 decimals.
/// The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity type int64.
/// This is useful when end users want to use int64 to save gas, e.g. with tight variable packing in contract storage.
type SD1x18 is int64;
/*//////////////////////////////////////////////////////////////////////////
CASTING
//////////////////////////////////////////////////////////////////////////*/
using { C.intoSD59x18, C.intoUD2x18, C.intoUD60x18, C.intoUint256, C.intoUint128, C.intoUint40, C.unwrap } for SD1x18 global;// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import "./sd59x18/Casting.sol"; import "./sd59x18/Constants.sol"; import "./sd59x18/Conversions.sol"; import "./sd59x18/Errors.sol"; import "./sd59x18/Helpers.sol"; import "./sd59x18/Math.sol"; import "./sd59x18/ValueType.sol";
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { MAX_UINT128, MAX_UINT40 } from "../Common.sol";
import { uMAX_SD1x18, uMIN_SD1x18 } from "../sd1x18/Constants.sol";
import { SD1x18 } from "../sd1x18/ValueType.sol";
import { uMAX_UD2x18 } from "../ud2x18/Constants.sol";
import { UD2x18 } from "../ud2x18/ValueType.sol";
import { UD60x18 } from "../ud60x18/ValueType.sol";
import {
PRBMath_SD59x18_IntoSD1x18_Overflow,
PRBMath_SD59x18_IntoSD1x18_Underflow,
PRBMath_SD59x18_IntoUD2x18_Overflow,
PRBMath_SD59x18_IntoUD2x18_Underflow,
PRBMath_SD59x18_IntoUD60x18_Underflow,
PRBMath_SD59x18_IntoUint128_Overflow,
PRBMath_SD59x18_IntoUint128_Underflow,
PRBMath_SD59x18_IntoUint256_Underflow,
PRBMath_SD59x18_IntoUint40_Overflow,
PRBMath_SD59x18_IntoUint40_Underflow
} from "./Errors.sol";
import { SD59x18 } from "./ValueType.sol";
/// @notice Casts an SD59x18 number into int256.
/// @dev This is basically a functional alias for the `unwrap` function.
function intoInt256(SD59x18 x) pure returns (int256 result) {
result = SD59x18.unwrap(x);
}
/// @notice Casts an SD59x18 number into SD1x18.
/// @dev Requirements:
/// - x must be greater than or equal to `uMIN_SD1x18`.
/// - x must be less than or equal to `uMAX_SD1x18`.
function intoSD1x18(SD59x18 x) pure returns (SD1x18 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < uMIN_SD1x18) {
revert PRBMath_SD59x18_IntoSD1x18_Underflow(x);
}
if (xInt > uMAX_SD1x18) {
revert PRBMath_SD59x18_IntoSD1x18_Overflow(x);
}
result = SD1x18.wrap(int64(xInt));
}
/// @notice Casts an SD59x18 number into UD2x18.
/// @dev Requirements:
/// - x must be positive.
/// - x must be less than or equal to `uMAX_UD2x18`.
function intoUD2x18(SD59x18 x) pure returns (UD2x18 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < 0) {
revert PRBMath_SD59x18_IntoUD2x18_Underflow(x);
}
if (xInt > int256(uint256(uMAX_UD2x18))) {
revert PRBMath_SD59x18_IntoUD2x18_Overflow(x);
}
result = UD2x18.wrap(uint64(uint256(xInt)));
}
/// @notice Casts an SD59x18 number into UD60x18.
/// @dev Requirements:
/// - x must be positive.
function intoUD60x18(SD59x18 x) pure returns (UD60x18 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < 0) {
revert PRBMath_SD59x18_IntoUD60x18_Underflow(x);
}
result = UD60x18.wrap(uint256(xInt));
}
/// @notice Casts an SD59x18 number into uint256.
/// @dev Requirements:
/// - x must be positive.
function intoUint256(SD59x18 x) pure returns (uint256 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < 0) {
revert PRBMath_SD59x18_IntoUint256_Underflow(x);
}
result = uint256(xInt);
}
/// @notice Casts an SD59x18 number into uint128.
/// @dev Requirements:
/// - x must be positive.
/// - x must be less than or equal to `uMAX_UINT128`.
function intoUint128(SD59x18 x) pure returns (uint128 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < 0) {
revert PRBMath_SD59x18_IntoUint128_Underflow(x);
}
if (xInt > int256(uint256(MAX_UINT128))) {
revert PRBMath_SD59x18_IntoUint128_Overflow(x);
}
result = uint128(uint256(xInt));
}
/// @notice Casts an SD59x18 number into uint40.
/// @dev Requirements:
/// - x must be positive.
/// - x must be less than or equal to `MAX_UINT40`.
function intoUint40(SD59x18 x) pure returns (uint40 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < 0) {
revert PRBMath_SD59x18_IntoUint40_Underflow(x);
}
if (xInt > int256(uint256(MAX_UINT40))) {
revert PRBMath_SD59x18_IntoUint40_Overflow(x);
}
result = uint40(uint256(xInt));
}
/// @notice Alias for the `wrap` function.
function sd(int256 x) pure returns (SD59x18 result) {
result = wrap(x);
}
/// @notice Alias for the `wrap` function.
function sd59x18(int256 x) pure returns (SD59x18 result) {
result = wrap(x);
}
/// @notice Unwraps an SD59x18 number into int256.
function unwrap(SD59x18 x) pure returns (int256 result) {
result = SD59x18.unwrap(x);
}
/// @notice Wraps an int256 number into the SD59x18 value type.
function wrap(int256 x) pure returns (SD59x18 result) {
result = SD59x18.wrap(x);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { SD59x18 } from "./ValueType.sol";
/// NOTICE: the "u" prefix stands for "unwrapped".
/// @dev Euler's number as an SD59x18 number.
SD59x18 constant E = SD59x18.wrap(2_718281828459045235);
/// @dev Half the UNIT number.
int256 constant uHALF_UNIT = 0.5e18;
SD59x18 constant HALF_UNIT = SD59x18.wrap(uHALF_UNIT);
/// @dev log2(10) as an SD59x18 number.
int256 constant uLOG2_10 = 3_321928094887362347;
SD59x18 constant LOG2_10 = SD59x18.wrap(uLOG2_10);
/// @dev log2(e) as an SD59x18 number.
int256 constant uLOG2_E = 1_442695040888963407;
SD59x18 constant LOG2_E = SD59x18.wrap(uLOG2_E);
/// @dev The maximum value an SD59x18 number can have.
int256 constant uMAX_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_792003956564819967;
SD59x18 constant MAX_SD59x18 = SD59x18.wrap(uMAX_SD59x18);
/// @dev The maximum whole value an SD59x18 number can have.
int256 constant uMAX_WHOLE_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_000000000000000000;
SD59x18 constant MAX_WHOLE_SD59x18 = SD59x18.wrap(uMAX_WHOLE_SD59x18);
/// @dev The minimum value an SD59x18 number can have.
int256 constant uMIN_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_792003956564819968;
SD59x18 constant MIN_SD59x18 = SD59x18.wrap(uMIN_SD59x18);
/// @dev The minimum whole value an SD59x18 number can have.
int256 constant uMIN_WHOLE_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_000000000000000000;
SD59x18 constant MIN_WHOLE_SD59x18 = SD59x18.wrap(uMIN_WHOLE_SD59x18);
/// @dev PI as an SD59x18 number.
SD59x18 constant PI = SD59x18.wrap(3_141592653589793238);
/// @dev The unit amount that implies how many trailing decimals can be represented.
int256 constant uUNIT = 1e18;
SD59x18 constant UNIT = SD59x18.wrap(1e18);
/// @dev Zero as an SD59x18 number.
SD59x18 constant ZERO = SD59x18.wrap(0);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { uMAX_SD59x18, uMIN_SD59x18, uUNIT } from "./Constants.sol";
import { PRBMath_SD59x18_Convert_Overflow, PRBMath_SD59x18_Convert_Underflow } from "./Errors.sol";
import { SD59x18 } from "./ValueType.sol";
/// @notice Converts a simple integer to SD59x18 by multiplying it by `UNIT`.
///
/// @dev Requirements:
/// - x must be greater than or equal to `MIN_SD59x18` divided by `UNIT`.
/// - x must be less than or equal to `MAX_SD59x18` divided by `UNIT`.
///
/// @param x The basic integer to convert.
/// @param result The same number converted to SD59x18.
function convert(int256 x) pure returns (SD59x18 result) {
if (x < uMIN_SD59x18 / uUNIT) {
revert PRBMath_SD59x18_Convert_Underflow(x);
}
if (x > uMAX_SD59x18 / uUNIT) {
revert PRBMath_SD59x18_Convert_Overflow(x);
}
unchecked {
result = SD59x18.wrap(x * uUNIT);
}
}
/// @notice Converts an SD59x18 number to a simple integer by dividing it by `UNIT`. Rounds towards zero in the process.
/// @param x The SD59x18 number to convert.
/// @return result The same number as a simple integer.
function convert(SD59x18 x) pure returns (int256 result) {
result = SD59x18.unwrap(x) / uUNIT;
}
/// @notice Alias for the `convert` function defined above.
/// @dev Here for backward compatibility. Will be removed in V4.
function fromSD59x18(SD59x18 x) pure returns (int256 result) {
result = convert(x);
}
/// @notice Alias for the `convert` function defined above.
/// @dev Here for backward compatibility. Will be removed in V4.
function toSD59x18(int256 x) pure returns (SD59x18 result) {
result = convert(x);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { SD59x18 } from "./ValueType.sol";
/// @notice Emitted when taking the absolute value of `MIN_SD59x18`.
error PRBMath_SD59x18_Abs_MinSD59x18();
/// @notice Emitted when ceiling a number overflows SD59x18.
error PRBMath_SD59x18_Ceil_Overflow(SD59x18 x);
/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.
error PRBMath_SD59x18_Convert_Overflow(int256 x);
/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.
error PRBMath_SD59x18_Convert_Underflow(int256 x);
/// @notice Emitted when dividing two numbers and one of them is `MIN_SD59x18`.
error PRBMath_SD59x18_Div_InputTooSmall();
/// @notice Emitted when dividing two numbers and one of the intermediary unsigned results overflows SD59x18.
error PRBMath_SD59x18_Div_Overflow(SD59x18 x, SD59x18 y);
/// @notice Emitted when taking the natural exponent of a base greater than 133.084258667509499441.
error PRBMath_SD59x18_Exp_InputTooBig(SD59x18 x);
/// @notice Emitted when taking the binary exponent of a base greater than 192.
error PRBMath_SD59x18_Exp2_InputTooBig(SD59x18 x);
/// @notice Emitted when flooring a number underflows SD59x18.
error PRBMath_SD59x18_Floor_Underflow(SD59x18 x);
/// @notice Emitted when taking the geometric mean of two numbers and their product is negative.
error PRBMath_SD59x18_Gm_NegativeProduct(SD59x18 x, SD59x18 y);
/// @notice Emitted when taking the geometric mean of two numbers and multiplying them overflows SD59x18.
error PRBMath_SD59x18_Gm_Overflow(SD59x18 x, SD59x18 y);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in SD1x18.
error PRBMath_SD59x18_IntoSD1x18_Overflow(SD59x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in SD1x18.
error PRBMath_SD59x18_IntoSD1x18_Underflow(SD59x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in UD2x18.
error PRBMath_SD59x18_IntoUD2x18_Overflow(SD59x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in UD2x18.
error PRBMath_SD59x18_IntoUD2x18_Underflow(SD59x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in UD60x18.
error PRBMath_SD59x18_IntoUD60x18_Underflow(SD59x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint128.
error PRBMath_SD59x18_IntoUint128_Overflow(SD59x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint128.
error PRBMath_SD59x18_IntoUint128_Underflow(SD59x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint256.
error PRBMath_SD59x18_IntoUint256_Underflow(SD59x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint40.
error PRBMath_SD59x18_IntoUint40_Overflow(SD59x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint40.
error PRBMath_SD59x18_IntoUint40_Underflow(SD59x18 x);
/// @notice Emitted when taking the logarithm of a number less than or equal to zero.
error PRBMath_SD59x18_Log_InputTooSmall(SD59x18 x);
/// @notice Emitted when multiplying two numbers and one of the inputs is `MIN_SD59x18`.
error PRBMath_SD59x18_Mul_InputTooSmall();
/// @notice Emitted when multiplying two numbers and the intermediary absolute result overflows SD59x18.
error PRBMath_SD59x18_Mul_Overflow(SD59x18 x, SD59x18 y);
/// @notice Emitted when raising a number to a power and hte intermediary absolute result overflows SD59x18.
error PRBMath_SD59x18_Powu_Overflow(SD59x18 x, uint256 y);
/// @notice Emitted when taking the square root of a negative number.
error PRBMath_SD59x18_Sqrt_NegativeInput(SD59x18 x);
/// @notice Emitted when the calculating the square root overflows SD59x18.
error PRBMath_SD59x18_Sqrt_Overflow(SD59x18 x);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { unwrap, wrap } from "./Casting.sol";
import { SD59x18 } from "./ValueType.sol";
/// @notice Implements the checked addition operation (+) in the SD59x18 type.
function add(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
return wrap(unwrap(x) + unwrap(y));
}
/// @notice Implements the AND (&) bitwise operation in the SD59x18 type.
function and(SD59x18 x, int256 bits) pure returns (SD59x18 result) {
return wrap(unwrap(x) & bits);
}
/// @notice Implements the equal (=) operation in the SD59x18 type.
function eq(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = unwrap(x) == unwrap(y);
}
/// @notice Implements the greater than operation (>) in the SD59x18 type.
function gt(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = unwrap(x) > unwrap(y);
}
/// @notice Implements the greater than or equal to operation (>=) in the SD59x18 type.
function gte(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = unwrap(x) >= unwrap(y);
}
/// @notice Implements a zero comparison check function in the SD59x18 type.
function isZero(SD59x18 x) pure returns (bool result) {
result = unwrap(x) == 0;
}
/// @notice Implements the left shift operation (<<) in the SD59x18 type.
function lshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) {
result = wrap(unwrap(x) << bits);
}
/// @notice Implements the lower than operation (<) in the SD59x18 type.
function lt(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = unwrap(x) < unwrap(y);
}
/// @notice Implements the lower than or equal to operation (<=) in the SD59x18 type.
function lte(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = unwrap(x) <= unwrap(y);
}
/// @notice Implements the unchecked modulo operation (%) in the SD59x18 type.
function mod(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
result = wrap(unwrap(x) % unwrap(y));
}
/// @notice Implements the not equal operation (!=) in the SD59x18 type.
function neq(SD59x18 x, SD59x18 y) pure returns (bool result) {
result = unwrap(x) != unwrap(y);
}
/// @notice Implements the OR (|) bitwise operation in the SD59x18 type.
function or(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
result = wrap(unwrap(x) | unwrap(y));
}
/// @notice Implements the right shift operation (>>) in the SD59x18 type.
function rshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) {
result = wrap(unwrap(x) >> bits);
}
/// @notice Implements the checked subtraction operation (-) in the SD59x18 type.
function sub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
result = wrap(unwrap(x) - unwrap(y));
}
/// @notice Implements the unchecked addition operation (+) in the SD59x18 type.
function uncheckedAdd(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
unchecked {
result = wrap(unwrap(x) + unwrap(y));
}
}
/// @notice Implements the unchecked subtraction operation (-) in the SD59x18 type.
function uncheckedSub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
unchecked {
result = wrap(unwrap(x) - unwrap(y));
}
}
/// @notice Implements the unchecked unary minus operation (-) in the SD59x18 type.
function uncheckedUnary(SD59x18 x) pure returns (SD59x18 result) {
unchecked {
result = wrap(-unwrap(x));
}
}
/// @notice Implements the XOR (^) bitwise operation in the SD59x18 type.
function xor(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
result = wrap(unwrap(x) ^ unwrap(y));
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { MAX_UINT128, MAX_UINT40, msb, mulDiv, mulDiv18, prbExp2, prbSqrt } from "../Common.sol";
import {
uHALF_UNIT,
uLOG2_10,
uLOG2_E,
uMAX_SD59x18,
uMAX_WHOLE_SD59x18,
uMIN_SD59x18,
uMIN_WHOLE_SD59x18,
UNIT,
uUNIT,
ZERO
} from "./Constants.sol";
import {
PRBMath_SD59x18_Abs_MinSD59x18,
PRBMath_SD59x18_Ceil_Overflow,
PRBMath_SD59x18_Div_InputTooSmall,
PRBMath_SD59x18_Div_Overflow,
PRBMath_SD59x18_Exp_InputTooBig,
PRBMath_SD59x18_Exp2_InputTooBig,
PRBMath_SD59x18_Floor_Underflow,
PRBMath_SD59x18_Gm_Overflow,
PRBMath_SD59x18_Gm_NegativeProduct,
PRBMath_SD59x18_Log_InputTooSmall,
PRBMath_SD59x18_Mul_InputTooSmall,
PRBMath_SD59x18_Mul_Overflow,
PRBMath_SD59x18_Powu_Overflow,
PRBMath_SD59x18_Sqrt_NegativeInput,
PRBMath_SD59x18_Sqrt_Overflow
} from "./Errors.sol";
import { unwrap, wrap } from "./Helpers.sol";
import { SD59x18 } from "./ValueType.sol";
/// @notice Calculate the absolute value of x.
///
/// @dev Requirements:
/// - x must be greater than `MIN_SD59x18`.
///
/// @param x The SD59x18 number for which to calculate the absolute value.
/// @param result The absolute value of x as an SD59x18 number.
function abs(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
if (xInt == uMIN_SD59x18) {
revert PRBMath_SD59x18_Abs_MinSD59x18();
}
result = xInt < 0 ? wrap(-xInt) : x;
}
/// @notice Calculates the arithmetic average of x and y, rounding towards zero.
/// @param x The first operand as an SD59x18 number.
/// @param y The second operand as an SD59x18 number.
/// @return result The arithmetic average as an SD59x18 number.
function avg(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
int256 yInt = unwrap(y);
unchecked {
// This is equivalent to "x / 2 + y / 2" but faster.
// This operation can never overflow.
int256 sum = (xInt >> 1) + (yInt >> 1);
if (sum < 0) {
// If at least one of x and y is odd, we add 1 to the result, since shifting negative numbers to the right rounds
// down to infinity. The right part is equivalent to "sum + (x % 2 == 1 || y % 2 == 1)" but faster.
assembly ("memory-safe") {
result := add(sum, and(or(xInt, yInt), 1))
}
} else {
// We need to add 1 if both x and y are odd to account for the double 0.5 remainder that is truncated after shifting.
result = wrap(sum + (xInt & yInt & 1));
}
}
}
/// @notice Yields the smallest whole SD59x18 number greater than or equal to x.
///
/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.
/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
///
/// Requirements:
/// - x must be less than or equal to `MAX_WHOLE_SD59x18`.
///
/// @param x The SD59x18 number to ceil.
/// @param result The least number greater than or equal to x, as an SD59x18 number.
function ceil(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
if (xInt > uMAX_WHOLE_SD59x18) {
revert PRBMath_SD59x18_Ceil_Overflow(x);
}
int256 remainder = xInt % uUNIT;
if (remainder == 0) {
result = x;
} else {
unchecked {
// Solidity uses C fmod style, which returns a modulus with the same sign as x.
int256 resultInt = xInt - remainder;
if (xInt > 0) {
resultInt += uUNIT;
}
result = wrap(resultInt);
}
}
}
/// @notice Divides two SD59x18 numbers, returning a new SD59x18 number. Rounds towards zero.
///
/// @dev This is a variant of `mulDiv` that works with signed numbers. Works by computing the signs and the absolute values
/// separately.
///
/// Requirements:
/// - All from `Common.mulDiv`.
/// - None of the inputs can be `MIN_SD59x18`.
/// - The denominator cannot be zero.
/// - The result must fit within int256.
///
/// Caveats:
/// - All from `Common.mulDiv`.
///
/// @param x The numerator as an SD59x18 number.
/// @param y The denominator as an SD59x18 number.
/// @param result The quotient as an SD59x18 number.
function div(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
int256 yInt = unwrap(y);
if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) {
revert PRBMath_SD59x18_Div_InputTooSmall();
}
// Get hold of the absolute values of x and y.
uint256 xAbs;
uint256 yAbs;
unchecked {
xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt);
yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt);
}
// Compute the absolute value (x*UNIT)÷y. The resulting value must fit within int256.
uint256 resultAbs = mulDiv(xAbs, uint256(uUNIT), yAbs);
if (resultAbs > uint256(uMAX_SD59x18)) {
revert PRBMath_SD59x18_Div_Overflow(x, y);
}
// Check if x and y have the same sign. This works thanks to two's complement; the left-most bit is the sign bit.
bool sameSign = (xInt ^ yInt) > -1;
// If the inputs don't have the same sign, the result should be negative. Otherwise, it should be positive.
unchecked {
result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs));
}
}
/// @notice Calculates the natural exponent of x.
///
/// @dev Based on the formula:
///
/// $$
/// e^x = 2^{x * log_2{e}}
/// $$
///
/// Requirements:
/// - All from `log2`.
/// - x must be less than 133.084258667509499441.
///
/// Caveats:
/// - All from `exp2`.
/// - For any x less than -41.446531673892822322, the result is zero.
///
/// @param x The exponent as an SD59x18 number.
/// @return result The result as an SD59x18 number.
function exp(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
// Without this check, the value passed to `exp2` would be less than -59.794705707972522261.
if (xInt < -41_446531673892822322) {
return ZERO;
}
// Without this check, the value passed to `exp2` would be greater than 192.
if (xInt >= 133_084258667509499441) {
revert PRBMath_SD59x18_Exp_InputTooBig(x);
}
unchecked {
// Do the fixed-point multiplication inline to save gas.
int256 doubleUnitProduct = xInt * uLOG2_E;
result = exp2(wrap(doubleUnitProduct / uUNIT));
}
}
/// @notice Calculates the binary exponent of x using the binary fraction method.
///
/// @dev Based on the formula:
///
/// $$
/// 2^{-x} = \frac{1}{2^x}
/// $$
///
/// See https://ethereum.stackexchange.com/q/79903/24693.
///
/// Requirements:
/// - x must be 192 or less.
/// - The result must fit within `MAX_SD59x18`.
///
/// Caveats:
/// - For any x less than -59.794705707972522261, the result is zero.
///
/// @param x The exponent as an SD59x18 number.
/// @return result The result as an SD59x18 number.
function exp2(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
if (xInt < 0) {
// 2^59.794705707972522262 is the maximum number whose inverse does not truncate down to zero.
if (xInt < -59_794705707972522261) {
return ZERO;
}
unchecked {
// Do the fixed-point inversion $1/2^x$ inline to save gas. 1e36 is UNIT * UNIT.
result = wrap(1e36 / unwrap(exp2(wrap(-xInt))));
}
} else {
// 2^192 doesn't fit within the 192.64-bit format used internally in this function.
if (xInt >= 192e18) {
revert PRBMath_SD59x18_Exp2_InputTooBig(x);
}
unchecked {
// Convert x to the 192.64-bit fixed-point format.
uint256 x_192x64 = uint256((xInt << 64) / uUNIT);
// It is safe to convert the result to int256 with no checks because the maximum input allowed in this function is 192.
result = wrap(int256(prbExp2(x_192x64)));
}
}
}
/// @notice Yields the greatest whole SD59x18 number less than or equal to x.
///
/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.
/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
///
/// Requirements:
/// - x must be greater than or equal to `MIN_WHOLE_SD59x18`.
///
/// @param x The SD59x18 number to floor.
/// @param result The greatest integer less than or equal to x, as an SD59x18 number.
function floor(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
if (xInt < uMIN_WHOLE_SD59x18) {
revert PRBMath_SD59x18_Floor_Underflow(x);
}
int256 remainder = xInt % uUNIT;
if (remainder == 0) {
result = x;
} else {
unchecked {
// Solidity uses C fmod style, which returns a modulus with the same sign as x.
int256 resultInt = xInt - remainder;
if (xInt < 0) {
resultInt -= uUNIT;
}
result = wrap(resultInt);
}
}
}
/// @notice Yields the excess beyond the floor of x for positive numbers and the part of the number to the right.
/// of the radix point for negative numbers.
/// @dev Based on the odd function definition. https://en.wikipedia.org/wiki/Fractional_part
/// @param x The SD59x18 number to get the fractional part of.
/// @param result The fractional part of x as an SD59x18 number.
function frac(SD59x18 x) pure returns (SD59x18 result) {
result = wrap(unwrap(x) % uUNIT);
}
/// @notice Calculates the geometric mean of x and y, i.e. sqrt(x * y), rounding down.
///
/// @dev Requirements:
/// - x * y must fit within `MAX_SD59x18`, lest it overflows.
/// - x * y must not be negative, since this library does not handle complex numbers.
///
/// @param x The first operand as an SD59x18 number.
/// @param y The second operand as an SD59x18 number.
/// @return result The result as an SD59x18 number.
function gm(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
int256 yInt = unwrap(y);
if (xInt == 0 || yInt == 0) {
return ZERO;
}
unchecked {
// Equivalent to "xy / x != y". Checking for overflow this way is faster than letting Solidity do it.
int256 xyInt = xInt * yInt;
if (xyInt / xInt != yInt) {
revert PRBMath_SD59x18_Gm_Overflow(x, y);
}
// The product must not be negative, since this library does not handle complex numbers.
if (xyInt < 0) {
revert PRBMath_SD59x18_Gm_NegativeProduct(x, y);
}
// We don't need to multiply the result by `UNIT` here because the x*y product had picked up a factor of `UNIT`
// during multiplication. See the comments within the `prbSqrt` function.
uint256 resultUint = prbSqrt(uint256(xyInt));
result = wrap(int256(resultUint));
}
}
/// @notice Calculates 1 / x, rounding toward zero.
///
/// @dev Requirements:
/// - x cannot be zero.
///
/// @param x The SD59x18 number for which to calculate the inverse.
/// @return result The inverse as an SD59x18 number.
function inv(SD59x18 x) pure returns (SD59x18 result) {
// 1e36 is UNIT * UNIT.
result = wrap(1e36 / unwrap(x));
}
/// @notice Calculates the natural logarithm of x.
///
/// @dev Based on the formula:
///
/// $$
/// ln{x} = log_2{x} / log_2{e}$$.
/// $$
///
/// Requirements:
/// - All from `log2`.
///
/// Caveats:
/// - All from `log2`.
/// - This doesn't return exactly 1 for 2.718281828459045235, for that more fine-grained precision is needed.
///
/// @param x The SD59x18 number for which to calculate the natural logarithm.
/// @return result The natural logarithm as an SD59x18 number.
function ln(SD59x18 x) pure returns (SD59x18 result) {
// Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)
// can return is 195.205294292027477728.
result = wrap((unwrap(log2(x)) * uUNIT) / uLOG2_E);
}
/// @notice Calculates the common logarithm of x.
///
/// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common
/// logarithm based on the formula:
///
/// $$
/// log_{10}{x} = log_2{x} / log_2{10}
/// $$
///
/// Requirements:
/// - All from `log2`.
///
/// Caveats:
/// - All from `log2`.
///
/// @param x The SD59x18 number for which to calculate the common logarithm.
/// @return result The common logarithm as an SD59x18 number.
function log10(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
if (xInt < 0) {
revert PRBMath_SD59x18_Log_InputTooSmall(x);
}
// Note that the `mul` in this block is the assembly mul operation, not the SD59x18 `mul`.
// prettier-ignore
assembly ("memory-safe") {
switch x
case 1 { result := mul(uUNIT, sub(0, 18)) }
case 10 { result := mul(uUNIT, sub(1, 18)) }
case 100 { result := mul(uUNIT, sub(2, 18)) }
case 1000 { result := mul(uUNIT, sub(3, 18)) }
case 10000 { result := mul(uUNIT, sub(4, 18)) }
case 100000 { result := mul(uUNIT, sub(5, 18)) }
case 1000000 { result := mul(uUNIT, sub(6, 18)) }
case 10000000 { result := mul(uUNIT, sub(7, 18)) }
case 100000000 { result := mul(uUNIT, sub(8, 18)) }
case 1000000000 { result := mul(uUNIT, sub(9, 18)) }
case 10000000000 { result := mul(uUNIT, sub(10, 18)) }
case 100000000000 { result := mul(uUNIT, sub(11, 18)) }
case 1000000000000 { result := mul(uUNIT, sub(12, 18)) }
case 10000000000000 { result := mul(uUNIT, sub(13, 18)) }
case 100000000000000 { result := mul(uUNIT, sub(14, 18)) }
case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) }
case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) }
case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) }
case 1000000000000000000 { result := 0 }
case 10000000000000000000 { result := uUNIT }
case 100000000000000000000 { result := mul(uUNIT, 2) }
case 1000000000000000000000 { result := mul(uUNIT, 3) }
case 10000000000000000000000 { result := mul(uUNIT, 4) }
case 100000000000000000000000 { result := mul(uUNIT, 5) }
case 1000000000000000000000000 { result := mul(uUNIT, 6) }
case 10000000000000000000000000 { result := mul(uUNIT, 7) }
case 100000000000000000000000000 { result := mul(uUNIT, 8) }
case 1000000000000000000000000000 { result := mul(uUNIT, 9) }
case 10000000000000000000000000000 { result := mul(uUNIT, 10) }
case 100000000000000000000000000000 { result := mul(uUNIT, 11) }
case 1000000000000000000000000000000 { result := mul(uUNIT, 12) }
case 10000000000000000000000000000000 { result := mul(uUNIT, 13) }
case 100000000000000000000000000000000 { result := mul(uUNIT, 14) }
case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) }
case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) }
case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) }
case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) }
case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) }
case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) }
case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) }
case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) }
case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) }
case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) }
case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) }
case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) }
case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) }
case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) }
case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) }
case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) }
case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) }
case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) }
case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) }
case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) }
case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) }
case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) }
case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) }
case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) }
case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) }
case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) }
case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) }
case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) }
case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) }
case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) }
case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) }
case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) }
case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) }
case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) }
case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) }
case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) }
case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) }
case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) }
case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) }
case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) }
default {
result := uMAX_SD59x18
}
}
if (unwrap(result) == uMAX_SD59x18) {
unchecked {
// Do the fixed-point division inline to save gas.
result = wrap((unwrap(log2(x)) * uUNIT) / uLOG2_10);
}
}
}
/// @notice Calculates the binary logarithm of x.
///
/// @dev Based on the iterative approximation algorithm.
/// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation
///
/// Requirements:
/// - x must be greater than zero.
///
/// Caveats:
/// - The results are not perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.
///
/// @param x The SD59x18 number for which to calculate the binary logarithm.
/// @return result The binary logarithm as an SD59x18 number.
function log2(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
if (xInt <= 0) {
revert PRBMath_SD59x18_Log_InputTooSmall(x);
}
unchecked {
// This works because of:
//
// $$
// log_2{x} = -log_2{\frac{1}{x}}
// $$
int256 sign;
if (xInt >= uUNIT) {
sign = 1;
} else {
sign = -1;
// Do the fixed-point inversion inline to save gas. The numerator is UNIT * UNIT.
xInt = 1e36 / xInt;
}
// Calculate the integer part of the logarithm and add it to the result and finally calculate $y = x * 2^(-n)$.
uint256 n = msb(uint256(xInt / uUNIT));
// This is the integer part of the logarithm as an SD59x18 number. The operation can't overflow
// because n is maximum 255, UNIT is 1e18 and sign is either 1 or -1.
int256 resultInt = int256(n) * uUNIT;
// This is $y = x * 2^{-n}$.
int256 y = xInt >> n;
// If y is 1, the fractional part is zero.
if (y == uUNIT) {
return wrap(resultInt * sign);
}
// Calculate the fractional part via the iterative approximation.
// The "delta >>= 1" part is equivalent to "delta /= 2", but shifting bits is faster.
int256 DOUBLE_UNIT = 2e18;
for (int256 delta = uHALF_UNIT; delta > 0; delta >>= 1) {
y = (y * y) / uUNIT;
// Is $y^2 > 2$ and so in the range [2,4)?
if (y >= DOUBLE_UNIT) {
// Add the 2^{-m} factor to the logarithm.
resultInt = resultInt + delta;
// Corresponds to z/2 on Wikipedia.
y >>= 1;
}
}
resultInt *= sign;
result = wrap(resultInt);
}
}
/// @notice Multiplies two SD59x18 numbers together, returning a new SD59x18 number.
///
/// @dev This is a variant of `mulDiv` that works with signed numbers and employs constant folding, i.e. the denominator
/// is always 1e18.
///
/// Requirements:
/// - All from `Common.mulDiv18`.
/// - None of the inputs can be `MIN_SD59x18`.
/// - The result must fit within `MAX_SD59x18`.
///
/// Caveats:
/// - To understand how this works in detail, see the NatSpec comments in `Common.mulDivSigned`.
///
/// @param x The multiplicand as an SD59x18 number.
/// @param y The multiplier as an SD59x18 number.
/// @return result The product as an SD59x18 number.
function mul(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
int256 yInt = unwrap(y);
if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) {
revert PRBMath_SD59x18_Mul_InputTooSmall();
}
// Get hold of the absolute values of x and y.
uint256 xAbs;
uint256 yAbs;
unchecked {
xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt);
yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt);
}
uint256 resultAbs = mulDiv18(xAbs, yAbs);
if (resultAbs > uint256(uMAX_SD59x18)) {
revert PRBMath_SD59x18_Mul_Overflow(x, y);
}
// Check if x and y have the same sign. This works thanks to two's complement; the left-most bit is the sign bit.
bool sameSign = (xInt ^ yInt) > -1;
// If the inputs have the same sign, the result should be negative. Otherwise, it should be positive.
unchecked {
result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs));
}
}
/// @notice Raises x to the power of y.
///
/// @dev Based on the formula:
///
/// $$
/// x^y = 2^{log_2{x} * y}
/// $$
///
/// Requirements:
/// - All from `exp2`, `log2` and `mul`.
/// - x cannot be zero.
///
/// Caveats:
/// - All from `exp2`, `log2` and `mul`.
/// - Assumes 0^0 is 1.
///
/// @param x Number to raise to given power y, as an SD59x18 number.
/// @param y Exponent to raise x to, as an SD59x18 number
/// @return result x raised to power y, as an SD59x18 number.
function pow(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
int256 yInt = unwrap(y);
if (xInt == 0) {
result = yInt == 0 ? UNIT : ZERO;
} else {
if (yInt == uUNIT) {
result = x;
} else {
result = exp2(mul(log2(x), y));
}
}
}
/// @notice Raises x (an SD59x18 number) to the power y (unsigned basic integer) using the famous algorithm
/// algorithm "exponentiation by squaring".
///
/// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring
///
/// Requirements:
/// - All from `abs` and `Common.mulDiv18`.
/// - The result must fit within `MAX_SD59x18`.
///
/// Caveats:
/// - All from `Common.mulDiv18`.
/// - Assumes 0^0 is 1.
///
/// @param x The base as an SD59x18 number.
/// @param y The exponent as an uint256.
/// @return result The result as an SD59x18 number.
function powu(SD59x18 x, uint256 y) pure returns (SD59x18 result) {
uint256 xAbs = uint256(unwrap(abs(x)));
// Calculate the first iteration of the loop in advance.
uint256 resultAbs = y & 1 > 0 ? xAbs : uint256(uUNIT);
// Equivalent to "for(y /= 2; y > 0; y /= 2)" but faster.
uint256 yAux = y;
for (yAux >>= 1; yAux > 0; yAux >>= 1) {
xAbs = mulDiv18(xAbs, xAbs);
// Equivalent to "y % 2 == 1" but faster.
if (yAux & 1 > 0) {
resultAbs = mulDiv18(resultAbs, xAbs);
}
}
// The result must fit within `MAX_SD59x18`.
if (resultAbs > uint256(uMAX_SD59x18)) {
revert PRBMath_SD59x18_Powu_Overflow(x, y);
}
unchecked {
// Is the base negative and the exponent an odd number?
int256 resultInt = int256(resultAbs);
bool isNegative = unwrap(x) < 0 && y & 1 == 1;
if (isNegative) {
resultInt = -resultInt;
}
result = wrap(resultInt);
}
}
/// @notice Calculates the square root of x, rounding down. Only the positive root is returned.
/// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
///
/// Requirements:
/// - x cannot be negative, since this library does not handle complex numbers.
/// - x must be less than `MAX_SD59x18` divided by `UNIT`.
///
/// @param x The SD59x18 number for which to calculate the square root.
/// @return result The result as an SD59x18 number.
function sqrt(SD59x18 x) pure returns (SD59x18 result) {
int256 xInt = unwrap(x);
if (xInt < 0) {
revert PRBMath_SD59x18_Sqrt_NegativeInput(x);
}
if (xInt > uMAX_SD59x18 / uUNIT) {
revert PRBMath_SD59x18_Sqrt_Overflow(x);
}
unchecked {
// Multiply x by `UNIT` to account for the factor of `UNIT` that is picked up when multiplying two SD59x18
// numbers together (in this case, the two numbers are both the square root).
uint256 resultUint = prbSqrt(uint256(xInt * uUNIT));
result = wrap(int256(resultUint));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import "./Casting.sol" as C;
import "./Helpers.sol" as H;
import "./Math.sol" as M;
/// @notice The signed 59.18-decimal fixed-point number representation, which can have up to 59 digits and up to 18 decimals.
/// The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity type int256.
type SD59x18 is int256;
/*//////////////////////////////////////////////////////////////////////////
CASTING
//////////////////////////////////////////////////////////////////////////*/
using {
C.intoInt256,
C.intoSD1x18,
C.intoUD2x18,
C.intoUD60x18,
C.intoUint256,
C.intoUint128,
C.intoUint40,
C.unwrap
} for SD59x18 global;
/*//////////////////////////////////////////////////////////////////////////
MATHEMATICAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
using {
M.abs,
M.avg,
M.ceil,
M.div,
M.exp,
M.exp2,
M.floor,
M.frac,
M.gm,
M.inv,
M.log10,
M.log2,
M.ln,
M.mul,
M.pow,
M.powu,
M.sqrt
} for SD59x18 global;
/*//////////////////////////////////////////////////////////////////////////
HELPER FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
using {
H.add,
H.and,
H.eq,
H.gt,
H.gte,
H.isZero,
H.lshift,
H.lt,
H.lte,
H.mod,
H.neq,
H.or,
H.rshift,
H.sub,
H.uncheckedAdd,
H.uncheckedSub,
H.uncheckedUnary,
H.xor
} for SD59x18 global;// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { MAX_UINT40 } from "../Common.sol";
import { uMAX_SD1x18 } from "../sd1x18/Constants.sol";
import { SD1x18 } from "../sd1x18/ValueType.sol";
import { SD59x18 } from "../sd59x18/ValueType.sol";
import { UD2x18 } from "../ud2x18/ValueType.sol";
import { UD60x18 } from "../ud60x18/ValueType.sol";
import { PRBMath_UD2x18_IntoSD1x18_Overflow, PRBMath_UD2x18_IntoUint40_Overflow } from "./Errors.sol";
import { UD2x18 } from "./ValueType.sol";
/// @notice Casts an UD2x18 number into SD1x18.
/// - x must be less than or equal to `uMAX_SD1x18`.
function intoSD1x18(UD2x18 x) pure returns (SD1x18 result) {
uint64 xUint = UD2x18.unwrap(x);
if (xUint > uint64(uMAX_SD1x18)) {
revert PRBMath_UD2x18_IntoSD1x18_Overflow(x);
}
result = SD1x18.wrap(int64(xUint));
}
/// @notice Casts an UD2x18 number into SD59x18.
/// @dev There is no overflow check because the domain of UD2x18 is a subset of SD59x18.
function intoSD59x18(UD2x18 x) pure returns (SD59x18 result) {
result = SD59x18.wrap(int256(uint256(UD2x18.unwrap(x))));
}
/// @notice Casts an UD2x18 number into UD60x18.
/// @dev There is no overflow check because the domain of UD2x18 is a subset of UD60x18.
function intoUD60x18(UD2x18 x) pure returns (UD60x18 result) {
result = UD60x18.wrap(UD2x18.unwrap(x));
}
/// @notice Casts an UD2x18 number into uint128.
/// @dev There is no overflow check because the domain of UD2x18 is a subset of uint128.
function intoUint128(UD2x18 x) pure returns (uint128 result) {
result = uint128(UD2x18.unwrap(x));
}
/// @notice Casts an UD2x18 number into uint256.
/// @dev There is no overflow check because the domain of UD2x18 is a subset of uint256.
function intoUint256(UD2x18 x) pure returns (uint256 result) {
result = uint256(UD2x18.unwrap(x));
}
/// @notice Casts an UD2x18 number into uint40.
/// @dev Requirements:
/// - x must be less than or equal to `MAX_UINT40`.
function intoUint40(UD2x18 x) pure returns (uint40 result) {
uint64 xUint = UD2x18.unwrap(x);
if (xUint > uint64(MAX_UINT40)) {
revert PRBMath_UD2x18_IntoUint40_Overflow(x);
}
result = uint40(xUint);
}
/// @notice Alias for the `wrap` function.
function ud2x18(uint64 x) pure returns (UD2x18 result) {
result = wrap(x);
}
/// @notice Unwrap an UD2x18 number into uint64.
function unwrap(UD2x18 x) pure returns (uint64 result) {
result = UD2x18.unwrap(x);
}
/// @notice Wraps an uint64 number into the UD2x18 value type.
function wrap(uint64 x) pure returns (UD2x18 result) {
result = UD2x18.wrap(x);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { UD2x18 } from "./ValueType.sol";
/// @dev Euler's number as an UD2x18 number.
UD2x18 constant E = UD2x18.wrap(2_718281828459045235);
/// @dev The maximum value an UD2x18 number can have.
uint64 constant uMAX_UD2x18 = 18_446744073709551615;
UD2x18 constant MAX_UD2x18 = UD2x18.wrap(uMAX_UD2x18);
/// @dev PI as an UD2x18 number.
UD2x18 constant PI = UD2x18.wrap(3_141592653589793238);
/// @dev The unit amount that implies how many trailing decimals can be represented.
uint256 constant uUNIT = 1e18;
UD2x18 constant UNIT = UD2x18.wrap(1e18);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { UD2x18 } from "./ValueType.sol";
/// @notice Emitted when trying to cast a UD2x18 number that doesn't fit in SD1x18.
error PRBMath_UD2x18_IntoSD1x18_Overflow(UD2x18 x);
/// @notice Emitted when trying to cast a UD2x18 number that doesn't fit in uint40.
error PRBMath_UD2x18_IntoUint40_Overflow(UD2x18 x);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import "./Casting.sol" as C;
/// @notice The unsigned 2.18-decimal fixed-point number representation, which can have up to 2 digits and up to 18 decimals.
/// The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity type uint64.
/// This is useful when end users want to use uint64 to save gas, e.g. with tight variable packing in contract storage.
type UD2x18 is uint64;
/*//////////////////////////////////////////////////////////////////////////
CASTING
//////////////////////////////////////////////////////////////////////////*/
using { C.intoSD1x18, C.intoSD59x18, C.intoUD60x18, C.intoUint256, C.intoUint128, C.intoUint40, C.unwrap } for UD2x18 global;// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { MAX_UINT128, MAX_UINT40 } from "../Common.sol";
import { uMAX_SD1x18 } from "../sd1x18/Constants.sol";
import { SD1x18 } from "../sd1x18/ValueType.sol";
import { uMAX_SD59x18 } from "../sd59x18/Constants.sol";
import { SD59x18 } from "../sd59x18/ValueType.sol";
import { uMAX_UD2x18 } from "../ud2x18/Constants.sol";
import { UD2x18 } from "../ud2x18/ValueType.sol";
import {
PRBMath_UD60x18_IntoSD1x18_Overflow,
PRBMath_UD60x18_IntoUD2x18_Overflow,
PRBMath_UD60x18_IntoSD59x18_Overflow,
PRBMath_UD60x18_IntoUint128_Overflow,
PRBMath_UD60x18_IntoUint40_Overflow
} from "./Errors.sol";
import { UD60x18 } from "./ValueType.sol";
/// @notice Casts an UD60x18 number into SD1x18.
/// @dev Requirements:
/// - x must be less than or equal to `uMAX_SD1x18`.
function intoSD1x18(UD60x18 x) pure returns (SD1x18 result) {
uint256 xUint = UD60x18.unwrap(x);
if (xUint > uint256(int256(uMAX_SD1x18))) {
revert PRBMath_UD60x18_IntoSD1x18_Overflow(x);
}
result = SD1x18.wrap(int64(uint64(xUint)));
}
/// @notice Casts an UD60x18 number into UD2x18.
/// @dev Requirements:
/// - x must be less than or equal to `uMAX_UD2x18`.
function intoUD2x18(UD60x18 x) pure returns (UD2x18 result) {
uint256 xUint = UD60x18.unwrap(x);
if (xUint > uMAX_UD2x18) {
revert PRBMath_UD60x18_IntoUD2x18_Overflow(x);
}
result = UD2x18.wrap(uint64(xUint));
}
/// @notice Casts an UD60x18 number into SD59x18.
/// @dev Requirements:
/// - x must be less than or equal to `uMAX_SD59x18`.
function intoSD59x18(UD60x18 x) pure returns (SD59x18 result) {
uint256 xUint = UD60x18.unwrap(x);
if (xUint > uint256(uMAX_SD59x18)) {
revert PRBMath_UD60x18_IntoSD59x18_Overflow(x);
}
result = SD59x18.wrap(int256(xUint));
}
/// @notice Casts an UD60x18 number into uint128.
/// @dev This is basically a functional alias for the `unwrap` function.
function intoUint256(UD60x18 x) pure returns (uint256 result) {
result = UD60x18.unwrap(x);
}
/// @notice Casts an UD60x18 number into uint128.
/// @dev Requirements:
/// - x must be less than or equal to `MAX_UINT128`.
function intoUint128(UD60x18 x) pure returns (uint128 result) {
uint256 xUint = UD60x18.unwrap(x);
if (xUint > MAX_UINT128) {
revert PRBMath_UD60x18_IntoUint128_Overflow(x);
}
result = uint128(xUint);
}
/// @notice Casts an UD60x18 number into uint40.
/// @dev Requirements:
/// - x must be less than or equal to `MAX_UINT40`.
function intoUint40(UD60x18 x) pure returns (uint40 result) {
uint256 xUint = UD60x18.unwrap(x);
if (xUint > MAX_UINT40) {
revert PRBMath_UD60x18_IntoUint40_Overflow(x);
}
result = uint40(xUint);
}
/// @notice Alias for the `wrap` function.
function ud(uint256 x) pure returns (UD60x18 result) {
result = wrap(x);
}
/// @notice Alias for the `wrap` function.
function ud60x18(uint256 x) pure returns (UD60x18 result) {
result = wrap(x);
}
/// @notice Unwraps an UD60x18 number into uint256.
function unwrap(UD60x18 x) pure returns (uint256 result) {
result = UD60x18.unwrap(x);
}
/// @notice Wraps an uint256 number into the UD60x18 value type.
function wrap(uint256 x) pure returns (UD60x18 result) {
result = UD60x18.wrap(x);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { UD60x18 } from "./ValueType.sol";
/// @dev Euler's number as an UD60x18 number.
UD60x18 constant E = UD60x18.wrap(2_718281828459045235);
/// @dev Half the UNIT number.
uint256 constant uHALF_UNIT = 0.5e18;
UD60x18 constant HALF_UNIT = UD60x18.wrap(uHALF_UNIT);
/// @dev log2(10) as an UD60x18 number.
uint256 constant uLOG2_10 = 3_321928094887362347;
UD60x18 constant LOG2_10 = UD60x18.wrap(uLOG2_10);
/// @dev log2(e) as an UD60x18 number.
uint256 constant uLOG2_E = 1_442695040888963407;
UD60x18 constant LOG2_E = UD60x18.wrap(uLOG2_E);
/// @dev The maximum value an UD60x18 number can have.
uint256 constant uMAX_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_584007913129639935;
UD60x18 constant MAX_UD60x18 = UD60x18.wrap(uMAX_UD60x18);
/// @dev The maximum whole value an UD60x18 number can have.
uint256 constant uMAX_WHOLE_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_000000000000000000;
UD60x18 constant MAX_WHOLE_UD60x18 = UD60x18.wrap(uMAX_WHOLE_UD60x18);
/// @dev PI as an UD60x18 number.
UD60x18 constant PI = UD60x18.wrap(3_141592653589793238);
/// @dev The unit amount that implies how many trailing decimals can be represented.
uint256 constant uUNIT = 1e18;
UD60x18 constant UNIT = UD60x18.wrap(uUNIT);
/// @dev Zero as an UD60x18 number.
UD60x18 constant ZERO = UD60x18.wrap(0);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { UD60x18 } from "./ValueType.sol";
/// @notice Emitted when ceiling a number overflows UD60x18.
error PRBMath_UD60x18_Ceil_Overflow(UD60x18 x);
/// @notice Emitted when converting a basic integer to the fixed-point format overflows UD60x18.
error PRBMath_UD60x18_Convert_Overflow(uint256 x);
/// @notice Emitted when taking the natural exponent of a base greater than 133.084258667509499441.
error PRBMath_UD60x18_Exp_InputTooBig(UD60x18 x);
/// @notice Emitted when taking the binary exponent of a base greater than 192.
error PRBMath_UD60x18_Exp2_InputTooBig(UD60x18 x);
/// @notice Emitted when taking the geometric mean of two numbers and multiplying them overflows UD60x18.
error PRBMath_UD60x18_Gm_Overflow(UD60x18 x, UD60x18 y);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in SD1x18.
error PRBMath_UD60x18_IntoSD1x18_Overflow(UD60x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in SD59x18.
error PRBMath_UD60x18_IntoSD59x18_Overflow(UD60x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in UD2x18.
error PRBMath_UD60x18_IntoUD2x18_Overflow(UD60x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint128.
error PRBMath_UD60x18_IntoUint128_Overflow(UD60x18 x);
/// @notice Emitted when trying to cast an UD60x18 number that doesn't fit in uint40.
error PRBMath_UD60x18_IntoUint40_Overflow(UD60x18 x);
/// @notice Emitted when taking the logarithm of a number less than 1.
error PRBMath_UD60x18_Log_InputTooSmall(UD60x18 x);
/// @notice Emitted when calculating the square root overflows UD60x18.
error PRBMath_UD60x18_Sqrt_Overflow(UD60x18 x);// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { unwrap, wrap } from "./Casting.sol";
import { UD60x18 } from "./ValueType.sol";
/// @notice Implements the checked addition operation (+) in the UD60x18 type.
function add(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(unwrap(x) + unwrap(y));
}
/// @notice Implements the AND (&) bitwise operation in the UD60x18 type.
function and(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {
result = wrap(unwrap(x) & bits);
}
/// @notice Implements the equal operation (==) in the UD60x18 type.
function eq(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = unwrap(x) == unwrap(y);
}
/// @notice Implements the greater than operation (>) in the UD60x18 type.
function gt(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = unwrap(x) > unwrap(y);
}
/// @notice Implements the greater than or equal to operation (>=) in the UD60x18 type.
function gte(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = unwrap(x) >= unwrap(y);
}
/// @notice Implements a zero comparison check function in the UD60x18 type.
function isZero(UD60x18 x) pure returns (bool result) {
// This wouldn't work if x could be negative.
result = unwrap(x) == 0;
}
/// @notice Implements the left shift operation (<<) in the UD60x18 type.
function lshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {
result = wrap(unwrap(x) << bits);
}
/// @notice Implements the lower than operation (<) in the UD60x18 type.
function lt(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = unwrap(x) < unwrap(y);
}
/// @notice Implements the lower than or equal to operation (<=) in the UD60x18 type.
function lte(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = unwrap(x) <= unwrap(y);
}
/// @notice Implements the checked modulo operation (%) in the UD60x18 type.
function mod(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(unwrap(x) % unwrap(y));
}
/// @notice Implements the not equal operation (!=) in the UD60x18 type
function neq(UD60x18 x, UD60x18 y) pure returns (bool result) {
result = unwrap(x) != unwrap(y);
}
/// @notice Implements the OR (|) bitwise operation in the UD60x18 type.
function or(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(unwrap(x) | unwrap(y));
}
/// @notice Implements the right shift operation (>>) in the UD60x18 type.
function rshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) {
result = wrap(unwrap(x) >> bits);
}
/// @notice Implements the checked subtraction operation (-) in the UD60x18 type.
function sub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(unwrap(x) - unwrap(y));
}
/// @notice Implements the unchecked addition operation (+) in the UD60x18 type.
function uncheckedAdd(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
unchecked {
result = wrap(unwrap(x) + unwrap(y));
}
}
/// @notice Implements the unchecked subtraction operation (-) in the UD60x18 type.
function uncheckedSub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
unchecked {
result = wrap(unwrap(x) - unwrap(y));
}
}
/// @notice Implements the XOR (^) bitwise operation in the UD60x18 type.
function xor(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(unwrap(x) ^ unwrap(y));
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import { msb, mulDiv, mulDiv18, prbExp2, prbSqrt } from "../Common.sol";
import { unwrap, wrap } from "./Casting.sol";
import { uHALF_UNIT, uLOG2_10, uLOG2_E, uMAX_UD60x18, uMAX_WHOLE_UD60x18, UNIT, uUNIT, ZERO } from "./Constants.sol";
import {
PRBMath_UD60x18_Ceil_Overflow,
PRBMath_UD60x18_Exp_InputTooBig,
PRBMath_UD60x18_Exp2_InputTooBig,
PRBMath_UD60x18_Gm_Overflow,
PRBMath_UD60x18_Log_InputTooSmall,
PRBMath_UD60x18_Sqrt_Overflow
} from "./Errors.sol";
import { UD60x18 } from "./ValueType.sol";
/*//////////////////////////////////////////////////////////////////////////
MATHEMATICAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/// @notice Calculates the arithmetic average of x and y, rounding down.
///
/// @dev Based on the formula:
///
/// $$
/// avg(x, y) = (x & y) + ((xUint ^ yUint) / 2)
/// $$
//
/// In English, what this formula does is:
///
/// 1. AND x and y.
/// 2. Calculate half of XOR x and y.
/// 3. Add the two results together.
///
/// This technique is known as SWAR, which stands for "SIMD within a register". You can read more about it here:
/// https://devblogs.microsoft.com/oldnewthing/20220207-00/?p=106223
///
/// @param x The first operand as an UD60x18 number.
/// @param y The second operand as an UD60x18 number.
/// @return result The arithmetic average as an UD60x18 number.
function avg(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
uint256 xUint = unwrap(x);
uint256 yUint = unwrap(y);
unchecked {
result = wrap((xUint & yUint) + ((xUint ^ yUint) >> 1));
}
}
/// @notice Yields the smallest whole UD60x18 number greater than or equal to x.
///
/// @dev This is optimized for fractional value inputs, because for every whole value there are "1e18 - 1" fractional
/// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
///
/// Requirements:
/// - x must be less than or equal to `MAX_WHOLE_UD60x18`.
///
/// @param x The UD60x18 number to ceil.
/// @param result The least number greater than or equal to x, as an UD60x18 number.
function ceil(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = unwrap(x);
if (xUint > uMAX_WHOLE_UD60x18) {
revert PRBMath_UD60x18_Ceil_Overflow(x);
}
assembly ("memory-safe") {
// Equivalent to "x % UNIT" but faster.
let remainder := mod(x, uUNIT)
// Equivalent to "UNIT - remainder" but faster.
let delta := sub(uUNIT, remainder)
// Equivalent to "x + delta * (remainder > 0 ? 1 : 0)" but faster.
result := add(x, mul(delta, gt(remainder, 0)))
}
}
/// @notice Divides two UD60x18 numbers, returning a new UD60x18 number. Rounds towards zero.
///
/// @dev Uses `mulDiv` to enable overflow-safe multiplication and division.
///
/// Requirements:
/// - The denominator cannot be zero.
///
/// @param x The numerator as an UD60x18 number.
/// @param y The denominator as an UD60x18 number.
/// @param result The quotient as an UD60x18 number.
function div(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(mulDiv(unwrap(x), uUNIT, unwrap(y)));
}
/// @notice Calculates the natural exponent of x.
///
/// @dev Based on the formula:
///
/// $$
/// e^x = 2^{x * log_2{e}}
/// $$
///
/// Requirements:
/// - All from `log2`.
/// - x must be less than 133.084258667509499441.
///
/// @param x The exponent as an UD60x18 number.
/// @return result The result as an UD60x18 number.
function exp(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = unwrap(x);
// Without this check, the value passed to `exp2` would be greater than 192.
if (xUint >= 133_084258667509499441) {
revert PRBMath_UD60x18_Exp_InputTooBig(x);
}
unchecked {
// We do the fixed-point multiplication inline rather than via the `mul` function to save gas.
uint256 doubleUnitProduct = xUint * uLOG2_E;
result = exp2(wrap(doubleUnitProduct / uUNIT));
}
}
/// @notice Calculates the binary exponent of x using the binary fraction method.
///
/// @dev See https://ethereum.stackexchange.com/q/79903/24693.
///
/// Requirements:
/// - x must be 192 or less.
/// - The result must fit within `MAX_UD60x18`.
///
/// @param x The exponent as an UD60x18 number.
/// @return result The result as an UD60x18 number.
function exp2(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = unwrap(x);
// Numbers greater than or equal to 2^192 don't fit within the 192.64-bit format.
if (xUint >= 192e18) {
revert PRBMath_UD60x18_Exp2_InputTooBig(x);
}
// Convert x to the 192.64-bit fixed-point format.
uint256 x_192x64 = (xUint << 64) / uUNIT;
// Pass x to the `prbExp2` function, which uses the 192.64-bit fixed-point number representation.
result = wrap(prbExp2(x_192x64));
}
/// @notice Yields the greatest whole UD60x18 number less than or equal to x.
/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.
/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
/// @param x The UD60x18 number to floor.
/// @param result The greatest integer less than or equal to x, as an UD60x18 number.
function floor(UD60x18 x) pure returns (UD60x18 result) {
assembly ("memory-safe") {
// Equivalent to "x % UNIT" but faster.
let remainder := mod(x, uUNIT)
// Equivalent to "x - remainder * (remainder > 0 ? 1 : 0)" but faster.
result := sub(x, mul(remainder, gt(remainder, 0)))
}
}
/// @notice Yields the excess beyond the floor of x.
/// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.
/// @param x The UD60x18 number to get the fractional part of.
/// @param result The fractional part of x as an UD60x18 number.
function frac(UD60x18 x) pure returns (UD60x18 result) {
assembly ("memory-safe") {
result := mod(x, uUNIT)
}
}
/// @notice Calculates the geometric mean of x and y, i.e. $$sqrt(x * y)$$, rounding down.
///
/// @dev Requirements:
/// - x * y must fit within `MAX_UD60x18`, lest it overflows.
///
/// @param x The first operand as an UD60x18 number.
/// @param y The second operand as an UD60x18 number.
/// @return result The result as an UD60x18 number.
function gm(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
uint256 xUint = unwrap(x);
uint256 yUint = unwrap(y);
if (xUint == 0 || yUint == 0) {
return ZERO;
}
unchecked {
// Checking for overflow this way is faster than letting Solidity do it.
uint256 xyUint = xUint * yUint;
if (xyUint / xUint != yUint) {
revert PRBMath_UD60x18_Gm_Overflow(x, y);
}
// We don't need to multiply the result by `UNIT` here because the x*y product had picked up a factor of `UNIT`
// during multiplication. See the comments in the `prbSqrt` function.
result = wrap(prbSqrt(xyUint));
}
}
/// @notice Calculates 1 / x, rounding toward zero.
///
/// @dev Requirements:
/// - x cannot be zero.
///
/// @param x The UD60x18 number for which to calculate the inverse.
/// @return result The inverse as an UD60x18 number.
function inv(UD60x18 x) pure returns (UD60x18 result) {
unchecked {
// 1e36 is UNIT * UNIT.
result = wrap(1e36 / unwrap(x));
}
}
/// @notice Calculates the natural logarithm of x.
///
/// @dev Based on the formula:
///
/// $$
/// ln{x} = log_2{x} / log_2{e}$$.
/// $$
///
/// Requirements:
/// - All from `log2`.
///
/// Caveats:
/// - All from `log2`.
/// - This doesn't return exactly 1 for 2.718281828459045235, for that more fine-grained precision is needed.
///
/// @param x The UD60x18 number for which to calculate the natural logarithm.
/// @return result The natural logarithm as an UD60x18 number.
function ln(UD60x18 x) pure returns (UD60x18 result) {
unchecked {
// We do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value
// that `log2` can return is 196.205294292027477728.
result = wrap((unwrap(log2(x)) * uUNIT) / uLOG2_E);
}
}
/// @notice Calculates the common logarithm of x.
///
/// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common
/// logarithm based on the formula:
///
/// $$
/// log_{10}{x} = log_2{x} / log_2{10}
/// $$
///
/// Requirements:
/// - All from `log2`.
///
/// Caveats:
/// - All from `log2`.
///
/// @param x The UD60x18 number for which to calculate the common logarithm.
/// @return result The common logarithm as an UD60x18 number.
function log10(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = unwrap(x);
if (xUint < uUNIT) {
revert PRBMath_UD60x18_Log_InputTooSmall(x);
}
// Note that the `mul` in this assembly block is the assembly multiplication operation, not the UD60x18 `mul`.
// prettier-ignore
assembly ("memory-safe") {
switch x
case 1 { result := mul(uUNIT, sub(0, 18)) }
case 10 { result := mul(uUNIT, sub(1, 18)) }
case 100 { result := mul(uUNIT, sub(2, 18)) }
case 1000 { result := mul(uUNIT, sub(3, 18)) }
case 10000 { result := mul(uUNIT, sub(4, 18)) }
case 100000 { result := mul(uUNIT, sub(5, 18)) }
case 1000000 { result := mul(uUNIT, sub(6, 18)) }
case 10000000 { result := mul(uUNIT, sub(7, 18)) }
case 100000000 { result := mul(uUNIT, sub(8, 18)) }
case 1000000000 { result := mul(uUNIT, sub(9, 18)) }
case 10000000000 { result := mul(uUNIT, sub(10, 18)) }
case 100000000000 { result := mul(uUNIT, sub(11, 18)) }
case 1000000000000 { result := mul(uUNIT, sub(12, 18)) }
case 10000000000000 { result := mul(uUNIT, sub(13, 18)) }
case 100000000000000 { result := mul(uUNIT, sub(14, 18)) }
case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) }
case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) }
case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) }
case 1000000000000000000 { result := 0 }
case 10000000000000000000 { result := uUNIT }
case 100000000000000000000 { result := mul(uUNIT, 2) }
case 1000000000000000000000 { result := mul(uUNIT, 3) }
case 10000000000000000000000 { result := mul(uUNIT, 4) }
case 100000000000000000000000 { result := mul(uUNIT, 5) }
case 1000000000000000000000000 { result := mul(uUNIT, 6) }
case 10000000000000000000000000 { result := mul(uUNIT, 7) }
case 100000000000000000000000000 { result := mul(uUNIT, 8) }
case 1000000000000000000000000000 { result := mul(uUNIT, 9) }
case 10000000000000000000000000000 { result := mul(uUNIT, 10) }
case 100000000000000000000000000000 { result := mul(uUNIT, 11) }
case 1000000000000000000000000000000 { result := mul(uUNIT, 12) }
case 10000000000000000000000000000000 { result := mul(uUNIT, 13) }
case 100000000000000000000000000000000 { result := mul(uUNIT, 14) }
case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) }
case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) }
case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) }
case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) }
case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) }
case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) }
case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) }
case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) }
case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) }
case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) }
case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) }
case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) }
case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) }
case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) }
case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) }
case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) }
case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) }
case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) }
case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) }
case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) }
case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) }
case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) }
case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) }
case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) }
case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) }
case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) }
case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) }
case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) }
case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) }
case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) }
case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) }
case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) }
case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) }
case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) }
case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) }
case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) }
case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) }
case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) }
case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) }
case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) }
case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 59) }
default {
result := uMAX_UD60x18
}
}
if (unwrap(result) == uMAX_UD60x18) {
unchecked {
// Do the fixed-point division inline to save gas.
result = wrap((unwrap(log2(x)) * uUNIT) / uLOG2_10);
}
}
}
/// @notice Calculates the binary logarithm of x.
///
/// @dev Based on the iterative approximation algorithm.
/// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation
///
/// Requirements:
/// - x must be greater than or equal to UNIT, otherwise the result would be negative.
///
/// Caveats:
/// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.
///
/// @param x The UD60x18 number for which to calculate the binary logarithm.
/// @return result The binary logarithm as an UD60x18 number.
function log2(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = unwrap(x);
if (xUint < uUNIT) {
revert PRBMath_UD60x18_Log_InputTooSmall(x);
}
unchecked {
// Calculate the integer part of the logarithm, add it to the result and finally calculate y = x * 2^(-n).
uint256 n = msb(xUint / uUNIT);
// This is the integer part of the logarithm as an UD60x18 number. The operation can't overflow because n
// n is maximum 255 and UNIT is 1e18.
uint256 resultUint = n * uUNIT;
// This is $y = x * 2^{-n}$.
uint256 y = xUint >> n;
// If y is 1, the fractional part is zero.
if (y == uUNIT) {
return wrap(resultUint);
}
// Calculate the fractional part via the iterative approximation.
// The "delta.rshift(1)" part is equivalent to "delta /= 2", but shifting bits is faster.
uint256 DOUBLE_UNIT = 2e18;
for (uint256 delta = uHALF_UNIT; delta > 0; delta >>= 1) {
y = (y * y) / uUNIT;
// Is y^2 > 2 and so in the range [2,4)?
if (y >= DOUBLE_UNIT) {
// Add the 2^{-m} factor to the logarithm.
resultUint += delta;
// Corresponds to z/2 on Wikipedia.
y >>= 1;
}
}
result = wrap(resultUint);
}
}
/// @notice Multiplies two UD60x18 numbers together, returning a new UD60x18 number.
/// @dev See the documentation for the `Common.mulDiv18` function.
/// @param x The multiplicand as an UD60x18 number.
/// @param y The multiplier as an UD60x18 number.
/// @return result The product as an UD60x18 number.
function mul(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
result = wrap(mulDiv18(unwrap(x), unwrap(y)));
}
/// @notice Raises x to the power of y.
///
/// @dev Based on the formula:
///
/// $$
/// x^y = 2^{log_2{x} * y}
/// $$
///
/// Requirements:
/// - All from `exp2`, `log2` and `mul`.
///
/// Caveats:
/// - All from `exp2`, `log2` and `mul`.
/// - Assumes 0^0 is 1.
///
/// @param x Number to raise to given power y, as an UD60x18 number.
/// @param y Exponent to raise x to, as an UD60x18 number.
/// @return result x raised to power y, as an UD60x18 number.
function pow(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) {
uint256 xUint = unwrap(x);
uint256 yUint = unwrap(y);
if (xUint == 0) {
result = yUint == 0 ? UNIT : ZERO;
} else {
if (yUint == uUNIT) {
result = x;
} else {
result = exp2(mul(log2(x), y));
}
}
}
/// @notice Raises x (an UD60x18 number) to the power y (unsigned basic integer) using the famous algorithm
/// "exponentiation by squaring".
///
/// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring
///
/// Requirements:
/// - The result must fit within `MAX_UD60x18`.
///
/// Caveats:
/// - All from "Common.mulDiv18".
/// - Assumes 0^0 is 1.
///
/// @param x The base as an UD60x18 number.
/// @param y The exponent as an uint256.
/// @return result The result as an UD60x18 number.
function powu(UD60x18 x, uint256 y) pure returns (UD60x18 result) {
// Calculate the first iteration of the loop in advance.
uint256 xUint = unwrap(x);
uint256 resultUint = y & 1 > 0 ? xUint : uUNIT;
// Equivalent to "for(y /= 2; y > 0; y /= 2)" but faster.
for (y >>= 1; y > 0; y >>= 1) {
xUint = mulDiv18(xUint, xUint);
// Equivalent to "y % 2 == 1" but faster.
if (y & 1 > 0) {
resultUint = mulDiv18(resultUint, xUint);
}
}
result = wrap(resultUint);
}
/// @notice Calculates the square root of x, rounding down.
/// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
///
/// Requirements:
/// - x must be less than `MAX_UD60x18` divided by `UNIT`.
///
/// @param x The UD60x18 number for which to calculate the square root.
/// @return result The result as an UD60x18 number.
function sqrt(UD60x18 x) pure returns (UD60x18 result) {
uint256 xUint = unwrap(x);
unchecked {
if (xUint > uMAX_UD60x18 / uUNIT) {
revert PRBMath_UD60x18_Sqrt_Overflow(x);
}
// Multiply x by `UNIT` to account for the factor of `UNIT` that is picked up when multiplying two UD60x18
// numbers together (in this case, the two numbers are both the square root).
result = wrap(prbSqrt(xUint * uUNIT));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.13;
import "./Casting.sol" as C;
import "./Helpers.sol" as H;
import "./Math.sol" as M;
/// @notice The unsigned 60.18-decimal fixed-point number representation, which can have up to 60 digits and up to 18 decimals.
/// The values of this are bound by the minimum and the maximum values permitted by the Solidity type uint256.
/// @dev The value type is defined here so it can be imported in all other files.
type UD60x18 is uint256;
/*//////////////////////////////////////////////////////////////////////////
CASTING
//////////////////////////////////////////////////////////////////////////*/
using { C.intoSD1x18, C.intoUD2x18, C.intoSD59x18, C.intoUint128, C.intoUint256, C.intoUint40, C.unwrap } for UD60x18 global;
/*//////////////////////////////////////////////////////////////////////////
MATHEMATICAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/// The global "using for" directive makes the functions in this library callable on the UD60x18 type.
using {
M.avg,
M.ceil,
M.div,
M.exp,
M.exp2,
M.floor,
M.frac,
M.gm,
M.inv,
M.ln,
M.log10,
M.log2,
M.mul,
M.pow,
M.powu,
M.sqrt
} for UD60x18 global;
/*//////////////////////////////////////////////////////////////////////////
HELPER FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/// The global "using for" directive makes the functions in this library callable on the UD60x18 type.
using {
H.add,
H.and,
H.eq,
H.gt,
H.gte,
H.isZero,
H.lshift,
H.lt,
H.lte,
H.mod,
H.neq,
H.or,
H.rshift,
H.sub,
H.uncheckedAdd,
H.uncheckedSub,
H.xor
} for UD60x18 global;// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.10;
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {Checkpoints} from "@openzeppelin/contracts/utils/Checkpoints.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {IFractionalGovernor} from "flexible-voting/src/interfaces/IFractionalGovernor.sol";
import {IVotingToken} from "flexible-voting/src/interfaces/IVotingToken.sol";
/// @notice This is an abstract contract designed to make it easy to build clients
/// for governance systems that inherit from GovernorCountingFractional, a.k.a.
/// Flexible Voting governors.
///
/// A "client" in this sense is a contract that:
/// - (a) receives deposits of governance tokens from its users,
/// - (b) gives said depositors the ability to express their voting preferences
/// on governance proposals, and
/// - (c) casts votes on said proposals to flexible voting governors according
/// to the expressed preferences of its depositors.
///
/// This contract assumes that a child contract will implement a mechanism for
/// receiving and storing deposit balances, part (a). With that in place, this
/// contract supplies features (b) and (c).
///
/// A key concept here is that of a user's "raw balance". The raw balance is the
/// system's internal representation of a user's claim on the governance tokens
/// that it custodies. Since different systems might represent such claims in
/// different ways, this contract leaves the implementation of the `_rawBalance`
/// function to the child contract.
///
/// The simplest such representation would be to directly store the cumulative
/// balance of the governance token that the user has deposited. In such a
/// system, the amount that the user deposits is the amount that the user has
/// claim to. If the user has claim to 1e18 governance tokens, the internal
/// representation is just 1e18.
///
/// In many systems, however, the raw balance will not be equivalent to the
/// amount of governance tokens the user has claim to. In Aave, for example,
/// deposit amounts are scaled down by an ever-increasing index that represents
/// the cumulative amount of interest earned over the lifetime of deposits. The
/// "raw balance" of a user in Aave's case is this scaled down amount, since it
/// is the value that represents the user's claim on deposits. Thus for Aave, a
/// users's raw balance will always be less than the actual amount they have
/// claim to.
///
/// If the raw balance can be identified and defined for a system, and
/// `_rawBalance` can be implemented for it, then this contract will take care
/// of the rest.
abstract contract FlexVotingClientUpgradeable is Initializable {
using SafeCast for uint256;
using Checkpoints for Checkpoints.History;
/// @notice The voting options corresponding to those used in the Governor.
enum VoteType {
Against,
For,
Abstain
}
/// @notice Data structure to store vote preferences expressed by depositors.
struct ProposalVote {
uint128 againstVotes;
uint128 forVotes;
uint128 abstainVotes;
}
/// @dev Map proposalId to an address to whether they have voted on this proposal.
mapping(uint256 => mapping(address => bool)) private proposalVotersHasVoted;
/// @notice Map proposalId to vote totals expressed on this proposal.
mapping(uint256 => ProposalVote) public proposalVotes;
/// @notice The governor contract associated with this governance token. It
/// must be one that supports fractional voting, e.g. GovernorCountingFractional.
IFractionalGovernor public GOVERNOR;
/// @dev Mapping from address to the checkpoint history of raw balances
/// of that address.
mapping(address => Checkpoints.History) private balanceCheckpoints;
/// @dev History of the sum total of raw balances in the system. May or may
/// not be equivalent to this contract's balance of `GOVERNOR`s token at a
/// given time.
Checkpoints.History internal totalBalanceCheckpoints;
function __FlexVotingClient_init(
address _governor
) internal onlyInitializing {
GOVERNOR = IFractionalGovernor(_governor);
}
/// @dev Returns a representation of the current amount of `GOVERNOR`s
/// token that `_user` has claim to in this system. It may or may not be
/// equivalent to the withdrawable balance of `GOVERNOR`s token for `user`,
/// e.g. if the internal representation of balance has been scaled down.
function _rawBalanceOf(
address _user
) internal view virtual returns (uint256);
/// @dev Used as the `reason` param when submitting a vote to `GOVERNOR`.
function _castVoteReasonString() internal virtual returns (string memory) {
return "rolled-up vote from governance token holders";
}
/// @dev Delegates the present contract's voting rights with `GOVERNOR` to itself.
function _selfDelegate() internal {
IVotingToken(GOVERNOR.token()).delegate(address(this));
}
/// @notice Allow the caller to express their voting preference for a given
/// proposal. Their preference is recorded internally but not moved to the
/// Governor until `castVote` is called.
/// @param proposalId The proposalId in the associated Governor
/// @param support The depositor's vote preferences in accordance with the `VoteType` enum.
function expressVote(uint256 proposalId, uint8 support) external {
uint256 weight = getPastRawBalance(
msg.sender,
GOVERNOR.proposalSnapshot(proposalId)
);
require(weight > 0, "no weight");
require(
!proposalVotersHasVoted[proposalId][msg.sender],
"already voted"
);
proposalVotersHasVoted[proposalId][msg.sender] = true;
if (support == uint8(VoteType.Against)) {
proposalVotes[proposalId].againstVotes += SafeCast.toUint128(
weight
);
} else if (support == uint8(VoteType.For)) {
proposalVotes[proposalId].forVotes += SafeCast.toUint128(weight);
} else if (support == uint8(VoteType.Abstain)) {
proposalVotes[proposalId].abstainVotes += SafeCast.toUint128(
weight
);
} else {
revert("invalid support value, must be included in VoteType enum");
}
}
/// @notice Causes this contract to cast a vote to the Governor for all of the
/// accumulated votes expressed by users. Uses the sum of all raw balances to
/// proportionally split its voting weight. Can be called by anyone. Can be
/// called multiple times during the lifecycle of a given proposal.
/// @param proposalId The ID of the proposal which the Pool will now vote on.
function castVote(uint256 proposalId) external {
ProposalVote storage _proposalVote = proposalVotes[proposalId];
require(
_proposalVote.forVotes +
_proposalVote.againstVotes +
_proposalVote.abstainVotes >
0,
"no votes expressed"
);
uint256 _proposalSnapshotBlockNumber = GOVERNOR.proposalSnapshot(
proposalId
);
// We use the snapshot of total raw balances to determine the weight with
// which to vote. We do this for two reasons:
// (1) We cannot use the proposalVote numbers alone, since some people with
// balances at the snapshot might never express their preferences. If a
// large holder never expressed a preference, but this contract nevertheless
// cast votes to the governor with all of its weight, then other users may
// effectively have *increased* their voting weight because someone else
// didn't participate, which creates all kinds of bad incentives.
// (2) Other people might have already expressed their preferences on this
// proposal and had those preferences submitted to the governor by an
// earlier call to this function. The weight of those preferences
// should still be taken into consideration when determining how much
// weight to vote with this time.
// Using the total raw balance to proportion votes in this way means that in
// many circumstances this function will not cast votes with all of its
// weight.
uint256 _totalRawBalanceAtSnapshot = getPastTotalBalance(
_proposalSnapshotBlockNumber
);
// We need 256 bits because of the multiplication we're about to do.
uint256 _votingWeightAtSnapshot = IVotingToken(
address(GOVERNOR.token())
).getPastVotes(address(this), _proposalSnapshotBlockNumber);
// forVotesRaw forVoteWeight
// --------------------- = ------------------
// totalRawBalance totalVoteWeight
//
// forVoteWeight = forVotesRaw * totalVoteWeight / totalRawBalance
uint128 _forVotesToCast = SafeCast.toUint128(
(_votingWeightAtSnapshot * _proposalVote.forVotes) /
_totalRawBalanceAtSnapshot
);
uint128 _againstVotesToCast = SafeCast.toUint128(
(_votingWeightAtSnapshot * _proposalVote.againstVotes) /
_totalRawBalanceAtSnapshot
);
uint128 _abstainVotesToCast = SafeCast.toUint128(
(_votingWeightAtSnapshot * _proposalVote.abstainVotes) /
_totalRawBalanceAtSnapshot
);
// This param is ignored by the governor when voting with fractional
// weights. It makes no difference what vote type this is.
uint8 unusedSupportParam = uint8(VoteType.Abstain);
// Clear the stored votes so that we don't double-cast them.
delete proposalVotes[proposalId];
bytes memory fractionalizedVotes = abi.encodePacked(
_againstVotesToCast,
_forVotesToCast,
_abstainVotesToCast
);
GOVERNOR.castVoteWithReasonAndParams(
proposalId,
unusedSupportParam,
_castVoteReasonString(),
fractionalizedVotes
);
}
/// @dev Checkpoints the _user's current raw balance.
function _checkpointRawBalanceOf(address _user) internal {
balanceCheckpoints[_user].push(_rawBalanceOf(_user));
}
/// @notice Returns the `_user`'s raw balance at `_blockNumber`.
/// @param _user The account that's historical raw balance will be looked up.
/// @param _blockNumber The block at which to lookup the _user's raw balance.
function getPastRawBalance(
address _user,
uint256 _blockNumber
) public view returns (uint256) {
return balanceCheckpoints[_user].getAtProbablyRecentBlock(_blockNumber);
}
/// @notice Returns the sum total of raw balances of all users at `_blockNumber`.
/// @param _blockNumber The block at which to lookup the total balance.
function getPastTotalBalance(
uint256 _blockNumber
) public view returns (uint256) {
return totalBalanceCheckpoints.getAtProbablyRecentBlock(_blockNumber);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./FlexVotingClientUpgradeable.sol";
abstract contract RebootFlexVotingClientUpgradeable is
FlexVotingClientUpgradeable
{
using Checkpoints for Checkpoints.History;
mapping(address => uint256) public rawBalanceOf;
uint256 public totalRawBalance;
function __RebootFlexVotingClient_init(
address _governor
) internal onlyInitializing {
__FlexVotingClient_init(_governor);
_selfDelegate();
}
function increaseRawBalance(address _user, uint256 _amount) internal {
unchecked {
rawBalanceOf[_user] += _amount;
totalRawBalance += _amount;
}
_writeCheckpoints(_user);
}
function decreaseRawBalance(address _user, uint256 _amount) internal {
unchecked {
rawBalanceOf[_user] -= _amount;
totalRawBalance -= _amount;
}
_writeCheckpoints(_user);
}
function _writeCheckpoints(address _user) private {
_checkpointRawBalanceOf(_user);
totalBalanceCheckpoints.push(totalRawBalance);
}
function _rawBalanceOf(
address _user
) internal view override returns (uint256) {
return rawBalanceOf[_user];
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
interface IAffiliateRegistry is IAccessControlUpgradeable {
struct Affiliate {
address receiver;
uint256 uniqueWallets;
uint256 lifetimeSales;
uint256 lifetimeSessionValue;
uint256 sessionShare;
uint256 saleShare;
}
error AlreadyRegistered();
error NoSelfAffiliate();
error AffiliateNotRegistered();
event AffiliateRegistered(uint256 indexed id, address indexed receiver);
event ReceiverChanged(uint256 indexed id, address indexed receiver);
event PlayerAssigned(uint256 indexed id, address indexed player);
event SessionShareChanged(uint256 indexed id, uint256 newSessionShare);
event SaleShareChanged(uint256 indexed id, uint256 newSaleShare);
event DefaultSessionShareChanged(uint256 newSessionShare);
event DefaultSaleShareChanged(uint256 newSaleShare);
function assignPlayer(address _player, uint256 _affiliateId) external;
function setDefaultSessionShare(uint256) external;
function setDefaultSaleShare(uint256) external;
function setAffiliateSessionShare(uint256, uint256) external;
function setAffiliateSaleShare(uint256, uint256) external;
function registerNewAffiliate(
address _revenueReceiver
) external returns (uint256 _affiliateId);
function registerSale(
address _player,
uint256 _fees
) external returns (address, uint256);
function registerSession(
address _player,
uint256 _basePrice,
uint256 _fees
) external returns (address, uint256);
function changeReceiver(
uint256 _affiliateId,
address _newReceiver
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
import {SD59x18, eq} from "@prb/math/src/SD59x18.sol";
interface IAMM is IAccessControlUpgradeable {
struct ExtractorCalc {
address account;
uint256 extractorId;
uint256 payout;
SD59x18 mu;
SD59x18 phi;
SD59x18 entryFee;
address gameDev;
}
struct FixedFeeSplit {
uint64 matchMakerFeePercentage;
uint64 validatorFeePercentage;
uint64 gameDevFeePercentage;
uint64 ecoFundFeePercentage;
}
struct ExtractorWeights {
SD59x18 payoutWeight;
SD59x18 skillWeight;
SD59x18 baseExtractorWeight;
}
struct PayoutData {
address account;
uint256 payout;
uint256 maxPayout;
uint256 gameId;
uint256 extractorId;
SD59x18 mu;
SD59x18 phi;
uint256 entryFee;
address gameDev;
}
error PercentagesMustSumToOne();
error PayoutTooHigh();
error IncorrectMaxPayout();
error InvalidPercentage();
error InvalidReward();
event FixedFeeSplitSet(FixedFeeSplit feeSplit);
event ExtractorWeightsUpdated(ExtractorWeights weights);
event ExtractorCoefficientSet(SD59x18 newCoefficient);
event FixedFeePercentageSet(uint256 newFee);
event BaseFeeSet(uint256 newFee);
event DevExtractorPercentSet(SD59x18 percentage);
function setExtractorWeights(ExtractorWeights calldata) external;
function setExtractorCoefficient(SD59x18) external;
function setFixedFeePercentage(uint256) external;
function setBaseFee(uint256) external;
function setDevExtractorPercent(SD59x18) external;
function fixedFeePercentage() external view returns (uint64);
function baseFee() external view returns (uint64);
function setFixedFeeSplit(FixedFeeSplit calldata) external;
function disperseFees(uint256, address, address, uint256) external;
function lockMaxPayout(uint256) external;
function payout(PayoutData memory) external returns (uint256, uint256);
function forfeit(uint256) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface ICommitmentPermissions {
function isAllowed(address _contract) external returns (bool);
function setPermission(address, bool) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Interface of the IOFT core standard
*/
interface ICommonOFT is IERC165 {
struct LzCallParams {
address payable refundAddress;
address zroPaymentAddress;
bytes adapterParams;
}
/**
* @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`)
* _dstChainId - L0 defined chain id to send tokens too
* _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain
* _amount - amount of the tokens to transfer
* _useZro - indicates to use zro to pay L0 fees
* _adapterParam - flexible bytes array to indicate messaging adapter services in L0
*/
function estimateSendFee(uint16 _dstChainId, bytes32 _toAddress, uint _amount, bool _useZro, bytes calldata _adapterParams) external view returns (uint nativeFee, uint zroFee);
function estimateSendAndCallFee(uint16 _dstChainId, bytes32 _toAddress, uint _amount, bytes calldata _payload, uint64 _dstGasForCall, bool _useZro, bytes calldata _adapterParams) external view returns (uint nativeFee, uint zroFee);
/**
* @dev returns the circulating amount of tokens on current chain
*/
function circulatingSupply() external view returns (uint);
/**
* @dev returns the address of the ERC20 token
*/
function token() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
interface ICredits is IAccessControlUpgradeable {
struct FailedTransfer {
address sender;
address user;
uint256 amount;
}
error BalanceTooLow();
error ZeroAddress();
error NoPermission();
error InsufficientBalance();
error CannotMintZeroCredits();
event GGWithdrawn(address holder, address receiver, uint256 amount);
event CreditsPurchased(
uint256 _amount,
address indexed _mintTo,
bool _ticketPay
);
event CreditsBurned(address account, uint256 creditId, uint256 amount);
event CreditsConverted(
address _account,
uint256 _creditId,
uint256 _convertAmount
);
event FailedTransfersRetrySuccess(uint256 from, uint256 to);
function creditGGTValue() external returns (uint256);
function creditForGame(address) external view returns (uint256);
function gameForCredit(uint256) external view returns (address);
function creditBalance(address, uint256) external view returns (uint256);
function purchaseCredits(
uint256 _amount,
address _payFrom,
address _mintTo,
uint256 _gameId,
bool _ticketPay
) external;
function purchaseCreditsInGG(
uint256 _amountGG,
address _payFrom,
address _mintTo
) external;
function mintCredits(
uint256 _creditId,
uint256 _amount,
address _mintTo
) external;
function release(
address _account,
uint256 _amount
) external returns (uint256);
function registerCredit(address _game, uint256 _id) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./IGGT.sol";
import "./ITokenMarket.sol";
import "./ITickets.sol";
import "./IExtractors.sol";
import "./ICredits.sol";
import "./IGameCard.sol";
import "./IRebootBeacon.sol";
import "./IPriceFeed.sol";
import "./IProfileStorage.sol";
import "./IAMM.sol";
import "./IRegistry.sol";
import "./ICommitmentPermissions.sol";
import "./IAffiliateRegistry.sol";
import "./IQRNGProvider.sol";
import "./IStakingContracts.sol";
import "./IGameFactory.sol";
import "./IMItemsFactory.sol";
import "./IRewardsPool.sol";
import "./IFactoryController.sol";
import "./IPartnerships.sol";
import "./IPermissionRegistry.sol";
interface IDirectory {
error ZeroAddress();
error InvalidCaller();
error MustBeGreaterZero();
event ProtocolPauseToggled(bool isPaused);
event AdminCouncilSet(address council);
event GGTSet(address newAddr);
event TicketsSet(address newAddr);
event ExtractorsSet(address newAddr);
event TokenMarketSet(address newAddr);
event CreditsSet(address newAddr);
event GameCardSet(address newAddr);
event GameBeaconSet(address newAddr);
event MItemBeaconSet(address newAddr);
event UItemBeaconSet(address newAddr);
event GItemBeaconSet(address newAddr);
event ProfileStorageSet(address newAddr);
event PriceFeedSet(address newAddr);
event AMMSet(address newAddr);
event MatchMakerRegistrySet(address newAddr);
event ValidatorRegistrySet(address newAddr);
event GovernorSet(address newAddr);
event GovernorContractSet(address newAddr);
event CommitmentPermissionsSet(address newAddr);
event AffiliateRegistrySet(address newAddr);
event NextProtocolDirectoryVersionSet(address newAddr);
event RandomNumberProviderSet(address newAddr);
event StakingContractsSet(address newAddr);
event GameFactorySet(address newAddr);
event MItemsFactorySet(address newAddr);
event EcoFundSet(address newAddr);
event FactoryControllerSet(address newAddr);
event RewardsPoolSet(address newAddr);
event PartnershipsSet(address newAddr);
event GGVotesSet(address newAddr);
event PermissionRegistrySet(address newAddr);
function paused() external view returns (bool);
function ggt() external view returns (IGGT);
function tickets() external view returns (ITickets);
function extractors() external view returns (IExtractors);
function tokenMarket() external view returns (ITokenMarket);
function gameBeacon() external view returns (IRebootBeacon);
function mItemBeacon() external view returns (IRebootBeacon);
function uItemBeacon() external view returns (IRebootBeacon);
function gItemBeacon() external view returns (IRebootBeacon);
function gameCard() external view returns (IGameCard);
function credits() external view returns (ICredits);
function priceFeed() external view returns (IPriceFeed);
function profileStorage() external view returns (IProfileStorage);
function permissionRegistry() external view returns (IPermissionRegistry);
function rewardsAMM() external view returns (IAMM);
function matchMakerRegistry() external view returns (IRegistry);
function validatorRegistry() external view returns (IRegistry);
function governor() external view returns (address);
function governorContract() external view returns (address);
function factoryController() external view returns (IFactoryController);
function commitmentPermissions()
external
view
returns (ICommitmentPermissions);
function affiliateRegistry() external view returns (IAffiliateRegistry);
function rnProvider() external view returns (IQRNGProvider);
function nextProtocolDirectoryVersion() external view returns (address);
function protocolStakingContracts()
external
view
returns (IStakingContracts);
function gameFactory() external view returns (IGameFactory);
function mItemsFactory() external view returns (IMItemsFactory);
function ecoFund() external view returns (address);
function rewardsPool() external view returns (IRewardsPool);
function partnerships() external view returns (IPartnerships);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
interface IExtractors is IAccessControlUpgradeable {
error MustHaveGGValue();
error InvalidExtractorId();
error ZeroLength();
error GGPerExtractorTooHigh();
error InvalidCaller();
event UriSet(string uri);
event NewExtractorAdded(uint256 id, uint256 ggPerExtractor);
function setURI(string memory _uri) external;
function addNewExtractor(uint256 _id, uint256 _ggPerExtractor) external;
function getGGPerExtractor(uint256) external view returns (uint256);
function mintBatch(
address,
uint256[] calldata,
uint256[] calldata
) external;
function mint(address, uint256, uint256) external;
function burn(address, uint256, uint256) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "../Libraries/Glicko.sol";
import "./IAMM.sol";
interface IFactoryController {
struct GameConfig {
address admin;
Glicko.Config glickoConfig;
IAMM rewardsAMM;
string itemName;
string itemSymbol;
uint256 ticketsPerGG;
uint256 ggPerExtractor;
}
error AddressAlreadySet();
error InvalidCaller();
error ZeroAddress();
error GameAlreadyApproved();
event GameCreated(
address game,
address admin,
address gItems,
address mItems,
address uItems
);
event GameApproved(uint256 gameId, address gameAddress);
function gameAddress(uint256) external view returns (address);
function gameId(address) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "../Libraries/Glicko.sol";
import "./IAMM.sol";
import "@openzeppelin/contracts/access/IAccessControl.sol";
interface IGame is IAccessControl {
struct PayoutTable {
uint256 maxStrength;
mapping(uint256 => uint256) strengthVals;
}
/**
* @notice Data passed to initial session commitment
*
* @param playerWallet The Ethereum address of the user making the commitment
* @param custodialAddress Optional custodial contract address
* @param startupData A hash of Game specific startup data associated with this commitment
* @param validatorTip A $GG tip to the validator to prioritize the transaction
* @param protocolVersion A valid protocol version, that must match the most current public version
* @param clientVersion A valid game client version, that must match the version used to generate the gameplay transcript
* @param payoutId ID of payout table player is committing to
*/
struct GameCommitment {
address playerWallet;
address custodialAddress;
bytes32 startupData;
uint256 validatorTip;
uint256 matchMakerTip;
uint256 creditId;
string protocolVersion;
string clientVersion;
uint256 payoutId;
uint256 maxCredits;
}
/**
* @notice Data stored on-chain for each game session.
*
* @param playerWallet The evm address of the player
* @param maxPayout The maximum possible rewards payout set aside by the protocol
* @param payoutAddress The address receiving the final payout
* @param expiration The timestamp that the game session will expire at
* @param entryFee Amount of GG paid as entry fee
* @param entropy VRF entropy to be used for initial session data
* @param startupData A hash of Game specific startup data associated with this commitment
* @param protocolVersion A valid protocol version
* @param clientVersion A valid game client version
* @param payoutId ID of payout table player is committing to
* @param playerGlicko Player's glicko rating at the time of game commitment
* @param resolved Boolean value representing if game session has ended or not
*/
struct Session {
address playerWallet;
address payoutAddress;
uint256 maxPayout;
uint256 expiration;
uint256 validatorTip;
uint256 matchMakerTipLeft;
uint256 entryFee;
uint256 entropy;
uint256 entropyReqId;
bytes32 startupData;
string protocolVersion;
string clientVersion;
uint256 payoutId;
Glicko.Profile playerGlicko;
bool resolved;
}
/**
* @notice Data stored on-chain for each round.
*
* @param roundHash A hash of selected moves by the player for this round
* @param entropy Random entropy generated by VRF roll for this round
* @param opponentSessionId The commitment id for the opponent game session selected by the match maker
* @param opponentRoundIdx The round index for the opponent round selected by the match maker
*/
struct RoundData {
bytes32 roundHash;
uint256 entropy;
uint256 entropyReqId;
uint128 opponentSessionId;
uint128 opponentRoundIdx;
}
/**
* @notice Game submission function.
*
* @param sessionId Session ID of game
* @param player Player's wallet address
* @param oppMus Array of opponent Glicko2 ratings
* @param oppPhis Array of opponent Glicko2 rating deviations
* @param outcomes Array of game outcomes (0 = loss, 0.5e18 = tie, 1e18 = win)
* @param gameEventId Event ID of game outcome
* @param validatorSig Signature from an approved validator address
* @param extractorId ID of extractor token to mint
* @param forfeit If true, update rating and send max payout back to rewards pool
*/
struct SubmitData {
uint256 sessionId;
address player;
SD59x18[] oppMus;
SD59x18[] oppPhis;
SD59x18[] outcomes;
uint256 gameEventId;
bytes validatorSig;
uint256 extractorId;
bool forfeit;
}
/**
* @notice Struct containing info for VRF requests.
*
* @param sessionId Session ID vrf request is for
* @param roundIndex Index of rounds array for session
*/
struct VRFRequest {
bool forMatch;
uint128 sessionId;
uint128 roundIndex;
}
error GameNotActive();
error PlayerAlreadyRegistered();
error PlayerMissingRating();
error StartupDataRequired();
error ValidatorHasActiveSession();
error MatchMakerHasActiveSession();
error CannotPlayYourself();
error InvalidCaller();
error ClientVersionRequired();
error WrongRound();
error SignatureInvalid();
error MatchAlreadyRecorded();
error ExceedsMaxSessions();
error ProtocolVersionRequired();
error InvalidPlayer();
error SessionResolved();
error GameExpired();
error PreviousRoundOpen();
error GameResolved();
error InvalidSession(uint256 sessionId);
error InvalidRound(uint256 sessionId, uint256 roundIndex);
error LengthMismatch();
error InvalidPayoutId();
error RoundCountMismatch();
error InvalidHash();
error ZeroLength();
error MaxRoundsReached();
error ZeroAddress();
error RoundsPerSessionRequired();
error MissingPermission();
error MaxCreditsExceeded();
event GameStatusChanged(bool active);
event MaxGameDurationSet(uint256 timeInSeconds);
event SessionPriceUSDSet(uint256 amount);
event MaxActiveSessionsSet(uint256 sessions);
event WhitelistUpdated(uint256 gameId, bool isWhitelisted);
event MaxRoundsPerSessionSet(uint256 rounds);
event CommitmentRecorded(address indexed player, uint256 sessionId);
event RoundCommitted(
address indexed player,
uint256 indexed sessionId,
uint256 roundId
);
event MatchRecorded(
uint256 sessionId,
uint256 roundIndex,
uint256 oppSessionId,
uint256 oppRoundIndex
);
event RoundEntropy(uint256 sessionId, uint256 round, uint256 entropy);
event SessionEntropy(uint256 sessionId, uint256 entropy);
event PayoutTableAdded(
uint256 id,
uint256[] gameEventIds,
uint256[] strengthVals
);
event GameSubmitted(
uint256 sessionId,
uint256 gameEventId,
uint256 extractorPayout,
uint256 ticketPayout
);
function rewardsAMM() external view returns (IAMM);
function getGlicko2Rating(
address _playerWallet
) external view returns (Glicko.Profile memory _rating);
function registerPlayer(address _player) external;
function calculateWinProbability(
address _player,
SD59x18 _oppRating,
SD59x18 _oppRD
) external view returns (SD59x18);
function calculateWinProbabilityBatch(
address _player,
SD59x18[] calldata _oppRatings,
SD59x18[] calldata _oppRDs
) external view returns (SD59x18[] memory);
function setMaxGameDuration(uint128 _maxDuration) external;
function isWhitelisted(uint256) external view returns (bool);
function setSessionPriceUSD(uint256 _sessionPriceUSD) external;
function setActive(bool _active) external;
function maxGameDuration() external view returns (uint128);
function getActiveSessionCount(
address _player
) external view returns (uint256);
function active() external view returns (bool);
function sessionPriceUSD() external view returns (uint256);
function maxActiveSessions() external view returns (uint128);
function getRewardsAMM() external view returns (address);
function randomNumberCallback(
bytes32 requestId,
uint256 randomNumber
) external;
function submitGame(
SubmitData calldata
) external returns (uint256, uint256);
function getSession(uint256) external view returns (Session memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "erc721a/contracts/extensions/IERC721AQueryable.sol";
import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
interface IGameCard is IERC721AQueryable, IAccessControlUpgradeable {
function mintCardIfRequired(address to) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "../Libraries/Glicko.sol";
import "./IAMM.sol";
import "./IDirectory.sol";
interface IGameFactory {
error InvalidCaller();
error ZeroAddress();
function deploy(
address _adminWallet,
Glicko.Config calldata _glickoConfig,
IAMM _rewardsAmm,
uint256 _gameId
) external returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IOFTV2.sol";
interface IGGT is IERC20, IOFTV2 {
function delegate(address delegatee) external;
function delegates(address account) external returns (address);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./IDirectory.sol";
import "./IGame.sol";
interface IMItemsFactory {
error ZeroAddress();
error InvalidCaller();
error AddressAlreadySet();
event ValidMItemsSet(address mItems, bool isValid);
function deploy(
string memory,
string memory,
address,
address,
IDirectory,
address
) external returns (address, address);
function validMItems(address _mitemContract) external view returns (bool);
function setValidMItem(address _mItem, bool _valid) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
import "./ICommonOFT.sol";
/**
* @dev Interface of the IOFT core standard
*/
interface IOFTV2 is ICommonOFT {
/**
* @dev send `_amount` amount of token to (`_dstChainId`, `_toAddress`) from `_from`
* `_from` the owner of token
* `_dstChainId` the destination chain identifier
* `_toAddress` can be any size depending on the `dstChainId`.
* `_amount` the quantity of tokens in wei
* `_refundAddress` the address LayerZero refunds if too much message fee is sent
* `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token)
* `_adapterParams` is a flexible bytes array to indicate messaging adapter services
*/
function sendFrom(address _from, uint16 _dstChainId, bytes32 _toAddress, uint _amount, LzCallParams calldata _callParams) external payable;
function sendAndCall(address _from, uint16 _dstChainId, bytes32 _toAddress, uint _amount, bytes calldata _payload, uint64 _dstGasForCall, LzCallParams calldata _callParams) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IPartnerships {
error GameDoesNotExist();
function rewardsPermission(
address game,
uint256 gameId,
uint256 ticketAmount,
uint256 extractorId,
uint256 extractorAmount
) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IPermissionRegistry {
struct Permission {
bytes permissionPayload;
bytes permissionFuncData;
address permissionQueryContract;
uint256 permissionCompareVal;
CompareOperator permissionCompareOperator;
}
enum CompareOperator {
EQUAL,
GREATER,
GREATER_OR_EQUAL,
LOWER,
LOWER_OR_EQUAL
}
error InvalidPermission();
error CallFailed();
event PermissionCreated(uint256 indexed id);
function isAllowed(
address _userWallet,
uint256 _permissionId
) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IPriceFeed {
event PriceUpdated(bytes32 pair, uint256 price);
function currentPrice(bytes32 _pair) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "../Libraries/Glicko.sol";
interface IProfileStorage {
error PlayerAlreadyRegistered();
error PlayerNotRegistered();
error InvalidCaller();
event RatingUpdated(
uint256 gameId,
address player,
SD59x18 mu,
SD59x18 phi,
SD59x18 volatility
);
function updateProfile(
address _player,
Glicko.Profile calldata _profile
) external;
function profile(
uint256 _gameId,
address _player,
uint256
) external view returns (Glicko.Profile memory);
function registerPlayer(
address _player,
Glicko.Config memory _glickoConfig
) external;
function getProfileUnknown(
address _player,
Glicko.Config memory _glickoConfig
) external returns (Glicko.Profile memory);
function getRatingPeriodsMissed(
uint256,
address,
uint256
) external view returns (SD59x18);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./IRandomNumberProvider.sol";
interface IQRNGProvider is IRandomNumberProvider {
struct GameSponsor {
address sponsor;
address sponsorWallet;
}
error InvalidCaller();
error RequestIdUnknown();
event RequestParametsSet(
address airnode,
bytes32 endpointIdUint256,
bytes32 endpointIdUint256Array
);
event GameSponsorSet(
address indexed game,
address sponsor,
address sponsorWallet
);
function setRequestParameters(
address _airnode,
bytes32 _endpointIdUint256,
bytes32 _endpointIdUint256Array
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IRandomNumberProvider {
function requestRN() external payable returns (bytes32);
}
interface IRandomizer {
// Makes a Randomizer VRF callback request with a callback gas limit
function request(uint256 callbackGasLimit) external returns (uint256);
// Estimates the VRF fee given a callback gas limit
function estimateFee(uint256 callbackGasLimit) external returns (uint256);
// Deposits ETH to Randomizer for the client contract
function clientDeposit(address client) external payable;
// Withdraws deposited ETH from the client contract to the destination address
function clientWithdrawTo(address to, uint256 amount) external;
function getFeeStats(
uint256 request
) external view returns (uint256[2] memory);
// Gets the amount of ETH deposited and reserved for the client contract
function clientBalanceOf(
address _client
) external view returns (uint256 deposit, uint256 reserved);
// Returns the request data
function getRequest(
uint256 request
)
external
view
returns (
bytes32 result,
bytes32 dataHash,
uint256 ethPaid,
uint256 ethRefunded,
bytes10[2] memory vrfHashes
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/access/IAccessControl.sol";
interface IRebootBeacon is IAccessControl {
function upgradeTo(address newImplementation) external;
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IRegistry {
error LengthMismatch();
error ZeroLength();
event AddressApprovalUpdated(address validator, bool isApproved);
event AddressApprovalBatchUpdated(address[] validators, bool[] areApproved);
function approvedAddresses(address) external view returns (bool);
function updateApprovedAddress(address, bool) external;
function updateApprovedAddressBatch(
address[] calldata,
bool[] calldata
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IRewardsPool {
error CallFailed(bytes data);
error NoPermission();
error InsufficientBalance();
error TransferFailed();
error ZeroAddress();
event GGWithdrawn(address sender, uint256 amount);
event ETHWithdrawn(address sender, uint256 amount);
event DepositedETH(address sender, uint256 amount);
event SwappedETH(uint256 amountETH, uint256 minOut);
function requestGG(uint256) external;
function withdrawGG(address _receiver, uint256 _amount) external;
function withdrawETH(address _receiver, uint256 _amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IStakingContracts {
function getVotes(address, uint256) external view returns (uint256);
function addStakingContract(address) external;
function removeStakingContract(uint256) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
interface ITickets is IAccessControlUpgradeable {
error InvalidContractAddress();
error ZeroTokens();
error MustHaveTicketPerGG();
error InvalidParams();
error TicketPerGGTooHigh();
error GameValueAlreadySet();
error ExtractorBlockedByGame();
error InvalidId();
error InvalidCaller();
error MustUseExtractors();
event UriSet(string uri);
event NovaChainIdSet(uint16 newId);
event AdapterParamsSet(uint16 version, uint256 gasForDestination);
event TicketsPerGGSet(uint256 gameId, uint256 ticketsPerGG);
function ticketsPerGG(uint256) external view returns (uint256);
function setTicketsPerGG(uint256, uint256) external;
function mint(
address to,
address ggFrom,
uint256 id,
uint256 amount
) external;
function burn(
address from,
address ggTo,
uint256 amount,
uint256 gameId,
uint256 extractorId
) external;
function burnAndTransferSaleShares(
address from,
uint256 gameId,
uint256[3] calldata shares,
address[4] calldata receivers,
uint256 totalAmount
) external returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface ITokenMarket {
enum CurveType {
NONE,
LINEAR,
LOGISTIC
}
/// @notice Target price for a token, to be scaled according to sales pace.
/// @dev Represented as an 18 decimal fixed point number.
/// @dev Precomputed constant that allows us to rewrite a pow() as an exp().
/// @dev Represented as an 18 decimal fixed point number.
/// @dev The maximum number of tokens of tokens to sell + 1. We add
/// 1 because the logistic function will never fully reach its limit.
/// @dev Represented as an 18 decimal fixed point number.
/// @dev The maximum number of tokens of tokens to sell + 1 multiplied
/// by 2. We could compute it on the fly each time but this saves gas.
/// @dev Represented as a 36 decimal fixed point number.
/// @dev Time scale controls the steepness of the logistic curve,
/// which affects how quickly we will reach the curve's asymptote.
/// @dev Represented as an 18 decimal fixed point number.
struct TokenSale {
CurveType curveType;
address devShareReceiver;
int256 decayConstant;
int256 maxSellable;
int256 targetPrice;
int256 time;
uint256 startTime;
// basis point share base on 10000 (permyriad)
uint256 devShare;
bool active;
uint256 permissionId;
uint256 startSupply;
}
/// _targetPrice The target price for a token if sold on pace, scaled by 1e18.
/// _priceDecayPercent The percent price decays per unit of time with no sales, scaled by 1e18.
/// _perTimeUnit The number of tokens to target selling in 1 full unit of time, scaled by 1e18.
/// _targetPrice The target price for a token if sold on pace, scaled by 1e18.
/// _priceDecayPercent The percent price decays per unit of time with no sales, scaled by 1e18.
/// _maxSellable The maximum number of tokens to sell, scaled by 1e18.
/// _timeScale The steepness of the logistic curve, scaled by 1e18.
struct SaleDetails {
CurveType curveType;
address tokenAddress;
address devShareReceiver;
int256 targetPrice;
int256 priceDecayPercent;
uint256 maxSellable;
int256 time;
uint256 tokenId;
// basis point share base on 10000 (permyriad)
uint256 devShare;
bool active;
uint256 permissionId;
bool reset;
}
enum CompareOperator {
EQUAL,
GREATER,
GREATER_OR_EQUAL,
LOWER,
LOWER_OR_EQUAL
}
error CurveNotSupported();
error InsufficientPayment();
error NonNegativeDecayConstant();
error PurchaseExceedsSupply();
error NoActiveSale();
error UnsupportedToken();
error DevShareTooHigh();
error MissingCurveType();
error SaleDoesNotExist();
error InvalidValue();
error CallFailed();
error InvalidParams();
error WrongGameId();
event ProtocolFeeReceiverUpdated(address indexed newReceiver);
event ProtocolFeeUpdated(uint256 newFee);
event MaxDevShareUpdated(uint256 newFee);
event UpdatedSale(address indexed token, uint256 indexed tokenId);
event AllowedBuyerUpdated(
address indexed token,
uint256 tokenId,
address indexed buyer,
bool allowed
);
event TokenSaleStatusUpdated(
address indexed token,
uint256 tokenId,
bool active
);
event AllowlistOnlyUpdated(
address indexed token,
uint256 tokenId,
bool allowlistOnly
);
event DevShareUpdated(
address indexed token,
uint256 tokenId,
address receiver,
uint256 devShare
);
event Purchased(
address indexed tokenAddress,
address purchaser,
uint256 tokenId,
uint256 amount,
uint256 totalPrice
);
function purchase(
address _tokenAddress,
uint256 _tokenId,
address _receivingAddress,
uint256 _amount,
uint256 _maxPrice,
uint256 _gameId
) external;
function setProtocolFeeReceiver(address _protocolFeeReceiver) external;
function setProtocolFee(uint256 _protocolFee) external;
function setMaxDevShare(uint256 _maxDevShare) external;
function getVRGDAPrice(
address _tokenAddress1155,
uint256 _tokenId,
uint256 _amount
) external view returns (uint256);
function getTokenSale(
address _token,
uint256 _tokenId
) external view returns (TokenSale memory);
function canPurchase(
address _player,
address _token,
uint256 _tokenId
) external returns (bool);
function grantProtocolRole(address _contract) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import { SD59x18, convert, exp, sub, div, mul, sqrt, add, unwrap, wrap, inv, ln, gt, lt, abs, isZero, intoUint256, ZERO, UNIT } from "@prb/math/src/SD59x18.sol";
/**
* @title Glicko Contract
*
* @author Jack Chuma
*
* @notice Library implementation of the Glicko2 rating system
*/
library Glicko {
SD59x18 constant PI_SQUARED = SD59x18.wrap(9.869604401089358618e18);
SD59x18 constant EPSILON = SD59x18.wrap(0.000001e18);
SD59x18 constant TWO = SD59x18.wrap(2e18);
SD59x18 constant THREE = SD59x18.wrap(3e18);
struct Profile {
SD59x18 mu;
SD59x18 phi;
SD59x18 volatility;
}
struct Config {
SD59x18 defaultMu;
SD59x18 defaultPhi;
SD59x18 defaultVolatility;
SD59x18 tau;
SD59x18 idealConvergenceThreshold;
uint256 epochDuration;
}
struct GlickoInstance {
Memo memo;
SD59x18 playerMu;
SD59x18 playerPhiSquared;
SD59x18[] oppPhisSquared;
SD59x18 v;
SD59x18 delta;
SD59x18 phiStarSquared;
SD59x18 phiPrime;
SD59x18 muPrime;
}
struct Memo {
SD59x18[] gPhis;
SD59x18[] Ecalcs;
SD59x18 gSMinusESum;
}
error LengthMismatch();
error ZeroLength();
/**
* @notice Calculates probability of a player winning a skill-based game based on glicko ratings.
*
* @param _oppMu Glicko rating of opponent in Glicko2 scale
* @param _oppRD Rating deviation of opponent in Glicko2 scale
*/
function calculateWinProbability(
Profile memory _playerRating,
SD59x18 _oppMu,
SD59x18 _oppRD
) external pure returns (SD59x18) {
return _winProb(_playerRating.mu, _playerRating.phi, _oppMu, _oppRD);
}
/**
* @notice Calculates probability of a player winning a batch of skill-based games based on glicko ratings.
*
* @param _oppRatings Array of opponent ratings
* @param _oppRDs Array of opponent rating deviations
*/
function calculateWinProbabilityBatch(
Profile memory _playerRating,
SD59x18[] calldata _oppRatings,
SD59x18[] calldata _oppRDs
) external pure returns (SD59x18[] memory) {
if (_oppRatings.length == 0) revert ZeroLength();
if (_oppRatings.length != _oppRDs.length) revert LengthMismatch();
// Initiate array to hold win probabilities
SD59x18[] memory _winProbs = new SD59x18[](_oppRatings.length);
// Loop through oppRatings array
for (uint256 i; i < _oppRatings.length; ) {
// Calculate win probability and store in _winProbs array
_winProbs[i] = _winProb(
_playerRating.mu,
_playerRating.phi,
_oppRatings[i],
_oppRDs[i]
);
// Increment loop iterator without checking for overflow
unchecked {
i++;
}
}
return _winProbs;
}
/**
* @dev Private helper function containing glicko rating update math
*/
function update(
Profile memory _player,
SD59x18[] calldata _oppMus,
SD59x18[] calldata _oppPhis,
SD59x18[] calldata _outcomes,
SD59x18 _tau,
SD59x18 _ratingPeriodsMissed
) external pure returns (Profile memory _newRating) {
if (_oppMus.length == 0) revert ZeroLength();
if (
_oppMus.length != _outcomes.length ||
_oppMus.length != _oppPhis.length
) revert LengthMismatch();
// Initiate a glicko instance structure to contain inter-calculation values
GlickoInstance memory _instance;
SD59x18 _adjustedPhi = _adjustPhi(
_player.phi,
_player.volatility,
_ratingPeriodsMissed
);
// Convert rating and rating deviations to glicko scale for player and opponents
_instance.playerMu = _player.mu;
_instance.playerPhiSquared = mul(_adjustedPhi, _adjustedPhi);
_instance.oppPhisSquared = new SD59x18[](_oppMus.length);
_instance.memo.gPhis = new SD59x18[](_oppMus.length);
_instance.memo.Ecalcs = new SD59x18[](_oppMus.length);
// Compute the estimated variance of the player's rating based only on game outcomes
_instance = _calculateV(_instance, _oppMus, _oppPhis);
// Compute the estimated change in rating based only on game outcomes
(_instance.delta, _instance.memo.gSMinusESum) = _calculateDelta(
_instance.v,
_oppMus,
_instance.memo.gPhis,
_instance.memo.Ecalcs,
_outcomes
);
// Compute the updated volatility for the player
_newRating.volatility = _calculateVolatility(
_tau,
_player.volatility,
_instance.delta,
_instance.playerPhiSquared,
_instance.v
);
// Update the rating deviation to the new pre-rating period value
_instance.phiStarSquared = add(
_instance.playerPhiSquared,
mul(_newRating.volatility, _newRating.volatility)
);
// Update the new glicko rating deviation
_instance.phiPrime = inv(
sqrt(add(inv(_instance.phiStarSquared), inv(_instance.v)))
);
// Update the new glicko rating
_instance.muPrime = _calculateMuPrime(
_instance.playerMu,
_instance.phiPrime,
_instance.memo.gSMinusESum
);
_newRating.mu = _instance.muPrime;
_newRating.phi = _instance.phiPrime;
}
/**
* @dev Private helper function to compute estimated variance of player's rating.
* Also memoizes g and E calculations for oppPhis.
*/
function _calculateV(
GlickoInstance memory _instance,
SD59x18[] calldata _oppMus,
SD59x18[] calldata _oppPhis
) private pure returns (GlickoInstance memory) {
SD59x18 gPhi;
SD59x18 currE;
for (uint256 i; i < _oppMus.length; ) {
_instance.oppPhisSquared[i] = mul(_oppPhis[i], _oppPhis[i]);
gPhi = g(_instance.oppPhisSquared[i]);
_instance.memo.gPhis[i] = gPhi;
currE = E(_instance.playerMu, _oppMus[i], gPhi);
_instance.memo.Ecalcs[i] = currE;
_instance.v = add(
_instance.v,
mul(mul(mul(gPhi, gPhi), currE), sub(UNIT, currE))
);
unchecked {
i++;
}
}
_instance.v = inv(_instance.v);
return _instance;
}
/**
* @dev Private helper function that calculates estimated rating change as
* outlined in glicko2 specification.
*/
function _calculateDelta(
SD59x18 _v,
SD59x18[] calldata _oppMus,
SD59x18[] memory _gPhis,
SD59x18[] memory _Ecalcs,
SD59x18[] memory _outcomes
) private pure returns (SD59x18 _delta, SD59x18 _gSMinusESum) {
for (uint256 i; i < _oppMus.length; ) {
_delta = add(_delta, mul(_gPhis[i], sub(_outcomes[i], _Ecalcs[i])));
unchecked {
i++;
}
}
_gSMinusESum = _delta;
_delta = mul(_delta, _v);
}
/**
* @dev Private helper function that calculates updated volatility as outlined
* in glicko2 specification.
*/
function _calculateVolatility(
SD59x18 _tau,
SD59x18 _volatility,
SD59x18 _delta,
SD59x18 _playerPhiSquared,
SD59x18 _v
) private pure returns (SD59x18 _sigmaPrime) {
SD59x18 a = ln(mul(_volatility, _volatility));
SD59x18 _deltaSquared = mul(_delta, _delta);
SD59x18 A = a;
SD59x18 B = _selectB(_tau, _deltaSquared, _playerPhiSquared, _v, a);
SD59x18 C;
SD59x18 fC;
SD59x18 fA = f(_tau, A, _deltaSquared, _playerPhiSquared, _v, a);
SD59x18 fB = f(_tau, B, _deltaSquared, _playerPhiSquared, _v, a);
while (gt(abs(sub(B, A)), EPSILON)) {
C = add(A, div(mul(sub(A, B), fA), sub(fB, fA)));
fC = f(_tau, C, _deltaSquared, _playerPhiSquared, _v, a);
if (!gt(mul(fC, fB), ZERO)) {
A = B;
fA = fB;
} else {
fA = div(fA, TWO);
}
B = C;
fB = fC;
}
_sigmaPrime = exp(div(A, TWO));
}
/**
* @dev Private helper function that calculates new player rating on glicko
* scale.
*/
function _calculateMuPrime(
SD59x18 _playerMu,
SD59x18 _phiPrime,
SD59x18 _gSMinusESum
) private pure returns (SD59x18 _muPrime) {
_muPrime = add(_playerMu, mul(_gSMinusESum, mul(_phiPrime, _phiPrime)));
}
function _adjustPhi(
SD59x18 _phi,
SD59x18 _vol,
SD59x18 _ratingPeriodsMissed
) public pure returns (SD59x18) {
if (isZero(_ratingPeriodsMissed)) {
return _phi;
}
SD59x18 _phiSquared = mul(_phi, _phi);
SD59x18 _volSquared = mul(_vol, _vol);
return sqrt(add(_phiSquared, mul(_ratingPeriodsMissed, _volSquared)));
}
/**
* @dev Selects starting B value in volatility calculation above.
*/
function _selectB(
SD59x18 _tau,
SD59x18 _deltaSquared,
SD59x18 _playerPhiSquared,
SD59x18 _v,
SD59x18 a
) private pure returns (SD59x18) {
SD59x18 B;
SD59x18 _phiSquaredPlusV = add(_playerPhiSquared, _v);
if (gt(_deltaSquared, _phiSquaredPlusV)) {
B = ln(sub(_deltaSquared, _phiSquaredPlusV));
} else {
SD59x18 k = UNIT;
while (
lt(
f(
_tau,
x(a, k, _tau),
_deltaSquared,
_playerPhiSquared,
_v,
a
),
ZERO
)
) {
k = add(k, UNIT);
}
B = x(a, k, _tau);
}
return B;
}
/**
* @dev Calculates `x` input for `f` equation when selecting `B`.
*/
function x(
SD59x18 _a,
SD59x18 _k,
SD59x18 _tau
) private pure returns (SD59x18) {
return sub(_a, mul(_k, _tau));
}
/**
* @dev Implementation of glicko2 `g` equation.
*/
function g(SD59x18 _phiSquared) private pure returns (SD59x18) {
return inv(sqrt(add(UNIT, div(mul(THREE, _phiSquared), PI_SQUARED))));
}
/**
* @dev Implementation of glicko2 `E` equation.
*/
function E(
SD59x18 _playerMu,
SD59x18 _oppMu,
SD59x18 _gPhi
) private pure returns (SD59x18) {
return inv(add(UNIT, exp(mul(_gPhi, sub(_oppMu, _playerMu)))));
}
/**
* @dev Calculates win probability based on player rating and rating deviation compared to opponent.
*/
function _winProb(
SD59x18 _playerMu,
SD59x18 _playerPhi,
SD59x18 _oppMu,
SD59x18 _oppPhi
) private pure returns (SD59x18) {
SD59x18 _gPhi = g(
add(mul(_playerPhi, _playerPhi), mul(_oppPhi, _oppPhi))
);
return E(_playerMu, _oppMu, _gPhi);
}
/**
* @dev Implementation of glicko2 `f` equation.
*/
function f(
SD59x18 _tau,
SD59x18 _x,
SD59x18 _deltaSquared,
SD59x18 _phiSquared,
SD59x18 _v,
SD59x18 _a
) private pure returns (SD59x18) {
SD59x18 _exp = exp(_x);
SD59x18 _helper = add(_phiSquared, add(_v, _exp));
return
sub(
div(
mul(_exp, sub(_deltaSquared, _helper)),
mul(TWO, mul(_helper, _helper))
),
div(sub(_x, _a), mul(_tau, _tau))
);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.6.0;
pragma experimental ABIEncoderV2;
library LzLib {
// LayerZero communication
struct CallParams {
address payable refundAddress;
address zroPaymentAddress;
}
//---------------------------------------------------------------------------
// Address type handling
struct AirdropParams {
uint airdropAmount;
bytes32 airdropAddress;
}
function buildAdapterParams(
LzLib.AirdropParams memory _airdropParams,
uint _uaGasLimit
) internal pure returns (bytes memory adapterParams) {
if (
_airdropParams.airdropAmount == 0 &&
_airdropParams.airdropAddress == bytes32(0x0)
) {
adapterParams = buildDefaultAdapterParams(_uaGasLimit);
} else {
adapterParams = buildAirdropAdapterParams(_uaGasLimit, _airdropParams);
}
}
// Build Adapter Params
function buildDefaultAdapterParams(
uint _uaGas
) internal pure returns (bytes memory) {
// txType 1
// bytes [2 32 ]
// fields [txType extraGas]
return abi.encodePacked(uint16(1), _uaGas);
}
function buildAirdropAdapterParams(
uint _uaGas,
AirdropParams memory _params
) internal pure returns (bytes memory) {
require(_params.airdropAmount > 0, "Airdrop amount must be greater than 0");
require(
_params.airdropAddress != bytes32(0x0),
"Airdrop address must be set"
);
// txType 2
// bytes [2 32 32 bytes[] ]
// fields [txType extraGas dstNativeAmt dstNativeAddress]
return
abi.encodePacked(
uint16(2),
_uaGas,
_params.airdropAmount,
_params.airdropAddress
);
}
function getGasLimit(
bytes memory _adapterParams
) internal pure returns (uint gasLimit) {
require(
_adapterParams.length == 34 || _adapterParams.length > 66,
"Invalid adapterParams"
);
assembly {
gasLimit := mload(add(_adapterParams, 34))
}
}
// Decode Adapter Params
function decodeAdapterParams(
bytes memory _adapterParams
)
internal
pure
returns (
uint16 txType,
uint uaGas,
uint airdropAmount,
address payable airdropAddress
)
{
require(
_adapterParams.length == 34 || _adapterParams.length > 66,
"Invalid adapterParams"
);
assembly {
txType := mload(add(_adapterParams, 2))
uaGas := mload(add(_adapterParams, 34))
}
require(txType == 1 || txType == 2, "Unsupported txType");
require(uaGas > 0, "Gas too low");
if (txType == 2) {
assembly {
airdropAmount := mload(add(_adapterParams, 66))
airdropAddress := mload(add(_adapterParams, 86))
}
}
}
//---------------------------------------------------------------------------
// Address type handling
// TODO: testing
function bytes32ToAddress(
bytes32 _bytes32Address
) internal pure returns (address _address) {
require(bytes12(_bytes32Address) == bytes12(0), "Invalid address"); // first 12 bytes should be empty
return address(uint160(uint(_bytes32Address)));
}
function addressToBytes32(
address _address
) internal pure returns (bytes32 _bytes32Address) {
return bytes32(uint(uint160(_address)));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
library PVMath {
uint256 constant ONE = 1e18;
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return (a * b) / ONE;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return (a * ONE) / b;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/ERC1155SupplyUpgradeable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
/**
* @title Soulbound ERC1155 Token
*
* @author Jack Chuma, Niftydude
*
* @notice A soulbound implementation for ERC1155. All transfers blocked.
*/
contract SoulboundERC1155Upgradeable is ERC1155SupplyUpgradeable {
using Strings for uint256;
error Soulbound();
function __SoulboundERC1155_init(
string memory _uri
) public onlyInitializing {
__ERC1155_init(_uri);
}
/**
* @notice Returns uri for specific token ID
*
* @param _tokenId ID of token
*/
function uri(
uint256 _tokenId
) public view override returns (string memory) {
string memory baseURI = super.uri(_tokenId);
return
bytes(baseURI).length > 0
? string(abi.encodePacked(baseURI, _tokenId.toString()))
: "";
}
function _safeTransferFrom(
address,
address,
uint256,
uint256,
bytes memory
) internal pure override {
revert Soulbound();
}
function _safeBatchTransferFrom(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) internal pure override {
revert Soulbound();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
abstract contract BaseContractRoles {
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant PROTOCOL_ROLE = keccak256("PROTOCOL_ROLE");
bytes32 public constant CONTROLLER_ROLE = keccak256("CONTROLLER_ROLE");
bytes32 public constant RELAYER_ROLE = keccak256("RELAYER_ROLE");
bytes32 public constant CREDIT_MINTER_ROLE =
keccak256("CREDIT_MINTER_ROLE");
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "../Interfaces/IDirectory.sol";
abstract contract BaseDirectoryConsumer {
IDirectory public directory;
event ProtocolDirectorySet(address directory);
error MustUpdateAddress();
error ZeroDirectoryAddress();
error OnlyGovernanceCanCall();
error ProtocolPaused();
/**
* @dev Reverts if tx does not originate from governance
*/
modifier onlyGov() {
if (
msg.sender != address(directory) &&
msg.sender != directory.governor()
) revert OnlyGovernanceCanCall();
_;
}
/**
* @dev Reverts if protocol is paused
*/
modifier protocolActive() {
if (directory.paused()) revert ProtocolPaused();
_;
}
/**
* @notice Config function to store new Protocol Directory.
*
* @dev Callable by anyone.
*/
function updateProtocolDirectoryAddress() external {
address _newDirectory = directory.nextProtocolDirectoryVersion();
if (_newDirectory == address(directory)) revert MustUpdateAddress();
if (_newDirectory == address(0)) revert ZeroDirectoryAddress();
directory = IDirectory(_newDirectory);
emit ProtocolDirectorySet(address(_newDirectory));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./BaseContractRoles.sol";
contract ContractRolesUpgradeable is
BaseContractRoles,
Initializable,
AccessControlUpgradeable
{
error ZeroAddress();
error NoPermission();
function __ContractRoles_init(
address _adminWallet
) internal onlyInitializing {
if (_adminWallet == address(0)) revert ZeroAddress();
_grantRole(DEFAULT_ADMIN_ROLE, _adminWallet);
}
/**
* @notice Reverts is msg sender does not equal address param and sender has not role param
*
* @param _player the address of the player verify
* @param _role the role to verify
*/
modifier onlySelfOrRole(address _player, bytes32 _role) {
if (_player != _msgSender() && !hasRole(_role, _msgSender()))
revert NoPermission();
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "../Interfaces/IDirectory.sol";
import "./BaseDirectoryConsumer.sol";
import "erc721a-upgradeable/contracts/ERC721A__Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
abstract contract DirectoryConsumerUpgradeable is
BaseDirectoryConsumer,
ERC721A__Initializable,
Initializable
{
function __Directory_Consumer_ERC721A_init(
IDirectory _directory
) internal onlyInitializingERC721A {
_init(_directory);
}
function __Directory_Consumer_init(
IDirectory _directory
) internal onlyInitializing {
_init(_directory);
}
function _init(IDirectory _directory) internal {
if (address(_directory) == address(0)) revert ZeroDirectoryAddress();
directory = _directory;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev This is a base contract to aid in writing upgradeable diamond facet contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
import {ERC721A__InitializableStorage} from './ERC721A__InitializableStorage.sol';
abstract contract ERC721A__Initializable {
using ERC721A__InitializableStorage for ERC721A__InitializableStorage.Layout;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializerERC721A() {
// If the contract is initializing we ignore whether _initialized is set in order to support multiple
// inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
// contract may have been reentered.
require(
ERC721A__InitializableStorage.layout()._initializing
? _isConstructor()
: !ERC721A__InitializableStorage.layout()._initialized,
'ERC721A__Initializable: contract is already initialized'
);
bool isTopLevelCall = !ERC721A__InitializableStorage.layout()._initializing;
if (isTopLevelCall) {
ERC721A__InitializableStorage.layout()._initializing = true;
ERC721A__InitializableStorage.layout()._initialized = true;
}
_;
if (isTopLevelCall) {
ERC721A__InitializableStorage.layout()._initializing = false;
}
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} modifier, directly or indirectly.
*/
modifier onlyInitializingERC721A() {
require(
ERC721A__InitializableStorage.layout()._initializing,
'ERC721A__Initializable: contract is not initializing'
);
_;
}
/// @dev Returns true if and only if the function is running in the constructor
function _isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
assembly {
cs := extcodesize(self)
}
return cs == 0;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev This is a base storage for the initialization function for upgradeable diamond facet contracts
**/
library ERC721A__InitializableStorage {
struct Layout {
/*
* Indicates that the contract has been initialized.
*/
bool _initialized;
/*
* Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
bytes32 internal constant STORAGE_SLOT = keccak256('ERC721A.contracts.storage.initializable.facet');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs
pragma solidity ^0.8.4;
import '../IERC721A.sol';
/**
* @dev Interface of ERC721AQueryable.
*/
interface IERC721AQueryable is IERC721A {
/**
* Invalid query range (`start` >= `stop`).
*/
error InvalidQueryRange();
/**
* @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
*
* If the `tokenId` is out of bounds:
*
* - `addr = address(0)`
* - `startTimestamp = 0`
* - `burned = false`
* - `extraData = 0`
*
* If the `tokenId` is burned:
*
* - `addr = <Address of owner before token was burned>`
* - `startTimestamp = <Timestamp when token was burned>`
* - `burned = true`
* - `extraData = <Extra data when token was burned>`
*
* Otherwise:
*
* - `addr = <Address of owner>`
* - `startTimestamp = <Timestamp of start of ownership>`
* - `burned = false`
* - `extraData = <Extra data at start of ownership>`
*/
function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory);
/**
* @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
* See {ERC721AQueryable-explicitOwnershipOf}
*/
function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory);
/**
* @dev Returns an array of token IDs owned by `owner`,
* in the range [`start`, `stop`)
* (i.e. `start <= tokenId < stop`).
*
* This function allows for tokens to be queried if the collection
* grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
*
* Requirements:
*
* - `start < stop`
*/
function tokensOfOwnerIn(
address owner,
uint256 start,
uint256 stop
) external view returns (uint256[] memory);
/**
* @dev Returns an array of token IDs owned by `owner`.
*
* This function scans the ownership mapping and is O(`totalSupply`) in complexity.
* It is meant to be called off-chain.
*
* See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
* multiple smaller scans if the collection is large enough to cause
* an out-of-gas error (10K collections should be fine).
*/
function tokensOfOwner(address owner) external view returns (uint256[] memory);
}// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs
pragma solidity ^0.8.4;
/**
* @dev Interface of ERC721A.
*/
interface IERC721A {
/**
* The caller must own the token or be an approved operator.
*/
error ApprovalCallerNotOwnerNorApproved();
/**
* The token does not exist.
*/
error ApprovalQueryForNonexistentToken();
/**
* Cannot query the balance for the zero address.
*/
error BalanceQueryForZeroAddress();
/**
* Cannot mint to the zero address.
*/
error MintToZeroAddress();
/**
* The quantity of tokens minted must be more than zero.
*/
error MintZeroQuantity();
/**
* The token does not exist.
*/
error OwnerQueryForNonexistentToken();
/**
* The caller must own the token or be an approved operator.
*/
error TransferCallerNotOwnerNorApproved();
/**
* The token must be owned by `from`.
*/
error TransferFromIncorrectOwner();
/**
* Cannot safely transfer to a contract that does not implement the
* ERC721Receiver interface.
*/
error TransferToNonERC721ReceiverImplementer();
/**
* Cannot transfer to the zero address.
*/
error TransferToZeroAddress();
/**
* The token does not exist.
*/
error URIQueryForNonexistentToken();
/**
* The `quantity` minted with ERC2309 exceeds the safety limit.
*/
error MintERC2309QuantityExceedsLimit();
/**
* The `extraData` cannot be set on an unintialized ownership slot.
*/
error OwnershipNotInitializedForExtraData();
// =============================================================
// STRUCTS
// =============================================================
struct TokenOwnership {
// The address of the owner.
address addr;
// Stores the start time of ownership with minimal overhead for tokenomics.
uint64 startTimestamp;
// Whether the token has been burned.
bool burned;
// Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
uint24 extraData;
}
// =============================================================
// TOKEN COUNTERS
// =============================================================
/**
* @dev Returns the total number of tokens in existence.
* Burned tokens will reduce the count.
* To get the total number of tokens minted, please see {_totalMinted}.
*/
function totalSupply() external view returns (uint256);
// =============================================================
// IERC165
// =============================================================
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
// =============================================================
// IERC721
// =============================================================
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables
* (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in `owner`'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`,
* checking first that contract recipients are aware of the ERC721 protocol
* to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move
* this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external payable;
/**
* @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external payable;
/**
* @dev Transfers `tokenId` from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom}
* whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token
* by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external payable;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the
* zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external payable;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom}
* for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
// =============================================================
// IERC721Metadata
// =============================================================
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
// =============================================================
// IERC2309
// =============================================================
/**
* @dev Emitted when tokens in `fromTokenId` to `toTokenId`
* (inclusive) is transferred from `from` to `to`, as defined in the
* [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
*
* See {_mintERC2309} for more details.
*/
event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.10;
/// @dev The interface that flexible voting-compatible governors are expected to support.
interface IFractionalGovernor {
function token() external returns (address);
function proposalSnapshot(uint256 proposalId) external view returns (uint256);
function proposalDeadline(uint256 proposalId) external view returns (uint256);
function castVoteWithReasonAndParams(
uint256 proposalId,
uint8 support,
string calldata reason,
bytes memory params
) external returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.10;
/// @dev The interface that flexible voting-compatible voting tokens are expected to support.
interface IVotingToken {
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function delegate(address delegatee) external;
function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);
}{
"optimizer": {
"enabled": true,
"runs": 10
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"ExtractorBlockedByGame","type":"error"},{"inputs":[],"name":"GameValueAlreadySet","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidContractAddress","type":"error"},{"inputs":[],"name":"InvalidId","type":"error"},{"inputs":[],"name":"InvalidParams","type":"error"},{"inputs":[],"name":"MustHaveTicketPerGG","type":"error"},{"inputs":[],"name":"MustUpdateAddress","type":"error"},{"inputs":[],"name":"MustUseExtractors","type":"error"},{"inputs":[],"name":"NoPermission","type":"error"},{"inputs":[],"name":"OnlyGovernanceCanCall","type":"error"},{"inputs":[],"name":"ProtocolPaused","type":"error"},{"inputs":[],"name":"Soulbound","type":"error"},{"inputs":[],"name":"TicketPerGGTooHigh","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroDirectoryAddress","type":"error"},{"inputs":[],"name":"ZeroTokens","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"version","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"gasForDestination","type":"uint256"}],"name":"AdapterParamsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"newId","type":"uint16"}],"name":"NovaChainIdSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"directory","type":"address"}],"name":"ProtocolDirectorySet","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":"gameId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ticketsPerGG","type":"uint256"}],"name":"TicketsPerGGSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"UriSet","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONTROLLER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CREDIT_MINTER_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":[],"name":"GOVERNOR","outputs":[{"internalType":"contract IFractionalGovernor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROTOCOL_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"__SoulboundERC1155_init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"},{"internalType":"address","name":"_adminWallet","type":"address"},{"internalType":"contract IDirectory","name":"_directory","type":"address"},{"internalType":"uint256","name":"_ticketsPerGG","type":"uint256"}],"name":"__Tickets_init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adapterParams","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"ggTo","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"gameId","type":"uint256"},{"internalType":"uint256","name":"extractorId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"gameId","type":"uint256"},{"internalType":"uint256[3]","name":"shares","type":"uint256[3]"},{"internalType":"address[4]","name":"receivers","type":"address[4]"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"burnAndTransferSaleShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"playerWallet","type":"address"},{"internalType":"uint256","name":"gameId","type":"uint256"},{"internalType":"uint256","name":"extractorId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"chainId","type":"uint16"}],"name":"burnToExtract","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"castVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"directory","outputs":[{"internalType":"contract IDirectory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"uint8","name":"support","type":"uint8"}],"name":"expressVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"getPastRawBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNumber","type":"uint256"}],"name":"getPastTotalBalance","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":"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":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"ggFrom","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"novaChainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposalVotes","outputs":[{"internalType":"uint128","name":"againstVotes","type":"uint128"},{"internalType":"uint128","name":"forVotes","type":"uint128"},{"internalType":"uint128","name":"abstainVotes","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rawBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint256","name":"_gasForDestination","type":"uint256"}],"name":"setAdapterParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_novaChainId","type":"uint16"}],"name":"setNovaChainId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gameId","type":"uint256"},{"internalType":"uint256","name":"_ticketsPerGG","type":"uint256"}],"name":"setTicketsPerGG","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setURI","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":"uint256","name":"","type":"uint256"}],"name":"ticketsPerGG","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRawBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updateProtocolDirectoryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a06040523060805234801561001457600080fd5b5060805161559e61004c600039600081816110c801528181611108015281816117380152818161177801526117f0015261559e6000f3fe6080604052600436106102175760003560e01c8062fdd58e1461021c57806301ffc9a71461024f57806302768de41461027f57806302fe5305146102a1578063083118d5146102c3578063092c5b3b146102e55780630e89341c1461031957806312064c341461033957806313c19841146103665780631b13ee8a14610386578063248a9ca3146103a65780632eb2c2d6146103c65780632f2ff15d146103e6578063316eac121461040657806336568abe146104265780633659cfe6146104465780633eb76b9c146104665780634bb17b1f146104865780634e1273f41461049b5780634f1ef286146104c85780634f558e79146104db57806352d1902d1461050a57806352e62a431461051f578063544ffc9c1461053f5780635a9bd576146105b45780636927850a146105e2578063696c81bb146105f85780636d1daa28146106185780636dc0ae221461063857806375b238fc146106655780637a26db171461069957806391d14854146106c8578063926d7d7f146106e8578063a217fddf1461070a578063a22cb4651461071f578063b18d6afd1461073f578063b3f1c93d1461075f578063bc9905191461077f578063bd85b03914610792578063c41c2f24146107bf578063c915c2b1146107df578063d547741f146107ff578063db7817f91461081f578063e985e9c51461083f578063f1bdebc014610888578063f242432a146108a8578063fb37f800146108c3575b600080fd5b34801561022857600080fd5b5061023c6102373660046146d7565b6108f7565b6040519081526020015b60405180910390f35b34801561025b57600080fd5b5061026f61026a366004614719565b610992565b6040519015158152602001610246565b34801561028b57600080fd5b5061023c6000805160206154f683398151915281565b3480156102ad57600080fd5b506102c16102bc3660046147eb565b61099d565b005b3480156102cf57600080fd5b506102d8610a9f565b604051610246919061486f565b3480156102f157600080fd5b5061023c7f7b765e0e932d348852a6f810bfa1ab891e259123f02db8cdcde614c57022335781565b34801561032557600080fd5b506102d8610334366004614882565b610b2e565b34801561034557600080fd5b5061023c61035436600461489b565b60ce6020526000908152604090205481565b34801561037257600080fd5b506102c16103813660046148b8565b610b8d565b34801561039257600080fd5b5061023c6103a13660046146d7565b610d4e565b3480156103b257600080fd5b5061023c6103c1366004614882565b610d70565b3480156103d257600080fd5b506102c16103e136600461496e565b610d85565b3480156103f257600080fd5b506102c1610401366004614a1b565b610e18565b34801561041257600080fd5b506102c1610421366004614a4b565b610e39565b34801561043257600080fd5b506102c1610441366004614a1b565b611040565b34801561045257600080fd5b506102c161046136600461489b565b6110be565b34801561047257600080fd5b506102c1610481366004614882565b611186565b34801561049257600080fd5b506102c16114e9565b3480156104a757600080fd5b506104bb6104b6366004614ab4565b611605565b6040516102469190614b80565b6102c16104d6366004614bc4565b61172e565b3480156104e757600080fd5b5061026f6104f6366004614882565b600090815260976020526040902054151590565b34801561051657600080fd5b5061023c6117e3565b34801561052b57600080fd5b506102c161053a366004614c09565b611892565b34801561054b57600080fd5b5061058a61055a366004614882565b60ca60205260009081526040902080546001909101546001600160801b0380831692600160801b90048116911683565b604080516001600160801b0394851681529284166020840152921691810191909152606001610246565b3480156105c057600080fd5b5061023c6105cf366004614882565b6101686020526000908152604090205481565b3480156105ee57600080fd5b5061023c60cf5481565b34801561060457600080fd5b506102c1610613366004614c4b565b611b0e565b34801561062457600080fd5b506102c1610633366004614c66565b611c12565b34801561064457600080fd5b5060cb54610658906001600160a01b031681565b6040516102469190614c82565b34801561067157600080fd5b5061023c7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b3480156106a557600080fd5b50610166546106b59061ffff1681565b60405161ffff9091168152602001610246565b3480156106d457600080fd5b5061026f6106e3366004614a1b565b611d15565b3480156106f457600080fd5b5061023c60008051602061549683398151915281565b34801561071657600080fd5b5061023c600081565b34801561072b57600080fd5b506102c161073a366004614ca4565b611d40565b34801561074b57600080fd5b506102c161075a366004614cd2565b611d4b565b34801561076b57600080fd5b506102c161077a366004614d23565b611e6c565b6102c161078d366004614d69565b611fbb565b34801561079e57600080fd5b5061023c6107ad366004614882565b60009081526097602052604090205490565b3480156107cb57600080fd5b50600054610658906001600160a01b031681565b3480156107eb57600080fd5b5061023c6107fa366004614dbb565b61236f565b34801561080b57600080fd5b506102c161081a366004614a1b565b6127e7565b34801561082b57600080fd5b5061023c61083a366004614882565b612803565b34801561084b57600080fd5b5061026f61085a366004614e22565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205460ff1690565b34801561089457600080fd5b506102c16108a33660046147eb565b612810565b3480156108b457600080fd5b506102c16103e1366004614e50565b3480156108cf57600080fd5b5061023c7f98eee63452386eeb3e8c10d0cfe42a80ba83b7826c38149de72788766ce2cb3681565b60006001600160a01b0383166109675760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b5060008181526065602090815260408083206001600160a01b03861684529091529020545b92915050565b600061098c82612842565b6000546001600160a01b03163314801590610a3e575060008054906101000a90046001600160a01b03166001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a289190614eb8565b6001600160a01b0316336001600160a01b031614155b15610a5c57604051637f242d1d60e11b815260040160405180910390fd5b610a6581612867565b7fd09d05534067f74dbc9e6af794edbd29e904d7698e428d0bc1378e45889acdd781604051610a94919061486f565b60405180910390a150565b6101678054610aad90614ed5565b80601f0160208091040260200160405190810160405280929190818152602001828054610ad990614ed5565b8015610b265780601f10610afb57610100808354040283529160200191610b26565b820191906000526020600020905b815481529060010190602001808311610b0957829003601f168201915b505050505081565b60606000610b3b83612873565b90506000815111610b5b5760405180602001604052806000815250610b86565b80610b6584612907565b604051602001610b76929190614f0f565b6040516020818303038152906040525b9392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c029190614f3e565b15610c2057604051634427925560e01b815260040160405180910390fd5b60008054906101000a90046001600160a01b03166001600160a01b0316631f2878096040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c959190614eb8565b6001600160a01b0316336001600160a01b031614610cc6576040516348f5c3ed60e01b815260040160405180910390fd5b6000828152610168602052604090205415610cf4576040516366134a9160e01b815260040160405180910390fd5b610cfd81612999565b6000828152610168602090815260409182902083905581518481529081018390527f971be14c38e44863d19d97730d26df2bcf87d0bc536b04d77e128b3514433b0291015b60405180910390a15050565b6001600160a01b038216600090815260cc60205260408120610b8690836129ed565b600090815260d0602052604090206001015490565b6001600160a01b038516331480610da15750610da1853361085a565b610e045760405162461bcd60e51b815260206004820152602e60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201526d195c881bdc88185c1c1c9bdd995960921b606482015260840161095e565b610e118585858585612b08565b5050505050565b610e2182610d70565b610e2a81612b21565b610e348383612b2b565b505050565b600054600160a81b900460ff1615808015610e6157506000546001600160a01b90910460ff16105b80610e895750610e7030612bb1565b158015610e895750600054600160a01b900460ff166001145b610eec5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161095e565b6000805460ff60a01b1916600160a01b1790558015610f19576000805460ff60a81b1916600160a81b1790555b610f2285612810565b610f2b84612bc0565b610f3483612c1b565b610f9e836001600160a01b0316635e8430ee6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f999190614eb8565b612c4d565b610fa782612999565b600080526101686020527fb8607e2a62c9ca25d8e6acf2f12b8faaf864bb6a81dedcf1dd61ecbd170ea7a5829055610166805461ffff191660af179055610ff26001621e8480612c87565b8015610e11576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6001600160a01b03811633146110b05760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b606482015260840161095e565b6110ba8282612cc6565b5050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036111065760405162461bcd60e51b815260040161095e90614f5b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611138612d2d565b6001600160a01b03161461115e5760405162461bcd60e51b815260040161095e90614f95565b61116781612d49565b6040805160008082526020820190925261118391839190612e08565b50565b600081815260ca60205260408120600181015481549192916001600160801b03918216916111c09180821691600160801b90910416614fe5565b6111ca9190614fe5565b6001600160801b0316116112155760405162461bcd60e51b81526020600482015260126024820152711b9bc81d9bdd195cc8195e1c1c995cdcd95960721b604482015260640161095e565b60cb54604051632d63f69360e01b8152600481018490526000916001600160a01b031690632d63f69390602401602060405180830381865afa15801561125f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611283919061500c565b9050600061129082612803565b9050600060cb60009054906101000a90046001600160a01b03166001600160a01b031663fc0c546a6040518163ffffffff1660e01b81526004016020604051808303816000875af11580156112e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130d9190614eb8565b6001600160a01b0316633a46b1a830856040518363ffffffff1660e01b815260040161133a929190615025565b602060405180830381865afa158015611357573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137b919061500c565b84549091506000906113b29084906113a390600160801b90046001600160801b03168561503e565b6113ad919061506b565b612f73565b85549091506000906113d39085906113a3906001600160801b03168661503e565b60018701549091506000906113f79086906113a3906001600160801b03168761503e565b600089815260ca6020908152604080832083815560010180546001600160801b03199081169091558151608088811b83169482019490945288841b821660308201529285901b169082015291925060029160500160408051601f1981840301815291905260cb549091506001600160a01b0316635f398a148b84611479612fe0565b856040518563ffffffff1660e01b8152600401611499949392919061508d565b6020604051808303816000875af11580156114b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114dc919061500c565b5050505050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b031663cf11c26b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561153d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115619190614eb8565b6000549091506001600160a01b03908116908216036115935760405163ee9d4f0f60e01b815260040160405180910390fd5b6001600160a01b0381166115ba5760405163e2417bff60e01b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b0383161790556040517f7d4400cf8a02e5f0690de634d2ab700d2d987649dcf96cdd70a971657a041b4a90610a94908390614c82565b6060815183511461166a5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b606482015260840161095e565b600083516001600160401b0381111561168557611685614736565b6040519080825280602002602001820160405280156116ae578160200160208202803683370190505b50905060005b8451811015611726576116f98582815181106116d2576116d26150cc565b60200260200101518583815181106116ec576116ec6150cc565b60200260200101516108f7565b82828151811061170b5761170b6150cc565b602090810291909101015261171f816150e2565b90506116b4565b509392505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036117765760405162461bcd60e51b815260040161095e90614f5b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166117a8612d2d565b6001600160a01b0316146117ce5760405162461bcd60e51b815260040161095e90614f95565b6117d782612d49565b6110ba82826001612e08565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461187e5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b606482015260840161095e565b506000805160206154d68339815191525b90565b60cb54604051632d63f69360e01b8152600481018490526000916119069133916001600160a01b031690632d63f69390602401602060405180830381865afa1580156118e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a1919061500c565b9050600081116119445760405162461bcd60e51b81526020600482015260096024820152681b9bc81dd95a59da1d60ba1b604482015260640161095e565b600083815260c96020908152604080832033845290915290205460ff161561199e5760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e481d9bdd1959609a1b604482015260640161095e565b600083815260c9602090815260408083203384529091529020805460ff1916600117905560ff8216611a23576119d381612f73565b600084815260ca6020526040812080549091906119fa9084906001600160801b0316614fe5565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550505050565b60001960ff831601611a6657611a3881612f73565b600084815260ca6020526040902080546010906119fa908490600160801b90046001600160801b0316614fe5565b60011960ff831601611aa557611a7b81612f73565b600084815260ca6020526040812060010180549091906119fa9084906001600160801b0316614fe5565b60405162461bcd60e51b815260206004820152603860248201527f696e76616c696420737570706f72742076616c75652c206d75737420626520696044820152776e636c7564656420696e20566f74655479706520656e756d60401b606482015260840161095e565b6000546001600160a01b03163314801590611baf575060008054906101000a90046001600160a01b03166001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b999190614eb8565b6001600160a01b0316336001600160a01b031614155b15611bcd57604051637f242d1d60e11b815260040160405180910390fd5b610166805461ffff191661ffff83169081179091556040519081527f4638b9d191c13f7c818328022e9a587f4050f58d4714724cc187da6307c8f51a90602001610a94565b6000546001600160a01b03163314801590611cb3575060008054906101000a90046001600160a01b03166001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9d9190614eb8565b6001600160a01b0316336001600160a01b031614155b15611cd157604051637f242d1d60e11b815260040160405180910390fd5b611cdb8282612c87565b6040805161ffff84168152602081018390527f2350f7c37c954a84e89df0b239e6b79e60b0b0466691f95df03c1a7a6469de089101610d42565b600091825260d0602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6110ba338383613000565b6000805160206154f6833981519152611d6381612b21565b6000611d71878585886130e0565b9050611d7d8782613416565b60008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611dce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df29190614eb8565b6001600160a01b031663a9059cbb87836040518363ffffffff1660e01b8152600401611e1f929190615025565b6020604051808303816000875af1158015611e3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e629190614f3e565b5050505050505050565b6000805160206154f6833981519152611e8481612b21565b81600003611ea55760405163b98a411360e01b815260040160405180910390fd5b6000838152610168602052604081205490819003611ed657604051631bf4348160e31b815260040160405180910390fd5b611ef186858560405180602001604052806000815250613447565b6000611efd848361355a565b9050611f098782613579565b60008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7e9190614eb8565b6040516323b872dd60e01b81526001600160a01b0388811660048301523060248301526044820184905291909116906323b872dd90606401611e1f565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561200c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120309190614f3e565b1561204e57604051634427925560e01b815260040160405180910390fd5b846000805160206154968339815191526001600160a01b038216331480159061207e575061207c8133611d15565b155b1561209c57604051639d7b369d60e01b815260040160405180910390fd5b846000036120bd57604051631174c25360e21b815260040160405180910390fd5b60006120cb888888886130e0565b90506120d78882613416565b6101665461ffff908116908516036121d45760008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215e9190614eb8565b6001600160a01b031663a9059cbb89836040518363ffffffff1660e01b815260040161218b929190615025565b6020604051808303816000875af11580156121aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ce9190614f3e565b50611e62565b60008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa158015612225573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122499190614eb8565b6001600160a01b031663695ef6bf34308761226a8d6001600160a01b031690565b604080516060810182523381526000602082015261016780548a938301919061229290614ed5565b80601f01602080910402602001604051908101604052809291908181526020018280546122be90614ed5565b801561230b5780601f106122e05761010080835404028352916020019161230b565b820191906000526020600020905b8154815290600101906020018083116122ee57829003601f168201915b50505050508152506040518763ffffffff1660e01b81526004016123339594939291906150fb565b6000604051808303818588803b15801561234c57600080fd5b505af1158015612360573d6000803e3d6000fd5b50505050505050505050505050565b60006000805160206154f683398151915261238981612b21565b600061239888886000876130e0565b905060008635156124ab576123b6828860005b6020020135906135a8565b905060008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa158015612409573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242d9190614eb8565b6001600160a01b031663a9059cbb612448602089018961489b565b836040518363ffffffff1660e01b8152600401612466929190615025565b6020604051808303816000875af1158015612485573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a99190614f3e565b505b60006124b9838960016123ab565b905060008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561250c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125309190614eb8565b6001600160a01b031663a9059cbb61254e60408a0160208b0161489b565b836040518363ffffffff1660e01b815260040161256c929190615025565b6020604051808303816000875af115801561258b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125af9190614f3e565b5060006125be848a60026123ab565b905060008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa158015612611573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126359190614eb8565b6001600160a01b031663a9059cbb61265360608b0160408c0161489b565b836040518363ffffffff1660e01b8152600401612671929190615025565b6020604051808303816000875af1158015612690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b49190614f3e565b50600081836126c38688615162565b6126cd9190615162565b6126d79190615162565b905060008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561272a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274e9190614eb8565b6001600160a01b031663a9059cbb61276c60808c0160608d0161489b565b836040518363ffffffff1660e01b815260040161278a929190615025565b6020604051808303816000875af11580156127a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cd9190614f3e565b506127d88c86613416565b9b9a5050505050505050505050565b6127f082610d70565b6127f981612b21565b610e348383612cc6565b600061098c60cd836129ed565b600054600160a81b900460ff166128395760405162461bcd60e51b815260040161095e90615175565b611183816135bd565b60006001600160e01b03198216637965db0b60e01b148061098c575061098c826135ef565b60676110ba8282615206565b60606067805461288290614ed5565b80601f01602080910402602001604051908101604052809291908181526020018280546128ae90614ed5565b80156128fb5780601f106128d0576101008083540402835291602001916128fb565b820191906000526020600020905b8154815290600101906020018083116128de57829003601f168201915b50505050509050919050565b606060006129148361363f565b60010190506000816001600160401b0381111561293357612933614736565b6040519080825280601f01601f19166020018201604052801561295d576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461296757509392505050565b806000036129ba576040516330d20d1b60e21b815260040160405180910390fd5b6ebc29a27c6e5299f5839b0e51b9b2d360301b811115611183576040516367b8cfe360e01b815260040160405180910390fd5b6000438210612a3e5760405162461bcd60e51b815260206004820181905260248201527f436865636b706f696e74733a20626c6f636b206e6f7420796574206d696e6564604482015260640161095e565b6000612a4983613715565b84549091506000816005811115612aa7576000612a658461377a565b612a6f9085615162565b60008981526020902090915081015463ffffffff9081169086161015612a9757809150612aa5565b612aa28160016152c5565b92505b505b6000612ab588868585613862565b90508015612af057612ada88612acc600184615162565b600091825260209091200190565b54600160201b90046001600160e01b0316612af3565b60005b6001600160e01b031698975050505050505050565b60405163a4420a9560e01b815260040160405180910390fd5b61118381336138b8565b612b358282611d15565b6110ba57600082815260d0602090815260408083206001600160a01b03851684529091529020805460ff19166001179055612b6d3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6001600160a01b03163b151590565b600054600160a81b900460ff16612be95760405162461bcd60e51b815260040161095e90615175565b6001600160a01b038116612c105760405163d92e233d60e01b815260040160405180910390fd5b611183600082612b2b565b600054600160a81b900460ff16612c445760405162461bcd60e51b815260040161095e90615175565b61118381613911565b600054600160a81b900460ff16612c765760405162461bcd60e51b815260040161095e90615175565b612c7f8161395a565b6111836139a5565b6040516001600160f01b031960f084901b166020820152602281018290526042016040516020818303038152906040526101679081610e349190615206565b612cd08282611d15565b156110ba57600082815260d0602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000805160206154d6833981519152546001600160a01b031690565b6000546001600160a01b03163314801590612dea575060008054906101000a90046001600160a01b03166001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa158015612db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd49190614eb8565b6001600160a01b0316336001600160a01b031614155b1561118357604051637f242d1d60e11b815260040160405180910390fd5b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612e3b57610e3483613a7d565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612e95575060408051601f3d908101601f19168201909252612e929181019061500c565b60015b612ef85760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161095e565b6000805160206154d68339815191528114612f675760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161095e565b50610e34838383613b17565b60006001600160801b03821115612fdc5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b606482015260840161095e565b5090565b60606040518060600160405280602c8152602001615516602c9139905090565b816001600160a01b0316836001600160a01b0316036130735760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b606482015260840161095e565b6001600160a01b03838116600081815260666020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000816000036131035760405163b98a411360e01b815260040160405180910390fd5b6000848152610168602052604090205461311e90839061355a565b9050821561340357831561329d5760008060009054906101000a90046001600160a01b03166001600160a01b0316631f2878096040518163ffffffff1660e01b8152600401602060405180830381865afa158015613180573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131a49190614eb8565b6001600160a01b031663bea1c286866040518263ffffffff1660e01b81526004016131d191815260200190565b602060405180830381865afa1580156131ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132129190614eb8565b604051633a8d816160e11b8152600481018690529091506001600160a01b0382169063751b02c290602401602060405180830381865afa15801561325a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327e9190614f3e565b61329b576040516340abe7db60e01b815260040160405180910390fd5b505b60008060009054906101000a90046001600160a01b03166001600160a01b0316635c0094c66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133159190614eb8565b6040516328dfc3ab60e21b8152600481018690529091506000906001600160a01b0383169063a37f0eac90602401602060405180830381865afa158015613360573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613384919061500c565b90506000613392848361355a565b604051637a94c56560e11b81526001600160a01b038a8116600483015260248201899052604482018390529192509084169063f5298aca90606401600060405180830381600087803b1580156133e757600080fd5b505af11580156133fb573d6000803e3d6000fd5b505050505050505b61340e858584613b3c565b949350505050565b6001600160a01b038216600090815260ce602052604090208054829003905560cf805482900390556110ba82613cbe565b6001600160a01b0384166134a75760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b606482015260840161095e565b3360006134b385613cd6565b905060006134c085613cd6565b90506134d183600089858589613d21565b60008681526065602090815260408083206001600160a01b038b168452909152812080548792906135039084906152c5565b909155505060408051878152602081018790526001600160a01b03808a169260009291871691600080516020615476833981519152910160405180910390a461355183600089898989613ea2565b50505050505050565b60008161356f670de0b6b3a76400008561503e565b610b86919061506b565b6001600160a01b038216600090815260ce6020526040902080548201905560cf8054820190556110ba82613cbe565b6000670de0b6b3a764000061356f838561503e565b600054600160a81b900460ff166135e65760405162461bcd60e51b815260040161095e90615175565b61118381614045565b60006001600160e01b03198216636cdb3d1360e11b148061362057506001600160e01b031982166303a24d0760e21b145b8061098c57506301ffc9a760e01b6001600160e01b031983161461098c565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061367e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6904ee2d6d415b85acef8160201b83106136a8576904ee2d6d415b85acef8160201b830492506020015b662386f26fc1000083106136c657662386f26fc10000830492506010015b6305f5e10083106136de576305f5e100830492506008015b61271083106136f257612710830492506004015b60648310613704576064830492506002015b600a831061098c5760010192915050565b600063ffffffff821115612fdc5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b606482015260840161095e565b60008160000361378c57506000919050565b6000600161379984614077565b901c6001901b905060018184816137b2576137b2615055565b048201901c905060018184816137ca576137ca615055565b048201901c905060018184816137e2576137e2615055565b048201901c905060018184816137fa576137fa615055565b048201901c9050600181848161381257613812615055565b048201901c9050600181848161382a5761382a615055565b048201901c9050600181848161384257613842615055565b048201901c9050610b868182858161385c5761385c615055565b0461410b565b60005b818310156117265760006138798484614121565b60008781526020902090915063ffffffff86169082015463ffffffff1611156138a4578092506138b2565b6138af8160016152c5565b93505b50613865565b6138c28282611d15565b6110ba576138cf8161413c565b6138da83602061414e565b6040516020016138eb9291906152d8565b60408051601f198184030181529082905262461bcd60e51b825261095e9160040161486f565b6001600160a01b0381166139385760405163e2417bff60e01b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600054600160a81b900460ff166139835760405162461bcd60e51b815260040161095e90615175565b60cb80546001600160a01b0319166001600160a01b0392909216919091179055565b60cb60009054906101000a90046001600160a01b03166001600160a01b031663fc0c546a6040518163ffffffff1660e01b81526004016020604051808303816000875af11580156139fa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a1e9190614eb8565b6001600160a01b0316635c19a95c306040518263ffffffff1660e01b8152600401613a499190614c82565b600060405180830381600087803b158015613a6357600080fd5b505af1158015613a77573d6000803e3d6000fd5b50505050565b613a8681612bb1565b613ae85760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161095e565b6000805160206154d683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b613b20836142e9565b600082511180613b2d5750805b15610e3457613a778383614329565b6001600160a01b038316613b9e5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b606482015260840161095e565b336000613baa84613cd6565b90506000613bb784613cd6565b9050613bd783876000858560405180602001604052806000815250613d21565b60008581526065602090815260408083206001600160a01b038a16845290915290205484811015613c565760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b606482015260840161095e565b60008681526065602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a9052909290881691600080516020615476833981519152910160405180910390a4604080516020810190915260009052613551565b613cc78161434e565b60cf54610e349060cd9061438a565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110613d1057613d106150cc565b602090810291909101015292915050565b6001600160a01b038516613da85760005b8351811015613da657828181518110613d4d57613d4d6150cc565b602002602001015160976000868481518110613d6b57613d6b6150cc565b602002602001015181526020019081526020016000206000828254613d9091906152c5565b90915550613d9f9050816150e2565b9050613d32565b505b6001600160a01b038416613e9a5760005b8351811015613551576000848281518110613dd657613dd66150cc565b602002602001015190506000848381518110613df457613df46150cc565b6020026020010151905060006097600084815260200190815260200160002054905081811015613e775760405162461bcd60e51b815260206004820152602860248201527f455243313135353a206275726e20616d6f756e74206578636565647320746f74604482015267616c537570706c7960c01b606482015260840161095e565b60009283526097602052604090922091039055613e93816150e2565b9050613db9565b505050505050565b613eb4846001600160a01b0316612bb1565b15613e9a5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613eed9089908990889088908890600401615347565b6020604051808303816000875af1925050508015613f28575060408051601f3d908101601f19168201909252613f2591810190615381565b60015b613fd457613f3461539e565b806308c379a003613f6d5750613f486153b9565b80613f535750613f6f565b8060405162461bcd60e51b815260040161095e919061486f565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b606482015260840161095e565b6001600160e01b0319811663f23a6e6160e01b146135515760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b606482015260840161095e565b600054600160a81b900460ff1661406e5760405162461bcd60e51b815260040161095e90615175565b61118381612867565b600080608083901c1561408c57608092831c92015b604083901c1561409e57604092831c92015b602083901c156140b057602092831c92015b601083901c156140c257601092831c92015b600883901c156140d457600892831c92015b600483901c156140e657600492831c92015b600283901c156140f857600292831c92015b600183901c1561098c5760010192915050565b600081831061411a5781610b86565b5090919050565b6000614130600284841861506b565b610b86908484166152c5565b606061098c6001600160a01b03831660145b6060600061415d83600261503e565b6141689060026152c5565b6001600160401b0381111561417f5761417f614736565b6040519080825280601f01601f1916602001820160405280156141a9576020820181803683370190505b509050600360fc1b816000815181106141c4576141c46150cc565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106141f3576141f36150cc565b60200101906001600160f81b031916908160001a905350600061421784600261503e565b6142229060016152c5565b90505b600181111561429a576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110614256576142566150cc565b1a60f81b82828151811061426c5761426c6150cc565b60200101906001600160f81b031916908160001a90535060049490941c9361429381615442565b9050614225565b508315610b865760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161095e565b6142f281613a7d565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060610b868383604051806060016040528060278152602001615542602791396143be565b610e34614370826001600160a01b0316600090815260ce602052604090205490565b6001600160a01b038316600090815260cc60205260409020905b6000806143a88461439a43613715565b6143a386614436565b61449f565b6001600160e01b03918216969116945092505050565b6060600080856001600160a01b0316856040516143db9190615459565b600060405180830381855af49150503d8060008114614416576040519150601f19603f3d011682016040523d82523d6000602084013e61441b565b606091505b509150915061442c86838387614640565b9695505050505050565b60006001600160e01b03821115612fdc5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b606482015260840161095e565b8254600090819080156145e35760006144bd87612acc600185615162565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b03166020840152919250908716101561453c5760405162461bcd60e51b815260206004820152601b60248201527a436865636b706f696e743a2064656372656173696e67206b65797360281b604482015260640161095e565b805163ffffffff808816911603614584578461455d88612acc600186615162565b80546001600160e01b0392909216600160201b0263ffffffff9092169190911790556145d3565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160201b029216919091179101555b6020015192508391506146389050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160201b0291909316179201919091559050815b935093915050565b606083156146ad5782516000036146a65761465a85612bb1565b6146a65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161095e565b508161340e565b61340e8383815115613f535781518083602001fd5b6001600160a01b038116811461118357600080fd5b600080604083850312156146ea57600080fd5b82356146f5816146c2565b946020939093013593505050565b6001600160e01b03198116811461118357600080fd5b60006020828403121561472b57600080fd5b8135610b8681614703565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b038111828210171561477157614771614736565b6040525050565b600082601f83011261478957600080fd5b81356001600160401b038111156147a2576147a2614736565b6040516147b9601f8301601f19166020018261474c565b8181528460208386010111156147ce57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156147fd57600080fd5b81356001600160401b0381111561481357600080fd5b61340e84828501614778565b60005b8381101561483a578181015183820152602001614822565b50506000910152565b6000815180845261485b81602086016020860161481f565b601f01601f19169290920160200192915050565b602081526000610b866020830184614843565b60006020828403121561489457600080fd5b5035919050565b6000602082840312156148ad57600080fd5b8135610b86816146c2565b600080604083850312156148cb57600080fd5b50508035926020909101359150565b60006001600160401b038211156148f3576148f3614736565b5060051b60200190565b600082601f83011261490e57600080fd5b8135602061491b826148da565b604051614928828261474c565b83815260059390931b850182019282810191508684111561494857600080fd5b8286015b84811015614963578035835291830191830161494c565b509695505050505050565b600080600080600060a0868803121561498657600080fd5b8535614991816146c2565b945060208601356149a1816146c2565b935060408601356001600160401b03808211156149bd57600080fd5b6149c989838a016148fd565b945060608801359150808211156149df57600080fd5b6149eb89838a016148fd565b93506080880135915080821115614a0157600080fd5b50614a0e88828901614778565b9150509295509295909350565b60008060408385031215614a2e57600080fd5b823591506020830135614a40816146c2565b809150509250929050565b60008060008060808587031215614a6157600080fd5b84356001600160401b03811115614a7757600080fd5b614a8387828801614778565b9450506020850135614a94816146c2565b92506040850135614aa4816146c2565b9396929550929360600135925050565b60008060408385031215614ac757600080fd5b82356001600160401b0380821115614ade57600080fd5b818501915085601f830112614af257600080fd5b81356020614aff826148da565b604051614b0c828261474c565b83815260059390931b8501820192828101915089841115614b2c57600080fd5b948201945b83861015614b53578535614b44816146c2565b82529482019490820190614b31565b96505086013592505080821115614b6957600080fd5b50614b76858286016148fd565b9150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015614bb857835183529284019291840191600101614b9c565b50909695505050505050565b60008060408385031215614bd757600080fd5b8235614be2816146c2565b915060208301356001600160401b03811115614bfd57600080fd5b614b7685828601614778565b60008060408385031215614c1c57600080fd5b82359150602083013560ff81168114614a4057600080fd5b803561ffff81168114614c4657600080fd5b919050565b600060208284031215614c5d57600080fd5b610b8682614c34565b60008060408385031215614c7957600080fd5b6146f583614c34565b6001600160a01b0391909116815260200190565b801515811461118357600080fd5b60008060408385031215614cb757600080fd5b8235614cc2816146c2565b91506020830135614a4081614c96565b600080600080600060a08688031215614cea57600080fd5b8535614cf5816146c2565b94506020860135614d05816146c2565b94979496505050506040830135926060810135926080909101359150565b60008060008060808587031215614d3957600080fd5b8435614d44816146c2565b93506020850135614d54816146c2565b93969395505050506040820135916060013590565b600080600080600060a08688031215614d8157600080fd5b8535614d8c816146c2565b9450602086013593506040860135925060608601359150614daf60808701614c34565b90509295509295909350565b60008060008060006101408688031215614dd457600080fd5b8535614ddf816146c2565b94506020860135935060a0860187811115614df957600080fd5b604087019350610120870188811115614e1157600080fd5b959894975092955091933592915050565b60008060408385031215614e3557600080fd5b8235614e40816146c2565b91506020830135614a40816146c2565b600080600080600060a08688031215614e6857600080fd5b8535614e73816146c2565b94506020860135614e83816146c2565b9350604086013592506060860135915060808601356001600160401b03811115614eac57600080fd5b614a0e88828901614778565b600060208284031215614eca57600080fd5b8151610b86816146c2565b600181811c90821680614ee957607f821691505b602082108103614f0957634e487b7160e01b600052602260045260246000fd5b50919050565b60008351614f2181846020880161481f565b835190830190614f3581836020880161481f565b01949350505050565b600060208284031215614f5057600080fd5b8151610b8681614c96565b6020808252602c908201526000805160206154b683398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201526000805160206154b683398151915260408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6001600160801b0381811683821601908082111561500557615005614fcf565b5092915050565b60006020828403121561501e57600080fd5b5051919050565b6001600160a01b03929092168252602082015260400190565b808202811582820484141761098c5761098c614fcf565b634e487b7160e01b600052601260045260246000fd5b60008261508857634e487b7160e01b600052601260045260246000fd5b500490565b84815260ff841660208201526080604082015260006150af6080830185614843565b82810360608401526150c18185614843565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016150f4576150f4614fcf565b5060010190565b600060018060a01b03808816835261ffff8716602084015285604084015284606084015260a060808401528084511660a08401528060208501511660c0840152506040830151606060e0840152615156610100840182614843565b98975050505050505050565b8181038181111561098c5761098c614fcf565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b601f821115610e3457600081815260208120601f850160051c810160208610156151e75750805b601f850160051c820191505b81811015613e9a578281556001016151f3565b81516001600160401b0381111561521f5761521f614736565b6152338161522d8454614ed5565b846151c0565b602080601f83116001811461526857600084156152505750858301515b600019600386901b1c1916600185901b178555613e9a565b600085815260208120601f198616915b8281101561529757888601518255948401946001909101908401615278565b50858210156152b55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561098c5761098c614fcf565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b81526000835161530a81601785016020880161481f565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161533b81602884016020880161481f565b01602801949350505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906150c190830184614843565b60006020828403121561539357600080fd5b8151610b8681614703565b600060033d111561188f5760046000803e5060005160e01c90565b600060443d10156153c75790565b6040516003193d81016004833e81513d6001600160401b0380831160248401831017156153f657505050505090565b828501915081518181111561540e5750505050505090565b843d87010160208285010111156154285750505050505090565b6154376020828601018761474c565b509095945050505050565b60008161545157615451614fcf565b506000190190565b6000825161546b81846020870161481f565b919091019291505056fec3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62e2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc446756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcba279271fb7bbf76a6f3df3cc57bf80647fcafdea60ec3383d90f459de74e7c0726f6c6c65642d757020766f74652066726f6d20676f7665726e616e636520746f6b656e20686f6c64657273416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d741518d81b661f039a30869d82aad8204bb09e650e97a4efa44a364fc68f29e64736f6c63430008130033
Deployed Bytecode
0x6080604052600436106102175760003560e01c8062fdd58e1461021c57806301ffc9a71461024f57806302768de41461027f57806302fe5305146102a1578063083118d5146102c3578063092c5b3b146102e55780630e89341c1461031957806312064c341461033957806313c19841146103665780631b13ee8a14610386578063248a9ca3146103a65780632eb2c2d6146103c65780632f2ff15d146103e6578063316eac121461040657806336568abe146104265780633659cfe6146104465780633eb76b9c146104665780634bb17b1f146104865780634e1273f41461049b5780634f1ef286146104c85780634f558e79146104db57806352d1902d1461050a57806352e62a431461051f578063544ffc9c1461053f5780635a9bd576146105b45780636927850a146105e2578063696c81bb146105f85780636d1daa28146106185780636dc0ae221461063857806375b238fc146106655780637a26db171461069957806391d14854146106c8578063926d7d7f146106e8578063a217fddf1461070a578063a22cb4651461071f578063b18d6afd1461073f578063b3f1c93d1461075f578063bc9905191461077f578063bd85b03914610792578063c41c2f24146107bf578063c915c2b1146107df578063d547741f146107ff578063db7817f91461081f578063e985e9c51461083f578063f1bdebc014610888578063f242432a146108a8578063fb37f800146108c3575b600080fd5b34801561022857600080fd5b5061023c6102373660046146d7565b6108f7565b6040519081526020015b60405180910390f35b34801561025b57600080fd5b5061026f61026a366004614719565b610992565b6040519015158152602001610246565b34801561028b57600080fd5b5061023c6000805160206154f683398151915281565b3480156102ad57600080fd5b506102c16102bc3660046147eb565b61099d565b005b3480156102cf57600080fd5b506102d8610a9f565b604051610246919061486f565b3480156102f157600080fd5b5061023c7f7b765e0e932d348852a6f810bfa1ab891e259123f02db8cdcde614c57022335781565b34801561032557600080fd5b506102d8610334366004614882565b610b2e565b34801561034557600080fd5b5061023c61035436600461489b565b60ce6020526000908152604090205481565b34801561037257600080fd5b506102c16103813660046148b8565b610b8d565b34801561039257600080fd5b5061023c6103a13660046146d7565b610d4e565b3480156103b257600080fd5b5061023c6103c1366004614882565b610d70565b3480156103d257600080fd5b506102c16103e136600461496e565b610d85565b3480156103f257600080fd5b506102c1610401366004614a1b565b610e18565b34801561041257600080fd5b506102c1610421366004614a4b565b610e39565b34801561043257600080fd5b506102c1610441366004614a1b565b611040565b34801561045257600080fd5b506102c161046136600461489b565b6110be565b34801561047257600080fd5b506102c1610481366004614882565b611186565b34801561049257600080fd5b506102c16114e9565b3480156104a757600080fd5b506104bb6104b6366004614ab4565b611605565b6040516102469190614b80565b6102c16104d6366004614bc4565b61172e565b3480156104e757600080fd5b5061026f6104f6366004614882565b600090815260976020526040902054151590565b34801561051657600080fd5b5061023c6117e3565b34801561052b57600080fd5b506102c161053a366004614c09565b611892565b34801561054b57600080fd5b5061058a61055a366004614882565b60ca60205260009081526040902080546001909101546001600160801b0380831692600160801b90048116911683565b604080516001600160801b0394851681529284166020840152921691810191909152606001610246565b3480156105c057600080fd5b5061023c6105cf366004614882565b6101686020526000908152604090205481565b3480156105ee57600080fd5b5061023c60cf5481565b34801561060457600080fd5b506102c1610613366004614c4b565b611b0e565b34801561062457600080fd5b506102c1610633366004614c66565b611c12565b34801561064457600080fd5b5060cb54610658906001600160a01b031681565b6040516102469190614c82565b34801561067157600080fd5b5061023c7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b3480156106a557600080fd5b50610166546106b59061ffff1681565b60405161ffff9091168152602001610246565b3480156106d457600080fd5b5061026f6106e3366004614a1b565b611d15565b3480156106f457600080fd5b5061023c60008051602061549683398151915281565b34801561071657600080fd5b5061023c600081565b34801561072b57600080fd5b506102c161073a366004614ca4565b611d40565b34801561074b57600080fd5b506102c161075a366004614cd2565b611d4b565b34801561076b57600080fd5b506102c161077a366004614d23565b611e6c565b6102c161078d366004614d69565b611fbb565b34801561079e57600080fd5b5061023c6107ad366004614882565b60009081526097602052604090205490565b3480156107cb57600080fd5b50600054610658906001600160a01b031681565b3480156107eb57600080fd5b5061023c6107fa366004614dbb565b61236f565b34801561080b57600080fd5b506102c161081a366004614a1b565b6127e7565b34801561082b57600080fd5b5061023c61083a366004614882565b612803565b34801561084b57600080fd5b5061026f61085a366004614e22565b6001600160a01b03918216600090815260666020908152604080832093909416825291909152205460ff1690565b34801561089457600080fd5b506102c16108a33660046147eb565b612810565b3480156108b457600080fd5b506102c16103e1366004614e50565b3480156108cf57600080fd5b5061023c7f98eee63452386eeb3e8c10d0cfe42a80ba83b7826c38149de72788766ce2cb3681565b60006001600160a01b0383166109675760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b5060008181526065602090815260408083206001600160a01b03861684529091529020545b92915050565b600061098c82612842565b6000546001600160a01b03163314801590610a3e575060008054906101000a90046001600160a01b03166001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a289190614eb8565b6001600160a01b0316336001600160a01b031614155b15610a5c57604051637f242d1d60e11b815260040160405180910390fd5b610a6581612867565b7fd09d05534067f74dbc9e6af794edbd29e904d7698e428d0bc1378e45889acdd781604051610a94919061486f565b60405180910390a150565b6101678054610aad90614ed5565b80601f0160208091040260200160405190810160405280929190818152602001828054610ad990614ed5565b8015610b265780601f10610afb57610100808354040283529160200191610b26565b820191906000526020600020905b815481529060010190602001808311610b0957829003601f168201915b505050505081565b60606000610b3b83612873565b90506000815111610b5b5760405180602001604052806000815250610b86565b80610b6584612907565b604051602001610b76929190614f0f565b6040516020818303038152906040525b9392505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c029190614f3e565b15610c2057604051634427925560e01b815260040160405180910390fd5b60008054906101000a90046001600160a01b03166001600160a01b0316631f2878096040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c959190614eb8565b6001600160a01b0316336001600160a01b031614610cc6576040516348f5c3ed60e01b815260040160405180910390fd5b6000828152610168602052604090205415610cf4576040516366134a9160e01b815260040160405180910390fd5b610cfd81612999565b6000828152610168602090815260409182902083905581518481529081018390527f971be14c38e44863d19d97730d26df2bcf87d0bc536b04d77e128b3514433b0291015b60405180910390a15050565b6001600160a01b038216600090815260cc60205260408120610b8690836129ed565b600090815260d0602052604090206001015490565b6001600160a01b038516331480610da15750610da1853361085a565b610e045760405162461bcd60e51b815260206004820152602e60248201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60448201526d195c881bdc88185c1c1c9bdd995960921b606482015260840161095e565b610e118585858585612b08565b5050505050565b610e2182610d70565b610e2a81612b21565b610e348383612b2b565b505050565b600054600160a81b900460ff1615808015610e6157506000546001600160a01b90910460ff16105b80610e895750610e7030612bb1565b158015610e895750600054600160a01b900460ff166001145b610eec5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161095e565b6000805460ff60a01b1916600160a01b1790558015610f19576000805460ff60a81b1916600160a81b1790555b610f2285612810565b610f2b84612bc0565b610f3483612c1b565b610f9e836001600160a01b0316635e8430ee6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f999190614eb8565b612c4d565b610fa782612999565b600080526101686020527fb8607e2a62c9ca25d8e6acf2f12b8faaf864bb6a81dedcf1dd61ecbd170ea7a5829055610166805461ffff191660af179055610ff26001621e8480612c87565b8015610e11576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6001600160a01b03811633146110b05760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b606482015260840161095e565b6110ba8282612cc6565b5050565b6001600160a01b037f000000000000000000000000cf295311b748d0bf685fcf9c5cd47c1310c246da1630036111065760405162461bcd60e51b815260040161095e90614f5b565b7f000000000000000000000000cf295311b748d0bf685fcf9c5cd47c1310c246da6001600160a01b0316611138612d2d565b6001600160a01b03161461115e5760405162461bcd60e51b815260040161095e90614f95565b61116781612d49565b6040805160008082526020820190925261118391839190612e08565b50565b600081815260ca60205260408120600181015481549192916001600160801b03918216916111c09180821691600160801b90910416614fe5565b6111ca9190614fe5565b6001600160801b0316116112155760405162461bcd60e51b81526020600482015260126024820152711b9bc81d9bdd195cc8195e1c1c995cdcd95960721b604482015260640161095e565b60cb54604051632d63f69360e01b8152600481018490526000916001600160a01b031690632d63f69390602401602060405180830381865afa15801561125f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611283919061500c565b9050600061129082612803565b9050600060cb60009054906101000a90046001600160a01b03166001600160a01b031663fc0c546a6040518163ffffffff1660e01b81526004016020604051808303816000875af11580156112e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130d9190614eb8565b6001600160a01b0316633a46b1a830856040518363ffffffff1660e01b815260040161133a929190615025565b602060405180830381865afa158015611357573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061137b919061500c565b84549091506000906113b29084906113a390600160801b90046001600160801b03168561503e565b6113ad919061506b565b612f73565b85549091506000906113d39085906113a3906001600160801b03168661503e565b60018701549091506000906113f79086906113a3906001600160801b03168761503e565b600089815260ca6020908152604080832083815560010180546001600160801b03199081169091558151608088811b83169482019490945288841b821660308201529285901b169082015291925060029160500160408051601f1981840301815291905260cb549091506001600160a01b0316635f398a148b84611479612fe0565b856040518563ffffffff1660e01b8152600401611499949392919061508d565b6020604051808303816000875af11580156114b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114dc919061500c565b5050505050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b031663cf11c26b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561153d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115619190614eb8565b6000549091506001600160a01b03908116908216036115935760405163ee9d4f0f60e01b815260040160405180910390fd5b6001600160a01b0381166115ba5760405163e2417bff60e01b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b0383161790556040517f7d4400cf8a02e5f0690de634d2ab700d2d987649dcf96cdd70a971657a041b4a90610a94908390614c82565b6060815183511461166a5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b606482015260840161095e565b600083516001600160401b0381111561168557611685614736565b6040519080825280602002602001820160405280156116ae578160200160208202803683370190505b50905060005b8451811015611726576116f98582815181106116d2576116d26150cc565b60200260200101518583815181106116ec576116ec6150cc565b60200260200101516108f7565b82828151811061170b5761170b6150cc565b602090810291909101015261171f816150e2565b90506116b4565b509392505050565b6001600160a01b037f000000000000000000000000cf295311b748d0bf685fcf9c5cd47c1310c246da1630036117765760405162461bcd60e51b815260040161095e90614f5b565b7f000000000000000000000000cf295311b748d0bf685fcf9c5cd47c1310c246da6001600160a01b03166117a8612d2d565b6001600160a01b0316146117ce5760405162461bcd60e51b815260040161095e90614f95565b6117d782612d49565b6110ba82826001612e08565b6000306001600160a01b037f000000000000000000000000cf295311b748d0bf685fcf9c5cd47c1310c246da161461187e5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b606482015260840161095e565b506000805160206154d68339815191525b90565b60cb54604051632d63f69360e01b8152600481018490526000916119069133916001600160a01b031690632d63f69390602401602060405180830381865afa1580156118e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a1919061500c565b9050600081116119445760405162461bcd60e51b81526020600482015260096024820152681b9bc81dd95a59da1d60ba1b604482015260640161095e565b600083815260c96020908152604080832033845290915290205460ff161561199e5760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e481d9bdd1959609a1b604482015260640161095e565b600083815260c9602090815260408083203384529091529020805460ff1916600117905560ff8216611a23576119d381612f73565b600084815260ca6020526040812080549091906119fa9084906001600160801b0316614fe5565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550505050565b60001960ff831601611a6657611a3881612f73565b600084815260ca6020526040902080546010906119fa908490600160801b90046001600160801b0316614fe5565b60011960ff831601611aa557611a7b81612f73565b600084815260ca6020526040812060010180549091906119fa9084906001600160801b0316614fe5565b60405162461bcd60e51b815260206004820152603860248201527f696e76616c696420737570706f72742076616c75652c206d75737420626520696044820152776e636c7564656420696e20566f74655479706520656e756d60401b606482015260840161095e565b6000546001600160a01b03163314801590611baf575060008054906101000a90046001600160a01b03166001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b999190614eb8565b6001600160a01b0316336001600160a01b031614155b15611bcd57604051637f242d1d60e11b815260040160405180910390fd5b610166805461ffff191661ffff83169081179091556040519081527f4638b9d191c13f7c818328022e9a587f4050f58d4714724cc187da6307c8f51a90602001610a94565b6000546001600160a01b03163314801590611cb3575060008054906101000a90046001600160a01b03166001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c79573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9d9190614eb8565b6001600160a01b0316336001600160a01b031614155b15611cd157604051637f242d1d60e11b815260040160405180910390fd5b611cdb8282612c87565b6040805161ffff84168152602081018390527f2350f7c37c954a84e89df0b239e6b79e60b0b0466691f95df03c1a7a6469de089101610d42565b600091825260d0602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6110ba338383613000565b6000805160206154f6833981519152611d6381612b21565b6000611d71878585886130e0565b9050611d7d8782613416565b60008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611dce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df29190614eb8565b6001600160a01b031663a9059cbb87836040518363ffffffff1660e01b8152600401611e1f929190615025565b6020604051808303816000875af1158015611e3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e629190614f3e565b5050505050505050565b6000805160206154f6833981519152611e8481612b21565b81600003611ea55760405163b98a411360e01b815260040160405180910390fd5b6000838152610168602052604081205490819003611ed657604051631bf4348160e31b815260040160405180910390fd5b611ef186858560405180602001604052806000815250613447565b6000611efd848361355a565b9050611f098782613579565b60008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7e9190614eb8565b6040516323b872dd60e01b81526001600160a01b0388811660048301523060248301526044820184905291909116906323b872dd90606401611e1f565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561200c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120309190614f3e565b1561204e57604051634427925560e01b815260040160405180910390fd5b846000805160206154968339815191526001600160a01b038216331480159061207e575061207c8133611d15565b155b1561209c57604051639d7b369d60e01b815260040160405180910390fd5b846000036120bd57604051631174c25360e21b815260040160405180910390fd5b60006120cb888888886130e0565b90506120d78882613416565b6101665461ffff908116908516036121d45760008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215e9190614eb8565b6001600160a01b031663a9059cbb89836040518363ffffffff1660e01b815260040161218b929190615025565b6020604051808303816000875af11580156121aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ce9190614f3e565b50611e62565b60008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa158015612225573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122499190614eb8565b6001600160a01b031663695ef6bf34308761226a8d6001600160a01b031690565b604080516060810182523381526000602082015261016780548a938301919061229290614ed5565b80601f01602080910402602001604051908101604052809291908181526020018280546122be90614ed5565b801561230b5780601f106122e05761010080835404028352916020019161230b565b820191906000526020600020905b8154815290600101906020018083116122ee57829003601f168201915b50505050508152506040518763ffffffff1660e01b81526004016123339594939291906150fb565b6000604051808303818588803b15801561234c57600080fd5b505af1158015612360573d6000803e3d6000fd5b50505050505050505050505050565b60006000805160206154f683398151915261238981612b21565b600061239888886000876130e0565b905060008635156124ab576123b6828860005b6020020135906135a8565b905060008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa158015612409573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242d9190614eb8565b6001600160a01b031663a9059cbb612448602089018961489b565b836040518363ffffffff1660e01b8152600401612466929190615025565b6020604051808303816000875af1158015612485573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a99190614f3e565b505b60006124b9838960016123ab565b905060008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561250c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125309190614eb8565b6001600160a01b031663a9059cbb61254e60408a0160208b0161489b565b836040518363ffffffff1660e01b815260040161256c929190615025565b6020604051808303816000875af115801561258b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125af9190614f3e565b5060006125be848a60026123ab565b905060008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa158015612611573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126359190614eb8565b6001600160a01b031663a9059cbb61265360608b0160408c0161489b565b836040518363ffffffff1660e01b8152600401612671929190615025565b6020604051808303816000875af1158015612690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b49190614f3e565b50600081836126c38688615162565b6126cd9190615162565b6126d79190615162565b905060008054906101000a90046001600160a01b03166001600160a01b031663060bbbd96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561272a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061274e9190614eb8565b6001600160a01b031663a9059cbb61276c60808c0160608d0161489b565b836040518363ffffffff1660e01b815260040161278a929190615025565b6020604051808303816000875af11580156127a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cd9190614f3e565b506127d88c86613416565b9b9a5050505050505050505050565b6127f082610d70565b6127f981612b21565b610e348383612cc6565b600061098c60cd836129ed565b600054600160a81b900460ff166128395760405162461bcd60e51b815260040161095e90615175565b611183816135bd565b60006001600160e01b03198216637965db0b60e01b148061098c575061098c826135ef565b60676110ba8282615206565b60606067805461288290614ed5565b80601f01602080910402602001604051908101604052809291908181526020018280546128ae90614ed5565b80156128fb5780601f106128d0576101008083540402835291602001916128fb565b820191906000526020600020905b8154815290600101906020018083116128de57829003601f168201915b50505050509050919050565b606060006129148361363f565b60010190506000816001600160401b0381111561293357612933614736565b6040519080825280601f01601f19166020018201604052801561295d576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461296757509392505050565b806000036129ba576040516330d20d1b60e21b815260040160405180910390fd5b6ebc29a27c6e5299f5839b0e51b9b2d360301b811115611183576040516367b8cfe360e01b815260040160405180910390fd5b6000438210612a3e5760405162461bcd60e51b815260206004820181905260248201527f436865636b706f696e74733a20626c6f636b206e6f7420796574206d696e6564604482015260640161095e565b6000612a4983613715565b84549091506000816005811115612aa7576000612a658461377a565b612a6f9085615162565b60008981526020902090915081015463ffffffff9081169086161015612a9757809150612aa5565b612aa28160016152c5565b92505b505b6000612ab588868585613862565b90508015612af057612ada88612acc600184615162565b600091825260209091200190565b54600160201b90046001600160e01b0316612af3565b60005b6001600160e01b031698975050505050505050565b60405163a4420a9560e01b815260040160405180910390fd5b61118381336138b8565b612b358282611d15565b6110ba57600082815260d0602090815260408083206001600160a01b03851684529091529020805460ff19166001179055612b6d3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6001600160a01b03163b151590565b600054600160a81b900460ff16612be95760405162461bcd60e51b815260040161095e90615175565b6001600160a01b038116612c105760405163d92e233d60e01b815260040160405180910390fd5b611183600082612b2b565b600054600160a81b900460ff16612c445760405162461bcd60e51b815260040161095e90615175565b61118381613911565b600054600160a81b900460ff16612c765760405162461bcd60e51b815260040161095e90615175565b612c7f8161395a565b6111836139a5565b6040516001600160f01b031960f084901b166020820152602281018290526042016040516020818303038152906040526101679081610e349190615206565b612cd08282611d15565b156110ba57600082815260d0602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000805160206154d6833981519152546001600160a01b031690565b6000546001600160a01b03163314801590612dea575060008054906101000a90046001600160a01b03166001600160a01b0316630c340a246040518163ffffffff1660e01b8152600401602060405180830381865afa158015612db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd49190614eb8565b6001600160a01b0316336001600160a01b031614155b1561118357604051637f242d1d60e11b815260040160405180910390fd5b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612e3b57610e3483613a7d565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612e95575060408051601f3d908101601f19168201909252612e929181019061500c565b60015b612ef85760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161095e565b6000805160206154d68339815191528114612f675760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161095e565b50610e34838383613b17565b60006001600160801b03821115612fdc5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b606482015260840161095e565b5090565b60606040518060600160405280602c8152602001615516602c9139905090565b816001600160a01b0316836001600160a01b0316036130735760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b606482015260840161095e565b6001600160a01b03838116600081815260666020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000816000036131035760405163b98a411360e01b815260040160405180910390fd5b6000848152610168602052604090205461311e90839061355a565b9050821561340357831561329d5760008060009054906101000a90046001600160a01b03166001600160a01b0316631f2878096040518163ffffffff1660e01b8152600401602060405180830381865afa158015613180573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131a49190614eb8565b6001600160a01b031663bea1c286866040518263ffffffff1660e01b81526004016131d191815260200190565b602060405180830381865afa1580156131ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132129190614eb8565b604051633a8d816160e11b8152600481018690529091506001600160a01b0382169063751b02c290602401602060405180830381865afa15801561325a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327e9190614f3e565b61329b576040516340abe7db60e01b815260040160405180910390fd5b505b60008060009054906101000a90046001600160a01b03166001600160a01b0316635c0094c66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133159190614eb8565b6040516328dfc3ab60e21b8152600481018690529091506000906001600160a01b0383169063a37f0eac90602401602060405180830381865afa158015613360573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613384919061500c565b90506000613392848361355a565b604051637a94c56560e11b81526001600160a01b038a8116600483015260248201899052604482018390529192509084169063f5298aca90606401600060405180830381600087803b1580156133e757600080fd5b505af11580156133fb573d6000803e3d6000fd5b505050505050505b61340e858584613b3c565b949350505050565b6001600160a01b038216600090815260ce602052604090208054829003905560cf805482900390556110ba82613cbe565b6001600160a01b0384166134a75760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b606482015260840161095e565b3360006134b385613cd6565b905060006134c085613cd6565b90506134d183600089858589613d21565b60008681526065602090815260408083206001600160a01b038b168452909152812080548792906135039084906152c5565b909155505060408051878152602081018790526001600160a01b03808a169260009291871691600080516020615476833981519152910160405180910390a461355183600089898989613ea2565b50505050505050565b60008161356f670de0b6b3a76400008561503e565b610b86919061506b565b6001600160a01b038216600090815260ce6020526040902080548201905560cf8054820190556110ba82613cbe565b6000670de0b6b3a764000061356f838561503e565b600054600160a81b900460ff166135e65760405162461bcd60e51b815260040161095e90615175565b61118381614045565b60006001600160e01b03198216636cdb3d1360e11b148061362057506001600160e01b031982166303a24d0760e21b145b8061098c57506301ffc9a760e01b6001600160e01b031983161461098c565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061367e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6904ee2d6d415b85acef8160201b83106136a8576904ee2d6d415b85acef8160201b830492506020015b662386f26fc1000083106136c657662386f26fc10000830492506010015b6305f5e10083106136de576305f5e100830492506008015b61271083106136f257612710830492506004015b60648310613704576064830492506002015b600a831061098c5760010192915050565b600063ffffffff821115612fdc5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b606482015260840161095e565b60008160000361378c57506000919050565b6000600161379984614077565b901c6001901b905060018184816137b2576137b2615055565b048201901c905060018184816137ca576137ca615055565b048201901c905060018184816137e2576137e2615055565b048201901c905060018184816137fa576137fa615055565b048201901c9050600181848161381257613812615055565b048201901c9050600181848161382a5761382a615055565b048201901c9050600181848161384257613842615055565b048201901c9050610b868182858161385c5761385c615055565b0461410b565b60005b818310156117265760006138798484614121565b60008781526020902090915063ffffffff86169082015463ffffffff1611156138a4578092506138b2565b6138af8160016152c5565b93505b50613865565b6138c28282611d15565b6110ba576138cf8161413c565b6138da83602061414e565b6040516020016138eb9291906152d8565b60408051601f198184030181529082905262461bcd60e51b825261095e9160040161486f565b6001600160a01b0381166139385760405163e2417bff60e01b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600054600160a81b900460ff166139835760405162461bcd60e51b815260040161095e90615175565b60cb80546001600160a01b0319166001600160a01b0392909216919091179055565b60cb60009054906101000a90046001600160a01b03166001600160a01b031663fc0c546a6040518163ffffffff1660e01b81526004016020604051808303816000875af11580156139fa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a1e9190614eb8565b6001600160a01b0316635c19a95c306040518263ffffffff1660e01b8152600401613a499190614c82565b600060405180830381600087803b158015613a6357600080fd5b505af1158015613a77573d6000803e3d6000fd5b50505050565b613a8681612bb1565b613ae85760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161095e565b6000805160206154d683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b613b20836142e9565b600082511180613b2d5750805b15610e3457613a778383614329565b6001600160a01b038316613b9e5760405162461bcd60e51b815260206004820152602360248201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260448201526265737360e81b606482015260840161095e565b336000613baa84613cd6565b90506000613bb784613cd6565b9050613bd783876000858560405180602001604052806000815250613d21565b60008581526065602090815260408083206001600160a01b038a16845290915290205484811015613c565760405162461bcd60e51b8152602060048201526024808201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604482015263616e636560e01b606482015260840161095e565b60008681526065602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a9052909290881691600080516020615476833981519152910160405180910390a4604080516020810190915260009052613551565b613cc78161434e565b60cf54610e349060cd9061438a565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110613d1057613d106150cc565b602090810291909101015292915050565b6001600160a01b038516613da85760005b8351811015613da657828181518110613d4d57613d4d6150cc565b602002602001015160976000868481518110613d6b57613d6b6150cc565b602002602001015181526020019081526020016000206000828254613d9091906152c5565b90915550613d9f9050816150e2565b9050613d32565b505b6001600160a01b038416613e9a5760005b8351811015613551576000848281518110613dd657613dd66150cc565b602002602001015190506000848381518110613df457613df46150cc565b6020026020010151905060006097600084815260200190815260200160002054905081811015613e775760405162461bcd60e51b815260206004820152602860248201527f455243313135353a206275726e20616d6f756e74206578636565647320746f74604482015267616c537570706c7960c01b606482015260840161095e565b60009283526097602052604090922091039055613e93816150e2565b9050613db9565b505050505050565b613eb4846001600160a01b0316612bb1565b15613e9a5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613eed9089908990889088908890600401615347565b6020604051808303816000875af1925050508015613f28575060408051601f3d908101601f19168201909252613f2591810190615381565b60015b613fd457613f3461539e565b806308c379a003613f6d5750613f486153b9565b80613f535750613f6f565b8060405162461bcd60e51b815260040161095e919061486f565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b606482015260840161095e565b6001600160e01b0319811663f23a6e6160e01b146135515760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b606482015260840161095e565b600054600160a81b900460ff1661406e5760405162461bcd60e51b815260040161095e90615175565b61118381612867565b600080608083901c1561408c57608092831c92015b604083901c1561409e57604092831c92015b602083901c156140b057602092831c92015b601083901c156140c257601092831c92015b600883901c156140d457600892831c92015b600483901c156140e657600492831c92015b600283901c156140f857600292831c92015b600183901c1561098c5760010192915050565b600081831061411a5781610b86565b5090919050565b6000614130600284841861506b565b610b86908484166152c5565b606061098c6001600160a01b03831660145b6060600061415d83600261503e565b6141689060026152c5565b6001600160401b0381111561417f5761417f614736565b6040519080825280601f01601f1916602001820160405280156141a9576020820181803683370190505b509050600360fc1b816000815181106141c4576141c46150cc565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106141f3576141f36150cc565b60200101906001600160f81b031916908160001a905350600061421784600261503e565b6142229060016152c5565b90505b600181111561429a576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110614256576142566150cc565b1a60f81b82828151811061426c5761426c6150cc565b60200101906001600160f81b031916908160001a90535060049490941c9361429381615442565b9050614225565b508315610b865760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161095e565b6142f281613a7d565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060610b868383604051806060016040528060278152602001615542602791396143be565b610e34614370826001600160a01b0316600090815260ce602052604090205490565b6001600160a01b038316600090815260cc60205260409020905b6000806143a88461439a43613715565b6143a386614436565b61449f565b6001600160e01b03918216969116945092505050565b6060600080856001600160a01b0316856040516143db9190615459565b600060405180830381855af49150503d8060008114614416576040519150601f19603f3d011682016040523d82523d6000602084013e61441b565b606091505b509150915061442c86838387614640565b9695505050505050565b60006001600160e01b03821115612fdc5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b606482015260840161095e565b8254600090819080156145e35760006144bd87612acc600185615162565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b03166020840152919250908716101561453c5760405162461bcd60e51b815260206004820152601b60248201527a436865636b706f696e743a2064656372656173696e67206b65797360281b604482015260640161095e565b805163ffffffff808816911603614584578461455d88612acc600186615162565b80546001600160e01b0392909216600160201b0263ffffffff9092169190911790556145d3565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160201b029216919091179101555b6020015192508391506146389050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160201b0291909316179201919091559050815b935093915050565b606083156146ad5782516000036146a65761465a85612bb1565b6146a65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161095e565b508161340e565b61340e8383815115613f535781518083602001fd5b6001600160a01b038116811461118357600080fd5b600080604083850312156146ea57600080fd5b82356146f5816146c2565b946020939093013593505050565b6001600160e01b03198116811461118357600080fd5b60006020828403121561472b57600080fd5b8135610b8681614703565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b038111828210171561477157614771614736565b6040525050565b600082601f83011261478957600080fd5b81356001600160401b038111156147a2576147a2614736565b6040516147b9601f8301601f19166020018261474c565b8181528460208386010111156147ce57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156147fd57600080fd5b81356001600160401b0381111561481357600080fd5b61340e84828501614778565b60005b8381101561483a578181015183820152602001614822565b50506000910152565b6000815180845261485b81602086016020860161481f565b601f01601f19169290920160200192915050565b602081526000610b866020830184614843565b60006020828403121561489457600080fd5b5035919050565b6000602082840312156148ad57600080fd5b8135610b86816146c2565b600080604083850312156148cb57600080fd5b50508035926020909101359150565b60006001600160401b038211156148f3576148f3614736565b5060051b60200190565b600082601f83011261490e57600080fd5b8135602061491b826148da565b604051614928828261474c565b83815260059390931b850182019282810191508684111561494857600080fd5b8286015b84811015614963578035835291830191830161494c565b509695505050505050565b600080600080600060a0868803121561498657600080fd5b8535614991816146c2565b945060208601356149a1816146c2565b935060408601356001600160401b03808211156149bd57600080fd5b6149c989838a016148fd565b945060608801359150808211156149df57600080fd5b6149eb89838a016148fd565b93506080880135915080821115614a0157600080fd5b50614a0e88828901614778565b9150509295509295909350565b60008060408385031215614a2e57600080fd5b823591506020830135614a40816146c2565b809150509250929050565b60008060008060808587031215614a6157600080fd5b84356001600160401b03811115614a7757600080fd5b614a8387828801614778565b9450506020850135614a94816146c2565b92506040850135614aa4816146c2565b9396929550929360600135925050565b60008060408385031215614ac757600080fd5b82356001600160401b0380821115614ade57600080fd5b818501915085601f830112614af257600080fd5b81356020614aff826148da565b604051614b0c828261474c565b83815260059390931b8501820192828101915089841115614b2c57600080fd5b948201945b83861015614b53578535614b44816146c2565b82529482019490820190614b31565b96505086013592505080821115614b6957600080fd5b50614b76858286016148fd565b9150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015614bb857835183529284019291840191600101614b9c565b50909695505050505050565b60008060408385031215614bd757600080fd5b8235614be2816146c2565b915060208301356001600160401b03811115614bfd57600080fd5b614b7685828601614778565b60008060408385031215614c1c57600080fd5b82359150602083013560ff81168114614a4057600080fd5b803561ffff81168114614c4657600080fd5b919050565b600060208284031215614c5d57600080fd5b610b8682614c34565b60008060408385031215614c7957600080fd5b6146f583614c34565b6001600160a01b0391909116815260200190565b801515811461118357600080fd5b60008060408385031215614cb757600080fd5b8235614cc2816146c2565b91506020830135614a4081614c96565b600080600080600060a08688031215614cea57600080fd5b8535614cf5816146c2565b94506020860135614d05816146c2565b94979496505050506040830135926060810135926080909101359150565b60008060008060808587031215614d3957600080fd5b8435614d44816146c2565b93506020850135614d54816146c2565b93969395505050506040820135916060013590565b600080600080600060a08688031215614d8157600080fd5b8535614d8c816146c2565b9450602086013593506040860135925060608601359150614daf60808701614c34565b90509295509295909350565b60008060008060006101408688031215614dd457600080fd5b8535614ddf816146c2565b94506020860135935060a0860187811115614df957600080fd5b604087019350610120870188811115614e1157600080fd5b959894975092955091933592915050565b60008060408385031215614e3557600080fd5b8235614e40816146c2565b91506020830135614a40816146c2565b600080600080600060a08688031215614e6857600080fd5b8535614e73816146c2565b94506020860135614e83816146c2565b9350604086013592506060860135915060808601356001600160401b03811115614eac57600080fd5b614a0e88828901614778565b600060208284031215614eca57600080fd5b8151610b86816146c2565b600181811c90821680614ee957607f821691505b602082108103614f0957634e487b7160e01b600052602260045260246000fd5b50919050565b60008351614f2181846020880161481f565b835190830190614f3581836020880161481f565b01949350505050565b600060208284031215614f5057600080fd5b8151610b8681614c96565b6020808252602c908201526000805160206154b683398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201526000805160206154b683398151915260408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6001600160801b0381811683821601908082111561500557615005614fcf565b5092915050565b60006020828403121561501e57600080fd5b5051919050565b6001600160a01b03929092168252602082015260400190565b808202811582820484141761098c5761098c614fcf565b634e487b7160e01b600052601260045260246000fd5b60008261508857634e487b7160e01b600052601260045260246000fd5b500490565b84815260ff841660208201526080604082015260006150af6080830185614843565b82810360608401526150c18185614843565b979650505050505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016150f4576150f4614fcf565b5060010190565b600060018060a01b03808816835261ffff8716602084015285604084015284606084015260a060808401528084511660a08401528060208501511660c0840152506040830151606060e0840152615156610100840182614843565b98975050505050505050565b8181038181111561098c5761098c614fcf565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b601f821115610e3457600081815260208120601f850160051c810160208610156151e75750805b601f850160051c820191505b81811015613e9a578281556001016151f3565b81516001600160401b0381111561521f5761521f614736565b6152338161522d8454614ed5565b846151c0565b602080601f83116001811461526857600084156152505750858301515b600019600386901b1c1916600185901b178555613e9a565b600085815260208120601f198616915b8281101561529757888601518255948401946001909101908401615278565b50858210156152b55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561098c5761098c614fcf565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b81526000835161530a81601785016020880161481f565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161533b81602884016020880161481f565b01602801949350505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906150c190830184614843565b60006020828403121561539357600080fd5b8151610b8681614703565b600060033d111561188f5760046000803e5060005160e01c90565b600060443d10156153c75790565b6040516003193d81016004833e81513d6001600160401b0380831160248401831017156153f657505050505090565b828501915081518181111561540e5750505050505090565b843d87010160208285010111156154285750505050505090565b6154376020828601018761474c565b509095945050505050565b60008161545157615451614fcf565b506000190190565b6000825161546b81846020870161481f565b919091019291505056fec3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62e2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc446756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcba279271fb7bbf76a6f3df3cc57bf80647fcafdea60ec3383d90f459de74e7c0726f6c6c65642d757020766f74652066726f6d20676f7665726e616e636520746f6b656e20686f6c64657273416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d741518d81b661f039a30869d82aad8204bb09e650e97a4efa44a364fc68f29e64736f6c63430008130033
Net Worth in USD
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.