Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
4780928 | 19 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
MarketManager
Compiler Version
v0.8.24+commit.e11b9ed9
ZkSolc Version
v1.5.7
Optimization Enabled:
Yes with Mode 3
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Roles.sol"; import "./Utility.sol"; import "./MarketState.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "./interface/IMarketManager.sol"; /** * @title MarketManager * @notice Manages market operations such as creation, updates, and pool management, with role-based access and upgradeability. */ contract MarketManager is IMarketManager, Initializable, UUPSUpgradeable, Roles, MarketState { /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /** * @notice Initializes the contract and sets the deployer as the owner. */ function initialize() public initializer { __AccessControl_init(); __UUPSUpgradeable_init(); __Ownable_init(); transferOwnership(_msgSender()); initializeMarketState(); // Set default K-range values kRange = [1e18, 2e18, 5e18, 10e18]; } /** * @notice Authorizes contract upgrades. * @param newImplementation The address of the new implementation contract. */ function _authorizeUpgrade( address newImplementation ) internal override onlyRole(DEFAULT_ADMIN_ROLE) {} /** * @notice Creates a new prediction market. * @param questionId Unique identifier for the question (off-chain data). * @param commissionPercentage The commission percentage for the team (0-100%). * @param endTime Market's end time (UNIX timestamp). */ function createMarket( uint256 questionId, uint256 commissionPercentage, uint256 endTime ) external override onlyTeam { require(questionId > 0, "Invalid questionId"); require(commissionPercentage <= 100, "Commission exceeds 100%"); require(endTime > block.timestamp, "End time must be in the future"); uint256 currentMarketId = marketCount; marketCount++; markets[currentMarketId] = Market({ questionId: questionId, yesVotes: 0, noVotes: 0, totalFunds: 0, commissionPercentage: commissionPercentage, baseLiquidity: 0, endTime: endTime, isResolved: false, winningOption: 0, yesPrice: 0, noPrice: 0 }); emit MarketCreated(currentMarketId, questionId, endTime); } /** * @notice Updates the end time of a market. * @param marketId The ID of the market. * @param newEndTime The new end time (UNIX timestamp). */ function updateEndTime( uint256 marketId, uint256 newEndTime ) external override onlyTeam { require(marketId < marketCount, "Market does not exist"); Market storage market = markets[marketId]; require(!market.isResolved, "Market already resolved"); require( newEndTime > block.timestamp, "New end time must be in the future" ); require(newEndTime != market.endTime, "End time is already set"); market.endTime = newEndTime; emit MarketEndTimeUpdated(marketId, newEndTime); } /** * @notice Updates the pool of a market when points are added or removed. * @param marketId The ID of the market. * @param isYesVote True if adding to the "Yes" option, false for "No". * @param points The amount of points to add. */ function updateMarketPool( uint256 marketId, bool isYesVote, uint256 points ) external override onlyAuthorized { require(points > 0, "MarketManager: Points must be greater than zero"); require(marketId < marketCount, "MarketManager: Market does not exist"); Market storage market = markets[marketId]; require(!market.isResolved, "MarketManager: Market already resolved"); require( block.timestamp < market.endTime, "MarketManager: Market expired" ); if (isYesVote) { market.yesVotes += points; } else { market.noVotes += points; } market.totalFunds += points; // Update LMSR prices updatePrices(marketId); emit MarketPoolUpdated( marketId, market.yesVotes, market.noVotes, market.totalFunds ); } /** * @notice Retrieves the price of a specific option in a market. * @param marketId The ID of the market. * @param optionId The ID of the option (0 = "No", 1 = "Yes"). * @return The price of the specified option in 18-decimal precision. */ function getPrice( uint256 marketId, uint256 optionId ) external view override returns (uint256) { require(marketId < marketCount, "Market does not exist"); require(optionId == 0 || optionId == 1, "Invalid option ID"); Market storage market = markets[marketId]; return optionId == 1 ? market.yesPrice : market.noPrice; } /** * @notice Retrieves details about a specific market. * @param marketId The ID of the market. * @return questionId The unique identifier for the question (off-chain data). * @return yesVotes The total points for the "Yes" option. * @return noVotes The total points for the "No" option. * @return isResolved Whether the market has been resolved. * @return winningOption The ID of the winning option (0 = "No", 1 = "Yes"). */ function getMarketDetails( uint256 marketId ) external view override returns ( uint256 questionId, uint256 yesVotes, uint256 noVotes, bool isResolved, uint256 winningOption ) { require(marketId < marketCount, "Market does not exist"); Market storage market = markets[marketId]; return ( market.questionId, market.yesVotes, market.noVotes, market.isResolved, market.winningOption ); } /** * @notice Checks if a market is resolved. * @param marketId ID of the market. * @return True if the market is resolved, false otherwise. */ function isMarketResolved( uint256 marketId ) external view override returns (bool) { require(marketId < marketCount, "Market does not exist"); return markets[marketId].isResolved; } /** * @notice Retrieves the end time of a specific market. * @param marketId ID of the market. * @return End time of the market (UNIX timestamp). */ function getMarketEndTime( uint256 marketId ) external view override returns (uint256) { require(marketId < marketCount, "Market does not exist"); return markets[marketId].endTime; } /** * @notice Retrieves all markets with their pool balances. * @return marketIds Array of market IDs. * @return questionIds Array of question IDs. * @return totalPoolBalances Array of total pool balances for each market. */ function getAllMarketsWithPools() external view override onlyTeam returns ( uint256[] memory marketIds, uint256[] memory questionIds, uint256[] memory totalPoolBalances ) { uint256 count = marketCount; require(count > 0, "No markets exist"); marketIds = new uint256[](count); questionIds = new uint256[](count); totalPoolBalances = new uint256[](count); for (uint256 i = 0; i < count; i++) { Market storage market = markets[i]; marketIds[i] = i; questionIds[i] = market.questionId; totalPoolBalances[i] = market.totalFunds; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; /** * @title Roles * @dev Provides role-based access control functionality with additional features for managing an authorized caller. * @notice Includes TEAM_ROLE, DEFAULT_ADMIN_ROLE, and authorized caller management. * Inherits from OpenZeppelin's `AccessControlUpgradeable` contract. */ abstract contract Roles is AccessControlUpgradeable { // Define role identifiers bytes32 public constant TEAM_ROLE = keccak256("TEAM_ROLE"); // Address of the authorized contract for restricted cross-contract interactions address public authorizedCaller; /** * @notice Initializes the contract and sets up the default admin and team roles. * @dev Should be called during contract initialization. * @param admin The address to be set as the default admin. */ function initializeRoles(address admin) internal onlyInitializing { require(admin != address(0), "Roles: Admin address cannot be zero"); _setupRole(DEFAULT_ADMIN_ROLE, admin); _setupRole(TEAM_ROLE, admin); } // ------------------------- // Existing Functions // ------------------------- /** * @notice Ensures that only users with the TEAM_ROLE can call the function. * @dev Throws if the caller does not have the TEAM_ROLE. */ modifier onlyTeam() { require( hasRole(TEAM_ROLE, msg.sender), "Roles: Not authorized - Requires TEAM_ROLE" ); _; } /** * @notice Ensures that only users with the DEFAULT_ADMIN_ROLE can call the function. * @dev Throws if the caller does not have the DEFAULT_ADMIN_ROLE. */ modifier onlyAdmin() { require( hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Roles: Not authorized - Requires DEFAULT_ADMIN_ROLE" ); _; } /** * @notice Adds a new team member by granting them the TEAM_ROLE. * @dev Can only be called by a user with the TEAM_ROLE. * @param account The address to be granted the TEAM_ROLE. */ function addTeamMember(address account) external onlyTeam { require(account != address(0), "Roles: Invalid address"); require( !hasRole(TEAM_ROLE, account), "Roles: Address already has TEAM_ROLE" ); grantRole(TEAM_ROLE, account); } /** * @notice Removes an existing team member by revoking their TEAM_ROLE. * @dev Can only be called by a user with the TEAM_ROLE. * @param account The address to be revoked from the TEAM_ROLE. */ function removeTeamMember(address account) external onlyTeam { require(account != address(0), "Roles: Invalid address"); require( hasRole(TEAM_ROLE, account), "Roles: Address does not have TEAM_ROLE" ); revokeRole(TEAM_ROLE, account); } /** * @notice Transfers the DEFAULT_ADMIN_ROLE to a new admin. * @dev Only the current admin can call this function. * @param newAdmin The address to be granted the DEFAULT_ADMIN_ROLE. */ function transferAdminRole(address newAdmin) external onlyAdmin { require(newAdmin != address(0), "Roles: Invalid new admin address"); require( !hasRole(DEFAULT_ADMIN_ROLE, newAdmin), "Roles: Address already has DEFAULT_ADMIN_ROLE" ); grantRole(DEFAULT_ADMIN_ROLE, newAdmin); revokeRole(DEFAULT_ADMIN_ROLE, msg.sender); } /** * @notice Checks whether an address has the TEAM_ROLE. * @param account The address to check. * @return A boolean indicating whether the address has the TEAM_ROLE. */ function isTeamMember(address account) external view returns (bool) { require(account != address(0), "Roles: Invalid address"); return hasRole(TEAM_ROLE, account); } /** * @notice Checks whether an address has the DEFAULT_ADMIN_ROLE. * @param account The address to check. * @return A boolean indicating whether the address has the DEFAULT_ADMIN_ROLE. */ function isAdmin(address account) external view returns (bool) { require(account != address(0), "Roles: Invalid address"); return hasRole(DEFAULT_ADMIN_ROLE, account); } // ------------------------- // New Functions // ------------------------- /** * @notice Ensures that only the authorized caller can call the function. * @dev Throws if the caller is not the authorized caller. */ modifier onlyAuthorized() { require( msg.sender == authorizedCaller, "Roles: Caller is not authorized" ); _; } /** * @notice Sets or updates the authorized caller for restricted functions. * @dev Can only be called by an admin. * @param caller The address to be set as the authorized caller. */ function setAuthorizedCaller(address caller) external onlyAdmin { require(caller != address(0), "Roles: Invalid caller address"); authorizedCaller = caller; } /** * @notice Checks whether an address is the authorized caller. * @param account The address to check. * @return A boolean indicating whether the address is authorized. */ function isAuthorized(address account) external view returns (bool) { require(account != address(0), "Roles: Invalid address"); return account == authorizedCaller; } /** * @notice Revokes the current authorized caller. * @dev Can only be called by an admin. */ function revokeAuthorizedCaller() external onlyAdmin { require(authorizedCaller != address(0), "Roles: No caller to revoke"); authorizedCaller = address(0); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Utility * @dev A library of utility functions for mathematical operations used in prediction markets. * Includes percentage calculations, logarithmic scaling, and LMSR-related computations. */ library Utility { /** * @notice Calculates a percentage of a given value. * @param base The base value. * @param percentage The percentage to calculate (0-100%). * @return The calculated percentage of the base value. */ function calculatePercentage( uint256 base, uint256 percentage ) internal pure returns (uint256) { require(percentage <= 100, "Percentage cannot exceed 100%"); return (base * percentage) / 100; } /** * @notice Calculates the proportional reward for a user based on their holdings and the total votes. * @param portion The portion value (e.g., user's holdings). * @param total The total funds in the pool. * @param votes The total votes for the winning option. * @return The proportional reward based on the user's holdings. */ function calculateProportion( uint256 portion, uint256 total, uint256 votes ) internal pure returns (uint256) { require(votes > 0, "Votes must be greater than zero"); require(total >= portion, "Total funds must be >= user portion"); return (portion * total) / votes; } /** * @notice Calculates the base liquidity for LMSR using logarithmic scaling. * @param k The scaling factor. * @param numUsers The number of users in the market. * @return The calculated base liquidity. */ function calculateBaseLiquidity( uint256 k, uint256 numUsers ) internal pure returns (uint256) { require(k > 0, "Scaling factor must be greater than zero"); require(numUsers > 0, "Number of users must be greater than zero"); return k * ln(numUsers + 1); // Using natural logarithm (ln) } /** * @notice Calculates LMSR prices for "Yes" and "No" options. * @param yesVotes Total points for "Yes". * @param noVotes Total points for "No". * @param baseLiquidity The base liquidity parameter. * @return yesPrice The price for "Yes". * @return noPrice The price for "No". */ function calculateLMSRPrices( uint256 yesVotes, uint256 noVotes, uint256 baseLiquidity ) internal pure returns (uint256 yesPrice, uint256 noPrice) { require(baseLiquidity > 0, "Base liquidity must be greater than zero"); uint256 yesExp = expScaled(yesVotes, baseLiquidity); uint256 noExp = expScaled(noVotes, baseLiquidity); // Prevent division by zero uint256 sumExp = yesExp + noExp; require(sumExp > 0, "Exponential sum must be greater than zero"); yesPrice = (yesExp * 1e18) / sumExp; noPrice = (noExp * 1e18) / sumExp; } /** * @notice Scales an exponential calculation for LMSR prices. * @param votes The votes for a specific option. * @param baseLiquidity The base liquidity parameter. * @return The scaled exponential value. */ function expScaled( uint256 votes, uint256 baseLiquidity ) internal pure returns (uint256) { require(baseLiquidity > 0, "Base liquidity must be greater than zero"); return exp((votes * 1e18) / baseLiquidity); } /** * @notice Approximates the exponential function for small inputs. * @param x The input value (in 18-decimal precision). * @return The approximate exponential value. */ function exp(uint256 x) internal pure returns (uint256) { uint256 result = 1e18; // Start with 1 in 18-decimal precision uint256 term = 1e18; for (uint8 i = 1; i < 20; i++) { term = (term * x) / (i * 1e18); result += term; // Stop the loop early if the term becomes negligible if (term < 1) break; } return result; } /** * @notice Calculates the natural logarithm of an input value. * @param x The input value (in 18-decimal precision). * @return The natural logarithm of the input. */ function ln(uint256 x) internal pure returns (uint256) { require(x > 0, "Input must be greater than zero"); uint256 result = 0; uint256 y = x; uint256 precision = 1e18; // Normalize input to the range [1, 10) by adjusting the result accordingly while (y < precision) { y *= 10; result -= 2302585092994045684; // ln(10) in 18-decimal precision } while (y >= precision * 10) { y /= 10; result += 2302585092994045684; // ln(10) in 18-decimal precision } // Taylor series approximation uint256 z = ((y - precision) * precision) / (y + precision); uint256 z2 = (z * z) / precision; result += z; uint256 term = z; for (uint8 i = 3; i < 40; i += 2) { term = (term * z2) / precision; result += term / i; // Stop if the term becomes negligible if (term < 1) break; } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Utility.sol"; import "./Roles.sol"; import "./UserState.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {UD60x18, ud, ln} from "@prb/math/src/UD60x18.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; /** * @title MarketState * @dev Abstract contract to manage prediction markets using LMSR with Yes/No outcomes in a points-based system. * Features include market creation, resolution, reward claims, and fund management. */ abstract contract MarketState is Roles, OwnableUpgradeable, UserState, ReentrancyGuard { using Utility for uint256; using Utility for uint256[]; struct Market { uint256 questionId; // Unique identifier for the question (off-chain data) uint256 yesVotes; // Total points for "Yes" option uint256 noVotes; // Total points for "No" option uint256 totalFunds; // Total points in the market uint256 commissionPercentage; // Commission percentage for the team uint256 baseLiquidity; // LMSR `b` parameter uint256 endTime; // Market's end time bool isResolved; // Status of market resolution uint256 winningOption; // Winning option (0 = "No", 1 = "Yes") uint256 yesPrice; // Cached price for "Yes" (18-decimal precision) uint256 noPrice; // Cached price for "No" (18-decimal precision) } uint256 public marketCount; // Counter for market IDs mapping(uint256 => Market) public markets; // Mapping of market IDs to Market structs uint256[] public kRange; // K-range values for LMSR calculations uint256 public constant POINTS_PER_DOLLAR = 100; // Conversion rate: 1 USD = 100 points uint256 public gracePeriod; // Default grace period for unclaimed rewards // Events event MarketCreated( uint256 indexed marketId, uint256 questionId, uint256 endTime ); event MarketResolved(uint256 indexed marketId, uint256 winningOption); event PricesUpdated( uint256 indexed marketId, uint256 yesPrice, uint256 noPrice ); event MarketPoolUpdated( uint256 indexed marketId, uint256 yesVotes, uint256 noVotes, uint256 totalFunds ); event MarketEndTimeUpdated(uint256 indexed marketId, uint256 newEndTime); event KRangeUpdated(uint256[] newKRange); event UnclaimedRewardsReclaimed(uint256 indexed marketId, uint256 amount); event GracePeriodUpdated(uint256 newGracePeriod); event EmptyMarketResolved(uint256 indexed marketId); event RewardClaimed( address indexed user, uint256 indexed marketId, uint256 reward ); mapping(address => uint256[]) private userUnclaimedMarkets; // Tracks unclaimed markets per user mapping(uint256 => mapping(address => bool)) private hasClaimed; // Tracks claim status per user and market /** * @notice Initializes the MarketState variables. */ function initializeMarketState() public initializer { gracePeriod = 30 days; // Default grace period for unclaimed rewards } /** * @notice Updates the K range values. * @param newKRange Array of new K values. */ function updateKRange(uint256[] calldata newKRange) external onlyTeam { require(newKRange.length > 0, "K range cannot be empty"); require(newKRange.length <= 10, "K range exceeds maximum length"); for (uint256 i = 0; i < newKRange.length; i++) { require(newKRange[i] > 0, "K values must be greater than zero"); } kRange = newKRange; emit KRangeUpdated(newKRange); } /** * @notice Updates the grace period for unclaimed rewards. * @param newPeriod The new grace period in seconds. */ function setGracePeriod(uint256 newPeriod) external onlyOwner { require(newPeriod > 0, "Grace period must be greater than zero"); require(newPeriod <= 365 days, "Grace period exceeds maximum limit"); gracePeriod = newPeriod; emit GracePeriodUpdated(newPeriod); } /** * @notice Reclaims unclaimed rewards after the grace period. * @param marketId The ID of the market to reclaim rewards from. */ function reclaimUnclaimedRewards(uint256 marketId) external onlyOwner { Market storage market = markets[marketId]; require(market.isResolved, "Market not resolved"); require( block.timestamp > market.endTime + gracePeriod, "Grace period not ended" ); require(market.totalFunds > 0, "No unclaimed rewards"); uint256 unclaimedRewards = market.totalFunds; market.totalFunds = 0; userPoints[owner()] += unclaimedRewards; emit UnclaimedRewardsReclaimed(marketId, unclaimedRewards); } /** * @notice Resolves a market by determining the winning option. * @param marketId The ID of the market to resolve. * @param winningOption The winning option (0 = "No", 1 = "Yes"). */ function resolveMarket( uint256 marketId, uint256 winningOption ) external onlyTeam { Market storage market = markets[marketId]; require(!market.isResolved, "Market already resolved"); require( winningOption == 0 || winningOption == 1, "Invalid winning option" ); // If both "Yes" and "No" votes are zero, resolve as empty market if (market.yesVotes == 0 && market.noVotes == 0) { market.isResolved = true; emit EmptyMarketResolved(marketId); return; } // Check if either "Yes" or "No" votes are zero, no commission applies if (market.yesVotes == 0 || market.noVotes == 0) { market.isResolved = true; market.winningOption = market.yesVotes > 0 ? 1 : 0; // Winning option is the one with non-zero votes emit MarketResolved(marketId, market.winningOption); return; } // Calculate team commission only if both "Yes" and "No" have votes uint256 teamCommission = market.totalFunds.calculatePercentage( market.commissionPercentage ); market.totalFunds -= teamCommission; userPoints[owner()] += teamCommission; market.isResolved = true; market.winningOption = winningOption; emit MarketResolved(marketId, winningOption); } /** * @notice Claims rewards for a resolved market. * @param marketId The ID of the market to claim rewards from. */ function claimReward(uint256 marketId) external nonReentrant { Market storage market = markets[marketId]; require(market.isResolved, "Market not resolved"); uint256 activeOption = market.yesVotes > 0 ? 1 : 0; uint256 userHolding = userHoldings[msg.sender][marketId][activeOption]; require(userHolding > 0, "No rewards to claim"); uint256 activeReward = userHolding.calculateProportion( market.totalFunds, activeOption == 1 ? market.yesVotes : market.noVotes ); market.totalFunds -= activeReward; // Update total funds after rewards are claimed userPoints[msg.sender] += activeReward; userHoldings[msg.sender][marketId][activeOption] = 0; emit RewardClaimed(msg.sender, marketId, activeReward); } /** * @notice Updates prices for "Yes" and "No" options in a market. * @param marketId The ID of the market. */ function updatePrices(uint256 marketId) internal { Market storage market = markets[marketId]; require(!market.isResolved, "Market already resolved"); require(kRange.length > 0, "K range not initialized"); uint256 k = kRange[market.totalFunds % kRange.length]; require(k > 0, "Invalid k value"); market.baseLiquidity = Utility.calculateBaseLiquidity( k, market.yesVotes + market.noVotes ); (market.yesPrice, market.noPrice) = Utility.calculateLMSRPrices( market.yesVotes, market.noVotes, market.baseLiquidity ); emit PricesUpdated(marketId, market.yesPrice, market.noPrice); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title IMarketManager * @notice Interface defining core functionalities for managing prediction markets. */ interface IMarketManager { /** * @notice Creates a new prediction market. * @param questionId The unique identifier for the question (off-chain data). * @param commissionPercentage The commission percentage for the team (0-100%). * @param endTime The timestamp (in seconds) when the market ends. */ function createMarket( uint256 questionId, uint256 commissionPercentage, uint256 endTime ) external; /** * @notice Updates the end time of an existing market. * @param marketId The ID of the market to update. * @param newEndTime The new end time (in seconds) for the market. */ function updateEndTime(uint256 marketId, uint256 newEndTime) external; /** * @notice Retrieves the price of a specific option in a market. * @param marketId The ID of the market. * @param optionId The ID of the option (0 = "No", 1 = "Yes"). * @return The price of the specified option in 18-decimal precision. */ function getPrice( uint256 marketId, uint256 optionId ) external view returns (uint256); /** * @notice Updates the market pool balances when points are added or removed. * @param marketId The ID of the market. * @param isYesVote True if adding points to "Yes" option, false for "No" option. * @param amount The amount of points to add or subtract from the pool. */ function updateMarketPool( uint256 marketId, bool isYesVote, uint256 amount ) external; /** * @notice Retrieves details about a specific market. * @param marketId The ID of the market. * @return questionId The unique identifier for the question (off-chain data). * @return yesVotes The total points for the "Yes" option. * @return noVotes The total points for the "No" option. * @return isResolved Whether the market has been resolved. * @return winningOption The ID of the winning option (0 = "No", 1 = "Yes"). */ function getMarketDetails( uint256 marketId ) external view returns ( uint256 questionId, uint256 yesVotes, uint256 noVotes, bool isResolved, uint256 winningOption ); /** * @notice Checks if a specific market has been resolved. * @param marketId The ID of the market. * @return True if the market is resolved, false otherwise. */ function isMarketResolved(uint256 marketId) external view returns (bool); /** * @notice Retrieves the end time of a specific market. * @param marketId The ID of the market. * @return The end time of the market in UNIX timestamp. */ function getMarketEndTime(uint256 marketId) external view returns (uint256); /** * @notice Retrieves details of all markets with their pool balances. * @return marketIds An array of market IDs. * @return questionIds An array of question IDs for the markets. * @return totalPoolBalances An array of total pool balances for each market. */ function getAllMarketsWithPools() external view returns ( uint256[] memory marketIds, uint256[] memory questionIds, uint256[] memory totalPoolBalances ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title UserState * @dev Abstract contract to manage user points and token holdings in prediction markets. */ abstract contract UserState { // State Variables mapping(address => uint256) public userPoints; // Maps user addresses to their points balance mapping(address => mapping(uint256 => uint256[2])) public userHoldings; // User holdings for "Yes" (index 1) and "No" (index 0) options in each market mapping(uint256 => address[]) public marketParticipants; // List of participants per market mapping(uint256 => mapping(address => bool)) private isMarketParticipant; // Events event UserDeposited(address indexed user, uint256 points); event UserWithdrawn(address indexed user, uint256 stablecoins); uint8 public stablecoinCount; // Total number of supported stablecoins uint256 public constant CONVERSION_RATE = 100; // $1 = 100 points // Events event StablecoinAdded( uint8 indexed stablecoinIndex, address stablecoinAddress ); event StablecoinUpdated( uint8 indexed stablecoinIndex, address oldStablecoinAddress, address newStablecoinAddress ); event TokensBought( address indexed user, uint256 indexed marketId, uint256 optionId, uint256 amount ); /** * @notice Internal function to update user holdings when buying tokens. * @dev Adds the specified amount of tokens to the user's holdings for a given market option. * Emits the TokensBought event in the calling function for logging purposes. * @param user The address of the user buying tokens. * @param marketId The ID of the market in which tokens are bought. * @param optionId The ID of the market option being bought (0 = "No", 1 = "Yes"). * @param amount The number of tokens being bought. */ function _updateHoldingsOnBuy( address user, uint256 marketId, uint256 optionId, uint256 amount ) internal { // Validate the option ID require(optionId == 0 || optionId == 1, "UserState: Invalid option ID"); // Ensure a valid user address require(user != address(0), "UserState: User address cannot be zero"); // Ensure a valid market ID require(marketId > 0, "UserState: Invalid market ID"); // Ensure a valid token amount require(amount > 0, "UserState: Amount must be greater than zero"); // Update user holdings userHoldings[user][marketId][optionId] += amount; } /** * @notice Internal function to validate if the user has sufficient balance for an action. * @dev Reverts with a specific message if the user's balance is insufficient. * @param user The address of the user to check. * @param pointsRequired The number of points required for the action. */ function _validateUserBalance( address user, uint256 pointsRequired ) internal view { require(user != address(0), "UserState: User address cannot be zero"); require( userPoints[user] >= pointsRequired, "UserState: Insufficient balance" ); } /** * @notice Internal function to add a participant to a market if not already added. * @param user The address of the participant. * @param marketId The ID of the market. */ function _addParticipantIfNotExists( address user, uint256 marketId ) internal { require(user != address(0), "UserState: User address cannot be zero"); require(marketId > 0, "UserState: Invalid market ID"); // Add user to participant list only if not already added if (!isMarketParticipant[marketId][user]) { marketParticipants[marketId].push(user); isMarketParticipant[marketId][user] = true; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.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 that the this implementation remains valid after 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. */ function upgradeTo(address newImplementation) external 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. */ function upgradeToAndCall(address newImplementation, bytes memory data) external 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.6.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = _setInitializedVersion(1); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { bool isTopLevelCall = _setInitializedVersion(version); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(version); } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { _setInitializedVersion(type(uint8).max); } function _setInitializedVersion(uint8 version) private returns (bool) { // 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, and for the lowest level // of initializers, because in other contexts the contract may have been reentered. if (_initializing) { require( version == 1 && !AddressUpgradeable.isContract(address(this)), "Initializable: contract is already initialized" ); return false; } else { require(_initialized < version, "Initializable: contract is already initialized"); _initialized = version; return true; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.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: * * ``` * 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}: * * ``` * 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. */ 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(uint160(account), 20), " 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. */ 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. */ 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`. */ 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. * * [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. */ 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. */ 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/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; /* ██████╗ ██████╗ ██████╗ ███╗ ███╗ █████╗ ████████╗██╗ ██╗ ██╔══██╗██╔══██╗██╔══██╗████╗ ████║██╔══██╗╚══██╔══╝██║ ██║ ██████╔╝██████╔╝██████╔╝██╔████╔██║███████║ ██║ ███████║ ██╔═══╝ ██╔══██╗██╔══██╗██║╚██╔╝██║██╔══██║ ██║ ██╔══██║ ██║ ██║ ██║██████╔╝██║ ╚═╝ ██║██║ ██║ ██║ ██║ ██║ ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ██╗ ██╗██████╗ ██████╗ ██████╗ ██╗ ██╗ ██╗ █████╗ ██║ ██║██╔══██╗██╔════╝ ██╔═████╗╚██╗██╔╝███║██╔══██╗ ██║ ██║██║ ██║███████╗ ██║██╔██║ ╚███╔╝ ╚██║╚█████╔╝ ██║ ██║██║ ██║██╔═══██╗████╔╝██║ ██╔██╗ ██║██╔══██╗ ╚██████╔╝██████╔╝╚██████╔╝╚██████╔╝██╔╝ ██╗ ██║╚█████╔╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚════╝ */ import "./ud60x18/Casting.sol"; import "./ud60x18/Constants.sol"; import "./ud60x18/Conversions.sol"; import "./ud60x18/Errors.sol"; import "./ud60x18/Helpers.sol"; import "./ud60x18/Math.sol"; import "./ud60x18/ValueType.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// 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.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeaconUpgradeable.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._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967UpgradeUpgradeable is Initializable { 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 Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @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) { _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 Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @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 Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @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) { _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @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) private returns (bytes memory) { require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed"); } /** * @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/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 (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 v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library StringsUpgradeable { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// 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 pragma solidity >=0.8.19; import "./Errors.sol" as CastingErrors; import { MAX_UINT128, MAX_UINT40 } from "../Common.sol"; import { uMAX_SD1x18 } from "../sd1x18/Constants.sol"; import { SD1x18 } from "../sd1x18/ValueType.sol"; import { uMAX_SD21x18 } from "../sd21x18/Constants.sol"; import { SD21x18 } from "../sd21x18/ValueType.sol"; import { uMAX_SD59x18 } from "../sd59x18/Constants.sol"; import { SD59x18 } from "../sd59x18/ValueType.sol"; import { uMAX_UD2x18 } from "../ud2x18/Constants.sol"; import { uMAX_UD21x18 } from "../ud21x18/Constants.sol"; import { UD2x18 } from "../ud2x18/ValueType.sol"; import { UD21x18 } from "../ud21x18/ValueType.sol"; import { UD60x18 } from "./ValueType.sol"; /// @notice Casts a UD60x18 number into SD1x18. /// @dev Requirements: /// - x ≤ uMAX_SD1x18 function intoSD1x18(UD60x18 x) pure returns (SD1x18 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > uint256(int256(uMAX_SD1x18))) { revert CastingErrors.PRBMath_UD60x18_IntoSD1x18_Overflow(x); } result = SD1x18.wrap(int64(uint64(xUint))); } /// @notice Casts a UD60x18 number into SD21x18. /// @dev Requirements: /// - x ≤ uMAX_SD21x18 function intoSD21x18(UD60x18 x) pure returns (SD21x18 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > uint256(int256(uMAX_SD21x18))) { revert CastingErrors.PRBMath_UD60x18_IntoSD21x18_Overflow(x); } result = SD21x18.wrap(int128(uint128(xUint))); } /// @notice Casts a UD60x18 number into UD2x18. /// @dev Requirements: /// - x ≤ uMAX_UD2x18 function intoUD2x18(UD60x18 x) pure returns (UD2x18 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > uMAX_UD2x18) { revert CastingErrors.PRBMath_UD60x18_IntoUD2x18_Overflow(x); } result = UD2x18.wrap(uint64(xUint)); } /// @notice Casts a UD60x18 number into UD21x18. /// @dev Requirements: /// - x ≤ uMAX_UD21x18 function intoUD21x18(UD60x18 x) pure returns (UD21x18 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > uMAX_UD21x18) { revert CastingErrors.PRBMath_UD60x18_IntoUD21x18_Overflow(x); } result = UD21x18.wrap(uint128(xUint)); } /// @notice Casts a UD60x18 number into SD59x18. /// @dev Requirements: /// - x ≤ uMAX_SD59x18 function intoSD59x18(UD60x18 x) pure returns (SD59x18 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > uint256(uMAX_SD59x18)) { revert CastingErrors.PRBMath_UD60x18_IntoSD59x18_Overflow(x); } result = SD59x18.wrap(int256(xUint)); } /// @notice Casts a UD60x18 number into uint128. /// @dev This is basically an alias for {unwrap}. function intoUint256(UD60x18 x) pure returns (uint256 result) { result = UD60x18.unwrap(x); } /// @notice Casts a UD60x18 number into uint128. /// @dev Requirements: /// - x ≤ MAX_UINT128 function intoUint128(UD60x18 x) pure returns (uint128 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > MAX_UINT128) { revert CastingErrors.PRBMath_UD60x18_IntoUint128_Overflow(x); } result = uint128(xUint); } /// @notice Casts a UD60x18 number into uint40. /// @dev Requirements: /// - x ≤ MAX_UINT40 function intoUint40(UD60x18 x) pure returns (uint40 result) { uint256 xUint = UD60x18.unwrap(x); if (xUint > MAX_UINT40) { revert CastingErrors.PRBMath_UD60x18_IntoUint40_Overflow(x); } result = uint40(xUint); } /// @notice Alias for {wrap}. function ud(uint256 x) pure returns (UD60x18 result) { result = UD60x18.wrap(x); } /// @notice Alias for {wrap}. function ud60x18(uint256 x) pure returns (UD60x18 result) { result = UD60x18.wrap(x); } /// @notice Unwraps a UD60x18 number into uint256. function unwrap(UD60x18 x) pure returns (uint256 result) { result = UD60x18.unwrap(x); } /// @notice Wraps a uint256 number into the UD60x18 value type. function wrap(uint256 x) pure returns (UD60x18 result) { result = UD60x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { UD60x18 } from "./ValueType.sol"; // NOTICE: the "u" prefix stands for "unwrapped". /// @dev Euler's number as a UD60x18 number. UD60x18 constant E = UD60x18.wrap(2_718281828459045235); /// @dev The maximum input permitted in {exp}. uint256 constant uEXP_MAX_INPUT = 133_084258667509499440; UD60x18 constant EXP_MAX_INPUT = UD60x18.wrap(uEXP_MAX_INPUT); /// @dev The maximum input permitted in {exp2}. uint256 constant uEXP2_MAX_INPUT = 192e18 - 1; UD60x18 constant EXP2_MAX_INPUT = UD60x18.wrap(uEXP2_MAX_INPUT); /// @dev Half the UNIT number. uint256 constant uHALF_UNIT = 0.5e18; UD60x18 constant HALF_UNIT = UD60x18.wrap(uHALF_UNIT); /// @dev $log_2(10)$ as a UD60x18 number. uint256 constant uLOG2_10 = 3_321928094887362347; UD60x18 constant LOG2_10 = UD60x18.wrap(uLOG2_10); /// @dev $log_2(e)$ as a UD60x18 number. uint256 constant uLOG2_E = 1_442695040888963407; UD60x18 constant LOG2_E = UD60x18.wrap(uLOG2_E); /// @dev The maximum value a UD60x18 number can have. uint256 constant uMAX_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_584007913129639935; UD60x18 constant MAX_UD60x18 = UD60x18.wrap(uMAX_UD60x18); /// @dev The maximum whole value a UD60x18 number can have. uint256 constant uMAX_WHOLE_UD60x18 = 115792089237316195423570985008687907853269984665640564039457_000000000000000000; UD60x18 constant MAX_WHOLE_UD60x18 = UD60x18.wrap(uMAX_WHOLE_UD60x18); /// @dev PI as a UD60x18 number. UD60x18 constant PI = UD60x18.wrap(3_141592653589793238); /// @dev The unit number, which gives the decimal precision of UD60x18. uint256 constant uUNIT = 1e18; UD60x18 constant UNIT = UD60x18.wrap(uUNIT); /// @dev The unit number squared. uint256 constant uUNIT_SQUARED = 1e36; UD60x18 constant UNIT_SQUARED = UD60x18.wrap(uUNIT_SQUARED); /// @dev Zero as a UD60x18 number. UD60x18 constant ZERO = UD60x18.wrap(0);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { wrap } from "./Casting.sol"; import { UD60x18 } from "./ValueType.sol"; /// @notice Implements the checked addition operation (+) in the UD60x18 type. function add(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() + y.unwrap()); } /// @notice Implements the AND (&) bitwise operation in the UD60x18 type. function and(UD60x18 x, uint256 bits) pure returns (UD60x18 result) { result = wrap(x.unwrap() & bits); } /// @notice Implements the AND (&) bitwise operation in the UD60x18 type. function and2(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() & y.unwrap()); } /// @notice Implements the equal operation (==) in the UD60x18 type. function eq(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() == y.unwrap(); } /// @notice Implements the greater than operation (>) in the UD60x18 type. function gt(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() > y.unwrap(); } /// @notice Implements the greater than or equal to operation (>=) in the UD60x18 type. function gte(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() >= y.unwrap(); } /// @notice Implements a zero comparison check function in the UD60x18 type. function isZero(UD60x18 x) pure returns (bool result) { // This wouldn't work if x could be negative. result = x.unwrap() == 0; } /// @notice Implements the left shift operation (<<) in the UD60x18 type. function lshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) { result = wrap(x.unwrap() << bits); } /// @notice Implements the lower than operation (<) in the UD60x18 type. function lt(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() < y.unwrap(); } /// @notice Implements the lower than or equal to operation (<=) in the UD60x18 type. function lte(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() <= y.unwrap(); } /// @notice Implements the checked modulo operation (%) in the UD60x18 type. function mod(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() % y.unwrap()); } /// @notice Implements the not equal operation (!=) in the UD60x18 type. function neq(UD60x18 x, UD60x18 y) pure returns (bool result) { result = x.unwrap() != y.unwrap(); } /// @notice Implements the NOT (~) bitwise operation in the UD60x18 type. function not(UD60x18 x) pure returns (UD60x18 result) { result = wrap(~x.unwrap()); } /// @notice Implements the OR (|) bitwise operation in the UD60x18 type. function or(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() | y.unwrap()); } /// @notice Implements the right shift operation (>>) in the UD60x18 type. function rshift(UD60x18 x, uint256 bits) pure returns (UD60x18 result) { result = wrap(x.unwrap() >> bits); } /// @notice Implements the checked subtraction operation (-) in the UD60x18 type. function sub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() - y.unwrap()); } /// @notice Implements the unchecked addition operation (+) in the UD60x18 type. function uncheckedAdd(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { unchecked { result = wrap(x.unwrap() + y.unwrap()); } } /// @notice Implements the unchecked subtraction operation (-) in the UD60x18 type. function uncheckedSub(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { unchecked { result = wrap(x.unwrap() - y.unwrap()); } } /// @notice Implements the XOR (^) bitwise operation in the UD60x18 type. function xor(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(x.unwrap() ^ y.unwrap()); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { UD60x18 } from "./ValueType.sol"; /// @notice Thrown when ceiling a number overflows UD60x18. error PRBMath_UD60x18_Ceil_Overflow(UD60x18 x); /// @notice Thrown when converting a basic integer to the fixed-point format overflows UD60x18. error PRBMath_UD60x18_Convert_Overflow(uint256 x); /// @notice Thrown when taking the natural exponent of a base greater than 133_084258667509499441. error PRBMath_UD60x18_Exp_InputTooBig(UD60x18 x); /// @notice Thrown when taking the binary exponent of a base greater than 192e18. error PRBMath_UD60x18_Exp2_InputTooBig(UD60x18 x); /// @notice Thrown when taking the geometric mean of two numbers and multiplying them overflows UD60x18. error PRBMath_UD60x18_Gm_Overflow(UD60x18 x, UD60x18 y); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD1x18. error PRBMath_UD60x18_IntoSD1x18_Overflow(UD60x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD21x18. error PRBMath_UD60x18_IntoSD21x18_Overflow(UD60x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in SD59x18. error PRBMath_UD60x18_IntoSD59x18_Overflow(UD60x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD2x18. error PRBMath_UD60x18_IntoUD2x18_Overflow(UD60x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in UD21x18. error PRBMath_UD60x18_IntoUD21x18_Overflow(UD60x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint128. error PRBMath_UD60x18_IntoUint128_Overflow(UD60x18 x); /// @notice Thrown when trying to cast a UD60x18 number that doesn't fit in uint40. error PRBMath_UD60x18_IntoUint40_Overflow(UD60x18 x); /// @notice Thrown when taking the logarithm of a number less than UNIT. error PRBMath_UD60x18_Log_InputTooSmall(UD60x18 x); /// @notice Thrown when calculating the square root overflows UD60x18. error PRBMath_UD60x18_Sqrt_Overflow(UD60x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { uMAX_UD60x18, uUNIT } from "./Constants.sol"; import { PRBMath_UD60x18_Convert_Overflow } from "./Errors.sol"; import { UD60x18 } from "./ValueType.sol"; /// @notice Converts a UD60x18 number to a simple integer by dividing it by `UNIT`. /// @dev The result is rounded toward zero. /// @param x The UD60x18 number to convert. /// @return result The same number in basic integer form. function convert(UD60x18 x) pure returns (uint256 result) { result = UD60x18.unwrap(x) / uUNIT; } /// @notice Converts a simple integer to UD60x18 by multiplying it by `UNIT`. /// /// @dev Requirements: /// - x ≤ MAX_UD60x18 / UNIT /// /// @param x The basic integer to convert. /// @return result The same number converted to UD60x18. function convert(uint256 x) pure returns (UD60x18 result) { if (x > uMAX_UD60x18 / uUNIT) { revert PRBMath_UD60x18_Convert_Overflow(x); } unchecked { result = UD60x18.wrap(x * uUNIT); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Casting.sol" as Casting; import "./Helpers.sol" as Helpers; import "./Math.sol" as Math; /// @notice The unsigned 60.18-decimal fixed-point number representation, which can have up to 60 digits and up to 18 /// decimals. The values of this are bound by the minimum and the maximum values permitted by the Solidity type uint256. /// @dev The value type is defined here so it can be imported in all other files. type UD60x18 is uint256; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { Casting.intoSD1x18, Casting.intoSD21x18, Casting.intoSD59x18, Casting.intoUD2x18, Casting.intoUD21x18, Casting.intoUint128, Casting.intoUint256, Casting.intoUint40, Casting.unwrap } for UD60x18 global; /*////////////////////////////////////////////////////////////////////////// MATHEMATICAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ // The global "using for" directive makes the functions in this library callable on the UD60x18 type. using { Math.avg, Math.ceil, Math.div, Math.exp, Math.exp2, Math.floor, Math.frac, Math.gm, Math.inv, Math.ln, Math.log10, Math.log2, Math.mul, Math.pow, Math.powu, Math.sqrt } for UD60x18 global; /*////////////////////////////////////////////////////////////////////////// HELPER FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ // The global "using for" directive makes the functions in this library callable on the UD60x18 type. using { Helpers.add, Helpers.and, Helpers.eq, Helpers.gt, Helpers.gte, Helpers.isZero, Helpers.lshift, Helpers.lt, Helpers.lte, Helpers.mod, Helpers.neq, Helpers.not, Helpers.or, Helpers.rshift, Helpers.sub, Helpers.uncheckedAdd, Helpers.uncheckedSub, Helpers.xor } for UD60x18 global; /*////////////////////////////////////////////////////////////////////////// OPERATORS //////////////////////////////////////////////////////////////////////////*/ // The global "using for" directive makes it possible to use these operators on the UD60x18 type. using { Helpers.add as +, Helpers.and2 as &, Math.div as /, Helpers.eq as ==, Helpers.gt as >, Helpers.gte as >=, Helpers.lt as <, Helpers.lte as <=, Helpers.or as |, Helpers.mod as %, Math.mul as *, Helpers.neq as !=, Helpers.not as ~, Helpers.sub as -, Helpers.xor as ^ } for UD60x18 global;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "../Common.sol" as Common; import "./Errors.sol" as Errors; import { wrap } from "./Casting.sol"; import { uEXP_MAX_INPUT, uEXP2_MAX_INPUT, uHALF_UNIT, uLOG2_10, uLOG2_E, uMAX_UD60x18, uMAX_WHOLE_UD60x18, UNIT, uUNIT, uUNIT_SQUARED, ZERO } from "./Constants.sol"; import { UD60x18 } from "./ValueType.sol"; /*////////////////////////////////////////////////////////////////////////// MATHEMATICAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice Calculates the arithmetic average of x and y using the following formula: /// /// $$ /// avg(x, y) = (x & y) + ((xUint ^ yUint) / 2) /// $$ /// /// In English, this is what this formula does: /// /// 1. AND x and y. /// 2. Calculate half of XOR x and y. /// 3. Add the two results together. /// /// This technique is known as SWAR, which stands for "SIMD within a register". You can read more about it here: /// https://devblogs.microsoft.com/oldnewthing/20220207-00/?p=106223 /// /// @dev Notes: /// - The result is rounded toward zero. /// /// @param x The first operand as a UD60x18 number. /// @param y The second operand as a UD60x18 number. /// @return result The arithmetic average as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function avg(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); uint256 yUint = y.unwrap(); unchecked { result = wrap((xUint & yUint) + ((xUint ^ yUint) >> 1)); } } /// @notice Yields the smallest whole number greater than or equal to x. /// /// @dev This is optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional /// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// /// Requirements: /// - x ≤ MAX_WHOLE_UD60x18 /// /// @param x The UD60x18 number to ceil. /// @return result The smallest whole number greater than or equal to x, as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function ceil(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); if (xUint > uMAX_WHOLE_UD60x18) { revert Errors.PRBMath_UD60x18_Ceil_Overflow(x); } assembly ("memory-safe") { // Equivalent to `x % UNIT`. let remainder := mod(x, uUNIT) // Equivalent to `UNIT - remainder`. let delta := sub(uUNIT, remainder) // Equivalent to `x + remainder > 0 ? delta : 0`. result := add(x, mul(delta, gt(remainder, 0))) } } /// @notice Divides two UD60x18 numbers, returning a new UD60x18 number. /// /// @dev Uses {Common.mulDiv} to enable overflow-safe multiplication and division. /// /// Notes: /// - Refer to the notes in {Common.mulDiv}. /// /// Requirements: /// - Refer to the requirements in {Common.mulDiv}. /// /// @param x The numerator as a UD60x18 number. /// @param y The denominator as a UD60x18 number. /// @return result The quotient as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function div(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(Common.mulDiv(x.unwrap(), uUNIT, y.unwrap())); } /// @notice Calculates the natural exponent of x using the following formula: /// /// $$ /// e^x = 2^{x * log_2{e}} /// $$ /// /// @dev Requirements: /// - x ≤ 133_084258667509499440 /// /// @param x The exponent as a UD60x18 number. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function exp(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); // This check prevents values greater than 192e18 from being passed to {exp2}. if (xUint > uEXP_MAX_INPUT) { revert Errors.PRBMath_UD60x18_Exp_InputTooBig(x); } unchecked { // Inline the fixed-point multiplication to save gas. uint256 doubleUnitProduct = xUint * uLOG2_E; result = exp2(wrap(doubleUnitProduct / uUNIT)); } } /// @notice Calculates the binary exponent of x using the binary fraction method. /// /// @dev See https://ethereum.stackexchange.com/q/79903/24693 /// /// Requirements: /// - x < 192e18 /// - The result must fit in UD60x18. /// /// @param x The exponent as a UD60x18 number. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function exp2(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); // Numbers greater than or equal to 192e18 don't fit in the 192.64-bit format. if (xUint > uEXP2_MAX_INPUT) { revert Errors.PRBMath_UD60x18_Exp2_InputTooBig(x); } // Convert x to the 192.64-bit fixed-point format. uint256 x_192x64 = (xUint << 64) / uUNIT; // Pass x to the {Common.exp2} function, which uses the 192.64-bit fixed-point number representation. result = wrap(Common.exp2(x_192x64)); } /// @notice Yields the greatest whole number less than or equal to x. /// @dev Optimized for fractional value inputs, because every whole value has (1e18 - 1) fractional counterparts. /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// @param x The UD60x18 number to floor. /// @return result The greatest whole number less than or equal to x, as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function floor(UD60x18 x) pure returns (UD60x18 result) { assembly ("memory-safe") { // Equivalent to `x % UNIT`. let remainder := mod(x, uUNIT) // Equivalent to `x - remainder > 0 ? remainder : 0)`. result := sub(x, mul(remainder, gt(remainder, 0))) } } /// @notice Yields the excess beyond the floor of x using the odd function definition. /// @dev See https://en.wikipedia.org/wiki/Fractional_part. /// @param x The UD60x18 number to get the fractional part of. /// @return result The fractional part of x as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function frac(UD60x18 x) pure returns (UD60x18 result) { assembly ("memory-safe") { result := mod(x, uUNIT) } } /// @notice Calculates the geometric mean of x and y, i.e. $\sqrt{x * y}$, rounding down. /// /// @dev Requirements: /// - x * y must fit in UD60x18. /// /// @param x The first operand as a UD60x18 number. /// @param y The second operand as a UD60x18 number. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function gm(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); uint256 yUint = y.unwrap(); if (xUint == 0 || yUint == 0) { return ZERO; } unchecked { // Checking for overflow this way is faster than letting Solidity do it. uint256 xyUint = xUint * yUint; if (xyUint / xUint != yUint) { revert Errors.PRBMath_UD60x18_Gm_Overflow(x, y); } // We don't need to multiply the result by `UNIT` here because the x*y product picked up a factor of `UNIT` // during multiplication. See the comments in {Common.sqrt}. result = wrap(Common.sqrt(xyUint)); } } /// @notice Calculates the inverse of x. /// /// @dev Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - x must not be zero. /// /// @param x The UD60x18 number for which to calculate the inverse. /// @return result The inverse as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function inv(UD60x18 x) pure returns (UD60x18 result) { unchecked { result = wrap(uUNIT_SQUARED / x.unwrap()); } } /// @notice Calculates the natural logarithm of x using the following formula: /// /// $$ /// ln{x} = log_2{x} / log_2{e} /// $$ /// /// @dev Notes: /// - Refer to the notes in {log2}. /// - The precision isn't sufficiently fine-grained to return exactly `UNIT` when the input is `E`. /// /// Requirements: /// - Refer to the requirements in {log2}. /// /// @param x The UD60x18 number for which to calculate the natural logarithm. /// @return result The natural logarithm as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function ln(UD60x18 x) pure returns (UD60x18 result) { unchecked { // Inline the fixed-point multiplication to save gas. This is overflow-safe because the maximum value that // {log2} can return is ~196_205294292027477728. result = wrap(log2(x).unwrap() * uUNIT / uLOG2_E); } } /// @notice Calculates the common logarithm of x using the following formula: /// /// $$ /// log_{10}{x} = log_2{x} / log_2{10} /// $$ /// /// However, if x is an exact power of ten, a hard coded value is returned. /// /// @dev Notes: /// - Refer to the notes in {log2}. /// /// Requirements: /// - Refer to the requirements in {log2}. /// /// @param x The UD60x18 number for which to calculate the common logarithm. /// @return result The common logarithm as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function log10(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); if (xUint < uUNIT) { revert Errors.PRBMath_UD60x18_Log_InputTooSmall(x); } // Note that the `mul` in this assembly block is the standard multiplication operation, not {UD60x18.mul}. // prettier-ignore assembly ("memory-safe") { switch x case 1 { result := mul(uUNIT, sub(0, 18)) } case 10 { result := mul(uUNIT, sub(1, 18)) } case 100 { result := mul(uUNIT, sub(2, 18)) } case 1000 { result := mul(uUNIT, sub(3, 18)) } case 10000 { result := mul(uUNIT, sub(4, 18)) } case 100000 { result := mul(uUNIT, sub(5, 18)) } case 1000000 { result := mul(uUNIT, sub(6, 18)) } case 10000000 { result := mul(uUNIT, sub(7, 18)) } case 100000000 { result := mul(uUNIT, sub(8, 18)) } case 1000000000 { result := mul(uUNIT, sub(9, 18)) } case 10000000000 { result := mul(uUNIT, sub(10, 18)) } case 100000000000 { result := mul(uUNIT, sub(11, 18)) } case 1000000000000 { result := mul(uUNIT, sub(12, 18)) } case 10000000000000 { result := mul(uUNIT, sub(13, 18)) } case 100000000000000 { result := mul(uUNIT, sub(14, 18)) } case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) } case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) } case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) } case 1000000000000000000 { result := 0 } case 10000000000000000000 { result := uUNIT } case 100000000000000000000 { result := mul(uUNIT, 2) } case 1000000000000000000000 { result := mul(uUNIT, 3) } case 10000000000000000000000 { result := mul(uUNIT, 4) } case 100000000000000000000000 { result := mul(uUNIT, 5) } case 1000000000000000000000000 { result := mul(uUNIT, 6) } case 10000000000000000000000000 { result := mul(uUNIT, 7) } case 100000000000000000000000000 { result := mul(uUNIT, 8) } case 1000000000000000000000000000 { result := mul(uUNIT, 9) } case 10000000000000000000000000000 { result := mul(uUNIT, 10) } case 100000000000000000000000000000 { result := mul(uUNIT, 11) } case 1000000000000000000000000000000 { result := mul(uUNIT, 12) } case 10000000000000000000000000000000 { result := mul(uUNIT, 13) } case 100000000000000000000000000000000 { result := mul(uUNIT, 14) } case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) } case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) } case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) } case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) } case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) } case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) } case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) } case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) } case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) } case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) } case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) } case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) } case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) } case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) } case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) } case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) } case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) } case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) } case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) } case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) } case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) } case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) } case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) } case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) } case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) } case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) } case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) } case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) } case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) } case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) } case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) } case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) } case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) } case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) } case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) } case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) } case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) } case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) } case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) } case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) } case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) } case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) } case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) } case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) } case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 59) } default { result := uMAX_UD60x18 } } if (result.unwrap() == uMAX_UD60x18) { unchecked { // Inline the fixed-point division to save gas. result = wrap(log2(x).unwrap() * uUNIT / uLOG2_10); } } } /// @notice Calculates the binary logarithm of x using the iterative approximation algorithm: /// /// $$ /// log_2{x} = n + log_2{y}, \text{ where } y = x*2^{-n}, \ y \in [1, 2) /// $$ /// /// For $0 \leq x \lt 1$, the input is inverted: /// /// $$ /// log_2{x} = -log_2{\frac{1}{x}} /// $$ /// /// @dev See https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation /// /// Notes: /// - Due to the lossy precision of the iterative approximation, the results are not perfectly accurate to the last decimal. /// /// Requirements: /// - x ≥ UNIT /// /// @param x The UD60x18 number for which to calculate the binary logarithm. /// @return result The binary logarithm as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function log2(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); if (xUint < uUNIT) { revert Errors.PRBMath_UD60x18_Log_InputTooSmall(x); } unchecked { // Calculate the integer part of the logarithm. uint256 n = Common.msb(xUint / uUNIT); // This is the integer part of the logarithm as a UD60x18 number. The operation can't overflow because n // n is at most 255 and UNIT is 1e18. uint256 resultUint = n * uUNIT; // Calculate $y = x * 2^{-n}$. uint256 y = xUint >> n; // If y is the unit number, the fractional part is zero. if (y == uUNIT) { return wrap(resultUint); } // Calculate the fractional part via the iterative approximation. // The `delta >>= 1` part is equivalent to `delta /= 2`, but shifting bits is more gas efficient. uint256 DOUBLE_UNIT = 2e18; for (uint256 delta = uHALF_UNIT; delta > 0; delta >>= 1) { y = (y * y) / uUNIT; // Is y^2 >= 2e18 and so in the range [2e18, 4e18)? if (y >= DOUBLE_UNIT) { // Add the 2^{-m} factor to the logarithm. resultUint += delta; // Halve y, which corresponds to z/2 in the Wikipedia article. y >>= 1; } } result = wrap(resultUint); } } /// @notice Multiplies two UD60x18 numbers together, returning a new UD60x18 number. /// /// @dev Uses {Common.mulDiv} to enable overflow-safe multiplication and division. /// /// Notes: /// - Refer to the notes in {Common.mulDiv}. /// /// Requirements: /// - Refer to the requirements in {Common.mulDiv}. /// /// @dev See the documentation in {Common.mulDiv18}. /// @param x The multiplicand as a UD60x18 number. /// @param y The multiplier as a UD60x18 number. /// @return result The product as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function mul(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { result = wrap(Common.mulDiv18(x.unwrap(), y.unwrap())); } /// @notice Raises x to the power of y. /// /// For $1 \leq x \leq \infty$, the following standard formula is used: /// /// $$ /// x^y = 2^{log_2{x} * y} /// $$ /// /// For $0 \leq x \lt 1$, since the unsigned {log2} is undefined, an equivalent formula is used: /// /// $$ /// i = \frac{1}{x} /// w = 2^{log_2{i} * y} /// x^y = \frac{1}{w} /// $$ /// /// @dev Notes: /// - Refer to the notes in {log2} and {mul}. /// - Returns `UNIT` for 0^0. /// - It may not perform well with very small values of x. Consider using SD59x18 as an alternative. /// /// Requirements: /// - Refer to the requirements in {exp2}, {log2}, and {mul}. /// /// @param x The base as a UD60x18 number. /// @param y The exponent as a UD60x18 number. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function pow(UD60x18 x, UD60x18 y) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); uint256 yUint = y.unwrap(); // If both x and y are zero, the result is `UNIT`. If just x is zero, the result is always zero. if (xUint == 0) { return yUint == 0 ? UNIT : ZERO; } // If x is `UNIT`, the result is always `UNIT`. else if (xUint == uUNIT) { return UNIT; } // If y is zero, the result is always `UNIT`. if (yUint == 0) { return UNIT; } // If y is `UNIT`, the result is always x. else if (yUint == uUNIT) { return x; } // If x is > UNIT, use the standard formula. if (xUint > uUNIT) { result = exp2(mul(log2(x), y)); } // Conversely, if x < UNIT, use the equivalent formula. else { UD60x18 i = wrap(uUNIT_SQUARED / xUint); UD60x18 w = exp2(mul(log2(i), y)); result = wrap(uUNIT_SQUARED / w.unwrap()); } } /// @notice Raises x (a UD60x18 number) to the power y (an unsigned basic integer) using the well-known /// algorithm "exponentiation by squaring". /// /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring. /// /// Notes: /// - Refer to the notes in {Common.mulDiv18}. /// - Returns `UNIT` for 0^0. /// /// Requirements: /// - The result must fit in UD60x18. /// /// @param x The base as a UD60x18 number. /// @param y The exponent as a uint256. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function powu(UD60x18 x, uint256 y) pure returns (UD60x18 result) { // Calculate the first iteration of the loop in advance. uint256 xUint = x.unwrap(); uint256 resultUint = y & 1 > 0 ? xUint : uUNIT; // Equivalent to `for(y /= 2; y > 0; y /= 2)`. for (y >>= 1; y > 0; y >>= 1) { xUint = Common.mulDiv18(xUint, xUint); // Equivalent to `y % 2 == 1`. if (y & 1 > 0) { resultUint = Common.mulDiv18(resultUint, xUint); } } result = wrap(resultUint); } /// @notice Calculates the square root of x using the Babylonian method. /// /// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. /// /// Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - x ≤ MAX_UD60x18 / UNIT /// /// @param x The UD60x18 number for which to calculate the square root. /// @return result The result as a UD60x18 number. /// @custom:smtchecker abstract-function-nondet function sqrt(UD60x18 x) pure returns (UD60x18 result) { uint256 xUint = x.unwrap(); unchecked { if (xUint > uMAX_UD60x18 / uUNIT) { revert Errors.PRBMath_UD60x18_Sqrt_Overflow(x); } // Multiply x by `UNIT` to account for the factor of `UNIT` picked up when multiplying two UD60x18 numbers. // In this case, the two numbers are both the square root. result = wrap(Common.sqrt(xUint * uUNIT)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol) 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: * ``` * 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`, and `uint256`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { assembly { r.slot := slot } } }
// 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 pragma solidity >=0.8.19; // Common.sol // // Common mathematical functions used in both SD59x18 and UD60x18. Note that these global functions do not // always operate with SD59x18 and UD60x18 numbers. /*////////////////////////////////////////////////////////////////////////// CUSTOM ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when the resultant value in {mulDiv} overflows uint256. error PRBMath_MulDiv_Overflow(uint256 x, uint256 y, uint256 denominator); /// @notice Thrown when the resultant value in {mulDiv18} overflows uint256. error PRBMath_MulDiv18_Overflow(uint256 x, uint256 y); /// @notice Thrown when one of the inputs passed to {mulDivSigned} is `type(int256).min`. error PRBMath_MulDivSigned_InputTooSmall(); /// @notice Thrown when the resultant value in {mulDivSigned} overflows int256. error PRBMath_MulDivSigned_Overflow(int256 x, int256 y); /*////////////////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////////////////*/ /// @dev The maximum value a uint128 number can have. uint128 constant MAX_UINT128 = type(uint128).max; /// @dev The maximum value a uint40 number can have. uint40 constant MAX_UINT40 = type(uint40).max; /// @dev The maximum value a uint64 number can have. uint64 constant MAX_UINT64 = type(uint64).max; /// @dev The unit number, which the decimal precision of the fixed-point types. uint256 constant UNIT = 1e18; /// @dev The unit number inverted mod 2^256. uint256 constant UNIT_INVERSE = 78156646155174841979727994598816262306175212592076161876661_508869554232690281; /// @dev The the largest power of two that divides the decimal value of `UNIT`. The logarithm of this value is the least significant /// bit in the binary representation of `UNIT`. uint256 constant UNIT_LPOTD = 262144; /*////////////////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice Calculates the binary exponent of x using the binary fraction method. /// @dev Has to use 192.64-bit fixed-point numbers. See https://ethereum.stackexchange.com/a/96594/24693. /// @param x The exponent as an unsigned 192.64-bit fixed-point number. /// @return result The result as an unsigned 60.18-decimal fixed-point number. /// @custom:smtchecker abstract-function-nondet function exp2(uint256 x) pure returns (uint256 result) { unchecked { // Start from 0.5 in the 192.64-bit fixed-point format. result = 0x800000000000000000000000000000000000000000000000; // The following logic multiplies the result by $\sqrt{2^{-i}}$ when the bit at position i is 1. Key points: // // 1. Intermediate results will not overflow, as the starting point is 2^191 and all magic factors are under 2^65. // 2. The rationale for organizing the if statements into groups of 8 is gas savings. If the result of performing // a bitwise AND operation between x and any value in the array [0x80; 0x40; 0x20; 0x10; 0x08; 0x04; 0x02; 0x01] is 1, // we know that `x & 0xFF` is also 1. if (x & 0xFF00000000000000 > 0) { if (x & 0x8000000000000000 > 0) { result = (result * 0x16A09E667F3BCC909) >> 64; } if (x & 0x4000000000000000 > 0) { result = (result * 0x1306FE0A31B7152DF) >> 64; } if (x & 0x2000000000000000 > 0) { result = (result * 0x1172B83C7D517ADCE) >> 64; } if (x & 0x1000000000000000 > 0) { result = (result * 0x10B5586CF9890F62A) >> 64; } if (x & 0x800000000000000 > 0) { result = (result * 0x1059B0D31585743AE) >> 64; } if (x & 0x400000000000000 > 0) { result = (result * 0x102C9A3E778060EE7) >> 64; } if (x & 0x200000000000000 > 0) { result = (result * 0x10163DA9FB33356D8) >> 64; } if (x & 0x100000000000000 > 0) { result = (result * 0x100B1AFA5ABCBED61) >> 64; } } if (x & 0xFF000000000000 > 0) { if (x & 0x80000000000000 > 0) { result = (result * 0x10058C86DA1C09EA2) >> 64; } if (x & 0x40000000000000 > 0) { result = (result * 0x1002C605E2E8CEC50) >> 64; } if (x & 0x20000000000000 > 0) { result = (result * 0x100162F3904051FA1) >> 64; } if (x & 0x10000000000000 > 0) { result = (result * 0x1000B175EFFDC76BA) >> 64; } if (x & 0x8000000000000 > 0) { result = (result * 0x100058BA01FB9F96D) >> 64; } if (x & 0x4000000000000 > 0) { result = (result * 0x10002C5CC37DA9492) >> 64; } if (x & 0x2000000000000 > 0) { result = (result * 0x1000162E525EE0547) >> 64; } if (x & 0x1000000000000 > 0) { result = (result * 0x10000B17255775C04) >> 64; } } if (x & 0xFF0000000000 > 0) { if (x & 0x800000000000 > 0) { result = (result * 0x1000058B91B5BC9AE) >> 64; } if (x & 0x400000000000 > 0) { result = (result * 0x100002C5C89D5EC6D) >> 64; } if (x & 0x200000000000 > 0) { result = (result * 0x10000162E43F4F831) >> 64; } if (x & 0x100000000000 > 0) { result = (result * 0x100000B1721BCFC9A) >> 64; } if (x & 0x80000000000 > 0) { result = (result * 0x10000058B90CF1E6E) >> 64; } if (x & 0x40000000000 > 0) { result = (result * 0x1000002C5C863B73F) >> 64; } if (x & 0x20000000000 > 0) { result = (result * 0x100000162E430E5A2) >> 64; } if (x & 0x10000000000 > 0) { result = (result * 0x1000000B172183551) >> 64; } } if (x & 0xFF00000000 > 0) { if (x & 0x8000000000 > 0) { result = (result * 0x100000058B90C0B49) >> 64; } if (x & 0x4000000000 > 0) { result = (result * 0x10000002C5C8601CC) >> 64; } if (x & 0x2000000000 > 0) { result = (result * 0x1000000162E42FFF0) >> 64; } if (x & 0x1000000000 > 0) { result = (result * 0x10000000B17217FBB) >> 64; } if (x & 0x800000000 > 0) { result = (result * 0x1000000058B90BFCE) >> 64; } if (x & 0x400000000 > 0) { result = (result * 0x100000002C5C85FE3) >> 64; } if (x & 0x200000000 > 0) { result = (result * 0x10000000162E42FF1) >> 64; } if (x & 0x100000000 > 0) { result = (result * 0x100000000B17217F8) >> 64; } } if (x & 0xFF000000 > 0) { if (x & 0x80000000 > 0) { result = (result * 0x10000000058B90BFC) >> 64; } if (x & 0x40000000 > 0) { result = (result * 0x1000000002C5C85FE) >> 64; } if (x & 0x20000000 > 0) { result = (result * 0x100000000162E42FF) >> 64; } if (x & 0x10000000 > 0) { result = (result * 0x1000000000B17217F) >> 64; } if (x & 0x8000000 > 0) { result = (result * 0x100000000058B90C0) >> 64; } if (x & 0x4000000 > 0) { result = (result * 0x10000000002C5C860) >> 64; } if (x & 0x2000000 > 0) { result = (result * 0x1000000000162E430) >> 64; } if (x & 0x1000000 > 0) { result = (result * 0x10000000000B17218) >> 64; } } if (x & 0xFF0000 > 0) { if (x & 0x800000 > 0) { result = (result * 0x1000000000058B90C) >> 64; } if (x & 0x400000 > 0) { result = (result * 0x100000000002C5C86) >> 64; } if (x & 0x200000 > 0) { result = (result * 0x10000000000162E43) >> 64; } if (x & 0x100000 > 0) { result = (result * 0x100000000000B1721) >> 64; } if (x & 0x80000 > 0) { result = (result * 0x10000000000058B91) >> 64; } if (x & 0x40000 > 0) { result = (result * 0x1000000000002C5C8) >> 64; } if (x & 0x20000 > 0) { result = (result * 0x100000000000162E4) >> 64; } if (x & 0x10000 > 0) { result = (result * 0x1000000000000B172) >> 64; } } if (x & 0xFF00 > 0) { if (x & 0x8000 > 0) { result = (result * 0x100000000000058B9) >> 64; } if (x & 0x4000 > 0) { result = (result * 0x10000000000002C5D) >> 64; } if (x & 0x2000 > 0) { result = (result * 0x1000000000000162E) >> 64; } if (x & 0x1000 > 0) { result = (result * 0x10000000000000B17) >> 64; } if (x & 0x800 > 0) { result = (result * 0x1000000000000058C) >> 64; } if (x & 0x400 > 0) { result = (result * 0x100000000000002C6) >> 64; } if (x & 0x200 > 0) { result = (result * 0x10000000000000163) >> 64; } if (x & 0x100 > 0) { result = (result * 0x100000000000000B1) >> 64; } } if (x & 0xFF > 0) { if (x & 0x80 > 0) { result = (result * 0x10000000000000059) >> 64; } if (x & 0x40 > 0) { result = (result * 0x1000000000000002C) >> 64; } if (x & 0x20 > 0) { result = (result * 0x10000000000000016) >> 64; } if (x & 0x10 > 0) { result = (result * 0x1000000000000000B) >> 64; } if (x & 0x8 > 0) { result = (result * 0x10000000000000006) >> 64; } if (x & 0x4 > 0) { result = (result * 0x10000000000000003) >> 64; } if (x & 0x2 > 0) { result = (result * 0x10000000000000001) >> 64; } if (x & 0x1 > 0) { result = (result * 0x10000000000000001) >> 64; } } // In the code snippet below, two operations are executed simultaneously: // // 1. The result is multiplied by $(2^n + 1)$, where $2^n$ represents the integer part, and the additional 1 // accounts for the initial guess of 0.5. This is achieved by subtracting from 191 instead of 192. // 2. The result is then converted to an unsigned 60.18-decimal fixed-point format. // // The underlying logic is based on the relationship $2^{191-ip} = 2^{ip} / 2^{191}$, where $ip$ denotes the, // integer part, $2^n$. result *= UNIT; result >>= (191 - (x >> 64)); } } /// @notice Finds the zero-based index of the first 1 in the binary representation of x. /// /// @dev See the note on "msb" in this Wikipedia article: https://en.wikipedia.org/wiki/Find_first_set /// /// Each step in this implementation is equivalent to this high-level code: /// /// ```solidity /// if (x >= 2 ** 128) { /// x >>= 128; /// result += 128; /// } /// ``` /// /// Where 128 is replaced with each respective power of two factor. See the full high-level implementation here: /// https://gist.github.com/PaulRBerg/f932f8693f2733e30c4d479e8e980948 /// /// The Yul instructions used below are: /// /// - "gt" is "greater than" /// - "or" is the OR bitwise operator /// - "shl" is "shift left" /// - "shr" is "shift right" /// /// @param x The uint256 number for which to find the index of the most significant bit. /// @return result The index of the most significant bit as a uint256. /// @custom:smtchecker abstract-function-nondet function msb(uint256 x) pure returns (uint256 result) { // 2^128 assembly ("memory-safe") { let factor := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^64 assembly ("memory-safe") { let factor := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^32 assembly ("memory-safe") { let factor := shl(5, gt(x, 0xFFFFFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^16 assembly ("memory-safe") { let factor := shl(4, gt(x, 0xFFFF)) x := shr(factor, x) result := or(result, factor) } // 2^8 assembly ("memory-safe") { let factor := shl(3, gt(x, 0xFF)) x := shr(factor, x) result := or(result, factor) } // 2^4 assembly ("memory-safe") { let factor := shl(2, gt(x, 0xF)) x := shr(factor, x) result := or(result, factor) } // 2^2 assembly ("memory-safe") { let factor := shl(1, gt(x, 0x3)) x := shr(factor, x) result := or(result, factor) } // 2^1 // No need to shift x any more. assembly ("memory-safe") { let factor := gt(x, 0x1) result := or(result, factor) } } /// @notice Calculates x*y÷denominator with 512-bit precision. /// /// @dev Credits to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv. /// /// Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - The denominator must not be zero. /// - The result must fit in uint256. /// /// @param x The multiplicand as a uint256. /// @param y The multiplier as a uint256. /// @param denominator The divisor as a uint256. /// @return result The result as a uint256. /// @custom:smtchecker abstract-function-nondet function mulDiv(uint256 x, uint256 y, uint256 denominator) pure returns (uint256 result) { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512-bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly ("memory-safe") { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { unchecked { return prod0 / denominator; } } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (prod1 >= denominator) { revert PRBMath_MulDiv_Overflow(x, y, denominator); } //////////////////////////////////////////////////////////////////////////// // 512 by 256 division //////////////////////////////////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly ("memory-safe") { // Compute remainder using the mulmod Yul instruction. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512-bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } unchecked { // Calculate the largest power of two divisor of the denominator using the unary operator ~. This operation cannot overflow // because the denominator cannot be zero at this point in the function execution. The result is always >= 1. // For more detail, see https://cs.stackexchange.com/q/138556/92363. uint256 lpotdod = denominator & (~denominator + 1); uint256 flippedLpotdod; assembly ("memory-safe") { // Factor powers of two out of denominator. denominator := div(denominator, lpotdod) // Divide [prod1 prod0] by lpotdod. prod0 := div(prod0, lpotdod) // Get the flipped value `2^256 / lpotdod`. If the `lpotdod` is zero, the flipped value is one. // `sub(0, lpotdod)` produces the two's complement version of `lpotdod`, which is equivalent to flipping all the bits. // However, `div` interprets this value as an unsigned value: https://ethereum.stackexchange.com/q/147168/24693 flippedLpotdod := add(div(sub(0, lpotdod), lpotdod), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * flippedLpotdod; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; } } /// @notice Calculates x*y÷1e18 with 512-bit precision. /// /// @dev A variant of {mulDiv} with constant folding, i.e. in which the denominator is hard coded to 1e18. /// /// Notes: /// - The body is purposely left uncommented; to understand how this works, see the documentation in {mulDiv}. /// - The result is rounded toward zero. /// - We take as an axiom that the result cannot be `MAX_UINT256` when x and y solve the following system of equations: /// /// $$ /// \begin{cases} /// x * y = MAX\_UINT256 * UNIT \\ /// (x * y) \% UNIT \geq \frac{UNIT}{2} /// \end{cases} /// $$ /// /// Requirements: /// - Refer to the requirements in {mulDiv}. /// - The result must fit in uint256. /// /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number. /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number. /// @return result The result as an unsigned 60.18-decimal fixed-point number. /// @custom:smtchecker abstract-function-nondet function mulDiv18(uint256 x, uint256 y) pure returns (uint256 result) { uint256 prod0; uint256 prod1; assembly ("memory-safe") { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } if (prod1 == 0) { unchecked { return prod0 / UNIT; } } if (prod1 >= UNIT) { revert PRBMath_MulDiv18_Overflow(x, y); } uint256 remainder; assembly ("memory-safe") { remainder := mulmod(x, y, UNIT) result := mul( or( div(sub(prod0, remainder), UNIT_LPOTD), mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1)) ), UNIT_INVERSE ) } } /// @notice Calculates x*y÷denominator with 512-bit precision. /// /// @dev This is an extension of {mulDiv} for signed numbers, which works by computing the signs and the absolute values separately. /// /// Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - Refer to the requirements in {mulDiv}. /// - None of the inputs can be `type(int256).min`. /// - The result must fit in int256. /// /// @param x The multiplicand as an int256. /// @param y The multiplier as an int256. /// @param denominator The divisor as an int256. /// @return result The result as an int256. /// @custom:smtchecker abstract-function-nondet function mulDivSigned(int256 x, int256 y, int256 denominator) pure returns (int256 result) { if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) { revert PRBMath_MulDivSigned_InputTooSmall(); } // Get hold of the absolute values of x, y and the denominator. uint256 xAbs; uint256 yAbs; uint256 dAbs; unchecked { xAbs = x < 0 ? uint256(-x) : uint256(x); yAbs = y < 0 ? uint256(-y) : uint256(y); dAbs = denominator < 0 ? uint256(-denominator) : uint256(denominator); } // Compute the absolute value of x*y÷denominator. The result must fit in int256. uint256 resultAbs = mulDiv(xAbs, yAbs, dAbs); if (resultAbs > uint256(type(int256).max)) { revert PRBMath_MulDivSigned_Overflow(x, y); } // Get the signs of x, y and the denominator. uint256 sx; uint256 sy; uint256 sd; assembly ("memory-safe") { // "sgt" is the "signed greater than" assembly instruction and "sub(0,1)" is -1 in two's complement. sx := sgt(x, sub(0, 1)) sy := sgt(y, sub(0, 1)) sd := sgt(denominator, sub(0, 1)) } // XOR over sx, sy and sd. What this does is to check whether there are 1 or 3 negative signs in the inputs. // If there are, the result should be negative. Otherwise, it should be positive. unchecked { result = sx ^ sy ^ sd == 0 ? -int256(resultAbs) : int256(resultAbs); } } /// @notice Calculates the square root of x using the Babylonian method. /// /// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. /// /// Notes: /// - If x is not a perfect square, the result is rounded down. /// - Credits to OpenZeppelin for the explanations in comments below. /// /// @param x The uint256 number for which to calculate the square root. /// @return result The result as a uint256. /// @custom:smtchecker abstract-function-nondet function sqrt(uint256 x) pure returns (uint256 result) { if (x == 0) { return 0; } // For our first guess, we calculate the biggest power of 2 which is smaller than the square root of x. // // We know that the "msb" (most significant bit) of x is a power of 2 such that we have: // // $$ // msb(x) <= x <= 2*msb(x)$ // $$ // // We write $msb(x)$ as $2^k$, and we get: // // $$ // k = log_2(x) // $$ // // Thus, we can write the initial inequality as: // // $$ // 2^{log_2(x)} <= x <= 2*2^{log_2(x)+1} \\ // sqrt(2^k) <= sqrt(x) < sqrt(2^{k+1}) \\ // 2^{k/2} <= sqrt(x) < 2^{(k+1)/2} <= 2^{(k/2)+1} // $$ // // Consequently, $2^{log_2(x) /2} is a good first approximation of sqrt(x) with at least one correct bit. uint256 xAux = uint256(x); result = 1; if (xAux >= 2 ** 128) { xAux >>= 128; result <<= 64; } if (xAux >= 2 ** 64) { xAux >>= 64; result <<= 32; } if (xAux >= 2 ** 32) { xAux >>= 32; result <<= 16; } if (xAux >= 2 ** 16) { xAux >>= 16; result <<= 8; } if (xAux >= 2 ** 8) { xAux >>= 8; result <<= 4; } if (xAux >= 2 ** 4) { xAux >>= 4; result <<= 2; } if (xAux >= 2 ** 2) { result <<= 1; } // At this point, `result` is an estimation with at least one bit of precision. We know the true value has at // most 128 bits, since it is the square root of a uint256. Newton's method converges quadratically (precision // doubles at every iteration). We thus need at most 7 iteration to turn our partial result with one bit of // precision into the expected uint128 result. unchecked { result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; result = (result + x / result) >> 1; // If x is not a perfect square, round the result toward zero. uint256 roundedResult = x / result; if (result >= roundedResult) { result = roundedResult; } } }
// SPDX-License-Identifier: MIT // 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 pragma solidity >=0.8.19; import { SD21x18 } from "./ValueType.sol"; /// @dev Euler's number as an SD21x18 number. SD21x18 constant E = SD21x18.wrap(2_718281828459045235); /// @dev The maximum value an SD21x18 number can have. int128 constant uMAX_SD21x18 = 170141183460469231731_687303715884105727; SD21x18 constant MAX_SD21x18 = SD21x18.wrap(uMAX_SD21x18); /// @dev The minimum value an SD21x18 number can have. int128 constant uMIN_SD21x18 = -170141183460469231731_687303715884105728; SD21x18 constant MIN_SD21x18 = SD21x18.wrap(uMIN_SD21x18); /// @dev PI as an SD21x18 number. SD21x18 constant PI = SD21x18.wrap(3_141592653589793238); /// @dev The unit number, which gives the decimal precision of SD21x18. SD21x18 constant UNIT = SD21x18.wrap(1e18); int128 constant uUNIT = 1e18;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Casting.sol" as Casting; /// @notice The signed 21.18-decimal fixed-point number representation, which can have up to 21 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 int128. This is useful when end users want to use int128 to save gas, e.g. with tight variable packing in contract /// storage. type SD21x18 is int128; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { Casting.intoSD59x18, Casting.intoUD60x18, Casting.intoUint128, Casting.intoUint256, Casting.intoUint40, Casting.unwrap } for SD21x18 global;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Casting.sol" as Casting; /// @notice The signed 1.18-decimal fixed-point number representation, which can have up to 1 digit and up to 18 /// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity /// type int64. This is useful when end users want to use int64 to save gas, e.g. with tight variable packing in contract /// storage. type SD1x18 is int64; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { Casting.intoSD59x18, Casting.intoUD60x18, Casting.intoUint128, Casting.intoUint256, Casting.intoUint40, Casting.unwrap } for SD1x18 global;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { SD1x18 } from "./ValueType.sol"; /// @dev Euler's number as an SD1x18 number. SD1x18 constant E = SD1x18.wrap(2_718281828459045235); /// @dev The maximum value an SD1x18 number can have. int64 constant uMAX_SD1x18 = 9_223372036854775807; SD1x18 constant MAX_SD1x18 = SD1x18.wrap(uMAX_SD1x18); /// @dev The minimum value an SD1x18 number can have. int64 constant uMIN_SD1x18 = -9_223372036854775808; SD1x18 constant MIN_SD1x18 = SD1x18.wrap(uMIN_SD1x18); /// @dev PI as an SD1x18 number. SD1x18 constant PI = SD1x18.wrap(3_141592653589793238); /// @dev The unit number, which gives the decimal precision of SD1x18. SD1x18 constant UNIT = SD1x18.wrap(1e18); int64 constant uUNIT = 1e18;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { UD2x18 } from "./ValueType.sol"; /// @dev Euler's number as a UD2x18 number. UD2x18 constant E = UD2x18.wrap(2_718281828459045235); /// @dev The maximum value a UD2x18 number can have. uint64 constant uMAX_UD2x18 = 18_446744073709551615; UD2x18 constant MAX_UD2x18 = UD2x18.wrap(uMAX_UD2x18); /// @dev PI as a UD2x18 number. UD2x18 constant PI = UD2x18.wrap(3_141592653589793238); /// @dev The unit number, which gives the decimal precision of UD2x18. UD2x18 constant UNIT = UD2x18.wrap(1e18); uint64 constant uUNIT = 1e18;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { SD59x18 } from "./ValueType.sol"; // NOTICE: the "u" prefix stands for "unwrapped". /// @dev Euler's number as an SD59x18 number. SD59x18 constant E = SD59x18.wrap(2_718281828459045235); /// @dev The maximum input permitted in {exp}. int256 constant uEXP_MAX_INPUT = 133_084258667509499440; SD59x18 constant EXP_MAX_INPUT = SD59x18.wrap(uEXP_MAX_INPUT); /// @dev Any value less than this returns 0 in {exp}. int256 constant uEXP_MIN_THRESHOLD = -41_446531673892822322; SD59x18 constant EXP_MIN_THRESHOLD = SD59x18.wrap(uEXP_MIN_THRESHOLD); /// @dev The maximum input permitted in {exp2}. int256 constant uEXP2_MAX_INPUT = 192e18 - 1; SD59x18 constant EXP2_MAX_INPUT = SD59x18.wrap(uEXP2_MAX_INPUT); /// @dev Any value less than this returns 0 in {exp2}. int256 constant uEXP2_MIN_THRESHOLD = -59_794705707972522261; SD59x18 constant EXP2_MIN_THRESHOLD = SD59x18.wrap(uEXP2_MIN_THRESHOLD); /// @dev Half the UNIT number. int256 constant uHALF_UNIT = 0.5e18; SD59x18 constant HALF_UNIT = SD59x18.wrap(uHALF_UNIT); /// @dev $log_2(10)$ as an SD59x18 number. int256 constant uLOG2_10 = 3_321928094887362347; SD59x18 constant LOG2_10 = SD59x18.wrap(uLOG2_10); /// @dev $log_2(e)$ as an SD59x18 number. int256 constant uLOG2_E = 1_442695040888963407; SD59x18 constant LOG2_E = SD59x18.wrap(uLOG2_E); /// @dev The maximum value an SD59x18 number can have. int256 constant uMAX_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_792003956564819967; SD59x18 constant MAX_SD59x18 = SD59x18.wrap(uMAX_SD59x18); /// @dev The maximum whole value an SD59x18 number can have. int256 constant uMAX_WHOLE_SD59x18 = 57896044618658097711785492504343953926634992332820282019728_000000000000000000; SD59x18 constant MAX_WHOLE_SD59x18 = SD59x18.wrap(uMAX_WHOLE_SD59x18); /// @dev The minimum value an SD59x18 number can have. int256 constant uMIN_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_792003956564819968; SD59x18 constant MIN_SD59x18 = SD59x18.wrap(uMIN_SD59x18); /// @dev The minimum whole value an SD59x18 number can have. int256 constant uMIN_WHOLE_SD59x18 = -57896044618658097711785492504343953926634992332820282019728_000000000000000000; SD59x18 constant MIN_WHOLE_SD59x18 = SD59x18.wrap(uMIN_WHOLE_SD59x18); /// @dev PI as an SD59x18 number. SD59x18 constant PI = SD59x18.wrap(3_141592653589793238); /// @dev The unit number, which gives the decimal precision of SD59x18. int256 constant uUNIT = 1e18; SD59x18 constant UNIT = SD59x18.wrap(1e18); /// @dev The unit number squared. int256 constant uUNIT_SQUARED = 1e36; SD59x18 constant UNIT_SQUARED = SD59x18.wrap(uUNIT_SQUARED); /// @dev Zero as an SD59x18 number. SD59x18 constant ZERO = SD59x18.wrap(0);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Casting.sol" as Casting; /// @notice The unsigned 2.18-decimal fixed-point number representation, which can have up to 2 digits and up to 18 /// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity /// type uint64. This is useful when end users want to use uint64 to save gas, e.g. with tight variable packing in contract /// storage. type UD2x18 is uint64; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { Casting.intoSD59x18, Casting.intoUD60x18, Casting.intoUint128, Casting.intoUint256, Casting.intoUint40, Casting.unwrap } for UD2x18 global;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Casting.sol" as Casting; import "./Helpers.sol" as Helpers; import "./Math.sol" as Math; /// @notice The signed 59.18-decimal fixed-point number representation, which can have up to 59 digits and up to 18 /// decimals. The values of this are bound by the minimum and the maximum values permitted by the underlying Solidity /// type int256. type SD59x18 is int256; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { Casting.intoInt256, Casting.intoSD1x18, Casting.intoSD21x18, Casting.intoUD2x18, Casting.intoUD21x18, Casting.intoUD60x18, Casting.intoUint256, Casting.intoUint128, Casting.intoUint40, Casting.unwrap } for SD59x18 global; /*////////////////////////////////////////////////////////////////////////// MATHEMATICAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ using { Math.abs, Math.avg, Math.ceil, Math.div, Math.exp, Math.exp2, Math.floor, Math.frac, Math.gm, Math.inv, Math.log10, Math.log2, Math.ln, Math.mul, Math.pow, Math.powu, Math.sqrt } for SD59x18 global; /*////////////////////////////////////////////////////////////////////////// HELPER FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ using { Helpers.add, Helpers.and, Helpers.eq, Helpers.gt, Helpers.gte, Helpers.isZero, Helpers.lshift, Helpers.lt, Helpers.lte, Helpers.mod, Helpers.neq, Helpers.not, Helpers.or, Helpers.rshift, Helpers.sub, Helpers.uncheckedAdd, Helpers.uncheckedSub, Helpers.uncheckedUnary, Helpers.xor } for SD59x18 global; /*////////////////////////////////////////////////////////////////////////// OPERATORS //////////////////////////////////////////////////////////////////////////*/ // The global "using for" directive makes it possible to use these operators on the SD59x18 type. using { Helpers.add as +, Helpers.and2 as &, Math.div as /, Helpers.eq as ==, Helpers.gt as >, Helpers.gte as >=, Helpers.lt as <, Helpers.lte as <=, Helpers.mod as %, Math.mul as *, Helpers.neq as !=, Helpers.not as ~, Helpers.or as |, Helpers.sub as -, Helpers.unary as -, Helpers.xor as ^ } for SD59x18 global;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { UD21x18 } from "./ValueType.sol"; /// @dev Euler's number as a UD21x18 number. UD21x18 constant E = UD21x18.wrap(2_718281828459045235); /// @dev The maximum value a UD21x18 number can have. uint128 constant uMAX_UD21x18 = 340282366920938463463_374607431768211455; UD21x18 constant MAX_UD21x18 = UD21x18.wrap(uMAX_UD21x18); /// @dev PI as a UD21x18 number. UD21x18 constant PI = UD21x18.wrap(3_141592653589793238); /// @dev The unit number, which gives the decimal precision of UD21x18. uint256 constant uUNIT = 1e18; UD21x18 constant UNIT = UD21x18.wrap(1e18);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Casting.sol" as Casting; /// @notice The unsigned 21.18-decimal fixed-point number representation, which can have up to 21 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 uint128. This is useful when end users want to use uint128 to save gas, e.g. with tight variable packing in contract /// storage. type UD21x18 is uint128; /*////////////////////////////////////////////////////////////////////////// CASTING //////////////////////////////////////////////////////////////////////////*/ using { Casting.intoSD59x18, Casting.intoUD60x18, Casting.intoUint128, Casting.intoUint256, Casting.intoUint40, Casting.unwrap } for UD21x18 global;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "../Common.sol" as Common; import "./Errors.sol" as CastingErrors; import { SD59x18 } from "../sd59x18/ValueType.sol"; import { UD60x18 } from "../ud60x18/ValueType.sol"; import { SD1x18 } from "./ValueType.sol"; /// @notice Casts an SD1x18 number into SD59x18. /// @dev There is no overflow check because SD1x18 ⊆ SD59x18. function intoSD59x18(SD1x18 x) pure returns (SD59x18 result) { result = SD59x18.wrap(int256(SD1x18.unwrap(x))); } /// @notice Casts an SD1x18 number into UD60x18. /// @dev Requirements: /// - x ≥ 0 function intoUD60x18(SD1x18 x) pure returns (UD60x18 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD1x18_ToUD60x18_Underflow(x); } result = UD60x18.wrap(uint64(xInt)); } /// @notice Casts an SD1x18 number into uint128. /// @dev Requirements: /// - x ≥ 0 function intoUint128(SD1x18 x) pure returns (uint128 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD1x18_ToUint128_Underflow(x); } result = uint128(uint64(xInt)); } /// @notice Casts an SD1x18 number into uint256. /// @dev Requirements: /// - x ≥ 0 function intoUint256(SD1x18 x) pure returns (uint256 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD1x18_ToUint256_Underflow(x); } result = uint256(uint64(xInt)); } /// @notice Casts an SD1x18 number into uint40. /// @dev Requirements: /// - x ≥ 0 /// - x ≤ MAX_UINT40 function intoUint40(SD1x18 x) pure returns (uint40 result) { int64 xInt = SD1x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD1x18_ToUint40_Underflow(x); } if (xInt > int64(uint64(Common.MAX_UINT40))) { revert CastingErrors.PRBMath_SD1x18_ToUint40_Overflow(x); } result = uint40(uint64(xInt)); } /// @notice Alias for {wrap}. function sd1x18(int64 x) pure returns (SD1x18 result) { result = SD1x18.wrap(x); } /// @notice Unwraps an SD1x18 number into int64. function unwrap(SD1x18 x) pure returns (int64 result) { result = SD1x18.unwrap(x); } /// @notice Wraps an int64 number into SD1x18. function wrap(int64 x) pure returns (SD1x18 result) { result = SD1x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "../Common.sol" as Common; import "./Errors.sol" as CastingErrors; import { SD59x18 } from "../sd59x18/ValueType.sol"; import { UD60x18 } from "../ud60x18/ValueType.sol"; import { SD21x18 } from "./ValueType.sol"; /// @notice Casts an SD21x18 number into SD59x18. /// @dev There is no overflow check because SD21x18 ⊆ SD59x18. function intoSD59x18(SD21x18 x) pure returns (SD59x18 result) { result = SD59x18.wrap(int256(SD21x18.unwrap(x))); } /// @notice Casts an SD21x18 number into UD60x18. /// @dev Requirements: /// - x ≥ 0 function intoUD60x18(SD21x18 x) pure returns (UD60x18 result) { int128 xInt = SD21x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD21x18_ToUD60x18_Underflow(x); } result = UD60x18.wrap(uint128(xInt)); } /// @notice Casts an SD21x18 number into uint128. /// @dev Requirements: /// - x ≥ 0 function intoUint128(SD21x18 x) pure returns (uint128 result) { int128 xInt = SD21x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD21x18_ToUint128_Underflow(x); } result = uint128(xInt); } /// @notice Casts an SD21x18 number into uint256. /// @dev Requirements: /// - x ≥ 0 function intoUint256(SD21x18 x) pure returns (uint256 result) { int128 xInt = SD21x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD21x18_ToUint256_Underflow(x); } result = uint256(uint128(xInt)); } /// @notice Casts an SD21x18 number into uint40. /// @dev Requirements: /// - x ≥ 0 /// - x ≤ MAX_UINT40 function intoUint40(SD21x18 x) pure returns (uint40 result) { int128 xInt = SD21x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD21x18_ToUint40_Underflow(x); } if (xInt > int128(uint128(Common.MAX_UINT40))) { revert CastingErrors.PRBMath_SD21x18_ToUint40_Overflow(x); } result = uint40(uint128(xInt)); } /// @notice Alias for {wrap}. function sd21x18(int128 x) pure returns (SD21x18 result) { result = SD21x18.wrap(x); } /// @notice Unwraps an SD21x18 number into int128. function unwrap(SD21x18 x) pure returns (int128 result) { result = SD21x18.unwrap(x); } /// @notice Wraps an int128 number into SD21x18. function wrap(int128 x) pure returns (SD21x18 result) { result = SD21x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { wrap } from "./Casting.sol"; import { SD59x18 } from "./ValueType.sol"; /// @notice Implements the checked addition operation (+) in the SD59x18 type. function add(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { return wrap(x.unwrap() + y.unwrap()); } /// @notice Implements the AND (&) bitwise operation in the SD59x18 type. function and(SD59x18 x, int256 bits) pure returns (SD59x18 result) { return wrap(x.unwrap() & bits); } /// @notice Implements the AND (&) bitwise operation in the SD59x18 type. function and2(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { return wrap(x.unwrap() & y.unwrap()); } /// @notice Implements the equal (=) operation in the SD59x18 type. function eq(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() == y.unwrap(); } /// @notice Implements the greater than operation (>) in the SD59x18 type. function gt(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() > y.unwrap(); } /// @notice Implements the greater than or equal to operation (>=) in the SD59x18 type. function gte(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() >= y.unwrap(); } /// @notice Implements a zero comparison check function in the SD59x18 type. function isZero(SD59x18 x) pure returns (bool result) { result = x.unwrap() == 0; } /// @notice Implements the left shift operation (<<) in the SD59x18 type. function lshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) { result = wrap(x.unwrap() << bits); } /// @notice Implements the lower than operation (<) in the SD59x18 type. function lt(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() < y.unwrap(); } /// @notice Implements the lower than or equal to operation (<=) in the SD59x18 type. function lte(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() <= y.unwrap(); } /// @notice Implements the unchecked modulo operation (%) in the SD59x18 type. function mod(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(x.unwrap() % y.unwrap()); } /// @notice Implements the not equal operation (!=) in the SD59x18 type. function neq(SD59x18 x, SD59x18 y) pure returns (bool result) { result = x.unwrap() != y.unwrap(); } /// @notice Implements the NOT (~) bitwise operation in the SD59x18 type. function not(SD59x18 x) pure returns (SD59x18 result) { result = wrap(~x.unwrap()); } /// @notice Implements the OR (|) bitwise operation in the SD59x18 type. function or(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(x.unwrap() | y.unwrap()); } /// @notice Implements the right shift operation (>>) in the SD59x18 type. function rshift(SD59x18 x, uint256 bits) pure returns (SD59x18 result) { result = wrap(x.unwrap() >> bits); } /// @notice Implements the checked subtraction operation (-) in the SD59x18 type. function sub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(x.unwrap() - y.unwrap()); } /// @notice Implements the checked unary minus operation (-) in the SD59x18 type. function unary(SD59x18 x) pure returns (SD59x18 result) { result = wrap(-x.unwrap()); } /// @notice Implements the unchecked addition operation (+) in the SD59x18 type. function uncheckedAdd(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { unchecked { result = wrap(x.unwrap() + y.unwrap()); } } /// @notice Implements the unchecked subtraction operation (-) in the SD59x18 type. function uncheckedSub(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { unchecked { result = wrap(x.unwrap() - y.unwrap()); } } /// @notice Implements the unchecked unary minus operation (-) in the SD59x18 type. function uncheckedUnary(SD59x18 x) pure returns (SD59x18 result) { unchecked { result = wrap(-x.unwrap()); } } /// @notice Implements the XOR (^) bitwise operation in the SD59x18 type. function xor(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { result = wrap(x.unwrap() ^ y.unwrap()); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "./Errors.sol" as CastingErrors; import { MAX_UINT128, MAX_UINT40 } from "../Common.sol"; import { uMAX_SD1x18, uMIN_SD1x18 } from "../sd1x18/Constants.sol"; import { SD1x18 } from "../sd1x18/ValueType.sol"; import { uMAX_SD21x18, uMIN_SD21x18 } from "../sd21x18/Constants.sol"; import { SD21x18 } from "../sd21x18/ValueType.sol"; import { uMAX_UD2x18 } from "../ud2x18/Constants.sol"; import { UD2x18 } from "../ud2x18/ValueType.sol"; import { uMAX_UD21x18 } from "../ud21x18/Constants.sol"; import { UD21x18 } from "../ud21x18/ValueType.sol"; import { UD60x18 } from "../ud60x18/ValueType.sol"; import { SD59x18 } from "./ValueType.sol"; /// @notice Casts an SD59x18 number into int256. /// @dev This is basically a functional alias for {unwrap}. function intoInt256(SD59x18 x) pure returns (int256 result) { result = SD59x18.unwrap(x); } /// @notice Casts an SD59x18 number into SD1x18. /// @dev Requirements: /// - x ≥ uMIN_SD1x18 /// - x ≤ uMAX_SD1x18 function intoSD1x18(SD59x18 x) pure returns (SD1x18 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < uMIN_SD1x18) { revert CastingErrors.PRBMath_SD59x18_IntoSD1x18_Underflow(x); } if (xInt > uMAX_SD1x18) { revert CastingErrors.PRBMath_SD59x18_IntoSD1x18_Overflow(x); } result = SD1x18.wrap(int64(xInt)); } /// @notice Casts an SD59x18 number into SD21x18. /// @dev Requirements: /// - x ≥ uMIN_SD21x18 /// - x ≤ uMAX_SD21x18 function intoSD21x18(SD59x18 x) pure returns (SD21x18 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < uMIN_SD21x18) { revert CastingErrors.PRBMath_SD59x18_IntoSD21x18_Underflow(x); } if (xInt > uMAX_SD21x18) { revert CastingErrors.PRBMath_SD59x18_IntoSD21x18_Overflow(x); } result = SD21x18.wrap(int128(xInt)); } /// @notice Casts an SD59x18 number into UD2x18. /// @dev Requirements: /// - x ≥ 0 /// - x ≤ uMAX_UD2x18 function intoUD2x18(SD59x18 x) pure returns (UD2x18 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD59x18_IntoUD2x18_Underflow(x); } if (xInt > int256(uint256(uMAX_UD2x18))) { revert CastingErrors.PRBMath_SD59x18_IntoUD2x18_Overflow(x); } result = UD2x18.wrap(uint64(uint256(xInt))); } /// @notice Casts an SD59x18 number into UD21x18. /// @dev Requirements: /// - x ≥ 0 /// - x ≤ uMAX_UD21x18 function intoUD21x18(SD59x18 x) pure returns (UD21x18 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD59x18_IntoUD21x18_Underflow(x); } if (xInt > int256(uint256(uMAX_UD21x18))) { revert CastingErrors.PRBMath_SD59x18_IntoUD21x18_Overflow(x); } result = UD21x18.wrap(uint128(uint256(xInt))); } /// @notice Casts an SD59x18 number into UD60x18. /// @dev Requirements: /// - x ≥ 0 function intoUD60x18(SD59x18 x) pure returns (UD60x18 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD59x18_IntoUD60x18_Underflow(x); } result = UD60x18.wrap(uint256(xInt)); } /// @notice Casts an SD59x18 number into uint256. /// @dev Requirements: /// - x ≥ 0 function intoUint256(SD59x18 x) pure returns (uint256 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD59x18_IntoUint256_Underflow(x); } result = uint256(xInt); } /// @notice Casts an SD59x18 number into uint128. /// @dev Requirements: /// - x ≥ 0 /// - x ≤ uMAX_UINT128 function intoUint128(SD59x18 x) pure returns (uint128 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD59x18_IntoUint128_Underflow(x); } if (xInt > int256(uint256(MAX_UINT128))) { revert CastingErrors.PRBMath_SD59x18_IntoUint128_Overflow(x); } result = uint128(uint256(xInt)); } /// @notice Casts an SD59x18 number into uint40. /// @dev Requirements: /// - x ≥ 0 /// - x ≤ MAX_UINT40 function intoUint40(SD59x18 x) pure returns (uint40 result) { int256 xInt = SD59x18.unwrap(x); if (xInt < 0) { revert CastingErrors.PRBMath_SD59x18_IntoUint40_Underflow(x); } if (xInt > int256(uint256(MAX_UINT40))) { revert CastingErrors.PRBMath_SD59x18_IntoUint40_Overflow(x); } result = uint40(uint256(xInt)); } /// @notice Alias for {wrap}. function sd(int256 x) pure returns (SD59x18 result) { result = SD59x18.wrap(x); } /// @notice Alias for {wrap}. function sd59x18(int256 x) pure returns (SD59x18 result) { result = SD59x18.wrap(x); } /// @notice Unwraps an SD59x18 number into int256. function unwrap(SD59x18 x) pure returns (int256 result) { result = SD59x18.unwrap(x); } /// @notice Wraps an int256 number into SD59x18. function wrap(int256 x) pure returns (SD59x18 result) { result = SD59x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "../Common.sol" as Common; import "./Errors.sol" as Errors; import { SD59x18 } from "../sd59x18/ValueType.sol"; import { UD60x18 } from "../ud60x18/ValueType.sol"; import { UD2x18 } from "./ValueType.sol"; /// @notice Casts a UD2x18 number into SD59x18. /// @dev There is no overflow check because UD2x18 ⊆ SD59x18. function intoSD59x18(UD2x18 x) pure returns (SD59x18 result) { result = SD59x18.wrap(int256(uint256(UD2x18.unwrap(x)))); } /// @notice Casts a UD2x18 number into UD60x18. /// @dev There is no overflow check because UD2x18 ⊆ UD60x18. function intoUD60x18(UD2x18 x) pure returns (UD60x18 result) { result = UD60x18.wrap(UD2x18.unwrap(x)); } /// @notice Casts a UD2x18 number into uint128. /// @dev There is no overflow check because UD2x18 ⊆ uint128. function intoUint128(UD2x18 x) pure returns (uint128 result) { result = uint128(UD2x18.unwrap(x)); } /// @notice Casts a UD2x18 number into uint256. /// @dev There is no overflow check because UD2x18 ⊆ uint256. function intoUint256(UD2x18 x) pure returns (uint256 result) { result = uint256(UD2x18.unwrap(x)); } /// @notice Casts a UD2x18 number into uint40. /// @dev Requirements: /// - x ≤ MAX_UINT40 function intoUint40(UD2x18 x) pure returns (uint40 result) { uint64 xUint = UD2x18.unwrap(x); if (xUint > uint64(Common.MAX_UINT40)) { revert Errors.PRBMath_UD2x18_IntoUint40_Overflow(x); } result = uint40(xUint); } /// @notice Alias for {wrap}. function ud2x18(uint64 x) pure returns (UD2x18 result) { result = UD2x18.wrap(x); } /// @notice Unwrap a UD2x18 number into uint64. function unwrap(UD2x18 x) pure returns (uint64 result) { result = UD2x18.unwrap(x); } /// @notice Wraps a uint64 number into UD2x18. function wrap(uint64 x) pure returns (UD2x18 result) { result = UD2x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "../Common.sol" as Common; import "./Errors.sol" as Errors; import { uEXP_MAX_INPUT, uEXP2_MAX_INPUT, uEXP_MIN_THRESHOLD, uEXP2_MIN_THRESHOLD, uHALF_UNIT, uLOG2_10, uLOG2_E, uMAX_SD59x18, uMAX_WHOLE_SD59x18, uMIN_SD59x18, uMIN_WHOLE_SD59x18, UNIT, uUNIT, uUNIT_SQUARED, ZERO } from "./Constants.sol"; import { wrap } from "./Helpers.sol"; import { SD59x18 } from "./ValueType.sol"; /// @notice Calculates the absolute value of x. /// /// @dev Requirements: /// - x > MIN_SD59x18. /// /// @param x The SD59x18 number for which to calculate the absolute value. /// @return result The absolute value of x as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function abs(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt == uMIN_SD59x18) { revert Errors.PRBMath_SD59x18_Abs_MinSD59x18(); } result = xInt < 0 ? wrap(-xInt) : x; } /// @notice Calculates the arithmetic average of x and y. /// /// @dev Notes: /// - The result is rounded toward zero. /// /// @param x The first operand as an SD59x18 number. /// @param y The second operand as an SD59x18 number. /// @return result The arithmetic average as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function avg(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); int256 yInt = y.unwrap(); unchecked { // This operation is equivalent to `x / 2 + y / 2`, and it can never overflow. int256 sum = (xInt >> 1) + (yInt >> 1); if (sum < 0) { // If at least one of x and y is odd, add 1 to the result, because shifting negative numbers to the right // rounds toward negative infinity. The right part is equivalent to `sum + (x % 2 == 1 || y % 2 == 1)`. assembly ("memory-safe") { result := add(sum, and(or(xInt, yInt), 1)) } } else { // Add 1 if both x and y are odd to account for the double 0.5 remainder truncated after shifting. result = wrap(sum + (xInt & yInt & 1)); } } } /// @notice Yields the smallest whole number greater than or equal to x. /// /// @dev Optimized for fractional value inputs, because every whole value has (1e18 - 1) fractional counterparts. /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// /// Requirements: /// - x ≤ MAX_WHOLE_SD59x18 /// /// @param x The SD59x18 number to ceil. /// @return result The smallest whole number greater than or equal to x, as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function ceil(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt > uMAX_WHOLE_SD59x18) { revert Errors.PRBMath_SD59x18_Ceil_Overflow(x); } int256 remainder = xInt % uUNIT; if (remainder == 0) { result = x; } else { unchecked { // Solidity uses C fmod style, which returns a modulus with the same sign as x. int256 resultInt = xInt - remainder; if (xInt > 0) { resultInt += uUNIT; } result = wrap(resultInt); } } } /// @notice Divides two SD59x18 numbers, returning a new SD59x18 number. /// /// @dev This is an extension of {Common.mulDiv} for signed numbers, which works by computing the signs and the absolute /// values separately. /// /// Notes: /// - Refer to the notes in {Common.mulDiv}. /// - The result is rounded toward zero. /// /// Requirements: /// - Refer to the requirements in {Common.mulDiv}. /// - None of the inputs can be `MIN_SD59x18`. /// - The denominator must not be zero. /// - The result must fit in SD59x18. /// /// @param x The numerator as an SD59x18 number. /// @param y The denominator as an SD59x18 number. /// @return result The quotient as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function div(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); int256 yInt = y.unwrap(); if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) { revert Errors.PRBMath_SD59x18_Div_InputTooSmall(); } // Get hold of the absolute values of x and y. uint256 xAbs; uint256 yAbs; unchecked { xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt); yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt); } // Compute the absolute value (x*UNIT÷y). The resulting value must fit in SD59x18. uint256 resultAbs = Common.mulDiv(xAbs, uint256(uUNIT), yAbs); if (resultAbs > uint256(uMAX_SD59x18)) { revert Errors.PRBMath_SD59x18_Div_Overflow(x, y); } // Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for // negative, 0 for positive or zero). bool sameSign = (xInt ^ yInt) > -1; // If the inputs have the same sign, the result should be positive. Otherwise, it should be negative. unchecked { result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs)); } } /// @notice Calculates the natural exponent of x using the following formula: /// /// $$ /// e^x = 2^{x * log_2{e}} /// $$ /// /// @dev Notes: /// - Refer to the notes in {exp2}. /// /// Requirements: /// - Refer to the requirements in {exp2}. /// - x < 133_084258667509499441. /// /// @param x The exponent as an SD59x18 number. /// @return result The result as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function exp(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); // Any input less than the threshold returns zero. // This check also prevents an overflow for very small numbers. if (xInt < uEXP_MIN_THRESHOLD) { return ZERO; } // This check prevents values greater than 192e18 from being passed to {exp2}. if (xInt > uEXP_MAX_INPUT) { revert Errors.PRBMath_SD59x18_Exp_InputTooBig(x); } unchecked { // Inline the fixed-point multiplication to save gas. int256 doubleUnitProduct = xInt * uLOG2_E; result = exp2(wrap(doubleUnitProduct / uUNIT)); } } /// @notice Calculates the binary exponent of x using the binary fraction method using the following formula: /// /// $$ /// 2^{-x} = \frac{1}{2^x} /// $$ /// /// @dev See https://ethereum.stackexchange.com/q/79903/24693. /// /// Notes: /// - If x < -59_794705707972522261, the result is zero. /// /// Requirements: /// - x < 192e18. /// - The result must fit in SD59x18. /// /// @param x The exponent as an SD59x18 number. /// @return result The result as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function exp2(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt < 0) { // The inverse of any number less than the threshold is truncated to zero. if (xInt < uEXP2_MIN_THRESHOLD) { return ZERO; } unchecked { // Inline the fixed-point inversion to save gas. result = wrap(uUNIT_SQUARED / exp2(wrap(-xInt)).unwrap()); } } else { // Numbers greater than or equal to 192e18 don't fit in the 192.64-bit format. if (xInt > uEXP2_MAX_INPUT) { revert Errors.PRBMath_SD59x18_Exp2_InputTooBig(x); } unchecked { // Convert x to the 192.64-bit fixed-point format. uint256 x_192x64 = uint256((xInt << 64) / uUNIT); // It is safe to cast the result to int256 due to the checks above. result = wrap(int256(Common.exp2(x_192x64))); } } } /// @notice Yields the greatest whole number less than or equal to x. /// /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional /// counterparts. See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. /// /// Requirements: /// - x ≥ MIN_WHOLE_SD59x18 /// /// @param x The SD59x18 number to floor. /// @return result The greatest whole number less than or equal to x, as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function floor(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt < uMIN_WHOLE_SD59x18) { revert Errors.PRBMath_SD59x18_Floor_Underflow(x); } int256 remainder = xInt % uUNIT; if (remainder == 0) { result = x; } else { unchecked { // Solidity uses C fmod style, which returns a modulus with the same sign as x. int256 resultInt = xInt - remainder; if (xInt < 0) { resultInt -= uUNIT; } result = wrap(resultInt); } } } /// @notice Yields the excess beyond the floor of x for positive numbers and the part of the number to the right. /// of the radix point for negative numbers. /// @dev Based on the odd function definition. https://en.wikipedia.org/wiki/Fractional_part /// @param x The SD59x18 number to get the fractional part of. /// @return result The fractional part of x as an SD59x18 number. function frac(SD59x18 x) pure returns (SD59x18 result) { result = wrap(x.unwrap() % uUNIT); } /// @notice Calculates the geometric mean of x and y, i.e. $\sqrt{x * y}$. /// /// @dev Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - x * y must fit in SD59x18. /// - x * y must not be negative, since complex numbers are not supported. /// /// @param x The first operand as an SD59x18 number. /// @param y The second operand as an SD59x18 number. /// @return result The result as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function gm(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); int256 yInt = y.unwrap(); if (xInt == 0 || yInt == 0) { return ZERO; } unchecked { // Equivalent to `xy / x != y`. Checking for overflow this way is faster than letting Solidity do it. int256 xyInt = xInt * yInt; if (xyInt / xInt != yInt) { revert Errors.PRBMath_SD59x18_Gm_Overflow(x, y); } // The product must not be negative, since complex numbers are not supported. if (xyInt < 0) { revert Errors.PRBMath_SD59x18_Gm_NegativeProduct(x, y); } // We don't need to multiply the result by `UNIT` here because the x*y product picked up a factor of `UNIT` // during multiplication. See the comments in {Common.sqrt}. uint256 resultUint = Common.sqrt(uint256(xyInt)); result = wrap(int256(resultUint)); } } /// @notice Calculates the inverse of x. /// /// @dev Notes: /// - The result is rounded toward zero. /// /// Requirements: /// - x must not be zero. /// /// @param x The SD59x18 number for which to calculate the inverse. /// @return result The inverse as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function inv(SD59x18 x) pure returns (SD59x18 result) { result = wrap(uUNIT_SQUARED / x.unwrap()); } /// @notice Calculates the natural logarithm of x using the following formula: /// /// $$ /// ln{x} = log_2{x} / log_2{e} /// $$ /// /// @dev Notes: /// - Refer to the notes in {log2}. /// - The precision isn't sufficiently fine-grained to return exactly `UNIT` when the input is `E`. /// /// Requirements: /// - Refer to the requirements in {log2}. /// /// @param x The SD59x18 number for which to calculate the natural logarithm. /// @return result The natural logarithm as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function ln(SD59x18 x) pure returns (SD59x18 result) { // Inline the fixed-point multiplication to save gas. This is overflow-safe because the maximum value that // {log2} can return is ~195_205294292027477728. result = wrap(log2(x).unwrap() * uUNIT / uLOG2_E); } /// @notice Calculates the common logarithm of x using the following formula: /// /// $$ /// log_{10}{x} = log_2{x} / log_2{10} /// $$ /// /// However, if x is an exact power of ten, a hard coded value is returned. /// /// @dev Notes: /// - Refer to the notes in {log2}. /// /// Requirements: /// - Refer to the requirements in {log2}. /// /// @param x The SD59x18 number for which to calculate the common logarithm. /// @return result The common logarithm as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function log10(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt < 0) { revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x); } // Note that the `mul` in this block is the standard multiplication operation, not {SD59x18.mul}. // prettier-ignore assembly ("memory-safe") { switch x case 1 { result := mul(uUNIT, sub(0, 18)) } case 10 { result := mul(uUNIT, sub(1, 18)) } case 100 { result := mul(uUNIT, sub(2, 18)) } case 1000 { result := mul(uUNIT, sub(3, 18)) } case 10000 { result := mul(uUNIT, sub(4, 18)) } case 100000 { result := mul(uUNIT, sub(5, 18)) } case 1000000 { result := mul(uUNIT, sub(6, 18)) } case 10000000 { result := mul(uUNIT, sub(7, 18)) } case 100000000 { result := mul(uUNIT, sub(8, 18)) } case 1000000000 { result := mul(uUNIT, sub(9, 18)) } case 10000000000 { result := mul(uUNIT, sub(10, 18)) } case 100000000000 { result := mul(uUNIT, sub(11, 18)) } case 1000000000000 { result := mul(uUNIT, sub(12, 18)) } case 10000000000000 { result := mul(uUNIT, sub(13, 18)) } case 100000000000000 { result := mul(uUNIT, sub(14, 18)) } case 1000000000000000 { result := mul(uUNIT, sub(15, 18)) } case 10000000000000000 { result := mul(uUNIT, sub(16, 18)) } case 100000000000000000 { result := mul(uUNIT, sub(17, 18)) } case 1000000000000000000 { result := 0 } case 10000000000000000000 { result := uUNIT } case 100000000000000000000 { result := mul(uUNIT, 2) } case 1000000000000000000000 { result := mul(uUNIT, 3) } case 10000000000000000000000 { result := mul(uUNIT, 4) } case 100000000000000000000000 { result := mul(uUNIT, 5) } case 1000000000000000000000000 { result := mul(uUNIT, 6) } case 10000000000000000000000000 { result := mul(uUNIT, 7) } case 100000000000000000000000000 { result := mul(uUNIT, 8) } case 1000000000000000000000000000 { result := mul(uUNIT, 9) } case 10000000000000000000000000000 { result := mul(uUNIT, 10) } case 100000000000000000000000000000 { result := mul(uUNIT, 11) } case 1000000000000000000000000000000 { result := mul(uUNIT, 12) } case 10000000000000000000000000000000 { result := mul(uUNIT, 13) } case 100000000000000000000000000000000 { result := mul(uUNIT, 14) } case 1000000000000000000000000000000000 { result := mul(uUNIT, 15) } case 10000000000000000000000000000000000 { result := mul(uUNIT, 16) } case 100000000000000000000000000000000000 { result := mul(uUNIT, 17) } case 1000000000000000000000000000000000000 { result := mul(uUNIT, 18) } case 10000000000000000000000000000000000000 { result := mul(uUNIT, 19) } case 100000000000000000000000000000000000000 { result := mul(uUNIT, 20) } case 1000000000000000000000000000000000000000 { result := mul(uUNIT, 21) } case 10000000000000000000000000000000000000000 { result := mul(uUNIT, 22) } case 100000000000000000000000000000000000000000 { result := mul(uUNIT, 23) } case 1000000000000000000000000000000000000000000 { result := mul(uUNIT, 24) } case 10000000000000000000000000000000000000000000 { result := mul(uUNIT, 25) } case 100000000000000000000000000000000000000000000 { result := mul(uUNIT, 26) } case 1000000000000000000000000000000000000000000000 { result := mul(uUNIT, 27) } case 10000000000000000000000000000000000000000000000 { result := mul(uUNIT, 28) } case 100000000000000000000000000000000000000000000000 { result := mul(uUNIT, 29) } case 1000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 30) } case 10000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 31) } case 100000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 32) } case 1000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 33) } case 10000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 34) } case 100000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 35) } case 1000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 36) } case 10000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 37) } case 100000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 38) } case 1000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 39) } case 10000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 40) } case 100000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 41) } case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 42) } case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 43) } case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 44) } case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 45) } case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 46) } case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 47) } case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 48) } case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 49) } case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 50) } case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 51) } case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 52) } case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 53) } case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 54) } case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 55) } case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 56) } case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 57) } case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(uUNIT, 58) } default { result := uMAX_SD59x18 } } if (result.unwrap() == uMAX_SD59x18) { unchecked { // Inline the fixed-point division to save gas. result = wrap(log2(x).unwrap() * uUNIT / uLOG2_10); } } } /// @notice Calculates the binary logarithm of x using the iterative approximation algorithm: /// /// $$ /// log_2{x} = n + log_2{y}, \text{ where } y = x*2^{-n}, \ y \in [1, 2) /// $$ /// /// For $0 \leq x \lt 1$, the input is inverted: /// /// $$ /// log_2{x} = -log_2{\frac{1}{x}} /// $$ /// /// @dev See https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation. /// /// Notes: /// - Due to the lossy precision of the iterative approximation, the results are not perfectly accurate to the last decimal. /// /// Requirements: /// - x > 0 /// /// @param x The SD59x18 number for which to calculate the binary logarithm. /// @return result The binary logarithm as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function log2(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt <= 0) { revert Errors.PRBMath_SD59x18_Log_InputTooSmall(x); } unchecked { int256 sign; if (xInt >= uUNIT) { sign = 1; } else { sign = -1; // Inline the fixed-point inversion to save gas. xInt = uUNIT_SQUARED / xInt; } // Calculate the integer part of the logarithm. uint256 n = Common.msb(uint256(xInt / uUNIT)); // This is the integer part of the logarithm as an SD59x18 number. The operation can't overflow // because n is at most 255, `UNIT` is 1e18, and the sign is either 1 or -1. int256 resultInt = int256(n) * uUNIT; // Calculate $y = x * 2^{-n}$. int256 y = xInt >> n; // If y is the unit number, the fractional part is zero. if (y == uUNIT) { return wrap(resultInt * sign); } // Calculate the fractional part via the iterative approximation. // The `delta >>= 1` part is equivalent to `delta /= 2`, but shifting bits is more gas efficient. int256 DOUBLE_UNIT = 2e18; for (int256 delta = uHALF_UNIT; delta > 0; delta >>= 1) { y = (y * y) / uUNIT; // Is y^2 >= 2e18 and so in the range [2e18, 4e18)? if (y >= DOUBLE_UNIT) { // Add the 2^{-m} factor to the logarithm. resultInt = resultInt + delta; // Halve y, which corresponds to z/2 in the Wikipedia article. y >>= 1; } } resultInt *= sign; result = wrap(resultInt); } } /// @notice Multiplies two SD59x18 numbers together, returning a new SD59x18 number. /// /// @dev Notes: /// - Refer to the notes in {Common.mulDiv18}. /// /// Requirements: /// - Refer to the requirements in {Common.mulDiv18}. /// - None of the inputs can be `MIN_SD59x18`. /// - The result must fit in SD59x18. /// /// @param x The multiplicand as an SD59x18 number. /// @param y The multiplier as an SD59x18 number. /// @return result The product as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function mul(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); int256 yInt = y.unwrap(); if (xInt == uMIN_SD59x18 || yInt == uMIN_SD59x18) { revert Errors.PRBMath_SD59x18_Mul_InputTooSmall(); } // Get hold of the absolute values of x and y. uint256 xAbs; uint256 yAbs; unchecked { xAbs = xInt < 0 ? uint256(-xInt) : uint256(xInt); yAbs = yInt < 0 ? uint256(-yInt) : uint256(yInt); } // Compute the absolute value (x*y÷UNIT). The resulting value must fit in SD59x18. uint256 resultAbs = Common.mulDiv18(xAbs, yAbs); if (resultAbs > uint256(uMAX_SD59x18)) { revert Errors.PRBMath_SD59x18_Mul_Overflow(x, y); } // Check if x and y have the same sign using two's complement representation. The left-most bit represents the sign (1 for // negative, 0 for positive or zero). bool sameSign = (xInt ^ yInt) > -1; // If the inputs have the same sign, the result should be positive. Otherwise, it should be negative. unchecked { result = wrap(sameSign ? int256(resultAbs) : -int256(resultAbs)); } } /// @notice Raises x to the power of y using the following formula: /// /// $$ /// x^y = 2^{log_2{x} * y} /// $$ /// /// @dev Notes: /// - Refer to the notes in {exp2}, {log2}, and {mul}. /// - Returns `UNIT` for 0^0. /// /// Requirements: /// - Refer to the requirements in {exp2}, {log2}, and {mul}. /// /// @param x The base as an SD59x18 number. /// @param y Exponent to raise x to, as an SD59x18 number /// @return result x raised to power y, as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function pow(SD59x18 x, SD59x18 y) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); int256 yInt = y.unwrap(); // If both x and y are zero, the result is `UNIT`. If just x is zero, the result is always zero. if (xInt == 0) { return yInt == 0 ? UNIT : ZERO; } // If x is `UNIT`, the result is always `UNIT`. else if (xInt == uUNIT) { return UNIT; } // If y is zero, the result is always `UNIT`. if (yInt == 0) { return UNIT; } // If y is `UNIT`, the result is always x. else if (yInt == uUNIT) { return x; } // Calculate the result using the formula. result = exp2(mul(log2(x), y)); } /// @notice Raises x (an SD59x18 number) to the power y (an unsigned basic integer) using the well-known /// algorithm "exponentiation by squaring". /// /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring. /// /// Notes: /// - Refer to the notes in {Common.mulDiv18}. /// - Returns `UNIT` for 0^0. /// /// Requirements: /// - Refer to the requirements in {abs} and {Common.mulDiv18}. /// - The result must fit in SD59x18. /// /// @param x The base as an SD59x18 number. /// @param y The exponent as a uint256. /// @return result The result as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function powu(SD59x18 x, uint256 y) pure returns (SD59x18 result) { uint256 xAbs = uint256(abs(x).unwrap()); // Calculate the first iteration of the loop in advance. uint256 resultAbs = y & 1 > 0 ? xAbs : uint256(uUNIT); // Equivalent to `for(y /= 2; y > 0; y /= 2)`. uint256 yAux = y; for (yAux >>= 1; yAux > 0; yAux >>= 1) { xAbs = Common.mulDiv18(xAbs, xAbs); // Equivalent to `y % 2 == 1`. if (yAux & 1 > 0) { resultAbs = Common.mulDiv18(resultAbs, xAbs); } } // The result must fit in SD59x18. if (resultAbs > uint256(uMAX_SD59x18)) { revert Errors.PRBMath_SD59x18_Powu_Overflow(x, y); } unchecked { // Is the base negative and the exponent odd? If yes, the result should be negative. int256 resultInt = int256(resultAbs); bool isNegative = x.unwrap() < 0 && y & 1 == 1; if (isNegative) { resultInt = -resultInt; } result = wrap(resultInt); } } /// @notice Calculates the square root of x using the Babylonian method. /// /// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. /// /// Notes: /// - Only the positive root is returned. /// - The result is rounded toward zero. /// /// Requirements: /// - x ≥ 0, since complex numbers are not supported. /// - x ≤ MAX_SD59x18 / UNIT /// /// @param x The SD59x18 number for which to calculate the square root. /// @return result The result as an SD59x18 number. /// @custom:smtchecker abstract-function-nondet function sqrt(SD59x18 x) pure returns (SD59x18 result) { int256 xInt = x.unwrap(); if (xInt < 0) { revert Errors.PRBMath_SD59x18_Sqrt_NegativeInput(x); } if (xInt > uMAX_SD59x18 / uUNIT) { revert Errors.PRBMath_SD59x18_Sqrt_Overflow(x); } unchecked { // Multiply x by `UNIT` to account for the factor of `UNIT` picked up when multiplying two SD59x18 numbers. // In this case, the two numbers are both the square root. uint256 resultUint = Common.sqrt(uint256(xInt * uUNIT)); result = wrap(int256(resultUint)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import "../Common.sol" as Common; import "./Errors.sol" as Errors; import { SD59x18 } from "../sd59x18/ValueType.sol"; import { UD60x18 } from "../ud60x18/ValueType.sol"; import { UD21x18 } from "./ValueType.sol"; /// @notice Casts a UD21x18 number into SD59x18. /// @dev There is no overflow check because UD21x18 ⊆ SD59x18. function intoSD59x18(UD21x18 x) pure returns (SD59x18 result) { result = SD59x18.wrap(int256(uint256(UD21x18.unwrap(x)))); } /// @notice Casts a UD21x18 number into UD60x18. /// @dev There is no overflow check because UD21x18 ⊆ UD60x18. function intoUD60x18(UD21x18 x) pure returns (UD60x18 result) { result = UD60x18.wrap(UD21x18.unwrap(x)); } /// @notice Casts a UD21x18 number into uint128. /// @dev This is basically an alias for {unwrap}. function intoUint128(UD21x18 x) pure returns (uint128 result) { result = UD21x18.unwrap(x); } /// @notice Casts a UD21x18 number into uint256. /// @dev There is no overflow check because UD21x18 ⊆ uint256. function intoUint256(UD21x18 x) pure returns (uint256 result) { result = uint256(UD21x18.unwrap(x)); } /// @notice Casts a UD21x18 number into uint40. /// @dev Requirements: /// - x ≤ MAX_UINT40 function intoUint40(UD21x18 x) pure returns (uint40 result) { uint128 xUint = UD21x18.unwrap(x); if (xUint > uint128(Common.MAX_UINT40)) { revert Errors.PRBMath_UD21x18_IntoUint40_Overflow(x); } result = uint40(xUint); } /// @notice Alias for {wrap}. function ud21x18(uint128 x) pure returns (UD21x18 result) { result = UD21x18.wrap(x); } /// @notice Unwrap a UD21x18 number into uint128. function unwrap(UD21x18 x) pure returns (uint128 result) { result = UD21x18.unwrap(x); } /// @notice Wraps a uint128 number into UD21x18. function wrap(uint128 x) pure returns (UD21x18 result) { result = UD21x18.wrap(x); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { SD1x18 } from "./ValueType.sol"; /// @notice Thrown when trying to cast an SD1x18 number that doesn't fit in UD60x18. error PRBMath_SD1x18_ToUD60x18_Underflow(SD1x18 x); /// @notice Thrown when trying to cast an SD1x18 number that doesn't fit in uint128. error PRBMath_SD1x18_ToUint128_Underflow(SD1x18 x); /// @notice Thrown when trying to cast an SD1x18 number that doesn't fit in uint256. error PRBMath_SD1x18_ToUint256_Underflow(SD1x18 x); /// @notice Thrown when trying to cast an SD1x18 number that doesn't fit in uint40. error PRBMath_SD1x18_ToUint40_Overflow(SD1x18 x); /// @notice Thrown when trying to cast an SD1x18 number that doesn't fit in uint40. error PRBMath_SD1x18_ToUint40_Underflow(SD1x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { SD59x18 } from "./ValueType.sol"; /// @notice Thrown when taking the absolute value of `MIN_SD59x18`. error PRBMath_SD59x18_Abs_MinSD59x18(); /// @notice Thrown when ceiling a number overflows SD59x18. error PRBMath_SD59x18_Ceil_Overflow(SD59x18 x); /// @notice Thrown when converting a basic integer to the fixed-point format overflows SD59x18. error PRBMath_SD59x18_Convert_Overflow(int256 x); /// @notice Thrown when converting a basic integer to the fixed-point format underflows SD59x18. error PRBMath_SD59x18_Convert_Underflow(int256 x); /// @notice Thrown when dividing two numbers and one of them is `MIN_SD59x18`. error PRBMath_SD59x18_Div_InputTooSmall(); /// @notice Thrown when dividing two numbers and one of the intermediary unsigned results overflows SD59x18. error PRBMath_SD59x18_Div_Overflow(SD59x18 x, SD59x18 y); /// @notice Thrown when taking the natural exponent of a base greater than 133_084258667509499441. error PRBMath_SD59x18_Exp_InputTooBig(SD59x18 x); /// @notice Thrown when taking the binary exponent of a base greater than 192e18. error PRBMath_SD59x18_Exp2_InputTooBig(SD59x18 x); /// @notice Thrown when flooring a number underflows SD59x18. error PRBMath_SD59x18_Floor_Underflow(SD59x18 x); /// @notice Thrown when taking the geometric mean of two numbers and their product is negative. error PRBMath_SD59x18_Gm_NegativeProduct(SD59x18 x, SD59x18 y); /// @notice Thrown when taking the geometric mean of two numbers and multiplying them overflows SD59x18. error PRBMath_SD59x18_Gm_Overflow(SD59x18 x, SD59x18 y); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in SD1x18. error PRBMath_SD59x18_IntoSD1x18_Overflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in SD1x18. error PRBMath_SD59x18_IntoSD1x18_Underflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in SD21x18. error PRBMath_SD59x18_IntoSD21x18_Overflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in SD21x18. error PRBMath_SD59x18_IntoSD21x18_Underflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in UD2x18. error PRBMath_SD59x18_IntoUD2x18_Overflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in UD2x18. error PRBMath_SD59x18_IntoUD2x18_Underflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in UD21x18. error PRBMath_SD59x18_IntoUD21x18_Overflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in UD21x18. error PRBMath_SD59x18_IntoUD21x18_Underflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in UD60x18. error PRBMath_SD59x18_IntoUD60x18_Underflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in uint128. error PRBMath_SD59x18_IntoUint128_Overflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in uint128. error PRBMath_SD59x18_IntoUint128_Underflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in uint256. error PRBMath_SD59x18_IntoUint256_Underflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in uint40. error PRBMath_SD59x18_IntoUint40_Overflow(SD59x18 x); /// @notice Thrown when trying to cast an SD59x18 number that doesn't fit in uint40. error PRBMath_SD59x18_IntoUint40_Underflow(SD59x18 x); /// @notice Thrown when taking the logarithm of a number less than or equal to zero. error PRBMath_SD59x18_Log_InputTooSmall(SD59x18 x); /// @notice Thrown when multiplying two numbers and one of the inputs is `MIN_SD59x18`. error PRBMath_SD59x18_Mul_InputTooSmall(); /// @notice Thrown when multiplying two numbers and the intermediary absolute result overflows SD59x18. error PRBMath_SD59x18_Mul_Overflow(SD59x18 x, SD59x18 y); /// @notice Thrown when raising a number to a power and the intermediary absolute result overflows SD59x18. error PRBMath_SD59x18_Powu_Overflow(SD59x18 x, uint256 y); /// @notice Thrown when taking the square root of a negative number. error PRBMath_SD59x18_Sqrt_NegativeInput(SD59x18 x); /// @notice Thrown when the calculating the square root overflows SD59x18. error PRBMath_SD59x18_Sqrt_Overflow(SD59x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { UD2x18 } from "./ValueType.sol"; /// @notice Thrown when trying to cast a UD2x18 number that doesn't fit in uint40. error PRBMath_UD2x18_IntoUint40_Overflow(UD2x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { SD21x18 } from "./ValueType.sol"; /// @notice Thrown when trying to cast an SD21x18 number that doesn't fit in uint128. error PRBMath_SD21x18_ToUint128_Underflow(SD21x18 x); /// @notice Thrown when trying to cast an SD21x18 number that doesn't fit in UD60x18. error PRBMath_SD21x18_ToUD60x18_Underflow(SD21x18 x); /// @notice Thrown when trying to cast an SD21x18 number that doesn't fit in uint256. error PRBMath_SD21x18_ToUint256_Underflow(SD21x18 x); /// @notice Thrown when trying to cast an SD21x18 number that doesn't fit in uint40. error PRBMath_SD21x18_ToUint40_Overflow(SD21x18 x); /// @notice Thrown when trying to cast an SD21x18 number that doesn't fit in uint40. error PRBMath_SD21x18_ToUint40_Underflow(SD21x18 x);
// SPDX-License-Identifier: MIT pragma solidity >=0.8.19; import { UD21x18 } from "./ValueType.sol"; /// @notice Thrown when trying to cast a UD21x18 number that doesn't fit in uint40. error PRBMath_UD21x18_IntoUint40_Overflow(UD21x18 x);
{ "evmVersion": "paris", "optimizer": { "enabled": true, "mode": "3" }, "outputSelection": { "*": { "*": [ "abi", "metadata" ], "": [ "ast" ] } }, "detectMissingLibraries": false, "forceEVMLA": false, "enableEraVMExtensions": false, "libraries": {} }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"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":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"EmptyMarketResolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newGracePeriod","type":"uint256"}],"name":"GracePeriodUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"newKRange","type":"uint256[]"}],"name":"KRangeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"questionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"MarketCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newEndTime","type":"uint256"}],"name":"MarketEndTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yesVotes","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"noVotes","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalFunds","type":"uint256"}],"name":"MarketPoolUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"winningOption","type":"uint256"}],"name":"MarketResolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yesPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"noPrice","type":"uint256"}],"name":"PricesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardClaimed","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":true,"internalType":"uint8","name":"stablecoinIndex","type":"uint8"},{"indexed":false,"internalType":"address","name":"stablecoinAddress","type":"address"}],"name":"StablecoinAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"stablecoinIndex","type":"uint8"},{"indexed":false,"internalType":"address","name":"oldStablecoinAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newStablecoinAddress","type":"address"}],"name":"StablecoinUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"optionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnclaimedRewardsReclaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"points","type":"uint256"}],"name":"UserDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"stablecoins","type":"uint256"}],"name":"UserWithdrawn","type":"event"},{"inputs":[],"name":"CONVERSION_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POINTS_PER_DOLLAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TEAM_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addTeamMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"authorizedCaller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"questionId","type":"uint256"},{"internalType":"uint256","name":"commissionPercentage","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"createMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllMarketsWithPools","outputs":[{"internalType":"uint256[]","name":"marketIds","type":"uint256[]"},{"internalType":"uint256[]","name":"questionIds","type":"uint256[]"},{"internalType":"uint256[]","name":"totalPoolBalances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"getMarketDetails","outputs":[{"internalType":"uint256","name":"questionId","type":"uint256"},{"internalType":"uint256","name":"yesVotes","type":"uint256"},{"internalType":"uint256","name":"noVotes","type":"uint256"},{"internalType":"bool","name":"isResolved","type":"bool"},{"internalType":"uint256","name":"winningOption","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"getMarketEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"optionId","type":"uint256"}],"name":"getPrice","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":[],"name":"gracePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initializeMarketState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"isMarketResolved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isTeamMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"kRange","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketParticipants","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"markets","outputs":[{"internalType":"uint256","name":"questionId","type":"uint256"},{"internalType":"uint256","name":"yesVotes","type":"uint256"},{"internalType":"uint256","name":"noVotes","type":"uint256"},{"internalType":"uint256","name":"totalFunds","type":"uint256"},{"internalType":"uint256","name":"commissionPercentage","type":"uint256"},{"internalType":"uint256","name":"baseLiquidity","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bool","name":"isResolved","type":"bool"},{"internalType":"uint256","name":"winningOption","type":"uint256"},{"internalType":"uint256","name":"yesPrice","type":"uint256"},{"internalType":"uint256","name":"noPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"reclaimUnclaimedRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeTeamMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"winningOption","type":"uint256"}],"name":"resolveMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revokeAuthorizedCaller","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":"caller","type":"address"}],"name":"setAuthorizedCaller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPeriod","type":"uint256"}],"name":"setGracePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stablecoinCount","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"transferAdminRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint256","name":"newEndTime","type":"uint256"}],"name":"updateEndTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"newKRange","type":"uint256[]"}],"name":"updateKRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"bool","name":"isYesVote","type":"bool"},{"internalType":"uint256","name":"points","type":"uint256"}],"name":"updateMarketPool","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":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userHoldings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
9c4d535b0000000000000000000000000000000000000000000000000000000000000000010006653d7774d281a2cc0b557fb2648f6db4e79bca78fcc74ff974f76fcda900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x000400000000000200120000000000020000006004100270000005710340019700030000003103550002000000010355000005710040019d00000001002001900000001e0000c13d0000008007000039000000400070043f000000040030008c000011830000413d000000000201043b000000e002200270000005770020009c000000430000213d000005970020009c000000620000213d000005a70020009c000001990000213d000005af0020009c0000024d0000213d000005b30020009c000006280000613d000005b40020009c000003b40000613d000005b50020009c000003ad0000613d000011830000013d000000a001000039000000400010043f0000000001000416000000000001004b000011830000c13d0000000002000410000000800020043f00000001010000390000013303000039000000000013041b000000000300041a0000ff0000300190000000370000c13d000000ff0430018f000000ff0040008c000000370000613d000000ff033001bf000000000030041b000001400000044300000160002004430000002002000039000001000020044300000120001004430000057201000041000015c00001042e0000057301000041000000a00010043f0000002001000039000000a40010043f0000002e01000039000000c40010043f0000057401000041000000e40010043f0000057501000041000001040010043f0000057601000041000015c100010430000005780020009c0000012a0000213d000005880020009c000001b20000213d000005900020009c000002660000213d000005940020009c000006390000613d000005950020009c000003ea0000613d000005960020009c000011830000c13d000000440030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000002402100370000000000202043b000e00000002001d000005b60020009c000011830000213d0000000401100370000000000101043b000000000010043f000000c901000039000000200010043f0000004002000039000000000100001915bf159b0000040f0000037c0000013d000005980020009c000001ea0000213d000005a00020009c000002720000213d000005a40020009c000006450000613d000005a50020009c000003ef0000613d000005a60020009c000011830000c13d000000440030008c000011830000413d0000000402100370000000000202043b000e00000002001d000005b60020009c000011830000213d0000002402100370000000000402043b000005b80040009c000011830000213d0000002302400039000000000032004b000011830000813d0000000405400039000000000251034f000000000202043b000005b80020009c0000133f0000213d0000001f062000390000065c066001970000003f066000390000065c06600197000006130060009c0000133f0000213d0000008006600039000000400060043f000000800020043f00000000042400190000002404400039000000000034004b000011830000213d000d00000007001d0000002003500039000000000331034f0000065c042001980000001f0520018f000000a001400039000000990000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000016004b000000950000c13d000000000005004b000000a60000613d000000000343034f0000000304500210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000310435000000a0012000390000000000010435000006330100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000005710010009c0000057101008041000000c00110021000000634011001c7000080050200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b000005b6011001970000000002000410000000000012004b0000077c0000613d0000063702000041000000000202041a000005b602200197000000000012004b000009c70000c13d0000000001000411000005b601100197000000000010043f000005f901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000010060000c13d000000400200043d0000060c0020009c0000133f0000213d0000006004200039000000400040043f0000002a01000039000000000112043600000000030000310000000203300367000000000503034f0000000006010019000000005705043c0000000006760436000000000046004b000000dd0000c13d00000000040104330000060d044001970000060e044001c70000000000410435000000210420003900000000050404330000060d055001970000060f055001c700000000005404350000002904000039000000000600041100000000050600190000000006020433000000000046004b000010f00000a13d000000000614001900000000070604330000060d077001970000000308500210000000780880018f000006100880021f0000061108800197000000000787019f00000000007604350000000406500270000000010440008a000000010040008c000000ec0000213d000000400800043d000000100050008c000010f60000813d000006130080009c0000133f0000213d0000008005800039000000400050043f000000420400003900000000044804360000000006040019000000003703043c0000000006760436000000000056004b000001070000c13d00000000030404330000060d033001970000060e033001c700000000003404350000000007080019000000210380003900000000050304330000060d055001970000060f055001c7000000000053043500000041030000390000000005070433000000000035004b000010f00000a13d000000000543001900000000060504330000060d066001970000060e066001c70000000000650435000000010330008a000000010030008c000001160000213d000000400500043d000e00000005001d0000002003500039000006140400004100000000004304350000000003020433000c00000003001d0000003702500039000009500000013d000005790020009c000002280000213d000005810020009c0000028f0000213d000005850020009c0000064c0000613d000005860020009c000004070000613d000005870020009c000011830000c13d000000440030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000002402100370000000000202043b000d00000002001d0000000401100370000000000101043b000e00000001001d000005f301000041000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000002000411000005b602200197000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000007cd0000613d0000013401000039000000000101041a0000000e02000029000000000012004b000009d10000813d000000000020043f0000013501000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000c00000001001d0000000701100039000000000101041a000000ff0010019000000f3a0000c13d000005d10100004100000000001004430000000001000414000005710010009c0000057101008041000000c001100210000005d2011001c70000800b0200003915bf15b50000040f0000000100200190000011f40000613d000000400200043d000000000101043b0000000d0010006b00000e280000a13d0000000c010000290000000601100039000000000301041a0000000d0030006b00000eff0000c13d0000004401200039000005f803000041000000000031043500000024012000390000001703000039000000000031043500000573010000410000000000120435000000040120003900000020030000390000000000310435000005710020009c00000571020080410000004001200210000005c4011001c7000015c100010430000005a80020009c0000029a0000213d000005ac0020009c000003ad0000613d000005ad0020009c000004220000613d000005ae0020009c000011830000c13d000000440030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000002402100370000000000302043b000005b60030009c000011830000213d0000000002000411000000000023004b0000086d0000c13d0000000401100370000000000101043b15bf14e40000040f0000000001000019000015c00001042e000005890020009c000003630000213d0000058d0020009c000006720000613d0000058e0020009c000004ce0000613d0000058f0020009c000011830000c13d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000013402000039000000000202041a0000000401100370000000000101043b000e00000001001d000000000021004b0000000001000039000000010100403915bf14090000040f0000000e01000029000000000010043f0000013501000039000000200010043f0000004002000039000000000100001915bf159b0000040f0000000702100039000000000202041a0000000103100039000000000303041a0000000204100039000000000404041a000000000501041a0000000801100039000000000101041a000000400600043d000000800760003900000000001704350000004001600039000000000041043500000020016000390000000000310435000000ff002001900000000001000039000000010100c039000000600260003900000000001204350000000000560435000005710060009c00000571060080410000004001600210000005fe011001c7000015c00001042e000005990020009c000003830000213d0000059d0020009c000006a10000613d0000059e0020009c000004e30000613d0000059f0020009c000011830000c13d000000440030008c000011830000413d0000000001000416000000000001004b000011830000c13d0000000001000411000005b601100197000000000010043f000005b901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000007cd0000613d00000002010003670000002402100370000000000202043b000e00000002001d0000000401100370000000000101043b000d00000001001d000000000010043f0000013501000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000401043b0000000703400039000000000103041a000000ff0010019000000f3a0000c13d0000000e02000029000000020020008c00000ad70000413d000000400100043d0000004402100039000006310300004100000b360000013d0000057a0020009c000003920000213d0000057e0020009c000006d40000613d0000057f0020009c000004fa0000613d000005800020009c000011830000c13d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b000005b60010009c000011830000213d000000fc02000039000000000202041a000005b6022001970000000003000411000000000032004b000007ea0000c13d000000000001004b000008ad0000c13d0000057301000041000000800010043f0000002001000039000000840010043f0000002601000039000000a40010043f000005c701000041000000c40010043f000005c801000041000000e40010043f000005c901000041000015c100010430000005b00020009c000006e20000613d000005b10020009c000005150000613d000005b20020009c000011830000c13d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000201043b000005b60020009c000011830000213d000e00000002001d000000000002004b0000000001000039000000010100c03915bf13f50000040f000000000000043f000000c901000039000000200010043f000005f9010000410000037c0000013d000005910020009c000007120000613d000005920020009c000005240000613d000005930020009c000011830000c13d0000000001000416000000000001004b000011830000c13d000000800000043f000005c601000041000015c00001042e000005a10020009c0000071b0000613d000005a20020009c000005290000613d000005a30020009c000011830000c13d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000013402000039000000000202041a0000000401100370000000000101043b000e00000001001d000000000021004b0000000001000039000000010100403915bf14090000040f0000000e01000029000000000010043f0000013501000039000000200010043f0000004002000039000000000100001915bf159b0000040f00000007011000390000037e0000013d000005820020009c000007390000613d000005830020009c000005480000613d000005840020009c000011830000c13d0000000001000416000000000001004b000011830000c13d0000013401000039000007e60000013d000005a90020009c0000075f0000613d000005aa0020009c0000058d0000613d000005ab0020009c000011830000c13d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b000e00000001001d000005b60010009c000011830000213d000005f301000041000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d0000000002000411000000000101043b000005b602200197000d00000002001d000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000007cd0000613d0000000e0000006b0000070e0000613d000005f301000041000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000e02000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff0010019000000e3b0000c13d0000064501000041000000000101041a000c00000001001d000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000d02000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff001001900000101a0000c13d000000400100043d0000060c0010009c0000133f0000213d00000000070100190000006002700039000000400020043f0000002a01000039000000000417043600000000010000310000000201100367000000000301034f0000000009040019000000003503043c0000000004540436000000000024004b000003160000c13d000000000a09001900000000020904330000060d022001970000060e022001c700000000002904350000000008070019000000210270003900000000030204330000060d033001970000060f033001c700000000003204350000002902000039000000000400041100000000030400190000000004080433000000000024004b000010f00000a13d0000000004a2001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000565019f00000000005404350000000404300270000000010220008a000000010020008c000003270000213d000000400800043d000000100030008c000010f60000813d000006130080009c0000133f0000213d0000008003800039000000400030043f000000420200003900000000022804360000000004020019000000001501043c0000000004540436000000000034004b000003420000c13d00000000010204330000060d011001970000060e011001c70000000000120435000000210180003900000000030104330000060d033001970000060f033001c7000000000031043500000041010000390000000c0400002900000000030400190000000004080433000000000014004b000010f00000a13d000000000421001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000565019f00000000005404350000000404300270000000010110008a000000010010008c000003510000213d000004b60000013d0000058a0020009c000007800000613d0000058b0020009c000005af0000613d0000058c0020009c000011830000c13d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000201043b000005b60020009c000011830000213d000e00000002001d000000000002004b0000000001000039000000010100c03915bf13f50000040f000005f301000041000000000010043f000000c901000039000000200010043f000005b9010000410000000e0200002915bf13da0000040f000000000101041a000000ff001001900000000001000039000000010100c039000007320000013d0000059a0020009c000007ab0000613d0000059b0020009c000005e10000613d0000059c0020009c000011830000c13d0000000001000416000000000001004b000011830000c13d0000013201000039000000000101041a000000ff0110018f000000800010043f000005c601000041000015c00001042e0000057b0020009c000007d70000613d0000057c0020009c000005f60000613d0000057d0020009c000011830000c13d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000201043b000005b60020009c000011830000213d000e00000002001d000000000002004b0000000001000039000000010100c03915bf13f50000040f000000fb01000039000000000101041a000005b6011001970000000e0010006b00000000010000390000000101006039000007320000013d0000000001000416000000000001004b000011830000c13d0000006401000039000000800010043f000005c601000041000015c00001042e000000640030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000004402100370000000000202043b000c00000002001d0000002402100370000000000202043b000d00000002001d0000000401100370000000000101043b000e00000001001d000005f301000041000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000002000411000005b602200197000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000007cd0000613d0000000e0000006b000009d80000c13d000000400100043d0000004402100039000006570300004100000000003204350000002402100039000000120300003900000f400000013d0000000001000416000000000001004b000011830000c13d000000fc01000039000007160000013d0000000001000416000000000001004b000011830000c13d000000000100041a0000ff0000100190000007f30000c13d000000ff00100190000008790000c13d00000620020000410000013703000039000000000023041b0000061d0110019700000001011001bf000000000010041b0000000103000039000000800030043f0000000001000414000005710010009c0000057101008041000000c001100210000005cb011001c70000800d020000390000062104000041000009b70000013d000000440030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000002402100370000000000202043b000e00000002001d000005b60020009c000011830000213d0000000401100370000000000101043b000d00000001001d000000000010043f000000c901000039000000200010043f0000004002000039000000000100001915bf159b0000040f0000000101100039000000000101041a15bf141d0000040f0000000d010000290000000e0200002915bf14e40000040f0000000001000019000015c00001042e000000440030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000402100370000000000202043b000e00000002001d0000002401100370000000000101043b000d00000001001d000005b60010009c000011830000213d0000000e01000029000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000101100039000000000101041a000c00000001001d000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d0000000002000411000000000101043b000005b602200197000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff0010019000000aea0000c13d000000400100043d0000060c0010009c0000133f0000213d00000000070100190000006002700039000000400020043f0000002a01000039000000000417043600000000010000310000000201100367000000000301034f0000000009040019000000003503043c0000000004540436000000000024004b0000046a0000c13d000000000a09001900000000020904330000060d022001970000060e022001c700000000002904350000000008070019000000210270003900000000030204330000060d033001970000060f033001c700000000003204350000002902000039000000000400041100000000030400190000000004080433000000000024004b000010f00000a13d0000000004a2001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000565019f00000000005404350000000404300270000000010220008a000000010020008c0000047b0000213d000000400800043d000000100030008c000010f60000813d000006130080009c0000133f0000213d0000008003800039000000400030043f000000420200003900000000022804360000000004020019000000001501043c0000000004540436000000000034004b000004960000c13d00000000010204330000060d011001970000060e011001c70000000000120435000000210180003900000000030104330000060d033001970000060f033001c7000000000031043500000041010000390000000c0400002900000000030400190000000004080433000000000014004b000010f00000a13d000000000421001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000565019f00000000005404350000000404300270000000010110008a000000010010008c000004a50000213d000000100030008c00000000010000390000000101004039000b00000007001d000c00000009001d000d00000008001d15bf15870000040f000000400400043d000e00000004001d0000002001400039000006140200004100000000002104350000000b010000290000000003010433000b00000003001d00000037024000390000000c0100002915bf15570000040f0000000b020000290000000e01200029000006150200004100000037031000390000000000230435000009570000013d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000301043b0000013302000039000000000102041a000000020010008c000008080000c13d0000057301000041000000800010043f0000002001000039000000840010043f0000001f01000039000000a40010043f0000060501000041000000c40010043f000005d801000041000015c100010430000000440030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000002402100370000000000302043b0000000401100370000000000101043b0000013402000039000000000202041a000000000021004b000008230000813d000000020030008c0000087b0000813d000e00000003001d15bf13b80000040f0000000e02000029000000010020008c0000000a0200003900000009020060390000000001210019000007310000013d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b000000fc02000039000000000202041a000005b6022001970000000003000411000000000032004b000007ea0000c13d000000000001004b000008850000c13d0000057301000041000000800010043f0000002001000039000000840010043f0000002601000039000000a40010043f000005cf01000041000000c40010043f000005d001000041000000e40010043f000005c901000041000015c100010430000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b000000000010043f000000c901000039000000200010043f0000004002000039000000000100001915bf159b0000040f0000000101100039000007e60000013d0000000001000416000000000001004b000011830000c13d0000013701000039000007e60000013d0000000001000416000000000001004b000011830000c13d000006330100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000005710010009c0000057101008041000000c00110021000000634011001c7000080050200003915bf15b50000040f0000000100200190000011f40000613d000000400300043d000005710030009c000005710200004100000000020340190000004002200210000000000101043b000005b6011001970000000004000410000000000014004b000008930000c13d00000637010000410000000000130435000005b7012001c7000015c00001042e000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000301043b000000fc01000039000000000101041a000005b6011001970000000002000411000000000021004b000007ea0000c13d000e00000003001d000000000030043f0000013501000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000201043b0000000701200039000000000101041a000000ff001001900000081c0000613d0000013701000039000000000301041a000b00000002001d0000000601200039000000000101041a000d00000003001d000c00000001001d000000000013001a00000e550000413d000005d10100004100000000001004430000000001000414000005710010009c0000057101008041000000c001100210000005d2011001c70000800b0200003915bf15b50000040f0000000100200190000011f40000613d0000000c030000290000000d02300029000000000101043b000000000021004b00000b330000a13d0000000b010000290000000301100039000000000201041a000d00000002001d000000000002004b00000c820000c13d000000400100043d0000004402100039000005d60300004100000000003204350000002402100039000000140300003900000f400000013d000000440030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000002402100370000000000202043b000e00000002001d0000000401100370000000000101043b000000000010043f0000013001000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000201041a0000000e0020006b000011830000813d000000000010043f0000002002000039000000000100001915bf159b0000040f0000000e01100029000000000101041a000005b601100197000007320000013d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b000000000010043f0000013501000039000000200010043f0000004002000039000000000100001915bf159b0000040f0000000a02100039000000000202041a0000000903100039000000000303041a0000000804100039000000000404041a0000000705100039000000000505041a0000000606100039000000000606041a0000000507100039000000000707041a0000000408100039000000000808041a0000000309100039000000000909041a000000020a100039000000000a0a041a000000010b100039000000000b0b041a000000000101041a000000800010043f000000a000b0043f000000c000a0043f000000e00090043f000001000080043f000001200070043f000001400060043f000000ff005001900000000001000039000000010100c039000001600010043f000001800040043f000001a00030043f000001c00020043f000005fc01000041000015c00001042e0000000001000416000000000001004b000011830000c13d000000fc01000039000000000201041a000005b6032001970000000005000411000000000053004b000007ea0000c13d000005fa02200197000000000021041b0000000001000414000005710010009c0000057101008041000000c00110021000000609011001c70000800d0200003900000003030000390000061e040000410000000006000019000009b70000013d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000402100370000000000202043b000005b80020009c000011830000213d0000002304200039000000000034004b000011830000813d000d00040020003d0000000d01100360000000000101043b000e00000001001d000005b80010009c000011830000213d0000000e0100002900000005011002100000002402200039000b00000001001d000c00000002001d0000000001210019000000000031004b000011830000213d0000000001000411000005b601100197000000000010043f000005b901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000007cd0000613d0000000e0000006b00000ca90000c13d000000400100043d0000004402100039000005c50300004100000f3d0000013d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b0000065900100198000011830000c13d0000065a0010009c000000000200003900000001020060390000065b0010009c00000001022061bf000000800020043f000005c601000041000015c00001042e0000000001000416000000000001004b000011830000c13d000000000100041a000eff00001001940000082d0000c13d000000ff0010019000000d710000c13d0000061d0110019700000101011001bf000000000010041b0000084a0000013d0000000001000416000000000001004b000011830000c13d000005f301000041000000800010043f000005c601000041000015c00001042e000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b000e00000001001d000005b60010009c000011830000213d0000000001000411000005b601100197000000000010043f000005f901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000007a10000613d0000000e03000029000000000003004b000009df0000c13d000000400100043d0000004402100039000005fb03000041000000000032043500000024021000390000001d0300003900000f400000013d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b000e00000001001d000005b60010009c000011830000213d000000000000043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d0000000002000411000000000101043b000005b602200197000d00000002001d000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000007a10000613d0000000e0000006b00000b3a0000c13d000000400100043d00000044021000390000061603000041000009bf0000013d000000640030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000402100370000000000202043b000005b60020009c000011830000213d0000004401100370000000000101043b000e00000001001d000000000020043f0000012f01000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b00000024020000390000000202200367000000000202043b000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d0000000e02000029000000010020008c000011830000213d000000000101043b0000000e0200002915bf13ea0000040f0000000302200210000000000101041a000000000121022f000000ff0020008c0000000001002019000007320000013d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b0000013602000039000000000302041a000000000031004b000011830000813d000000000020043f000005bb0110009a000007e60000013d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b000e00000001001d000005b60010009c000011830000213d000005f301000041000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d0000000002000411000000000101043b000005b602200197000d00000002001d000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000007cd0000613d0000000e0000006b00000bd00000c13d000000400100043d0000004402100039000006520300004100000b360000013d0000000001000416000000000001004b000011830000c13d000000fb01000039000000000101041a000005b601100197000000800010043f000005c601000041000015c00001042e000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000013402000039000000000202041a0000000401100370000000000101043b000e00000001001d000000000021004b0000000001000039000000010100403915bf14090000040f0000000e01000029000000000010043f0000013501000039000000200010043f0000004002000039000000000100001915bf159b0000040f0000000601100039000000000101041a000000400200043d0000000000120435000005710020009c00000571020080410000004001200210000005b7011001c7000015c00001042e000000640030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000402100370000000000202043b000e00000002001d0000002402100370000000000302043b000000000003004b0000000002000039000000010200c039000d00000003001d000000000023004b000011830000c13d0000004401100370000000000301043b000000fb01000039000000000101041a000005b6011001970000000002000411000000000012004b000008a30000c13d000000000003004b000008b00000c13d0000057301000041000000800010043f0000002001000039000000840010043f0000002f01000039000000a40010043f000005f101000041000000c40010043f000005f201000041000000e40010043f000005c901000041000015c100010430000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b000e00000001001d000005b60010009c000011830000213d000006330100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000005710010009c0000057101008041000000c00110021000000634011001c7000080050200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b000005b6011001970000000002000410000000000012004b000008df0000c13d000000400100043d00000064021000390000064b03000041000009ca0000013d0000000001000416000000000001004b000011830000c13d000000000000043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000002000411000005b602200197000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000009690000c13d000000400100043d0000006402100039000006170300004100000000003204350000004402100039000006180300004100000000003204350000002402100039000000330300003900000d7a0000013d0000000001000416000000000001004b000011830000c13d000005f301000041000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000002000411000005b602200197000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000009740000c13d000000400100043d00000064021000390000065803000041000000000032043500000044021000390000061803000041000000000032043500000024021000390000002a0300003900000d7a0000013d000000240030008c000011830000413d0000000002000416000000000002004b000011830000c13d0000000401100370000000000101043b000005b60010009c000011830000213d000000000010043f0000012e01000039000000200010043f0000004002000039000000000100001915bf159b0000040f000000000101041a000000800010043f000005c601000041000015c00001042e0000057301000041000000800010043f0000002001000039000000840010043f000000a40010043f0000061f01000041000000c40010043f000005d801000041000015c10001043000000619010000410000000000100443000000000100041000000004001004430000000001000414000005710010009c0000057101008041000000c0011002100000061a011001c7000080020200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b000000000001004b00000d710000c13d00000620010000410000013702000039000000000012041b0000000001000019000015c00001042e0000000201000039000000000012041b000e00000003001d000000000030043f0000013501000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000201043b0000000701200039000000000101041a000000ff001001900000097f0000c13d000000400100043d0000004402100039000006040300004100000000003204350000002402100039000000130300003900000f400000013d0000057301000041000000800010043f0000002001000039000000840010043f0000001501000039000000a40010043f000005f401000041000000c40010043f000005d801000041000015c10001043000000619010000410000000000100443000000000100041000000004001004430000000001000414000005710010009c0000057101008041000000c0011002100000061a011001c7000080020200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b000000000001004b00000d710000c13d000000000100041a0000ff00001001900000084a0000c13d000000400100043d00000064021000390000061b03000041000000000032043500000044021000390000061c03000041000000000032043500000024021000390000002b0300003900000d7a0000013d0000000001000411000005b606100197000000fc03000039000000000103041a000005fa02100197000000000262019f000000000023041b0000000002000414000005b605100197000005710020009c0000057102008041000000c00120021000000609011001c70000800d0200003900000003030000390000061e04000041000d00000006001d15bf15b00000040f0000000100200190000011830000613d000000fc03000039000000000103041a000005b6021001970000000005000411000000000052004b000009bc0000c13d000000000005004b00000aab0000c13d000000400100043d0000006402100039000005c80300004100000000003204350000004402100039000005c70300004100000cb60000013d0000057301000041000000800010043f0000002001000039000000840010043f0000002f01000039000000a40010043f0000064c01000041000000c40010043f0000064d01000041000000e40010043f000005c901000041000015c100010430000000800100003900000d720000013d0000057301000041000000800010043f0000002001000039000000840010043f0000001101000039000000a40010043f0000063201000041000000c40010043f000005d801000041000015c100010430000005ca0010009c000009ac0000413d0000057301000041000000800010043f0000002001000039000000840010043f0000002201000039000000a40010043f000005cd01000041000000c40010043f000005ce01000041000000e40010043f000005c901000041000015c10001043000000064013000390000063504000041000000000041043500000044013000390000063604000041000000000041043500000024013000390000003804000039000000000041043500000573010000410000000000130435000000040130003900000020030000390000000000310435000005c2012001c7000015c1000104300000057301000041000000800010043f0000002001000039000000840010043f0000001f01000039000000a40010043f000005d701000041000000c40010043f000005d801000041000015c10001043015bf15420000040f0000000001000019000015c00001042e0000013401000039000000000101041a0000000e02000029000000000012004b000009e60000813d000c00000003001d000000000020043f0000013501000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000b00000001001d0000000701100039000000000101041a000000ff0010019000000cb00000c13d0000000b010000290000000601100039000000000101041a000a00000001001d000005d10100004100000000001004430000000001000414000005710010009c0000057101008041000000c001100210000005d2011001c70000800b0200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b0000000a0010006c00000e450000813d0000000d0000006b00000f100000c13d0000000b01000029000000020110003900000f120000013d0000063702000041000000000202041a000005b602200197000000000012004b000009c70000c13d0000000001000411000005b601100197000000000010043f000005f901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000400200043d000000000101043b000000000101041a000000ff00100190000d00000002001d00000cba0000c13d0000060c0020009c0000133f0000213d0000000d020000290000006003200039000000400030043f0000002a01000039000000000112043600000000020000310000000202200367000000000402034f0000000005010019000000004604043c0000000005650436000000000035004b000009030000c13d00000000030104330000060d033001970000060e033001c700000000003104350000000d08000029000000210380003900000000040304330000060d044001970000060f044001c700000000004304350000002903000039000000000500041100000000040500190000000005080433000000000035004b000010f00000a13d000000000513001900000000060504330000060d066001970000000307400210000000780770018f000006100770021f0000061107700197000000000676019f00000000006504350000000405400270000000010330008a000000010030008c000009130000213d000000400700043d000000100040008c00000fcc0000813d000006130070009c0000133f0000213d0000008004700039000000400040043f000000420300003900000000033704360000000005030019000000002602043c0000000005650436000000000045004b0000092e0000c13d00000000020304330000060d022001970000060e022001c70000000000230435000000210270003900000000040204330000060d044001970000060f044001c7000000000042043500000041020000390000000d060000290000000004070433000000000024004b000010f00000a13d000000000432001900000000050404330000060d055001970000060e055001c70000000000540435000000010220008a000000010020008c0000093d0000213d000000400400043d000e00000004001d0000002002400039000006140300004100000000003204350000000003060433000c00000003001d0000003702400039000d00000007001d15bf15570000040f0000000c020000290000000e0120002900000037021000390000061503000041000000000032043500000048021000390000000d0100002915bf15640000040f0000000e030000290000000002310049000000200120008a0000000000130435000000000103001915bf13c80000040f0000057301000041000000400200043d000d00000002001d000000000012043500000004012000390000000e0200002915bf15720000040f0000000d020000290000118c0000013d000000fb01000039000000000201041a000005b600200198000009f20000c13d000000400100043d0000004402100039000005fd03000041000000000032043500000024021000390000001a0300003900000f400000013d0000013401000039000000000501041a000000000005004b000009f60000c13d000000400100043d00000044021000390000062c0300004100000000003204350000002402100039000000100300003900000f400000013d000b00000002001d0000000101200039000000000101041a000d00000001001d0000000001000411000005b601100197000a00000001001d000000000010043f0000012f01000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000d0000006b0000000003000039000000010300c039000c00000003001d0000000100200190000011830000613d000000000101043b0000000e02000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000c01100029000000000201041a000000000002004b00000cd50000c13d000000400100043d000000440210003900000603030000410000081f0000013d0000013702000039000000000012041b000000800010043f0000000001000414000005710010009c0000057101008041000000c001100210000005cb011001c70000800d020000390000000103000039000005cc0400004115bf15b00000040f0000000100200190000011830000613d0000000001000019000015c00001042e000000400100043d00000044021000390000061f03000041000000000032043500000573020000410000000000210435000000240210003900000020030000390000000000320435000000040210003900000f450000013d000000400100043d00000064021000390000064603000041000000000032043500000044021000390000064703000041000000000032043500000024021000390000002c0300003900000d7a0000013d000000400100043d0000004402100039000005f40300004100000000003204350000002402100039000000150300003900000f400000013d0000000d01000029000000650010008c00000bf50000413d000000400100043d0000004402100039000006560300004100000f3d0000013d000000fb01000039000000000201041a000005fa02200197000000000232019f000000000021041b0000000001000019000015c00001042e0000057301000041000000800010043f0000002001000039000000840010043f0000002401000039000000a40010043f000005d901000041000000c40010043f000005da01000041000000e40010043f000005c901000041000015c100010430000005fa02200197000000000021041b0000000001000019000015c00001042e000005b80050009c0000133f0000213d00000005015002100000003f021000390000062b04200197000000400300043d0000000002430019000d00000003001d000000000032004b00000000030000390000000103004039000005b80020009c0000133f0000213d00000001003001900000133f0000c13d000000400020043f0000000d02000029000c00000005001d0000000002520436000a00000002001d0000001f0210018f00000000030000310000000203300367000000000001004b00000a160000613d0000000a070000290000000005170019000000000603034f000000006806043c0000000007870436000000000057004b00000a120000c13d000000000002004b000000400600043d0000000005460019000b00000006001d000000000065004b00000000060000390000000106004039000005b80050009c0000000c070000290000133f0000213d00000001006001900000133f0000c13d000000400050043f0000000b050000290000000005750436000800000005001d000000000001004b00000a2f0000613d00000008070000290000000005170019000000000603034f000000006806043c0000000007870436000000000057004b00000a2b0000c13d000000000002004b000000400500043d0000000004450019000900000005001d000000000054004b00000000050000390000000105004039000005b80040009c0000000c060000290000133f0000213d00000001005001900000133f0000c13d000000400040043f00000009040000290000000004640436000700000004001d000000000001004b00000a470000613d00000007040000290000000001140019000000003503043c0000000004540436000000000014004b00000a430000c13d000000000002004b0000000006000019000e00000006001d000000000060043f0000013501000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000d0200002900000000020204330000000e06000029000000000062004b0000000b040000290000000905000029000010f00000a13d00000005026002100000000a0320002900000000006304350000000003040433000000000063004b000010f00000a13d0000000803200029000000000401041a00000000004304350000000003050433000000000063004b000010f00000a13d00000007022000290000000301100039000000000101041a000000000012043500000001066000390000000c0060006c00000a490000413d000000400100043d000000600200003900000000022104360000000d030000290000000004030433000000600310003900000000004304350000008003100039000000000004004b00000a830000613d00000000050000190000000d070000290000002007700039000000000607043300000000036304360000000105500039000000000045004b00000a7d0000413d000000000413004900000000004204350000000b0200002900000000040204330000000002430436000000000004004b00000a920000613d00000000030000190000000b060000290000002006600039000000000506043300000000025204360000000103300039000000000043004b00000a8c0000413d000000000312004900000040041000390000000000340435000000090300002900000000030304330000000002320436000000000003004b00000aa20000613d000000000400001900000009060000290000002006600039000000000506043300000000025204360000000104400039000000000034004b00000a9c0000413d0000000002120049000005710020009c00000571020080410000006002200210000005710010009c00000571010080410000004001100210000000000112019f000015c00001042e000005fa011001970000000d06000029000000000161019f000000000013041b0000000001000414000005710010009c0000057101008041000000c00110021000000609011001c70000800d0200003900000003030000390000061e0400004115bf15b00000040f0000000100200190000011830000613d000000000100041a0000ff000010019000000d1c0000c13d000000ff0010019000000d710000c13d00000620020000410000013703000039000000000023041b0000061d0110019700000001011001bf000000000010041b0000000103000039000000400100043d0000000000310435000005710010009c000005710100804100000040011002100000000002000414000005710020009c0000057102008041000000c002200210000000000112019f000005d4011001c70000800d02000039000006210400004115bf15b00000040f000000010020019000000d2f0000c13d000011830000013d000b00000003001d0000000202400039000000000302041a000c00000004001d0000000102400039000000000202041a000000000002004b00000ce70000613d000000000003004b00000cf60000613d0000000c010000290000000401100039000000000201041a000000650020008c00000e490000413d000000400100043d000000440210003900000630030000410000066e0000013d0000000e01000029000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000d02000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000009ba0000c13d0000000e01000029000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000d02000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000201041a0000065d0220019700000001022001bf000000000021041b0000000001000414000005710010009c0000057101008041000000c00110021000000609011001c70000800d0200003900000004030000390000060a040000410000000e050000290000000d060000290000000007000411000009b70000013d000000400100043d0000004402100039000005d30300004100000000003204350000002402100039000000160300003900000f400000013d000000000000043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000e02000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff0010019000000e5b0000c13d0000060801000041000000000101041a000c00000001001d000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000d02000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000010460000c13d000000400100043d0000060c0010009c0000133f0000213d00000000070100190000006002700039000000400020043f0000002a01000039000000000417043600000000010000310000000201100367000000000301034f0000000009040019000000003503043c0000000004540436000000000024004b00000b830000c13d000000000a09001900000000020904330000060d022001970000060e022001c700000000002904350000000008070019000000210270003900000000030204330000060d033001970000060f033001c700000000003204350000002902000039000000000400041100000000030400190000000004080433000000000024004b000010f00000a13d0000000004a2001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000565019f00000000005404350000000404300270000000010220008a000000010020008c00000b940000213d000000400800043d000000100030008c000010f60000813d000006130080009c0000133f0000213d0000008003800039000000400030043f000000420200003900000000022804360000000004020019000000001501043c0000000004540436000000000034004b00000baf0000c13d00000000010204330000060d011001970000060e011001c70000000000120435000000210180003900000000030104330000060d033001970000060f033001c7000000000031043500000041010000390000000c0400002900000000030400190000000004080433000000000014004b000010f00000a13d000000000421001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000565019f00000000005404350000000404300270000000010110008a000000010010008c00000bbe0000213d000004b60000013d000005f301000041000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000e02000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff0010019000000e620000c13d000000400100043d0000006402100039000006500300004100000000003204350000004402100039000006510300004100000cb60000013d000005d10100004100000000001004430000000001000414000005710010009c0000057101008041000000c001100210000005d2011001c70000800b0200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b0000000c0010006b00000d850000a13d0000013401000039000000000201041a000b00000002001d000000010220003a00000e550000613d000000000021041b000000400100043d000a00000001001d000006540010009c0000133f0000813d0000000a030000290000016001300039000000400010043f000000c0023000390000000c01000029000700000002001d000000000012043500000080023000390000000d01000029000500000002001d00000000001204350000000e0100002900000000021304360000014001300039000d00000001001d00000000000104350000012001300039000900000001001d00000000000104350000010001300039000800000001001d0000000000010435000000e001300039000600000001001d0000000000010435000000a001300039000400000001001d00000000000104350000006001300039000200000001001d00000000000104350000004001300039000100000001001d0000000000010435000300000002001d00000000000204350000000b01000029000000000010043f0000013501000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d0000000a020000290000000002020433000000000101043b000000000021041b000000030200002900000000020204330000000103100039000000000023041b000000010200002900000000020204330000000203100039000000000023041b000000020200002900000000020204330000000303100039000000000023041b000000050200002900000000020204330000000403100039000000000023041b000000040200002900000000020204330000000503100039000000000023041b000000070200002900000000020204330000000603100039000000000023041b0000000702100039000000000402041a0000065d0340019700000006040000290000000004040433000000000004004b000000010330c1bf000000000032041b000000080200002900000000020204330000000803100039000000000023041b000000090200002900000000020204330000000903100039000000000023041b0000000a011000390000000d020000290000000002020433000000000021041b000000400100043d00000020021000390000000c0300002900000000003204350000000e020000290000000000210435000005710010009c000005710100804100000040011002100000000002000414000005710020009c0000057102008041000000c002200210000000000112019f000005ba011001c70000800d02000039000000020300003900000655040000410000000b05000029000009b70000013d000000000001041b000000fc01000039000000000101041a000005b601100197000000000010043f0000012e01000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000201041a0000000d0020002a00000e550000413d0000000d030000290000000002320019000000000021041b000000400100043d0000000000310435000005710010009c000005710100804100000040011002100000000002000414000005710020009c0000057102008041000000c002200210000000000112019f000005d4011001c70000800d020000390000000203000039000005d5040000410000000e05000029000009b70000013d0000000e010000290000000a0010008c00000d8c0000a13d000000400100043d0000004402100039000005c30300004100000d880000013d000000400100043d0000006402100039000005db0300004100000000003204350000004402100039000005dc0300004100000000003204350000002402100039000000260300003900000d7a0000013d000006480020009c0000133f0000213d0000000d010000290000002002100039000b00000002001d000000400020043f00000000000104350000063801000041000000000101041a000000ff0010019000000edb0000c13d000000400200043d0000063901000041000c00000002001d000000000012043500000000010004140000000e02000029000000040020008c00000f4b0000c13d0000000005000415000000120550008a00000005055002100000000103000031000000200030008c0000002004000039000000000403401900000f790000013d0000000b010000290000000301100039000000000301041a0000000d0000006b00000d100000c13d0000000b040000290000000204400039000000000404041a000d00000004001d000000000004004b00000d100000c13d000000400100043d0000004402100039000005ff03000041000000000032043500000024021000390000001f0300003900000f400000013d000000000003004b00000cf60000c13d0000065d0110019700000001011001bf0000000b02000029000000000012041b0000000001000414000005710010009c0000057101008041000000c00110021000000609011001c70000800d0200003900000002030000390000062e0400004100000d0e0000013d0000065d0110019700000001011001bf0000000b03000029000000000013041b000000000002004b0000000001000039000000010100c0390000000c020000290000000802200039000000000012041b000000400200043d0000000000120435000005710020009c000005710200804100000040012002100000000002000414000005710020009c0000057102008041000000c002200210000000000112019f000005d4011001c70000800d0200003900000002030000390000062f040000410000000d05000029000009b70000013d000000000023004b00000dd70000813d000000400100043d0000006402100039000006010300004100000000003204350000004402100039000006020300004100000000003204350000002402100039000000230300003900000d7a0000013d00000619010000410000000000100443000000000100041000000004001004430000000001000414000005710010009c0000057101008041000000c0011002100000061a011001c7000080020200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b000000000001004b00000d710000c13d00000620010000410000013702000039000000000012041b000000400200043d000006130020009c0000133f0000213d0000008001200039000000400010043f000000600120003900000622030000410000000000310435000000400320003900000623040000410000000000430435000005e5040000410000000004420436000006240500004100000000005404350000013605000039000000000605041a0000000407000039000000000075041b000000050060008c00000d4c0000413d000005bb0660009a000006250060009c00000d4c0000413d0000062607000041000000000007041b0000000107700039000000000067004b00000d480000413d000000000050043f0000000002020433000005b8022001970000062705000041000000000025041b0000000002040433000005b8022001970000062804000041000000000024041b0000000002030433000005b8022001970000062903000041000000000023041b0000000001010433000005b8011001970000062a02000041000000000012041b0000000e0000006b000009ba0000c13d000000000200041a0000065e01200197000000000010041b0000000103000039000000400100043d0000000000310435000005710010009c000005710100804100000040011002100000000002000414000005710020009c0000057102008041000000c002200210000000000112019f000005d4011001c70000800d020000390000062104000041000009b70000013d000000400100043d00000064021000390000057503000041000000000032043500000044021000390000057403000041000000000032043500000024021000390000002e03000039000000000032043500000573020000410000000000210435000000040210003900000020030000390000000000320435000005710010009c00000571010080410000004001100210000005c2011001c7000015c100010430000000400100043d00000044021000390000065303000041000000000032043500000024021000390000001e0300003900000f400000013d000000020100036700000000020000190000000e050000290000000c0400002900000005032002100000000003430019000000000331034f000000000303043b000000000003004b00000ef50000613d0000000102200039000000000052004b00000d900000413d0000013602000039000000000402041a000000000052041b000000000054004b00000da70000a13d0000000e03000029000005bb0330009a000005bb0440009a000000000043004b00000da70000813d000000000003041b0000000103300039000000000043004b00000da30000413d000000000020043f0000000d020000290000002002200039000000000121034f0000000002000019000000000301034f0000000e06000029000000003403043c000005bb0520009a000000000045041b0000000102200039000000000062004b00000dae0000413d000000400200043d000000200300003900000000033204360000000000630435000005bc0060009c000011830000213d0000000b040000290000001f0340018f000000000004004b00000dc40000613d00000040042000390000000b05400029000000001601043c0000000004640436000000000054004b00000dc00000c13d000000000003004b000005710020009c000005710200804100000040012002100000000b02000029000005bd0020009c000005bd020080410000006002200210000000000112019f0000000002000414000005710020009c0000057102008041000000c002200210000000000121019f000005be0110009a0000800d020000390000000103000039000005bf04000041000009b70000013d00000000042300a900000000022400d9000000000032004b00000e550000c13d000d000d004001020000000d0230006c00000e550000413d000000000021041b0000000a01000029000000000010043f0000012e01000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000201041a0000000d0020002a00000e550000413d0000000d02200029000000000021041b0000000a01000029000000000010043f0000012f01000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000e02000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000c01100029000000000001041b000000400100043d0000000d020000290000000000210435000005710010009c000005710100804100000040011002100000000002000414000005710020009c0000057102008041000000c002200210000000000112019f000005d4011001c70000800d020000390000000303000039000006000400004100000000050004110000000e0600002915bf15b00000040f0000000100200190000011830000613d00000001010000390000013302000039000000000012041b0000000001000019000015c00001042e0000006401200039000005f50300004100000000003104350000004401200039000005f603000041000000000031043500000024012000390000002203000039000000000031043500000573010000410000000000120435000000040120003900000020030000390000000000310435000005710020009c00000571020080410000004001200210000005c2011001c7000015c100010430000000400100043d0000006402100039000006430300004100000000003204350000004402100039000006440300004100000000003204350000002402100039000000240300003900000d7a0000013d000000400100043d0000004402100039000005dd030000410000066e0000013d0000000c010000290000000301100039000000000301041a00000000043200a9000000000003004b00000e520000613d00000000053400d9000000000025004b00000e550000c13d000a0064004001220000000a0230006c00000fdb0000813d0000064e01000041000000000010043f0000001101000039000000040010043f0000064f01000041000015c100010430000000400100043d0000006402100039000006060300004100000000003204350000004402100039000006070300004100000ef10000013d0000064501000041000000000101041a000c00000001001d000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000d02000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000011050000c13d000000400100043d0000060c0010009c0000133f0000213d00000000070100190000006002700039000000400020043f0000002a01000039000000000417043600000000010000310000000201100367000000000301034f0000000009040019000000003503043c0000000004540436000000000024004b00000e8e0000c13d000000000a09001900000000020904330000060d022001970000060e022001c700000000002904350000000008070019000000210270003900000000030204330000060d033001970000060f033001c700000000003204350000002902000039000000000400041100000000030400190000000004080433000000000024004b000010f00000a13d0000000004a2001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000565019f00000000005404350000000404300270000000010220008a000000010020008c00000e9f0000213d000000400800043d000000100030008c000010f60000813d000006130080009c0000133f0000213d0000008003800039000000400030043f000000420200003900000000022804360000000004020019000000001501043c0000000004540436000000000034004b00000eba0000c13d00000000010204330000060d011001970000060e011001c70000000000120435000000210180003900000000030104330000060d033001970000060f033001c7000000000031043500000041010000390000000c0400002900000000030400190000000004080433000000000014004b000010f00000a13d000000000421001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000565019f00000000005404350000000404300270000000010110008a000000010010008c00000ec90000213d000004b60000013d000006190100004100000000001004430000000e0100002900000004001004430000000001000414000005710010009c0000057101008041000000c0011002100000061a011001c7000080020200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b000000000001004b000010010000c13d000000400100043d00000064021000390000064903000041000000000032043500000044021000390000064a03000041000000000032043500000024021000390000002d0300003900000d7a0000013d000000400100043d0000006402100039000005c00300004100000000003204350000004402100039000005c10300004100000000003204350000002402100039000000220300003900000d7a0000013d0000000d03000029000000000031041b0000000000320435000005710020009c000005710200804100000040012002100000000002000414000005710020009c0000057102008041000000c002200210000000000112019f000005d4011001c70000800d020000390000000203000039000005f7040000410000000e05000029000009b70000013d0000000b010000290000000101100039000000000201041a0000000c0020002a00000e550000413d0000000c02200029000000000021041b0000000b010000290000000301100039000d00000001001d000000000101041a0000000c0010002a00000e550000413d0000000c011000290000000d02000029000000000012041b0000000e01000029000000000010043f0000013501000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000702100039000000000202041a000000ff0020019000000f3a0000c13d0000013603000039000000000203041a000000000002004b000011330000c13d000000400100043d0000004402100039000005f00300004100000f3d0000013d000000400100043d00000044021000390000062d03000041000000000032043500000024021000390000001703000039000000000032043500000573020000410000000000210435000000040210003900000020030000390000000000320435000005710010009c00000571010080410000004001100210000005c4011001c7000015c1000104300000000c02000029000005710020009c00000571020080410000004002200210000005710010009c0000057101008041000000c001100210000000000121019f0000063a011001c70000000e0200002915bf15b50000040f00000060031002700000057103300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000c0570002900000f650000613d000000000801034f0000000c09000029000000008a08043c0000000009a90436000000000059004b00000f610000c13d000000000006004b00000f720000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f00030000000103550000000005000415000000110550008a00000005055002100000000100200190000011850000613d0000001f01400039000000600210018f0000000c01200029000000000021004b00000000020000390000000102004039000005b80010009c0000133f0000213d00000001002001900000133f0000c13d000000400010043f000000200030008c000011830000413d0000000c0200002900000000020204330000000503500270000000000302001f000006370020009c000011f50000c13d000006190100004100000000001004430000000e0100002900000004001004430000000001000414000005710010009c0000057101008041000000c0011002100000061a011001c7000080020200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b000000000001004b00000eeb0000613d0000063701000041000000000201041a000005fa022001970000000e05000029000000000252019f000000000021041b000000400100043d000c00000001001d0000000001000414000005710010009c0000057101008041000000c00110021000000609011001c70000800d0200003900000002030000390000063d0400004115bf15b00000040f0000000100200190000011830000613d0000000d010000290000000001010433000000000001004b000009ba0000613d000006190100004100000000001004430000000e0100002900000004001004430000000001000414000005710010009c0000057101008041000000c0011002100000061a011001c7000080020200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b000000000001004b000011e00000613d0000000d01000029000000000201043300000000010004140000000e03000029000000040030008c000012740000c13d00000001030000390000000102000031000012870000013d0000004401700039000006120200004100000000002104350000057301000041000000000017043500000024017000390000002002000039000000000021043500000004017000390000000000210435000005710070009c00000571070080410000004001700210000005c4011001c7000015c100010430000000000021041b000000fc01000039000000000101041a000005b601100197000000000010043f0000012e01000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000201041a0000000a0020002a00000e550000413d0000000a02200029000000000021041b0000000b03000029000000000103041a0000065d0110019700000001011001bf000000000013041b0000000c0100002900000008011000390000000e02000029000000000021041b000000400100043d0000000000210435000005710010009c00000571010080410000004001100210000000000200041400000d060000013d0000063701000041000000000201041a000005fa022001970000000e03000029000009e20000013d0000063801000041000000000101041a000000ff00100190000011420000c13d000000400200043d0000063901000041000c00000002001d000000000012043500000000010004140000000e02000029000000040020008c000011480000c13d0000000005000415000000100550008a00000005055002100000000103000031000000200030008c00000020040000390000000004034019000011760000013d0000000e01000029000000000010043f000005b901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000009ba0000c13d0000000e01000029000000000010043f000005b901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000201041a0000065d0220019700000001022001bf000000000021041b0000000001000414000005710010009c0000057101008041000000c00110021000000609011001c70000800d0200003900000004030000390000060a040000410000112f0000013d0000000e01000029000000000010043f000005f901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000010770000c13d0000000e01000029000000000010043f000005f901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000201041a0000065d0220019700000001022001bf000000000021041b0000000001000414000005710010009c0000057101008041000000c00110021000000609011001c70000800d0200003900000004030000390000060a0400004100000000050000190000000e06000029000000000700041115bf15b00000040f0000000100200190000011830000613d0000060801000041000000000101041a000e00000001001d000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b0000000d02000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000012480000c13d000000400100043d0000060c0010009c0000133f0000213d00000000070100190000006002700039000000400020043f0000002a01000039000000000417043600000000010000310000000201100367000000000301034f0000000009040019000000003503043c0000000004540436000000000024004b000010a30000c13d000000000a09001900000000020904330000060d022001970000060e022001c700000000002904350000000008070019000000210270003900000000030204330000060d033001970000060f033001c700000000003204350000002902000039000000000400041100000000030400190000000004080433000000000024004b000010f00000a13d0000000004a2001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000565019f00000000005404350000000404300270000000010220008a000000010020008c000010b40000213d000000400800043d000000100030008c000010f60000813d000006130080009c0000133f0000213d0000008003800039000000400030043f000000420200003900000000022804360000000004020019000000001501043c0000000004540436000000000034004b000010cf0000c13d00000000010204330000060d011001970000060e011001c70000000000120435000000210180003900000000030104330000060d033001970000060f033001c7000000000031043500000041010000390000000e0400002900000000030400190000000004080433000000000014004b000010f00000a13d000000000421001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000565019f00000000005404350000000404300270000000010110008a000000010010008c000010de0000213d000004b60000013d0000064e01000041000000000010043f0000003201000039000000040010043f0000064f01000041000015c1000104300000004401800039000006120200004100000000002104350000057301000041000000000018043500000024018000390000002002000039000000000021043500000004018000390000000000210435000005710080009c00000571080080410000004001800210000005c4011001c7000015c1000104300000000e01000029000000000010043f000005b901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000009ba0000613d0000000e01000029000000000010043f000005b901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000201041a0000065d02200197000000000021041b0000000001000414000005710010009c0000057101008041000000c00110021000000609011001c70000800d0200003900000004030000390000060b04000041000005f3050000410000000e060000290000000007000411000009b70000013d0000000304100039000000000404041a000000000030043f00000000202400d9000005bb0220009a000000000402041a000000000004004b000011950000c13d000000400100043d0000004402100039000005ef03000041000000000032043500000024021000390000000f0300003900000f400000013d000006190100004100000000001004430000000e010000290000000400100443000000000100041400000ee00000013d0000000c02000029000005710020009c00000571020080410000004002200210000005710010009c0000057101008041000000c001100210000000000121019f0000063a011001c70000000e0200002915bf15b50000040f00000060031002700000057103300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000c05700029000011620000613d000000000801034f0000000c09000029000000008a08043c0000000009a90436000000000059004b0000115e0000c13d000000000006004b0000116f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f000300000001035500000000050004150000000f0550008a00000005055002100000000100200190000011850000613d0000001f01400039000000600210018f0000000c01200029000000000021004b00000000020000390000000102004039000005b80010009c0000133f0000213d00000001002001900000133f0000c13d000000400010043f000000200030008c000011a70000813d0000000001000019000015c100010430000000400200043d000e00000002001d00000573010000410000000000120435000000040120003915bf15350000040f0000000e020000290000000001210049000005710010009c00000571010080410000006001100210000005710020009c00000571020080410000004002200210000000000121019f000015c1000104300000000102100039000000000302041a0000000202100039000000000202041a000000000032001a00000e550000413d00000000053200190000065f0050009c00000e550000613d000000000005004b000011fe0000c13d000000400100043d0000006402100039000005de0300004100000000003204350000004402100039000005df03000041000011fa0000013d0000000c0200002900000000020204330000000503500270000000000302001f000006370020009c000011f50000c13d000006190100004100000000001004430000000e0100002900000004001004430000000001000414000005710010009c0000057101008041000000c0011002100000061a011001c7000080020200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b000000000001004b00000eeb0000613d0000063701000041000000000201041a000005fa022001970000000e05000029000000000252019f000000000021041b000000400100043d000c00000001001d0000000001000414000005710010009c0000057101008041000000c00110021000000609011001c70000800d0200003900000002030000390000063d0400004115bf15b00000040f0000000100200190000011830000613d000006190100004100000000001004430000000e0100002900000004001004430000000001000414000005710010009c0000057101008041000000c0011002100000061a011001c7000080020200003915bf15b50000040f0000000100200190000011f40000613d000000000101043b000000000001004b0000130a0000c13d0000000c0300002900000064013000390000064102000041000000000021043500000044013000390000064202000041000000000021043500000024013000390000002602000039000000000021043500000573010000410000000000130435000000040130003900000020020000390000000000210435000005710030009c00000571030080410000004001300210000005c2011001c7000015c100010430000000000001042f00000064021000390000063b03000041000000000032043500000044021000390000063c0300004100000000003204350000002402100039000000290300003900000d7a0000013d000005e00050009c00000e550000413d0000000106500039000005e10050009c0000120a0000413d0000000005000019000005e30550009c00000e550000813d000005e40060009c0000000a0660011a000012040000213d0000120b0000013d0000000005000019000005e50860009c0000000007000019000012140000613d000005e609800197000005e5078000d1000005e70870019700000000089800d9000005e50080009c00000e550000c13d000005e607700197000005e80660009a000005e60960019700000000069700d900000000086600a9000000000079004b000012200000213d000005e607600197000005e60980019700000000097900d9000000000079004b00000e550000c13d000000000065001a00000e550000413d0000000007650019000005e605800197000005e50550012a0000000308000039000000000006004b000012360000613d00000000095600a900000000066900d9000000000056004b00000e550000c13d000005e50690012a000000000a8600d900000000007a001a00000e550000413d00000000077a0019000005e50090009c000012360000413d000000260080008c0000000208800039000012260000413d00000000054700a900000000044500d9000000000074004b00000e550000c13d0000000504100039000000000054041b000000000005004b000012a10000c13d000000400100043d0000006402100039000005ed0300004100000000003204350000004402100039000005ee0300004100000000003204350000002402100039000000280300003900000d7a0000013d0000000d01000029000000000010043f000005f901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000101041a000000ff00100190000009ba0000613d0000000d01000029000000000010043f000005f901000041000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000011830000613d000000000101043b000000000201041a0000065d02200197000000000021041b0000000001000414000005710010009c0000057101008041000000c00110021000000609011001c70000800d0200003900000004030000390000060b04000041000000000500001900000b300000013d0000000b03000029000005710030009c00000571030080410000004003300210000005710020009c00000571020080410000006002200210000000000232019f000005710010009c0000057101008041000000c001100210000000000112019f0000000e0200002915bf15ba0000040f000000010320018f00030000000103550000006001100270000105710010019d0000057102100197000000000002004b000012e00000c13d00000060010000390000008004000039000000400200043d0000060c0020009c0000133f0000213d0000006005200039000000400050043f00000040052000390000063f06000041000000000065043500000020052000390000064006000041000000000065043500000027050000390000000000520435000000000003004b000009ba0000c13d0000000001010433000000000001004b000013360000613d000005710040009c00000571040080410000004002400210000013b30000013d000005e5043000d1000000000003004b000012a70000613d00000000033400d9000005e50030009c00000e550000c13d00000000045400d9000005e5070000410000000106000039000005e50300004100000000084700a9000000000007004b000012b10000613d00000000077800d9000000000047004b00000e550000c13d000000120060008c00000e550000213d000005e5096000d100000000079800d9000000000037001a00000e550000413d00000000033700190000000106600039000000000089004b000012ab0000a13d000005e5042000d1000000000002004b000012c10000613d00000000022400d9000005e50020009c00000e550000c13d00000000045400d9000005e5060000410000000105000039000005e50200004100000000074600a9000000000006004b000012cb0000613d00000000066700d9000000000046004b00000e550000c13d000000120050008c00000e550000213d000005e5085000d100000000068700d9000000000026001a00000e550000413d00000000022600190000000105500039000000000078004b000012c50000a13d000000000032001a00000e550000413d000000000432001a0000136e0000c13d000000400100043d0000006402100039000005de0300004100000000003204350000004402100039000005ec03000041000011fa0000013d000005b80020009c0000133f0000213d0000001f012000390000065c011001970000003f011000390000065c04100197000000400100043d0000000004410019000000000014004b00000000060000390000000106004039000005b80040009c0000133f0000213d00000001006001900000133f0000c13d000000400040043f00000000042104360000065c052001980000001f0620018f00000000025400190000000307000367000012fc0000613d000000000807034f0000000009040019000000008a08043c0000000009a90436000000000029004b000012f80000c13d000000000006004b0000128b0000613d000000000557034f0000000306600210000000000702043300000000076701cf000000000767022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000575019f00000000005204350000128b0000013d000000800200043d00000000010004140000000e03000029000000040030008c000013120000c13d00000001030000390000000102000031000013210000013d000005710020009c00000571020080410000006002200210000005710010009c0000057101008041000000c001100210000000000121019f0000063e011001c70000000e0200002915bf15ba0000040f000000010320018f00030000000103550000006001100270000105710010019d0000057102100197000000000002004b0000133d0000c13d0000006001000039000000400200043d0000060c0020009c0000133f0000213d0000006004200039000000400040043f00000040042000390000063f05000041000000000054043500000020042000390000064005000041000000000054043500000027040000390000000000420435000000000003004b000009ba0000c13d0000000001010433000000000001004b000013af0000c13d000000400300043d000e00000003001d00000573010000410000000000130435000000040130003915bf15720000040f0000118b0000013d000005b80020009c000013450000a13d0000064e01000041000000000010043f0000004101000039000000040010043f0000064f01000041000015c1000104300000001f012000390000065c011001970000003f011000390000065c04100197000000400100043d0000000004410019000000000014004b00000000050000390000000105004039000005b80040009c0000133f0000213d00000001005001900000133f0000c13d000000400040043f00000000062104360000065c042001980000001f0520018f000d00000006001d00000000024600190000000306000367000013600000613d000000000706034f0000000d08000029000000007907043c0000000008980436000000000028004b0000135c0000c13d000000000005004b000013240000613d000000000446034f0000000305500210000000000602043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000420435000013240000013d000005e5053000d1000000000003004b000013740000613d00000000033500d9000005e50030009c00000e550000c13d000005e5032000d1000000000002004b0000137a0000613d00000000022300d9000005e50020009c00000e550000c13d00000000024300d90000000a03100039000000000023041b00000000034500d90000000901100039000000000031041b000000400100043d000000200410003900000000002404350000000000310435000005710010009c000005710100804100000040011002100000000002000414000005710020009c0000057102008041000000c002200210000000000112019f000005ba011001c70000800d020000390000000203000039000005e9040000410000000e0500002915bf15b00000040f0000000100200190000011830000613d0000000b020000290000000101200039000000000101041a0000000202200039000000000202041a0000000d03000029000000000303041a000000400400043d00000040054000390000000000350435000000200340003900000000002304350000000000140435000005710040009c000005710400804100000040014002100000000002000414000005710020009c0000057102008041000000c002200210000000000112019f000005ea011001c70000800d020000390000000203000039000005eb040000410000000e05000029000009b70000013d0000000d02000029000005710020009c00000571020080410000004002200210000005710010009c00000571010080410000006001100210000000000121019f000015c100010430000000000010043f0000013501000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000013c60000613d000000000101043b000000000001042d0000000001000019000015c1000104300000001f022000390000065c022001970000000001120019000000000021004b00000000020000390000000102004039000005b80010009c000013d40000213d0000000100200190000013d40000c13d000000400010043f000000000001042d0000064e01000041000000000010043f0000004101000039000000040010043f0000064f01000041000015c100010430000005b602200197000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000013e80000613d000000000101043b000000000001042d0000000001000019000015c100010430000000020020008c000013ef0000813d00000000011200190000000002000019000000000001042d0000064e01000041000000000010043f0000003201000039000000040010043f0000064f01000041000015c100010430000000000001004b000013f80000613d000000000001042d000000400100043d00000044021000390000065203000041000000000032043500000024021000390000001603000039000000000032043500000573020000410000000000210435000000040210003900000020030000390000000000320435000005710010009c00000571010080410000004001100210000005c4011001c7000015c100010430000000000001004b0000140c0000613d000000000001042d000000400100043d0000004402100039000005f403000041000000000032043500000024021000390000001503000039000000000032043500000573020000410000000000210435000000040210003900000020030000390000000000320435000005710010009c00000571010080410000004001100210000005c4011001c7000015c1000104300004000000000002000400000001001d000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f00000001002001900000143e0000613d0000000002000411000000000101043b000005b602200197000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f00000001002001900000143e0000613d000000000101043b000000000101041a000000ff00100190000014400000613d000000000001042d0000000001000019000015c100010430000000400100043d000006600010009c000014490000413d0000064e01000041000000000010043f0000004101000039000000040010043f0000064f01000041000015c10001043000000000070100190000006002700039000000400020043f0000002a01000039000000000417043600000000010000310000000201100367000000000301034f0000000009040019000000003503043c0000000004540436000000000024004b000014520000c13d000000000a09001900000000020904330000060d022001970000060e022001c700000000002904350000000008070019000000210270003900000000030204330000060d033001970000060f033001c700000000003204350000002902000039000000000400041100000000030400190000000004080433000000000024004b000014cf0000a13d0000000004a2001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000565019f00000000005404350000000404300270000000010220008a000000010020008c000014630000213d000000400800043d000000100030008c000014d50000813d000006130080009c000014430000213d0000008003800039000000400030043f000000420200003900000000022804360000000004020019000000001501043c0000000004540436000000000034004b0000147e0000c13d00000000010204330000060d011001970000060e011001c70000000000120435000000210180003900000000030104330000060d033001970000060f033001c700000000003104350000004101000039000000040400002900000000030400190000000004080433000000000014004b000014cf0000a13d000000000421001900000000050404330000060d055001970000000306300210000000780660018f000006100660021f0000061106600197000000000556019f00000000005404350000000404300270000000010110008a000000010010008c0000148d0000213d000000100030008c00000000010000390000000101004039000100000007001d000200000009001d000300000008001d15bf15870000040f000000400400043d000400000004001d00000020014000390000061402000041000000000021043500000001010000290000000003010433000100000003001d0000003702400039000000020100002915bf15570000040f000000010200002900000004012000290000061502000041000000370310003900000000002304350000004802100039000000030100002915bf15640000040f00000004030000290000000002310049000000200120008a0000000000130435000000000103001915bf13c80000040f0000057301000041000000400200043d000300000002001d00000000001204350000000401200039000000040200002915bf15720000040f00000003020000290000000001210049000005710010009c00000571010080410000006001100210000005710020009c00000571020080410000004002200210000000000121019f000015c1000104300000064e01000041000000000010043f0000003201000039000000040010043f0000064f01000041000015c1000104300000004401800039000006120200004100000000002104350000057301000041000000000018043500000024018000390000002002000039000000000021043500000004018000390000000000210435000005710080009c00000571080080410000004001800210000005c4011001c7000015c1000104300002000000000002000100000002001d000200000001001d000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000015330000613d000000000101043b0000000102000029000005b602200197000100000002001d000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000015330000613d000000000101043b000000000101041a000000ff00100190000015320000613d0000000201000029000000000010043f000000c901000039000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000015330000613d000000000101043b0000000102000029000000000020043f000000200010043f0000000001000414000005710010009c0000057101008041000000c001100210000005ba011001c7000080100200003915bf15b50000040f0000000100200190000015330000613d000000000101043b000000000201041a0000065d02200197000000000021041b0000000001000414000005710010009c0000057101008041000000c00110021000000609011001c70000800d02000039000000040300003900000000070004110000060b040000410000000205000029000000010600002915bf15b00000040f0000000100200190000015330000613d000000000001042d0000000001000019000015c10001043000000060021000390000066103000041000000000032043500000040021000390000066203000041000000000032043500000020021000390000002e030000390000000000320435000000200200003900000000002104350000008001100039000000000001042d000005b606100197000000fc01000039000000000201041a000005fa03200197000000000363019f000000000031041b0000000001000414000005b605200197000005710010009c0000057101008041000000c00110021000000609011001c70000800d0200003900000003030000390000061e0400004115bf15b00000040f0000000100200190000015550000613d000000000001042d0000000001000019000015c100010430000000000003004b000015610000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000034004b0000155a0000413d00000000012300190000000000010435000000000001042d0000000031010434000000000001004b0000156f0000613d000000000400001900000000052400190000000006430019000000000606043300000000006504350000002004400039000000000014004b000015680000413d00000000012100190000000000010435000000000001042d00000020030000390000000004310436000000003202043400000000002404350000004001100039000000000002004b000015810000613d000000000400001900000000051400190000000006430019000000000606043300000000006504350000002004400039000000000024004b0000157a0000413d000000000312001900000000000304350000001f022000390000065c022001970000000001210019000000000001042d000000000001004b0000158a0000613d000000000001042d000000400100043d0000004402100039000006120300004100000000003204350000057302000041000000000021043500000024021000390000002003000039000000000032043500000004021000390000000000320435000005710010009c00000571010080410000004001100210000005c4011001c7000015c100010430000000000001042f000005710010009c00000571010080410000004001100210000005710020009c00000571020080410000006002200210000000000112019f0000000002000414000005710020009c0000057102008041000000c002200210000000000112019f00000609011001c7000080100200003915bf15b50000040f0000000100200190000015ae0000613d000000000101043b000000000001042d0000000001000019000015c100010430000015b3002104210000000102000039000000000001042d0000000002000019000000000001042d000015b8002104230000000102000039000000000001042d0000000002000019000000000001042d000015bd002104250000000102000039000000000001042d0000000002000019000000000001042d000015bf00000432000015c00001042e000015c1000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff000000020000000000000000000000000000008000000100000000000000000008c379a000000000000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65640000000000000000000000000000000000000000000000000000000000000000000000000084000000a00000000000000000000000000000000000000000000000000000000000000000000000008129fc1b00000000000000000000000000000000000000000000000000000000cf8fbec800000000000000000000000000000000000000000000000000000000edf6d55900000000000000000000000000000000000000000000000000000000f50ddbc600000000000000000000000000000000000000000000000000000000f50ddbc700000000000000000000000000000000000000000000000000000000fbc4972d00000000000000000000000000000000000000000000000000000000fe9fbb8000000000000000000000000000000000000000000000000000000000edf6d55a00000000000000000000000000000000000000000000000000000000f2f6596000000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000e8e914b700000000000000000000000000000000000000000000000000000000e8e914b800000000000000000000000000000000000000000000000000000000e901386c00000000000000000000000000000000000000000000000000000000ec97908200000000000000000000000000000000000000000000000000000000cf8fbec900000000000000000000000000000000000000000000000000000000d547741f00000000000000000000000000000000000000000000000000000000e44542df00000000000000000000000000000000000000000000000000000000ada8f91800000000000000000000000000000000000000000000000000000000b083327300000000000000000000000000000000000000000000000000000000b083327400000000000000000000000000000000000000000000000000000000b1283e7700000000000000000000000000000000000000000000000000000000bbe9f99d00000000000000000000000000000000000000000000000000000000ada8f91900000000000000000000000000000000000000000000000000000000ae169a5000000000000000000000000000000000000000000000000000000000b06c1ba30000000000000000000000000000000000000000000000000000000097dc97ca0000000000000000000000000000000000000000000000000000000097dc97cb00000000000000000000000000000000000000000000000000000000a06db7dc00000000000000000000000000000000000000000000000000000000a217fddf000000000000000000000000000000000000000000000000000000008129fc1c000000000000000000000000000000000000000000000000000000008da5cb5b0000000000000000000000000000000000000000000000000000000091d148540000000000000000000000000000000000000000000000000000000049d5e6030000000000000000000000000000000000000000000000000000000058b578bf000000000000000000000000000000000000000000000000000000006ae89736000000000000000000000000000000000000000000000000000000006ae8973700000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000007b053df40000000000000000000000000000000000000000000000000000000058b578c0000000000000000000000000000000000000000000000000000000005cf4ee910000000000000000000000000000000000000000000000000000000060557333000000000000000000000000000000000000000000000000000000004fcf9e02000000000000000000000000000000000000000000000000000000004fcf9e030000000000000000000000000000000000000000000000000000000052d1902d0000000000000000000000000000000000000000000000000000000053ac55f50000000000000000000000000000000000000000000000000000000049d5e604000000000000000000000000000000000000000000000000000000004ef39e0e000000000000000000000000000000000000000000000000000000004f1ef286000000000000000000000000000000000000000000000000000000002c8bff30000000000000000000000000000000000000000000000000000000003659cfe5000000000000000000000000000000000000000000000000000000003659cfe600000000000000000000000000000000000000000000000000000000399567b9000000000000000000000000000000000000000000000000000000003eb2b5ad000000000000000000000000000000000000000000000000000000002c8bff31000000000000000000000000000000000000000000000000000000002f2ff15d0000000000000000000000000000000000000000000000000000000036568abe0000000000000000000000000000000000000000000000000000000014eba0250000000000000000000000000000000000000000000000000000000014eba02600000000000000000000000000000000000000000000000000000000248a9ca30000000000000000000000000000000000000000000000000000000024d7806c0000000000000000000000000000000000000000000000000000000001ffc9a700000000000000000000000000000000000000000000000000000000059a3384000000000000000000000000000000000000000000000000000000000ddd02a1000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff2f3f579cec0e5574e53401a6a7dc7efd1ef9933fcb83a4ab1796de62c242b8c40200000000000000000000000000000000000040000000000000000000000000c625d24caaecf530bd72996040e3eb05562aec665da486c03dab44421990fd1e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000ffffffbffdffffffffffffffffffffffffffffffffffffc00000000000000000000000008679c217a95b895d3c7a63afa1d6bd7d8b421f63c729fce98f3f1b89549ca59a726f0000000000000000000000000000000000000000000000000000000000004b2076616c756573206d7573742062652067726561746572207468616e207a6500000000000000000000000000000000000000840000000000000000000000004b2072616e67652065786365656473206d6178696d756d206c656e677468000000000000000000000000000000000000000000640000000000000000000000004b2072616e67652063616e6e6f7420626520656d70747900000000000000000000000000000000000000000000000000000000200000008000000000000000004f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000840000008000000000000000000000000000000000000000000000000000000000000000000000000001e13381020000000000000000000000000000000000002000000080000000000000000033d1191f5a3abfe19d468d51bb5ece97489f1277a912a5b5c65992fc279ad3d4477261636520706572696f642065786365656473206d6178696d756d206c696d6974000000000000000000000000000000000000000000000000000000000000477261636520706572696f64206d7573742062652067726561746572207468616e207a65726f0000000000000000000000000000000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391320200000200000000000000000000000000000004000000000000000000000000477261636520706572696f64206e6f7420656e646564000000000000000000000200000000000000000000000000000000000020000000000000000000000000faae1a41726009a7db0f69fd2f71bf067fb48bedf10ec9d7efd2edb55b2787f14e6f20756e636c61696d65642072657761726473000000000000000000000000526f6c65733a2043616c6c6572206973206e6f7420617574686f72697a65640000000000000000000000000000000000000000640000008000000000000000004d61726b65744d616e616765723a204d61726b657420646f6573206e6f7420657869737400000000000000000000000000000000000000000000000000000000736f6c76656400000000000000000000000000000000000000000000000000004d61726b65744d616e616765723a204d61726b657420616c72656164792072654d61726b65744d616e616765723a204d61726b657420657870697265640000007468616e207a65726f00000000000000000000000000000000000000000000004e756d626572206f66207573657273206d7573742062652067726561746572200000000000000000000000000000000000000000000000000de0b6b3a763ffff0000000000000000000000000000000000000000000000008ac7230489e7ffffffffffffffffffffffffffffffffffffffffffffffffffffe00b930ebafae90bffffffffffffffffffffffffffffffffffffffffffffffffe00b930ebafae90c0000000000000000000000000000000000000000000000056bc75e2d630fffff0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000fffffffffffffffffffffffffffc0000fffffffffffffffffffffffffffffffffffffffffffffffff21f494c589c0000a6b830b74e52d7d1140e76252f225dc7bed28782519845600bbd3182341dc11502000000000000000000000000000000000000600000000000000000000000006226e2b93095e20aa7dd8de941f901b5912ba2e016db413ceef703147b414ce54578706f6e656e7469616c2073756d206d75737420626520677265617465722068616e207a65726f00000000000000000000000000000000000000000000000042617365206c6971756964697479206d75737420626520677265617465722074496e76616c6964206b2076616c756500000000000000000000000000000000004b2072616e6765206e6f7420696e697469616c697a65640000000000000000004d61726b65744d616e616765723a20506f696e7473206d7573742062652067726561746572207468616e207a65726f00000000000000000000000000000000005146a08baf902532d0ee2f909971144f12ca32651cd70cbee1117cddfb3b3b334d61726b657420646f6573206e6f74206578697374000000000000000000000072650000000000000000000000000000000000000000000000000000000000004e657720656e642074696d65206d75737420626520696e207468652066757475f8319b4f77d193e862e5beb21f5165da7314bc5962cd6b8838f2e2a6c77cc1db456e642074696d6520697320616c72656164792073657400000000000000000081fe90a866a48a634a12852c1be675b683a22307409932a7443b8029347be756ffffffffffffffffffffffff0000000000000000000000000000000000000000526f6c65733a20496e76616c69642063616c6c657220616464726573730000000000000000000000000000000000000000000160000000800000000000000000526f6c65733a204e6f2063616c6c657220746f207265766f6b6500000000000000000000000000000000000000000000000000a0000000000000000000000000566f746573206d7573742062652067726561746572207468616e207a65726f00f01da32686223933d8a18a391060918c7f11a3648639edd87ae013e2e2731743696f6e0000000000000000000000000000000000000000000000000000000000546f74616c2066756e6473206d757374206265203e3d207573657220706f72744e6f207265776172647320746f20636c61696d000000000000000000000000004d61726b6574206e6f74207265736f6c766564000000000000000000000000005265656e7472616e637947756172643a207265656e7472616e742063616c6c004c545f41444d494e5f524f4c4500000000000000000000000000000000000000526f6c65733a204164647265737320616c72656164792068617320444546415581fe90a866a48a634a12852c1be675b683a22307409932a7443b8029347be75702000000000000000000000000000000000000000000000000000000000000002f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0df6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b000000000000000000000000000000000000000000000000ffffffffffffff9f00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3000000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000000030313233343536373839616263646566000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000537472696e67733a20686578206c656e67746820696e73756666696369656e74000000000000000000000000000000000000000000000000ffffffffffffff7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000206973206d697373696e6720726f6c6520000000000000000000000000000000526f6c65733a20496e76616c6964206e65772061646d696e20616464726573732044454641554c545f41444d494e5f524f4c4500000000000000000000000000526f6c65733a204e6f7420617574686f72697a6564202d2052657175697265731806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8302000002000000000000000000000000000000240000000000000000000000006e697469616c697a696e67000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e04f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65720000000000000000000000000000000000000000000000000000000000278d007f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024980000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000001bc16d674ec8000039da2db355130acf428d669fbf1c14faa9d51399a25b793fc254bbbde66f02e739da2db355130acf428d669fbf1c14faa9d51399a25b793fc254bbbde66f02e639da2db355130acf428d669fbf1c14faa9d51399a25b793fc254bbbde66f02e239da2db355130acf428d669fbf1c14faa9d51399a25b793fc254bbbde66f02e339da2db355130acf428d669fbf1c14faa9d51399a25b793fc254bbbde66f02e439da2db355130acf428d669fbf1c14faa9d51399a25b793fc254bbbde66f02e57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe04e6f206d61726b657473206578697374000000000000000000000000000000004d61726b657420616c7265616479207265736f6c766564000000000000000000f85843b53cd58e4cb402988148bc632d299ae8e30e550dd71f6b6d1b318c11416dfc24f0f2fb42e49fb4fa3ffa8abb148cab908a1fb8335b3f128a08b2594af150657263656e746167652063616e6e6f74206578636565642031303025000000496e76616c69642077696e6e696e67206f7074696f6e00000000000000000000496e76616c6964206f7074696f6e204944000000000000000000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e02000002000000000000000000000000000000440000000000000000000000006c6564207468726f7567682064656c656761746563616c6c0000000000000000555550535570677261646561626c653a206d757374206e6f742062652063616c360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914352d1902d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000006961626c6555554944000000000000000000000000000000000000000000000045524331393637557067726164653a20756e737570706f727465642070726f78bc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b0000000000000000000000000000000000000000000000a00000000000000000206661696c656400000000000000000000000000000000000000000000000000416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6e74726163740000000000000000000000000000000000000000000000000000416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f524f4c4500000000000000000000000000000000000000000000000000000000526f6c65733a204164647265737320616c726561647920686173205445414d5f2f3f579cec0e5574e53401a6a7dc7efd1ef9933fcb83a4ab1796de62c242b8c56163746976652070726f7879000000000000000000000000000000000000000046756e6374696f6e206d7573742062652063616c6c6564207468726f75676820000000000000000000000000000000000000000000000000ffffffffffffffdf6f74206120636f6e747261637400000000000000000000000000000000000000455243313936373a206e657720696d706c656d656e746174696f6e206973206e64656c656761746563616c6c0000000000000000000000000000000000000000416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636520726f6c657320666f722073656c6600000000000000000000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000004d5f524f4c450000000000000000000000000000000000000000000000000000526f6c65733a204164647265737320646f6573206e6f74206861766520544541526f6c65733a20496e76616c6964206164647265737300000000000000000000456e642074696d65206d75737420626520696e20746865206675747572650000000000000000000000000000000000000000000000000000fffffffffffffea0ed25ec23d979bebc7c6a7e5ffebb0fbd64b71f7e6dc13dec21f220f5b91081b9436f6d6d697373696f6e20657863656564732031303025000000000000000000496e76616c6964207175657374696f6e49640000000000000000000000000000205445414d5f524f4c450000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff01ffc9a7000000000000000000000000000000000000000000000000000000007965db0b00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffa06f6e206973206e6f74205555505300000000000000000000000000000000000045524331393637557067726164653a206e657720696d706c656d656e7461746900000000000000000000000000000000000000000000000000000000000000000b7428c3e9719db6a628cfe7967fa32d69925c172756ff7d7507e968297f946e
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.