Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 5,393 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Purchase Token W... | 19549436 | 323 days ago | IN | 0.1 ETH | 0.00061446 | ||||
Purchase Token W... | 19544735 | 324 days ago | IN | 0.125 ETH | 0.00061181 | ||||
Purchase Token W... | 19537520 | 325 days ago | IN | 0.1 ETH | 0.00062872 | ||||
Purchase Token W... | 19534945 | 325 days ago | IN | 0.15 ETH | 0.00095308 | ||||
Purchase Token W... | 19533342 | 325 days ago | IN | 0.1 ETH | 0.0059093 | ||||
Purchase Token W... | 19533338 | 325 days ago | IN | 0.3 ETH | 0.00607853 | ||||
Purchase Token W... | 19533337 | 325 days ago | IN | 0.23 ETH | 0.00707395 | ||||
Purchase Token W... | 19533335 | 325 days ago | IN | 0.1 ETH | 0.00711231 | ||||
Purchase Token W... | 19533334 | 325 days ago | IN | 0.5 ETH | 0.00711374 | ||||
Purchase Token W... | 19533333 | 325 days ago | IN | 0.1 ETH | 0.0070824 | ||||
Purchase Token W... | 19533329 | 325 days ago | IN | 0.14 ETH | 0.00663893 | ||||
Purchase Token W... | 19533328 | 325 days ago | IN | 0.1 ETH | 0.00750209 | ||||
Purchase Token W... | 19533326 | 325 days ago | IN | 0.5 ETH | 0.00694423 | ||||
Purchase Token W... | 19533325 | 325 days ago | IN | 0.11 ETH | 0.00696478 | ||||
Purchase Token W... | 19533322 | 325 days ago | IN | 0.42 ETH | 0.00588237 | ||||
Purchase Token W... | 19533316 | 325 days ago | IN | 0.4 ETH | 0.00689558 | ||||
Purchase Token W... | 19533312 | 325 days ago | IN | 0.1 ETH | 0.00646468 | ||||
Purchase Token W... | 19533309 | 325 days ago | IN | 0.1 ETH | 0.0063368 | ||||
Purchase Token W... | 19533308 | 325 days ago | IN | 0.1 ETH | 0.00720516 | ||||
Purchase Token W... | 19533307 | 325 days ago | IN | 0.5 ETH | 0.00633808 | ||||
Purchase Token W... | 19533306 | 325 days ago | IN | 0.1 ETH | 0.00687392 | ||||
Purchase Token W... | 19533306 | 325 days ago | IN | 0.5 ETH | 0.00705509 | ||||
Purchase Token W... | 19533305 | 325 days ago | IN | 0.11 ETH | 0.00645988 | ||||
Purchase Token W... | 19533305 | 325 days ago | IN | 0.1025 ETH | 0.00703874 | ||||
Purchase Token W... | 19533304 | 325 days ago | IN | 0.5 ETH | 0.00580228 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
19533342 | 325 days ago | 0.1 ETH | ||||
19533338 | 325 days ago | 0.3 ETH | ||||
19533337 | 325 days ago | 0.23 ETH | ||||
19533335 | 325 days ago | 0.1 ETH | ||||
19533334 | 325 days ago | 0.5 ETH | ||||
19533333 | 325 days ago | 0.1 ETH | ||||
19533329 | 325 days ago | 0.14 ETH | ||||
19533328 | 325 days ago | 0.1 ETH | ||||
19533326 | 325 days ago | 0.5 ETH | ||||
19533325 | 325 days ago | 0.11 ETH | ||||
19533322 | 325 days ago | 0.42 ETH | ||||
19533316 | 325 days ago | 0.4 ETH | ||||
19533312 | 325 days ago | 0.1 ETH | ||||
19533309 | 325 days ago | 0.1 ETH | ||||
19533308 | 325 days ago | 0.1 ETH | ||||
19533307 | 325 days ago | 0.5 ETH | ||||
19533306 | 325 days ago | 0.1 ETH | ||||
19533306 | 325 days ago | 0.5 ETH | ||||
19533305 | 325 days ago | 0.11 ETH | ||||
19533305 | 325 days ago | 0.1025 ETH | ||||
19533304 | 325 days ago | 0.5 ETH | ||||
19533302 | 325 days ago | 0.1 ETH | ||||
19533296 | 325 days ago | 0.11 ETH | ||||
19533295 | 325 days ago | 0.5 ETH | ||||
19533294 | 325 days ago | 0.1 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
PreSaleDop
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IAggregatorV3 } from "./IAggregatorV3.sol"; /// @title PreSaleDop contract /// @notice Implements the preSale of DOP token for testnet users /// @notice The presale contract allows you to purchase dop token with allowed tokens /// @notice The recorded DOP tokens and NFT claims will be distributed later using another distributor contract. contract PreSaleDop is ReentrancyGuard, Ownable { using Address for address payable; /// @notice Thrown when purchase time is not started error PurchaseNotStarted(); /// @notice Thrown when purchase time is ended error PurchaseEnded(); /// @notice Thrown when address is blacklisted error Blacklisted(); /// @notice Thrown when purchase is disabled error PurchaseDisabled(); /// @notice Thrown when sign deadline is expired error DeadlineExpired(); /// @notice Thrown when Sign is invalid error InvalidSignature(); /// @notice Thrown when Eth price suddenly drops while purchasing with ETH error UnexpectedPriceDifference(); /// @notice Thrown when value to transfer is zero error ZeroValue(); /// @notice Thrown when minAllowed is greater than maxAllowed error MinValueExceedsMaxValue(); /// @notice Thrown when price from priceFeed is zero error PriceNotFound(); /// @notice Thrown if the price is not updated error PriceNotUpdated(); /// @notice Thrown if the roundId of price is not updated error RoundIdNotUpdated(); /// @notice Thrown when the start time is invalid error InvalidStartTime(); /// @notice Thrown when the end time is invalid error InvalidEndTime(); /// @notice Thrown when purchase amount is less than minimum allowed error PurchaseBelowMinimum(); /// @notice Thrown when updating with the same value as previously stored error IdenticalValue(); /// @notice Thrown when updating an address with zero address error ZeroAddress(); /// @notice It is use to calculate dop value uint8 private immutable NORMALIZATION_FACTOR; /// @notice That isPurchaseEnabled or not bool public isPurchaseEnabled = true; /// @notice Time to start purchases uint256 public immutable purchaseStartTime; /// @notice Time to end purchases uint256 public immutable purchaseEndTime; /// @notice Price of token uint256 public immutable tokenPrice; /// @notice Allocation of every user. No user can purchase more than this value. uint256 public immutable maxAllowed; /// @notice No user can purchase less than this value. uint256 public immutable minAllowed; /// @notice Price updation time difference uint256 public immutable PRICE_UPDATE_TIMEOUT; /// @notice The price feed contract address IAggregatorV3 internal immutable dataFeed; /// @notice The address of signerWallet address public signerWallet; /// @notice The address of fundsWallet address public fundsWallet; /// @notice Gives claim info of user mapping(address => uint256) public claims; /// @notice Gives purchases of the users mapping(address => uint256) public purchases; /// @notice Gives info about address's permission mapping(address => bool) public blacklistAddress; /// @dev Emitted when dop is purchased with ETH event PurchasedWithETH(address indexed by, uint256 amountPurchasedEth, uint256 dopPurchased); /// @dev Emitted when address of signer is updated event SignerUpdated(address oldSigner, address newSigner); /// @dev Emitted when address of funds wallet is updated event FundsWalletUpdated(address oldAddress, address newAddress); /// @dev Emitted when blacklist access of address is updated event BlacklistUpdated(address which, bool accessNow); /// @dev Emitted when purchase access changes event PurchaseEnableUpdated(bool oldStatus, bool newStatus); /// @dev Emitted when starting token purchase event PurchaseCreated(uint256 indexed startTime, uint256 indexed endTime, uint256 indexed price); /// @notice Restricts when updating wallet/contract address to zero address modifier checkAddressZero(address which) { if (which == address(0)) { revert ZeroAddress(); } _; } /// @notice Ensures that purchase is enabled when purchasing modifier canPurchase() { if (!isPurchaseEnabled) { revert PurchaseDisabled(); } _; } /// @dev Constructor /// @param fundsWalletAddress The address of funds wallet /// @param signerAddress The address of signer wallet /// @param owner The address of owner wallet /// @param priceFeed The address of price feed contract /// @param startTime The start time of the purchase /// @param endTime The end time of the purchase /// @param price The DOP Token price in 18 decimals, because our calculations returns a value in 36 decimals and to get returning value in 18 decimals we divide by purchase price /// @param minimumDifference Time difference to check if ETH live price update occured in it /// @param maxPurchasePerUser Maximum limit of funds a user can particapte from /// @param minPurchasePerUser Minimum limit of funds a user can particapte from constructor( address fundsWalletAddress, address signerAddress, address owner, address priceFeed, uint8 normalizationFactor, uint256 startTime, uint256 endTime, uint256 price, uint256 minimumDifference, uint256 maxPurchasePerUser, uint256 minPurchasePerUser ) Ownable(owner) { if ( fundsWalletAddress == address(0) || signerAddress == address(0) || owner == address(0) || priceFeed == address(0) ) { revert ZeroAddress(); } if (normalizationFactor == 0 || minimumDifference == 0 || maxPurchasePerUser == 0 || minPurchasePerUser == 0) { revert ZeroValue(); } if (minPurchasePerUser > maxPurchasePerUser) { revert MinValueExceedsMaxValue(); } if (startTime < block.timestamp) { revert InvalidStartTime(); } if (endTime <= startTime) { revert InvalidEndTime(); } purchaseStartTime = startTime; purchaseEndTime = endTime; tokenPrice = price; fundsWallet = fundsWalletAddress; signerWallet = signerAddress; dataFeed = IAggregatorV3(priceFeed); maxAllowed = maxPurchasePerUser; minAllowed = minPurchasePerUser; NORMALIZATION_FACTOR = normalizationFactor; PRICE_UPDATE_TIMEOUT = minimumDifference; emit PurchaseCreated({ startTime: startTime, endTime: endTime, price: price }); } /// @notice Changes access of purchase /// @param enabled The decision about purchase function enablePurchase(bool enabled) external onlyOwner { if (isPurchaseEnabled == enabled) { revert IdenticalValue(); } emit PurchaseEnableUpdated({ oldStatus: isPurchaseEnabled, newStatus: enabled }); isPurchaseEnabled = enabled; } /// @notice Changes signer wallet address /// @param newSigner The address of the new signer wallet function changeSigner(address newSigner) external checkAddressZero(newSigner) onlyOwner { address oldSigner = signerWallet; if (oldSigner == newSigner) { revert IdenticalValue(); } emit SignerUpdated({ oldSigner: oldSigner, newSigner: newSigner }); signerWallet = newSigner; } /// @notice Changes funds wallet to a new address /// @param newFundsWallet The address of the new funds wallet function changeFundsWallet(address newFundsWallet) external checkAddressZero(newFundsWallet) onlyOwner { address oldWallet = fundsWallet; if (oldWallet == newFundsWallet) { revert IdenticalValue(); } emit FundsWalletUpdated({ oldAddress: oldWallet, newAddress: newFundsWallet }); fundsWallet = newFundsWallet; } /// @notice Changes the access of any address in contract interaction /// @param which The address for which access is updated /// @param access The access decision of `which` address function updateBlackListedUser(address which, bool access) external checkAddressZero(which) onlyOwner { bool oldAccess = blacklistAddress[which]; if (oldAccess == access) { revert IdenticalValue(); } emit BlacklistUpdated({ which: which, accessNow: access }); blacklistAddress[which] = access; } /// @notice Purchases dopToken with Eth /// @param deadline The deadline is validity of the signature /// @param minAmountDop The minAmountDop user agrees to purchase /// @param v The `v` signature parameter /// @param r The `r` signature parameter /// @param s The `s` signature parameter function purchaseTokenWithEth( uint256 deadline, uint256 minAmountDop, uint8 v, bytes32 r, bytes32 s ) external payable canPurchase nonReentrant { // The input must have been signed by the presale signer uint256 actualPurchaseAmount = msg.value; uint256 prevPurchase = purchases[msg.sender]; uint256 maxPurchaseAllowed = maxAllowed; if (prevPurchase + actualPurchaseAmount < minAllowed) { revert PurchaseBelowMinimum(); } if (prevPurchase + actualPurchaseAmount > maxPurchaseAllowed) { actualPurchaseAmount = maxPurchaseAllowed - prevPurchase; payable(msg.sender).sendValue(msg.value - actualPurchaseAmount); } _validatePurchaseWithEth(actualPurchaseAmount, deadline, v, r, s); uint256 latestPrice = getLatestPrice(); if (latestPrice == 0) { revert PriceNotFound(); } uint256 toReturn = _calculateDop(actualPurchaseAmount, latestPrice, NORMALIZATION_FACTOR, tokenPrice); if (toReturn < minAmountDop) { revert UnexpectedPriceDifference(); } claims[msg.sender] += toReturn; purchases[msg.sender] = prevPurchase + actualPurchaseAmount; payable(fundsWallet).sendValue(actualPurchaseAmount); emit PurchasedWithETH({ by: msg.sender, amountPurchasedEth: actualPurchaseAmount, dopPurchased: toReturn }); } /// @notice Returns the user claim /// @param user Address of user function getClaims(address user) external view returns (uint256) { return claims[user]; } /// @notice The Chainlink inherited function, give us ETH live price function getLatestPrice() public view returns (uint256) { ( uint80 roundId, /*uint80 roundID*/ int price /*uint256 startedAt*/ /*uint80 answeredInRound*/, , uint256 updatedAt, ) = /*uint256 timeStamp*/ dataFeed.latestRoundData(); if (roundId == 0) { revert RoundIdNotUpdated(); } if (updatedAt == 0 || block.timestamp - updatedAt > PRICE_UPDATE_TIMEOUT) { revert PriceNotUpdated(); } return uint256(price); } /// @notice Checks value, if zero then reverts function _checkValue(uint256 value) private pure { if (value == 0) { revert ZeroValue(); } } /// @notice The helper function which verifies signature, signed by signerWallet, reverts if Invalid function _verifySign(uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) private view { bytes32 encodedMessageHash = keccak256(abi.encodePacked(msg.sender, amount, deadline)); _verifyMessage(encodedMessageHash, v, r, s); } /// @notice Verifies the address that signed a hashed message (`hash`) with /// `signature` function _verifyMessage(bytes32 encodedMessageHash, uint8 v, bytes32 r, bytes32 s) private view { if (signerWallet != ECDSA.recover(MessageHashUtils.toEthSignedMessageHash(encodedMessageHash), v, r, s)) { revert InvalidSignature(); } } /// @notice Checks that address is blacklisted or not function _checkBlacklist(address which) private view { if (blacklistAddress[which]) { revert Blacklisted(); } } /// @notice Validates value, deadline and signature function _validatePurchaseWithEth(uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) private view { _verifyInPurchase(); _checkValue(amount); _validatePurchase(deadline); _verifySign(amount, deadline, v, r, s); } /// @notice Calculates the dop amount function _calculateDop( uint256 purchaseAmount, uint256 referenceTokenPrice, uint256 normalizationFactor, uint256 price ) private pure returns (uint256) { return (purchaseAmount * referenceTokenPrice * (10 ** normalizationFactor)) / price; } /// @notice Validates blacklist address and deadline function _validatePurchase(uint256 deadline) private view { if (block.timestamp > deadline) { revert DeadlineExpired(); } _checkBlacklist(msg.sender); } /// @notice Checks purchase start and end time, reverts if Invalid function _verifyInPurchase() internal view { if (block.timestamp < purchaseStartTime) { revert PurchaseNotStarted(); } if (block.timestamp >= purchaseEndTime) { revert PurchaseEnded(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "../Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; 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_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; interface IAggregatorV3 { /// @notice Returns the number of decimals used to get its user representation. /// For example, if `decimals` equals `2`, a balance of `505` tokens should /// be displayed to a user as `5.05` (`505 / 10 ** 2`). function decimals() external view returns (uint8); /// @notice returns the description of the aggregator the proxy points to. function description() external view returns (string memory); /// @notice the version number representing the type of aggregator the proxy points to. function version() external view returns (uint256); /// @notice get data about a round. Consumers are encouraged to check /// that they're receiving fresh data by inspecting the updatedAt and /// answeredInRound return values. /// Note that different underlying implementations of AggregatorV3Interface /// have slightly different semantics for some of the return values. Consumers /// should determine what implementations they expect to receive /// data from and validate that they can properly handle return data from all /// of them. /// @param _roundId the round ID to retrieve the round data for /// @return roundId is the round ID from the aggregator for which the data was /// retrieved combined with a phase to ensure that round IDs get larger as /// time moves forward. /// @return answer is the answer for the given round /// @return startedAt is the timestamp when the round was started. /// (Only some AggregatorV3Interface implementations return meaningful values) /// @return updatedAt is the timestamp when the round last was updated (i.e. /// answer was last computed) /// @return answeredInRound is the round ID of the round in which the answer /// was computed. /// (Only some AggregatorV3Interface implementations return meaningful values) /// @dev Note that answer and updatedAt may change between queries. function getRoundData( uint80 _roundId ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); /// @notice get data about the latest round. Consumers are encouraged to check /// that they're receiving fresh data by inspecting the updatedAt and /// answeredInRound return values. /// Note that different underlying implementations of AggregatorV3Interface /// have slightly different semantics for some of the return values. Consumers /// should determine what implementations they expect to receive /// data from and validate that they can properly handle return data from all /// of them. /// @return roundId is the round ID from the aggregator for which the data was /// retrieved combined with a phase to ensure that round IDs get larger as /// time moves forward. /// @return answer is the answer for the given round /// @return startedAt is the timestamp when the round was started. /// (Only some AggregatorV3Interface implementations return meaningful values) /// @return updatedAt is the timestamp when the round last was updated (i.e. /// answer was last computed) /// @return answeredInRound is the round ID of the round in which the answer /// was computed. /// (Only some AggregatorV3Interface implementations return meaningful values) /// @dev Note that answer and updatedAt may change between queries. function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 1000000 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"fundsWalletAddress","type":"address"},{"internalType":"address","name":"signerAddress","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"normalizationFactor","type":"uint8"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"minimumDifference","type":"uint256"},{"internalType":"uint256","name":"maxPurchasePerUser","type":"uint256"},{"internalType":"uint256","name":"minPurchasePerUser","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"Blacklisted","type":"error"},{"inputs":[],"name":"DeadlineExpired","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"IdenticalValue","type":"error"},{"inputs":[],"name":"InvalidEndTime","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidStartTime","type":"error"},{"inputs":[],"name":"MinValueExceedsMaxValue","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"PriceNotFound","type":"error"},{"inputs":[],"name":"PriceNotUpdated","type":"error"},{"inputs":[],"name":"PurchaseBelowMinimum","type":"error"},{"inputs":[],"name":"PurchaseDisabled","type":"error"},{"inputs":[],"name":"PurchaseEnded","type":"error"},{"inputs":[],"name":"PurchaseNotStarted","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"RoundIdNotUpdated","type":"error"},{"inputs":[],"name":"UnexpectedPriceDifference","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"which","type":"address"},{"indexed":false,"internalType":"bool","name":"accessNow","type":"bool"}],"name":"BlacklistUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"FundsWalletUpdated","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":"startTime","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endTime","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"price","type":"uint256"}],"name":"PurchaseCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"oldStatus","type":"bool"},{"indexed":false,"internalType":"bool","name":"newStatus","type":"bool"}],"name":"PurchaseEnableUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountPurchasedEth","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dopPurchased","type":"uint256"}],"name":"PurchasedWithETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldSigner","type":"address"},{"indexed":false,"internalType":"address","name":"newSigner","type":"address"}],"name":"SignerUpdated","type":"event"},{"inputs":[],"name":"PRICE_UPDATE_TIMEOUT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"blacklistAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newFundsWallet","type":"address"}],"name":"changeFundsWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSigner","type":"address"}],"name":"changeSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claims","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"enablePurchase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fundsWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getClaims","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLatestPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPurchaseEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxAllowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minAllowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"purchaseEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"purchaseStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"minAmountDop","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"purchaseTokenWithEth","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"purchases","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signerWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"which","type":"address"},{"internalType":"bool","name":"access","type":"bool"}],"name":"updateBlackListedUser","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
610180346200032f57601f620019d238819003918201601f19168301916001600160401b038311848410176200033457808492610160946040528339810103126200032f576200004f816200034a565b906200005e602082016200034a565b6200006c604083016200034a565b916200007b606082016200034a565b91608082015160ff811681036200032f5760a08301519460c08401519360e08101519561010098898301519561014061012085015194015194600160005560018060a01b03811615620003165760015460405191906001600160a01b038083169082167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a36001600160a81b0319166001600160a01b0391821617600160a01b17600155831615801562000304575b8015620002fb575b8015620002e9575b620002da575060ff8616158015620002d1575b8015620002c8575b8015620002bf575b620002ad578385116200029b57428a10620002895789881115620002775760a08a905260c088905260e0899052600380546001600160a01b03199081166001600160a01b039485161790915560028054909116918316919091179055166101605287526101205260805261014052604051927f442ed730700f838241cae3355e84e2b2eb8d00b406665a43d705feb51a9d69e4600080a4611672918262000360833960805182610c51015260a051828181610b080152610fec015260c051828181610b2f0152611045015260e05182818161078e0152610c2a01525181818161050e0152610aa50152610120518181816107e70152610ad00152610140518181816109230152611281015261016051816111f30152f35b6040516338af65f760e01b8152600490fd5b604051632ca4094f60e21b8152600490fd5b604051633421d59f60e11b8152600490fd5b604051637c946ed760e01b8152600490fd5b50841562000160565b50831562000158565b50861562000150565b63d92e233d60e01b8152600490fd5b506001600160a01b038416156200013d565b50600062000135565b506001600160a01b038216156200012d565b604051631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036200032f5756fe608060408181526004908136101561001657600080fd5b600092833560e01c9081632194f3a214611068575080632f0e23fb1461100f57806355832ffc14610fb65780635f14b71a14610f7157806361e27eca14610a3a57806364f0d35e146109e7578063715018a6146109465780637a5b70f5146108ed5780637d6f0d5f1461080a5780637fb30c35146107b15780637ff9b59614610758578063842a77d3146106f65780638da5cb5b146106a35780638e15f47314610661578063aad2b72314610531578063c6788bdd14610477578063ca399671146104d8578063d0d46a0b14610477578063e09590d114610363578063f2fde38b1461027e578063f3290d75146102135763f7446dec1461011657600080fd5b3461020f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f5781359081151580920361020b5761015a611467565b6001549260ff8460a01c161515908382146101e45750917fc23ab846138884adee4f764a9dcf892428b1337bc9b30ffe6506ae2fec4bacaa827fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9474ff00000000000000000000000000000000000000009451908152836020820152a160a01b1691161760015580f35b82517f2620eb3a000000000000000000000000000000000000000000000000000000008152fd5b8380fd5b8280fd5b83823461027a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760ff8160209373ffffffffffffffffffffffffffffffffffffffff6102676110b8565b1681526006855220541690519015158152f35b5080fd5b50903461020f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f576102b76110b8565b906102c0611467565b73ffffffffffffffffffffffffffffffffffffffff809216928315610334575050600154827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b908460249251917f1e4fbdf7000000000000000000000000000000000000000000000000000000008352820152fd5b503461020f57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f5761039a6110b8565b91602435928315158094036104735773ffffffffffffffffffffffffffffffffffffffff1690811561044c576103ce611467565b81855260066020528360ff84872054161515146101e457507f6a12b3df6cba4203bd7fd06b816789f87de8c594299aed5717ae070fac781bac828051838152856020820152a18352600660205282209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00835416911617905580f35b82517fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b8480fd5b50903461020f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f57602092829173ffffffffffffffffffffffffffffffffffffffff6104ca6110b8565b168252845220549051908152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b50903461020f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f5761056a6110b8565b73ffffffffffffffffffffffffffffffffffffffff9182821693841561063b57610592611467565b6002549384169185831461061457505173ffffffffffffffffffffffffffffffffffffffff9182168152911660208201527fffffffffffffffffffffffff000000000000000000000000000000000000000091907f2d025324f0a785e8c12d0a0d91a9caa49df4ef20ff87e0df7213a1d4f3157beb90604090a1161760025580f35b90517f2620eb3a000000000000000000000000000000000000000000000000000000008152fd5b517fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760209061069c6111b0565b9051908152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760209073ffffffffffffffffffffffffffffffffffffffff600154169051908152f35b83823461027a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a578060209273ffffffffffffffffffffffffffffffffffffffff6107486110b8565b1681526005845220549051908152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b50903461020f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f576108436110b8565b73ffffffffffffffffffffffffffffffffffffffff9182821693841561063b5761086b611467565b6003549384169185831461061457505173ffffffffffffffffffffffffffffffffffffffff9182168152911660208201527fffffffffffffffffffffffff000000000000000000000000000000000000000091907fe22b566ac7db56412e2e041c88a7fd3151151ad6c6647e954f9bdc054bcb780e90604090a1161760035580f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b83346109e457807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109e45761097d611467565b8073ffffffffffffffffffffffffffffffffffffffff6001547fffffffffffffffffffffffff00000000000000000000000000000000000000008116600155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760209073ffffffffffffffffffffffffffffffffffffffff600254169051908152f35b50829060a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760443590833560ff8316830361020b5760ff60015460a01c1615610f49576002845414610f21576002845534923385526020906005825283862054927f0000000000000000000000000000000000000000000000000000000000000000610ace34866110e0565b7f000000000000000000000000000000000000000000000000000000000000000011610ef95780610aff34876110e0565b11610ed2575b507f00000000000000000000000000000000000000000000000000000000000000004210610eaa577f0000000000000000000000000000000000000000000000000000000000000000421015610e82578515610e5a57804211610e32573387526006835260ff8588205416610e0a578451838101913360601b83528760348301526054820152605481526080810181811067ffffffffffffffff821117610dde5790610c0b939291875251902090610c1473ffffffffffffffffffffffffffffffffffffffff9384928360025416947f19457468657265756d205369676e6564204d6573736167653a0a3332000000008c52601c526084359060643590603c8d206114b8565b90929192611555565b1603610db657610c226111b0565b8015610d8e577f000000000000000000000000000000000000000000000000000000000000000090610c7860ff7f0000000000000000000000000000000000000000000000000000000000000000169188611454565b90604d8111610d625790610c8f91600a0a90611454565b8115610d365704926024358410610d0e5794610cfc91610ce8827f75d069e9e7e0d67d46bb0585fe6b1067253ac1e9c3f2ac5ec8a6f404926f83a298819a9b338d528752888c20610ce18982546110e0565b90556110e0565b338a5260058552868a205560035416611340565b82519485528401523392a26001815580f35b8785517fbde82093000000000000000000000000000000000000000000000000000000008152fd5b60248860128b7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b60248960118c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8785517f358e2ce7000000000000000000000000000000000000000000000000000000008152fd5b8684517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b60248960418c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8785517f09550c77000000000000000000000000000000000000000000000000000000008152fd5b8785517f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b8785517f7c946ed7000000000000000000000000000000000000000000000000000000008152fd5b8785517fd55f0066000000000000000000000000000000000000000000000000000000008152fd5b8785517f2e58aa51000000000000000000000000000000000000000000000000000000008152fd5b610edf919650849061111c565b94610ef3610eed873461111c565b33611340565b88610b05565b8886517fbd70f35d000000000000000000000000000000000000000000000000000000008152fd5b8482517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b8482517f654d7171000000000000000000000000000000000000000000000000000000008152fd5b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760209060ff60015460a01c1690519015158152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b84903461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760209073ffffffffffffffffffffffffffffffffffffffff600354168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff821682036110db57565b600080fd5b919082018092116110ed57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116110ed57565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761116a57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b519069ffffffffffffffffffff821682036110db57565b6040517ffeaf968c00000000000000000000000000000000000000000000000000000000815260a08160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa8015611334576000809281926112d1575b5069ffffffffffffffffffff16156112a7578015908115611274575b5061124a5790565b60046040517f1f4bcb2b000000000000000000000000000000000000000000000000000000008152fd5b61127f91504261111c565b7f00000000000000000000000000000000000000000000000000000000000000001038611242565b60046040517fa5959c59000000000000000000000000000000000000000000000000000000008152fd5b9250905060a0823d60a01161132c575b816112ee60a09383611129565b810103126109e4575061130081611199565b69ffffffffffffffffffff602083015191611322608060608601519501611199565b5091929190611226565b3d91506112e1565b6040513d6000823e3d90fd5b8147106114245773ffffffffffffffffffffffffffffffffffffffff90600080809481948294165af1903d1561141e573d9067ffffffffffffffff82116113f157604051916113b760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184611129565b825260203d92013e5b156113c757565b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526041600452fd5b506113c0565b60246040517fcd786059000000000000000000000000000000000000000000000000000000008152306004820152fd5b818102929181159184041417156110ed57565b73ffffffffffffffffffffffffffffffffffffffff60015416330361148857565b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161154957926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa1561153d57805173ffffffffffffffffffffffffffffffffffffffff81161561153457918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b600481101561160d5780611567575050565b600181036115995760046040517ff645eedf000000000000000000000000000000000000000000000000000000008152fd5b600281036115d257602482604051907ffce698f70000000000000000000000000000000000000000000000000000000082526004820152fd5b6003146115dc5750565b602490604051907fd78bce0c0000000000000000000000000000000000000000000000000000000082526004820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea26469706673582212206cb00b0ebe5d1e5bbe09378f3f847452f87fbeadf17576362d45c4d61cd42ba564736f6c63430008180033000000000000000000000000f95844e82447eba0ce9ede88810fdeab7b051d6200000000000000000000000080a931fc0fdb0062548e46cbc60a69d3b7383fdd0000000000000000000000009d0cf00f85015567084e79a76a65d6f5e912b8d20000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000006602808000000000000000000000000000000000000000000000000000000000660585f000000000000000000000000000000000000000000000000001235290c79500000000000000000000000000000000000000000000000000000000000000001c2000000000000000000000000000000000000000000000000006f05b59d3b20000000000000000000000000000000000000000000000000000016345785d8a0000
Deployed Bytecode
0x608060408181526004908136101561001657600080fd5b600092833560e01c9081632194f3a214611068575080632f0e23fb1461100f57806355832ffc14610fb65780635f14b71a14610f7157806361e27eca14610a3a57806364f0d35e146109e7578063715018a6146109465780637a5b70f5146108ed5780637d6f0d5f1461080a5780637fb30c35146107b15780637ff9b59614610758578063842a77d3146106f65780638da5cb5b146106a35780638e15f47314610661578063aad2b72314610531578063c6788bdd14610477578063ca399671146104d8578063d0d46a0b14610477578063e09590d114610363578063f2fde38b1461027e578063f3290d75146102135763f7446dec1461011657600080fd5b3461020f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f5781359081151580920361020b5761015a611467565b6001549260ff8460a01c161515908382146101e45750917fc23ab846138884adee4f764a9dcf892428b1337bc9b30ffe6506ae2fec4bacaa827fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9474ff00000000000000000000000000000000000000009451908152836020820152a160a01b1691161760015580f35b82517f2620eb3a000000000000000000000000000000000000000000000000000000008152fd5b8380fd5b8280fd5b83823461027a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760ff8160209373ffffffffffffffffffffffffffffffffffffffff6102676110b8565b1681526006855220541690519015158152f35b5080fd5b50903461020f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f576102b76110b8565b906102c0611467565b73ffffffffffffffffffffffffffffffffffffffff809216928315610334575050600154827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b908460249251917f1e4fbdf7000000000000000000000000000000000000000000000000000000008352820152fd5b503461020f57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f5761039a6110b8565b91602435928315158094036104735773ffffffffffffffffffffffffffffffffffffffff1690811561044c576103ce611467565b81855260066020528360ff84872054161515146101e457507f6a12b3df6cba4203bd7fd06b816789f87de8c594299aed5717ae070fac781bac828051838152856020820152a18352600660205282209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00835416911617905580f35b82517fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b8480fd5b50903461020f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f57602092829173ffffffffffffffffffffffffffffffffffffffff6104ca6110b8565b168252845220549051908152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f00000000000000000000000000000000000000000000000006f05b59d3b200008152f35b50903461020f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f5761056a6110b8565b73ffffffffffffffffffffffffffffffffffffffff9182821693841561063b57610592611467565b6002549384169185831461061457505173ffffffffffffffffffffffffffffffffffffffff9182168152911660208201527fffffffffffffffffffffffff000000000000000000000000000000000000000091907f2d025324f0a785e8c12d0a0d91a9caa49df4ef20ff87e0df7213a1d4f3157beb90604090a1161760025580f35b90517f2620eb3a000000000000000000000000000000000000000000000000000000008152fd5b517fd92e233d000000000000000000000000000000000000000000000000000000008152fd5b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760209061069c6111b0565b9051908152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760209073ffffffffffffffffffffffffffffffffffffffff600154169051908152f35b83823461027a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a578060209273ffffffffffffffffffffffffffffffffffffffff6107486110b8565b1681526005845220549051908152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f00000000000000000000000000000000000000000000000001235290c79500008152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f000000000000000000000000000000000000000000000000016345785d8a00008152f35b50903461020f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020f576108436110b8565b73ffffffffffffffffffffffffffffffffffffffff9182821693841561063b5761086b611467565b6003549384169185831461061457505173ffffffffffffffffffffffffffffffffffffffff9182168152911660208201527fffffffffffffffffffffffff000000000000000000000000000000000000000091907fe22b566ac7db56412e2e041c88a7fd3151151ad6c6647e954f9bdc054bcb780e90604090a1161760035580f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f0000000000000000000000000000000000000000000000000000000000001c208152f35b83346109e457807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109e45761097d611467565b8073ffffffffffffffffffffffffffffffffffffffff6001547fffffffffffffffffffffffff00000000000000000000000000000000000000008116600155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760209073ffffffffffffffffffffffffffffffffffffffff600254169051908152f35b50829060a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760443590833560ff8316830361020b5760ff60015460a01c1615610f49576002845414610f21576002845534923385526020906005825283862054927f00000000000000000000000000000000000000000000000006f05b59d3b20000610ace34866110e0565b7f000000000000000000000000000000000000000000000000016345785d8a000011610ef95780610aff34876110e0565b11610ed2575b507f00000000000000000000000000000000000000000000000000000000660280804210610eaa577f00000000000000000000000000000000000000000000000000000000660585f0421015610e82578515610e5a57804211610e32573387526006835260ff8588205416610e0a578451838101913360601b83528760348301526054820152605481526080810181811067ffffffffffffffff821117610dde5790610c0b939291875251902090610c1473ffffffffffffffffffffffffffffffffffffffff9384928360025416947f19457468657265756d205369676e6564204d6573736167653a0a3332000000008c52601c526084359060643590603c8d206114b8565b90929192611555565b1603610db657610c226111b0565b8015610d8e577f00000000000000000000000000000000000000000000000001235290c795000090610c7860ff7f000000000000000000000000000000000000000000000000000000000000000a169188611454565b90604d8111610d625790610c8f91600a0a90611454565b8115610d365704926024358410610d0e5794610cfc91610ce8827f75d069e9e7e0d67d46bb0585fe6b1067253ac1e9c3f2ac5ec8a6f404926f83a298819a9b338d528752888c20610ce18982546110e0565b90556110e0565b338a5260058552868a205560035416611340565b82519485528401523392a26001815580f35b8785517fbde82093000000000000000000000000000000000000000000000000000000008152fd5b60248860128b7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b60248960118c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8785517f358e2ce7000000000000000000000000000000000000000000000000000000008152fd5b8684517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b60248960418c7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8785517f09550c77000000000000000000000000000000000000000000000000000000008152fd5b8785517f1ab7da6b000000000000000000000000000000000000000000000000000000008152fd5b8785517f7c946ed7000000000000000000000000000000000000000000000000000000008152fd5b8785517fd55f0066000000000000000000000000000000000000000000000000000000008152fd5b8785517f2e58aa51000000000000000000000000000000000000000000000000000000008152fd5b610edf919650849061111c565b94610ef3610eed873461111c565b33611340565b88610b05565b8886517fbd70f35d000000000000000000000000000000000000000000000000000000008152fd5b8482517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b8482517f654d7171000000000000000000000000000000000000000000000000000000008152fd5b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760209060ff60015460a01c1690519015158152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f00000000000000000000000000000000000000000000000000000000660280808152f35b83823461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a57602090517f00000000000000000000000000000000000000000000000000000000660585f08152f35b84903461027a57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261027a5760209073ffffffffffffffffffffffffffffffffffffffff600354168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff821682036110db57565b600080fd5b919082018092116110ed57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116110ed57565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761116a57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b519069ffffffffffffffffffff821682036110db57565b6040517ffeaf968c00000000000000000000000000000000000000000000000000000000815260a08160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419165afa8015611334576000809281926112d1575b5069ffffffffffffffffffff16156112a7578015908115611274575b5061124a5790565b60046040517f1f4bcb2b000000000000000000000000000000000000000000000000000000008152fd5b61127f91504261111c565b7f0000000000000000000000000000000000000000000000000000000000001c201038611242565b60046040517fa5959c59000000000000000000000000000000000000000000000000000000008152fd5b9250905060a0823d60a01161132c575b816112ee60a09383611129565b810103126109e4575061130081611199565b69ffffffffffffffffffff602083015191611322608060608601519501611199565b5091929190611226565b3d91506112e1565b6040513d6000823e3d90fd5b8147106114245773ffffffffffffffffffffffffffffffffffffffff90600080809481948294165af1903d1561141e573d9067ffffffffffffffff82116113f157604051916113b760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184611129565b825260203d92013e5b156113c757565b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526041600452fd5b506113c0565b60246040517fcd786059000000000000000000000000000000000000000000000000000000008152306004820152fd5b818102929181159184041417156110ed57565b73ffffffffffffffffffffffffffffffffffffffff60015416330361148857565b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161154957926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa1561153d57805173ffffffffffffffffffffffffffffffffffffffff81161561153457918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b600481101561160d5780611567575050565b600181036115995760046040517ff645eedf000000000000000000000000000000000000000000000000000000008152fd5b600281036115d257602482604051907ffce698f70000000000000000000000000000000000000000000000000000000082526004820152fd5b6003146115dc5750565b602490604051907fd78bce0c0000000000000000000000000000000000000000000000000000000082526004820152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea26469706673582212206cb00b0ebe5d1e5bbe09378f3f847452f87fbeadf17576362d45c4d61cd42ba564736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f95844e82447eba0ce9ede88810fdeab7b051d6200000000000000000000000080a931fc0fdb0062548e46cbc60a69d3b7383fdd0000000000000000000000009d0cf00f85015567084e79a76a65d6f5e912b8d20000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000006602808000000000000000000000000000000000000000000000000000000000660585f000000000000000000000000000000000000000000000000001235290c79500000000000000000000000000000000000000000000000000000000000000001c2000000000000000000000000000000000000000000000000006f05b59d3b20000000000000000000000000000000000000000000000000000016345785d8a0000
-----Decoded View---------------
Arg [0] : fundsWalletAddress (address): 0xF95844e82447ebA0ce9EDe88810fDeab7b051d62
Arg [1] : signerAddress (address): 0x80a931FC0fDB0062548E46cbC60A69d3B7383FdD
Arg [2] : owner (address): 0x9D0CF00f85015567084E79A76a65D6F5e912b8d2
Arg [3] : priceFeed (address): 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
Arg [4] : normalizationFactor (uint8): 10
Arg [5] : startTime (uint256): 1711440000
Arg [6] : endTime (uint256): 1711638000
Arg [7] : price (uint256): 82000000000000000
Arg [8] : minimumDifference (uint256): 7200
Arg [9] : maxPurchasePerUser (uint256): 500000000000000000
Arg [10] : minPurchasePerUser (uint256): 100000000000000000
-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 000000000000000000000000f95844e82447eba0ce9ede88810fdeab7b051d62
Arg [1] : 00000000000000000000000080a931fc0fdb0062548e46cbc60a69d3b7383fdd
Arg [2] : 0000000000000000000000009d0cf00f85015567084e79a76a65d6f5e912b8d2
Arg [3] : 0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419
Arg [4] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [5] : 0000000000000000000000000000000000000000000000000000000066028080
Arg [6] : 00000000000000000000000000000000000000000000000000000000660585f0
Arg [7] : 00000000000000000000000000000000000000000000000001235290c7950000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000001c20
Arg [9] : 00000000000000000000000000000000000000000000000006f05b59d3b20000
Arg [10] : 000000000000000000000000000000000000000000000000016345785d8a0000
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.