Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
TokenPresale
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: GPL-3.0 pragma solidity ^0.8.24; import './ITokenPresale.sol'; import '@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol'; import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; import '@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol'; import '@uniswap/lib/contracts/libraries/TransferHelper.sol'; interface IERC20 { function decimals() external view returns (uint8); } // @notice A contract for handling the token presale, supporting payments in native coins and USD ERC20 tokens. contract TokenPresale is PausableUpgradeable, OwnableUpgradeable, ITokenPresale { uint256 constant FULL_PERCENT = 100; uint256 constant TOKEN_BASE = 1e18; uint256 constant USD_BASE = 1e6; uint256 constant NATIVE_COIN_PRICE_TO_USD_CONVERSION_FACTOR = 1e20; AggregatorV3Interface public nativeCoinPriceFeed; mapping(address => uint256) public paymentTokensBases; uint128 public tokenPrice; uint128 public totalCollectedUSD; address public treasury; mapping(address => uint256) internal _balances; mapping(bytes32 => uint256) internal _discounts; mapping(address => bool) internal _maintainers; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /** * @param nativeCoinPriceFeed_ Price feed for the native currency. * @param paymentTokens_ Array of accepted USD ERC20 tokens for payment. * @param tokenPrice_ Initial price of 1 token in USD, scaled by 1e6. * @param treasury_ Address of the treasury to receive payments. * @param owner_ The contract owner address. */ function initialize( AggregatorV3Interface nativeCoinPriceFeed_, address[] calldata paymentTokens_, uint128 tokenPrice_, address treasury_, address owner_ ) external initializer { if (tokenPrice_ == 0) revert InvalidPrice(); __Ownable_init(owner_); _pause(); nativeCoinPriceFeed = nativeCoinPriceFeed_; tokenPrice = tokenPrice_; treasury = treasury_; for (uint256 i = 0; i < paymentTokens_.length; i++) { _addPaymentToken(paymentTokens_[i]); } } /** * @notice Owner: Pauses the presale, preventing purchases. */ function pause() external onlyOwner { _pause(); } /** * @notice Owner: Unpauses the presale, allowing purchases. */ function unpause() external onlyOwner { _unpause(); } /** * @notice Owner: Credits a recipient with tokens from an external purchase. * @param recipient Address receiving the purchased tokens. * @param purchasedTokens Amount of tokens purchased. * @param paidUSD The amount of the USD used for the purchase, scaled by 1e6; * @param paymentDetails Additional details of the payment. */ function creditExternalPurchase( address recipient, uint256 purchasedTokens, uint128 paidUSD, bytes[] calldata paymentDetails ) external onlyOwner { _balances[recipient] += purchasedTokens; totalCollectedUSD += paidUSD; emit ExternallyPurchased(recipient, purchasedTokens, paidUSD, paymentDetails); } /** * @notice Owner: Updates the discount codes and their corresponding discount percentages. * @param data An array of `DiscountCodeData` structs containing discount code hashes and their associated discount percentages [0-99]. */ function updateDiscountCodes(DiscountCodeData[] calldata data) external onlyOwner { uint256 numOfCodes = data.length; for (uint256 i; i < numOfCodes; ++i) { if (data[i].discount >= FULL_PERCENT) revert InvalidDiscount(); _discounts[data[i].discountCodeHash] = data[i].discount; } } /** * @notice Owner: Updates the maintainer status of a given account. * @param account The address of the account whose maintainer status is being updated. * @param isMaintainer Whether the account should be a maintainer or not. */ function updateMaintainerStatus(address account, bool isMaintainer) external onlyOwner { if (_maintainers[account] == isMaintainer) revert NoChange(); _maintainers[account] = isMaintainer; emit MaintainerUpdated(account, isMaintainer); } /** * @notice Owner: Updates the address of the price feed for the native currency. * @param newNativeCoinPriceFeed The new address of the price feed for the native currency. */ function updateNativeCoinPriceFeed(address newNativeCoinPriceFeed) external onlyOwner { nativeCoinPriceFeed = AggregatorV3Interface(newNativeCoinPriceFeed); } /** * @notice Owner: Updates the status of an ERC20 token as a valid payment method. * @param token The token address to update. * @param isPaymentToken Whether the token is accepted for payment. */ function updateTokenStatus(address token, bool isPaymentToken) external onlyOwner { if (bool(paymentTokensBases[token] != 0) == isPaymentToken) revert NoChange(); if (isPaymentToken) { _addPaymentToken(token); } else { paymentTokensBases[token] = 0; } emit TokenStatusUpdated(token, isPaymentToken); } /** * @notice Owner: Updates the treasury address where payments are sent. * @param newTreasury The new treasury address. */ function updateTreasuryAddress(address newTreasury) external onlyOwner { if (treasury == newTreasury) revert NoChange(); treasury = newTreasury; emit TreasuryAddressUpdated(newTreasury); } /** * @notice Owner/Maintainer: Updates the price of the token. * @param newPrice The new price for Token in USD, scaled by 1e6. */ function updateTokenPrice(uint128 newPrice) external { if (msg.sender != owner() && !_maintainers[msg.sender]) revert OnlyMaintainer(); if (newPrice == tokenPrice) revert NoChange(); if (newPrice == 0) revert InvalidPrice(); tokenPrice = newPrice; emit TokenPriceUpdated(newPrice); } /** * @notice Purchase tokens using native currency. * @param recipient The address receiving the purchased tokens. * @param discountCode The discount code applied to the purchase. */ function purchaseWithNativeCoin(address recipient, string calldata discountCode) external payable whenNotPaused { TransferHelper.safeTransferETH(treasury, msg.value); (, int256 nativeCoinPrice, , , ) = nativeCoinPriceFeed.latestRoundData(); uint256 paidUSD = (msg.value * uint256(nativeCoinPrice)) / NATIVE_COIN_PRICE_TO_USD_CONVERSION_FACTOR; uint256 purchasedTokens = _processPurchase(recipient, paidUSD, discountCode); emit Purchased(msg.sender, recipient, address(0), msg.value, purchasedTokens, paidUSD, discountCode); } /** * @notice Purchase tokens using an ERC20 token. * @param recipient The address receiving the purchased tokens. * @param paymentToken The ERC20 token used for payment. * @param paymentAmount The amount of the token used for the purchase. * @param discountCode The discount code applied to the purchase. */ function purchaseWithToken( address recipient, address paymentToken, uint256 paymentAmount, string calldata discountCode ) external whenNotPaused { uint256 paymentTokenBase = paymentTokensBases[paymentToken]; if (paymentTokenBase == 0) revert InvalidPaymentToken(); TransferHelper.safeTransferFrom(paymentToken, msg.sender, treasury, paymentAmount); uint256 paidUSD = (paymentAmount * USD_BASE) / paymentTokenBase; uint256 purchasedTokens = _processPurchase(recipient, paidUSD, discountCode); emit Purchased(msg.sender, recipient, paymentToken, paymentAmount, purchasedTokens, paidUSD, discountCode); } /** * @notice Returns the balance of tokens for `account`. */ function balanceOf(address account) external view returns (uint256) { return _balances[account]; } /** * @notice Returns the current price of 1 token in native currency. * @return The price of 1 token in native coin. */ function tokenPriceInNativeCoin() external view returns (uint256) { (, int256 nativeCoinPrice, , , ) = nativeCoinPriceFeed.latestRoundData(); return (tokenPrice * NATIVE_COIN_PRICE_TO_USD_CONVERSION_FACTOR) / uint256(nativeCoinPrice); } /** * @notice Adds an ERC20 token to the list of accepted payment tokens. * @param paymentToken The ERC20 token to add. */ function _addPaymentToken(address paymentToken) internal { uint256 paymentTokenDecimals = IERC20(paymentToken).decimals(); if (paymentTokenDecimals == 0) revert ZeroDecimalsPaymentToken(); paymentTokensBases[paymentToken] = 10 ** paymentTokenDecimals; } /** * @notice Processes the purchase and calculates the amount of tokens to credit. * @param recipient The address receiving the purchased tokens. * @param paidUSD The amount of USD used for the purchase, scaled by 1e6. * @param discountCode The discount code applied to the purchase. * @return The amount of tokens credited to the recipient. */ function _processPurchase( address recipient, uint256 paidUSD, string calldata discountCode ) internal returns (uint256) { uint256 discount = _discounts[keccak256(abi.encodePacked(discountCode))]; uint256 purchasedTokens = ((paidUSD * TOKEN_BASE) * FULL_PERCENT) / (tokenPrice * (FULL_PERCENT - discount)); if (purchasedTokens == 0) revert InsufficientPurchase(); totalCollectedUSD += uint128(paidUSD); _balances[recipient] += purchasedTokens; return purchasedTokens; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // solhint-disable-next-line interface-starts-with-i interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); function getRoundData( uint80 _roundId ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Pausable struct PausableStorage { bool _paused; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300; function _getPausableStorage() private pure returns (PausableStorage storage $) { assembly { $.slot := PausableStorageLocation } } /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { PausableStorage storage $ = _getPausableStorage(); $._paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { PausableStorage storage $ = _getPausableStorage(); return $._paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.0; // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeApprove: approve failed' ); } function safeTransfer( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeTransfer: transfer failed' ); } function safeTransferFrom( address token, address from, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::transferFrom: transferFrom failed' ); } function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, 'TransferHelper::safeTransferETH: ETH transfer failed'); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.24; interface ITokenPresale { struct DiscountCodeData { bytes32 discountCodeHash; uint256 discount; } event ExternallyPurchased( address indexed recipient, uint256 purchasedTokens, uint128 paidUSD, bytes[] paymentDetails ); event MaintainerUpdated(address account, bool isMaintainer); event Purchased( address indexed purchaseer, address indexed recipient, address indexed paymentToken, uint256 paymentAmount, uint256 purchasedTokens, uint256 paidUSD, string discountCode ); event TokenStatusUpdated(address token, bool isPaymentToken); event TreasuryAddressUpdated(address newTreasury); event TokenPriceUpdated(uint256 newPrice); error InsufficientPurchase(); error InvalidDiscount(); error InvalidPaymentToken(); error InvalidPrice(); error NoChange(); error OnlyMaintainer(); error ZeroDecimalsPaymentToken(); function pause() external; function unpause() external; function creditExternalPurchase( address recipient, uint256 purchasedTokens, uint128 paidUSD, bytes[] calldata paymentDetails ) external; function updateDiscountCodes(DiscountCodeData[] calldata data) external; function updateMaintainerStatus(address account, bool isMaintainer) external; function updateTokenStatus(address token, bool isPaymentToken) external; function updateTreasuryAddress(address newTreasury) external; function updateTokenPrice(uint128 newPrice) external; function purchaseWithNativeCoin(address recipient, string calldata discountCode) external payable; function purchaseWithToken( address recipient, address paymentToken, uint256 paymentAmount, string calldata discountCode ) external; function balanceOf(address account) external view returns (uint256); function tokenPriceInNativeCoin() external view returns (uint256); }
{ "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":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"InsufficientPurchase","type":"error"},{"inputs":[],"name":"InvalidDiscount","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidPaymentToken","type":"error"},{"inputs":[],"name":"InvalidPrice","type":"error"},{"inputs":[],"name":"NoChange","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"OnlyMaintainer","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":"ZeroDecimalsPaymentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"purchasedTokens","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"paidUSD","type":"uint128"},{"indexed":false,"internalType":"bytes[]","name":"paymentDetails","type":"bytes[]"}],"name":"ExternallyPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isMaintainer","type":"bool"}],"name":"MaintainerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"purchaseer","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"paymentToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"paymentAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"purchasedTokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"paidUSD","type":"uint256"},{"indexed":false,"internalType":"string","name":"discountCode","type":"string"}],"name":"Purchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"TokenPriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"isPaymentToken","type":"bool"}],"name":"TokenStatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newTreasury","type":"address"}],"name":"TreasuryAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"purchasedTokens","type":"uint256"},{"internalType":"uint128","name":"paidUSD","type":"uint128"},{"internalType":"bytes[]","name":"paymentDetails","type":"bytes[]"}],"name":"creditExternalPurchase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AggregatorV3Interface","name":"nativeCoinPriceFeed_","type":"address"},{"internalType":"address[]","name":"paymentTokens_","type":"address[]"},{"internalType":"uint128","name":"tokenPrice_","type":"uint128"},{"internalType":"address","name":"treasury_","type":"address"},{"internalType":"address","name":"owner_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nativeCoinPriceFeed","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"paymentTokensBases","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"string","name":"discountCode","type":"string"}],"name":"purchaseWithNativeCoin","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"paymentToken","type":"address"},{"internalType":"uint256","name":"paymentAmount","type":"uint256"},{"internalType":"string","name":"discountCode","type":"string"}],"name":"purchaseWithToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenPrice","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenPriceInNativeCoin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalCollectedUSD","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"discountCodeHash","type":"bytes32"},{"internalType":"uint256","name":"discount","type":"uint256"}],"internalType":"struct ITokenPresale.DiscountCodeData[]","name":"data","type":"tuple[]"}],"name":"updateDiscountCodes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"isMaintainer","type":"bool"}],"name":"updateMaintainerStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newNativeCoinPriceFeed","type":"address"}],"name":"updateNativeCoinPriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"newPrice","type":"uint128"}],"name":"updateTokenPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"isPaymentToken","type":"bool"}],"name":"updateTokenStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTreasury","type":"address"}],"name":"updateTreasuryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061001961001e565b6100d0565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161561006e5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100cd5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b61239480620000e06000396000f3fe6080604052600436106101805760003560e01c80638456cb59116100d6578063ace7cc7a1161007f578063dc71752d11610059578063dc71752d146104c6578063f2fde38b14610503578063f58f81711461052357600080fd5b8063ace7cc7a14610471578063c3d2c24314610491578063dbee1773146104a657600080fd5b80638da5cb5b116100b05780638da5cb5b146103e7578063900ed17814610431578063970982bf1461045157600080fd5b80638456cb59146103925780638a6769ad146103a75780638b4b2328146103c757600080fd5b806361d027b31161013857806378e4a8391161011257806378e4a839146103155780637ff9b59614610328578063841e45611461037257600080fd5b806361d027b31461029057806370a08231146102bd578063715018a61461030057600080fd5b80633f4ba83a116101695780633f4ba83a146101e7578063480a58ee146101fc5780635c975abb1461024e57600080fd5b80632430e9d6146101855780632458a95f146101c5575b600080fd5b34801561019157600080fd5b506101b26101a0366004611b63565b60016020526000908152604090205481565b6040519081526020015b60405180910390f35b3480156101d157600080fd5b506101e56101e0366004611bf8565b610543565b005b3480156101f357600080fd5b506101e5610651565b34801561020857600080fd5b506000546102299073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b34801561025a57600080fd5b507fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1660405190151581526020016101bc565b34801561029c57600080fd5b506003546102299073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102c957600080fd5b506101b26102d8366004611b63565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561030c57600080fd5b506101e5610663565b6101e5610323366004611cab565b610675565b34801561033457600080fd5b50600254610351906fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020016101bc565b34801561037e57600080fd5b506101e561038d366004611b63565b6107f9565b34801561039e57600080fd5b506101e56108cf565b3480156103b357600080fd5b506101e56103c2366004611d0e565b6108df565b3480156103d357600080fd5b506101e56103e2366004611b63565b6109dd565b3480156103f357600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff16610229565b34801561043d57600080fd5b506101e561044c366004611d0e565b610a2c565b34801561045d57600080fd5b506101e561046c366004611d47565b610b1f565b34801561047d57600080fd5b506101e561048c366004611d62565b610cb8565b34801561049d57600080fd5b506101b2610e01565b3480156104b257600080fd5b506101e56104c1366004611dc4565b610ed7565b3480156104d257600080fd5b506002546103519070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b34801561050f57600080fd5b506101e561051e366004611b63565b610f9a565b34801561052f57600080fd5b506101e561053e366004611e39565b611003565b61054b6112ab565b73ffffffffffffffffffffffffffffffffffffffff851660009081526004602052604081208054869290610580908490611ef5565b9091555050600280548491906010906105c090849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16611f0e565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055508473ffffffffffffffffffffffffffffffffffffffff167fbaf9add78373f0cac93f4be4f43865565b55440f8d45a3f8a94d884c6a51fc66858585856040516106429493929190611f87565b60405180910390a25050505050565b6106596112ab565b610661611339565b565b61066b6112ab565b61066160006113d0565b61067d611466565b6003546106a09073ffffffffffffffffffffffffffffffffffffffff16346114c2565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561070e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610732919061209e565b505050915050600068056bc75e2d63100000823461075091906120ee565b61075a9190612105565b9050600061076a868387876115d1565b9050600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f175f773d79a100015e158dd603bc37e4c2d99c4149fa41e80535c288edd719a43485878b8b6040516107e9959493929190612140565b60405180910390a4505050505050565b6108016112ab565b60035473ffffffffffffffffffffffffffffffffffffffff808316911603610855576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fb6a5e89655cf506139085f051af608195ed056f8dc550b180a1c38d401e2b6c4906020015b60405180910390a150565b6108d76112ab565b610661611766565b6108e76112ab565b73ffffffffffffffffffffffffffffffffffffffff821660009081526006602052604090205481151560ff90911615150361094e576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526006602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168515159081179091558251938452908301527f2098a4098c1f50924be4b44fa1120ec3af0426e0e4fe723666e38659c252385e91015b60405180910390a15050565b6109e56112ab565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610a346112ab565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090205481151590151503610a97576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8015610aab57610aa6826117df565b610ad2565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160205260408120555b6040805173ffffffffffffffffffffffffffffffffffffffff8416815282151560208201527fc2af510a9d71a987e12298c8d681a18ee686d181e6fb0bd4166cc01cd7eed4b391016109d1565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff163314801590610b7657503360009081526006602052604090205460ff16155b15610bad576040517f710bcc4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546fffffffffffffffffffffffffffffffff90811690821603610bfe576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806fffffffffffffffffffffffffffffffff16600003610c49576040517ebfc92100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff83169081179091556040519081527f6b361c807733cc94a3b7bda39c1c94dcc0511e91aa47b0f7f918068e93976890906020016108c4565b610cc0611466565b73ffffffffffffffffffffffffffffffffffffffff841660009081526001602052604081205490819003610d20576040517f56e7ec5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600354610d47908690339073ffffffffffffffffffffffffffffffffffffffff16876118c7565b600081610d57620f4240876120ee565b610d619190612105565b90506000610d71888387876115d1565b90508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f175f773d79a100015e158dd603bc37e4c2d99c4149fa41e80535c288edd719a48985878b8b604051610def959493929190612140565b60405180910390a45050505050505050565b60008054604080517ffeaf968c0000000000000000000000000000000000000000000000000000000081529051839273ffffffffffffffffffffffffffffffffffffffff169163feaf968c9160048083019260a09291908290030181865afa158015610e71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e95919061209e565b5050600254919350839250610ec79168056bc75e2d6310000091506fffffffffffffffffffffffffffffffff166120ee565b610ed19190612105565b91505090565b610edf6112ab565b8060005b81811015610f94576064848483818110610eff57610eff612171565b9050604002016020013510610f40576040517f997ea36000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838382818110610f5257610f52612171565b9050604002016020013560056000868685818110610f7257610f72612171565b6040908102929092013583525060208201929092520160002055600101610ee3565b50505050565b610fa26112ab565b73ffffffffffffffffffffffffffffffffffffffff8116610ff7576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024015b60405180910390fd5b611000816113d0565b50565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff1660008115801561104e5750825b905060008267ffffffffffffffff16600114801561106b5750303b155b905081158015611079575080155b156110b0576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156111115784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b876fffffffffffffffffffffffffffffffff1660000361115c576040517ebfc92100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61116586611a66565b61116d611766565b6000805473ffffffffffffffffffffffffffffffffffffffff808e167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316178355600280546fffffffffffffffffffffffffffffffff8d167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090911617905560038054918b16919092161790555b8981101561123c576112348b8b8381811061121a5761121a612171565b905060200201602081019061122f9190611b63565b6117df565b6001016111fd565b50831561129e5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050565b336112ea7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610661576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610fee565b611341611a77565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016108c4565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1615610661576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040516114f991906121a0565b60006040518083038185875af1925050503d8060008114611536576040519150601f19603f3d011682016040523d82523d6000602084013e61153b565b606091505b50509050806115cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527f20455448207472616e73666572206661696c65640000000000000000000000006064820152608401610fee565b505050565b6000806005600085856040516020016115eb9291906121cf565b604051602081830303815290604052805190602001208152602001908152602001600020549050600081606461162191906121df565b60025461164091906fffffffffffffffffffffffffffffffff166120ee565b6064611654670de0b6b3a7640000896120ee565b61165e91906120ee565b6116689190612105565b9050806000036116a4576040517fda2fc5e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85600260108282829054906101000a90046fffffffffffffffffffffffffffffffff166116d19190611f0e565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555080600460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546117569190611ef5565b9091555090979650505050505050565b61176e611466565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258336113ab565b60008173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561182c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185091906121f2565b60ff1690508060000361188f576040517f2e99569000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61189a81600a612335565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526001602052604090209190915550565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161196691906121a0565b6000604051808303816000865af19150503d80600081146119a3576040519150601f19603f3d011682016040523d82523d6000602084013e6119a8565b606091505b50915091508180156119d25750805115806119d25750808060200190518101906119d29190612341565b611a5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c65640000000000000000000000000000006064820152608401610fee565b505050505050565b611a6e611ad2565b61100081611b39565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff16610661576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16610661576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fa2611ad2565b73ffffffffffffffffffffffffffffffffffffffff8116811461100057600080fd5b600060208284031215611b7557600080fd5b8135611b8081611b41565b9392505050565b80356fffffffffffffffffffffffffffffffff81168114611ba757600080fd5b919050565b60008083601f840112611bbe57600080fd5b50813567ffffffffffffffff811115611bd657600080fd5b6020830191508360208260051b8501011115611bf157600080fd5b9250929050565b600080600080600060808688031215611c1057600080fd5b8535611c1b81611b41565b945060208601359350611c3060408701611b87565b9250606086013567ffffffffffffffff811115611c4c57600080fd5b611c5888828901611bac565b969995985093965092949392505050565b60008083601f840112611c7b57600080fd5b50813567ffffffffffffffff811115611c9357600080fd5b602083019150836020828501011115611bf157600080fd5b600080600060408486031215611cc057600080fd5b8335611ccb81611b41565b9250602084013567ffffffffffffffff811115611ce757600080fd5b611cf386828701611c69565b9497909650939450505050565b801515811461100057600080fd5b60008060408385031215611d2157600080fd5b8235611d2c81611b41565b91506020830135611d3c81611d00565b809150509250929050565b600060208284031215611d5957600080fd5b611b8082611b87565b600080600080600060808688031215611d7a57600080fd5b8535611d8581611b41565b94506020860135611d9581611b41565b935060408601359250606086013567ffffffffffffffff811115611db857600080fd5b611c5888828901611c69565b60008060208385031215611dd757600080fd5b823567ffffffffffffffff80821115611def57600080fd5b818501915085601f830112611e0357600080fd5b813581811115611e1257600080fd5b8660208260061b8501011115611e2757600080fd5b60209290920196919550909350505050565b60008060008060008060a08789031215611e5257600080fd5b8635611e5d81611b41565b9550602087013567ffffffffffffffff811115611e7957600080fd5b611e8589828a01611bac565b9096509450611e98905060408801611b87565b92506060870135611ea881611b41565b91506080870135611eb881611b41565b809150509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115611f0857611f08611ec6565b92915050565b6fffffffffffffffffffffffffffffffff818116838216019080821115611f3757611f37611ec6565b5092915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60006060820186835260206fffffffffffffffffffffffffffffffff87166020850152606060408501528185835260808501905060808660051b86010192508660005b87811015612075577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8087860301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18a360301811261202b57600080fd5b8901848101903567ffffffffffffffff81111561204757600080fd5b80360382131561205657600080fd5b612061878284611f3e565b965050509183019190830190600101611fca565b50929998505050505050505050565b805169ffffffffffffffffffff81168114611ba757600080fd5b600080600080600060a086880312156120b657600080fd5b6120bf86612084565b94506020860151935060408601519250606086015191506120e260808701612084565b90509295509295909350565b8082028115828204841417611f0857611f08611ec6565b60008261213b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b858152846020820152836040820152608060608201526000612166608083018486611f3e565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b818110156121c157602081860181015185830152016121a7565b506000920191825250919050565b8183823760009101908152919050565b81810381811115611f0857611f08611ec6565b60006020828403121561220457600080fd5b815160ff81168114611b8057600080fd5b600181815b8085111561226e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561225457612254611ec6565b8085161561226157918102915b93841c939080029061221a565b509250929050565b60008261228557506001611f08565b8161229257506000611f08565b81600181146122a857600281146122b2576122ce565b6001915050611f08565b60ff8411156122c3576122c3611ec6565b50506001821b611f08565b5060208310610133831016604e8410600b84101617156122f1575081810a611f08565b6122fb8383612215565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561232d5761232d611ec6565b029392505050565b6000611b808383612276565b60006020828403121561235357600080fd5b8151611b8081611d0056fea2646970667358221220c993a6a40abeda1a7e4045e6beba5fd24fe864f9c4222670c5683dceb1ab966764736f6c63430008180033
Deployed Bytecode
0x6080604052600436106101805760003560e01c80638456cb59116100d6578063ace7cc7a1161007f578063dc71752d11610059578063dc71752d146104c6578063f2fde38b14610503578063f58f81711461052357600080fd5b8063ace7cc7a14610471578063c3d2c24314610491578063dbee1773146104a657600080fd5b80638da5cb5b116100b05780638da5cb5b146103e7578063900ed17814610431578063970982bf1461045157600080fd5b80638456cb59146103925780638a6769ad146103a75780638b4b2328146103c757600080fd5b806361d027b31161013857806378e4a8391161011257806378e4a839146103155780637ff9b59614610328578063841e45611461037257600080fd5b806361d027b31461029057806370a08231146102bd578063715018a61461030057600080fd5b80633f4ba83a116101695780633f4ba83a146101e7578063480a58ee146101fc5780635c975abb1461024e57600080fd5b80632430e9d6146101855780632458a95f146101c5575b600080fd5b34801561019157600080fd5b506101b26101a0366004611b63565b60016020526000908152604090205481565b6040519081526020015b60405180910390f35b3480156101d157600080fd5b506101e56101e0366004611bf8565b610543565b005b3480156101f357600080fd5b506101e5610651565b34801561020857600080fd5b506000546102299073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b34801561025a57600080fd5b507fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1660405190151581526020016101bc565b34801561029c57600080fd5b506003546102299073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102c957600080fd5b506101b26102d8366004611b63565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561030c57600080fd5b506101e5610663565b6101e5610323366004611cab565b610675565b34801561033457600080fd5b50600254610351906fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff90911681526020016101bc565b34801561037e57600080fd5b506101e561038d366004611b63565b6107f9565b34801561039e57600080fd5b506101e56108cf565b3480156103b357600080fd5b506101e56103c2366004611d0e565b6108df565b3480156103d357600080fd5b506101e56103e2366004611b63565b6109dd565b3480156103f357600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff16610229565b34801561043d57600080fd5b506101e561044c366004611d0e565b610a2c565b34801561045d57600080fd5b506101e561046c366004611d47565b610b1f565b34801561047d57600080fd5b506101e561048c366004611d62565b610cb8565b34801561049d57600080fd5b506101b2610e01565b3480156104b257600080fd5b506101e56104c1366004611dc4565b610ed7565b3480156104d257600080fd5b506002546103519070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b34801561050f57600080fd5b506101e561051e366004611b63565b610f9a565b34801561052f57600080fd5b506101e561053e366004611e39565b611003565b61054b6112ab565b73ffffffffffffffffffffffffffffffffffffffff851660009081526004602052604081208054869290610580908490611ef5565b9091555050600280548491906010906105c090849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16611f0e565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055508473ffffffffffffffffffffffffffffffffffffffff167fbaf9add78373f0cac93f4be4f43865565b55440f8d45a3f8a94d884c6a51fc66858585856040516106429493929190611f87565b60405180910390a25050505050565b6106596112ab565b610661611339565b565b61066b6112ab565b61066160006113d0565b61067d611466565b6003546106a09073ffffffffffffffffffffffffffffffffffffffff16346114c2565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561070e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610732919061209e565b505050915050600068056bc75e2d63100000823461075091906120ee565b61075a9190612105565b9050600061076a868387876115d1565b9050600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f175f773d79a100015e158dd603bc37e4c2d99c4149fa41e80535c288edd719a43485878b8b6040516107e9959493929190612140565b60405180910390a4505050505050565b6108016112ab565b60035473ffffffffffffffffffffffffffffffffffffffff808316911603610855576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fb6a5e89655cf506139085f051af608195ed056f8dc550b180a1c38d401e2b6c4906020015b60405180910390a150565b6108d76112ab565b610661611766565b6108e76112ab565b73ffffffffffffffffffffffffffffffffffffffff821660009081526006602052604090205481151560ff90911615150361094e576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660008181526006602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168515159081179091558251938452908301527f2098a4098c1f50924be4b44fa1120ec3af0426e0e4fe723666e38659c252385e91015b60405180910390a15050565b6109e56112ab565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610a346112ab565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090205481151590151503610a97576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8015610aab57610aa6826117df565b610ad2565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160205260408120555b6040805173ffffffffffffffffffffffffffffffffffffffff8416815282151560208201527fc2af510a9d71a987e12298c8d681a18ee686d181e6fb0bd4166cc01cd7eed4b391016109d1565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff163314801590610b7657503360009081526006602052604090205460ff16155b15610bad576040517f710bcc4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546fffffffffffffffffffffffffffffffff90811690821603610bfe576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806fffffffffffffffffffffffffffffffff16600003610c49576040517ebfc92100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff83169081179091556040519081527f6b361c807733cc94a3b7bda39c1c94dcc0511e91aa47b0f7f918068e93976890906020016108c4565b610cc0611466565b73ffffffffffffffffffffffffffffffffffffffff841660009081526001602052604081205490819003610d20576040517f56e7ec5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600354610d47908690339073ffffffffffffffffffffffffffffffffffffffff16876118c7565b600081610d57620f4240876120ee565b610d619190612105565b90506000610d71888387876115d1565b90508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f175f773d79a100015e158dd603bc37e4c2d99c4149fa41e80535c288edd719a48985878b8b604051610def959493929190612140565b60405180910390a45050505050505050565b60008054604080517ffeaf968c0000000000000000000000000000000000000000000000000000000081529051839273ffffffffffffffffffffffffffffffffffffffff169163feaf968c9160048083019260a09291908290030181865afa158015610e71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e95919061209e565b5050600254919350839250610ec79168056bc75e2d6310000091506fffffffffffffffffffffffffffffffff166120ee565b610ed19190612105565b91505090565b610edf6112ab565b8060005b81811015610f94576064848483818110610eff57610eff612171565b9050604002016020013510610f40576040517f997ea36000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838382818110610f5257610f52612171565b9050604002016020013560056000868685818110610f7257610f72612171565b6040908102929092013583525060208201929092520160002055600101610ee3565b50505050565b610fa26112ab565b73ffffffffffffffffffffffffffffffffffffffff8116610ff7576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024015b60405180910390fd5b611000816113d0565b50565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff1660008115801561104e5750825b905060008267ffffffffffffffff16600114801561106b5750303b155b905081158015611079575080155b156110b0576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156111115784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b876fffffffffffffffffffffffffffffffff1660000361115c576040517ebfc92100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61116586611a66565b61116d611766565b6000805473ffffffffffffffffffffffffffffffffffffffff808e167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316178355600280546fffffffffffffffffffffffffffffffff8d167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090911617905560038054918b16919092161790555b8981101561123c576112348b8b8381811061121a5761121a612171565b905060200201602081019061122f9190611b63565b6117df565b6001016111fd565b50831561129e5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050565b336112ea7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610661576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610fee565b611341611a77565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016108c4565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1615610661576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040516114f991906121a0565b60006040518083038185875af1925050503d8060008114611536576040519150601f19603f3d011682016040523d82523d6000602084013e61153b565b606091505b50509050806115cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527f20455448207472616e73666572206661696c65640000000000000000000000006064820152608401610fee565b505050565b6000806005600085856040516020016115eb9291906121cf565b604051602081830303815290604052805190602001208152602001908152602001600020549050600081606461162191906121df565b60025461164091906fffffffffffffffffffffffffffffffff166120ee565b6064611654670de0b6b3a7640000896120ee565b61165e91906120ee565b6116689190612105565b9050806000036116a4576040517fda2fc5e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85600260108282829054906101000a90046fffffffffffffffffffffffffffffffff166116d19190611f0e565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555080600460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546117569190611ef5565b9091555090979650505050505050565b61176e611466565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258336113ab565b60008173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561182c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185091906121f2565b60ff1690508060000361188f576040517f2e99569000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61189a81600a612335565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526001602052604090209190915550565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161196691906121a0565b6000604051808303816000865af19150503d80600081146119a3576040519150601f19603f3d011682016040523d82523d6000602084013e6119a8565b606091505b50915091508180156119d25750805115806119d25750808060200190518101906119d29190612341565b611a5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c65640000000000000000000000000000006064820152608401610fee565b505050505050565b611a6e611ad2565b61100081611b39565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff16610661576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16610661576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610fa2611ad2565b73ffffffffffffffffffffffffffffffffffffffff8116811461100057600080fd5b600060208284031215611b7557600080fd5b8135611b8081611b41565b9392505050565b80356fffffffffffffffffffffffffffffffff81168114611ba757600080fd5b919050565b60008083601f840112611bbe57600080fd5b50813567ffffffffffffffff811115611bd657600080fd5b6020830191508360208260051b8501011115611bf157600080fd5b9250929050565b600080600080600060808688031215611c1057600080fd5b8535611c1b81611b41565b945060208601359350611c3060408701611b87565b9250606086013567ffffffffffffffff811115611c4c57600080fd5b611c5888828901611bac565b969995985093965092949392505050565b60008083601f840112611c7b57600080fd5b50813567ffffffffffffffff811115611c9357600080fd5b602083019150836020828501011115611bf157600080fd5b600080600060408486031215611cc057600080fd5b8335611ccb81611b41565b9250602084013567ffffffffffffffff811115611ce757600080fd5b611cf386828701611c69565b9497909650939450505050565b801515811461100057600080fd5b60008060408385031215611d2157600080fd5b8235611d2c81611b41565b91506020830135611d3c81611d00565b809150509250929050565b600060208284031215611d5957600080fd5b611b8082611b87565b600080600080600060808688031215611d7a57600080fd5b8535611d8581611b41565b94506020860135611d9581611b41565b935060408601359250606086013567ffffffffffffffff811115611db857600080fd5b611c5888828901611c69565b60008060208385031215611dd757600080fd5b823567ffffffffffffffff80821115611def57600080fd5b818501915085601f830112611e0357600080fd5b813581811115611e1257600080fd5b8660208260061b8501011115611e2757600080fd5b60209290920196919550909350505050565b60008060008060008060a08789031215611e5257600080fd5b8635611e5d81611b41565b9550602087013567ffffffffffffffff811115611e7957600080fd5b611e8589828a01611bac565b9096509450611e98905060408801611b87565b92506060870135611ea881611b41565b91506080870135611eb881611b41565b809150509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115611f0857611f08611ec6565b92915050565b6fffffffffffffffffffffffffffffffff818116838216019080821115611f3757611f37611ec6565b5092915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60006060820186835260206fffffffffffffffffffffffffffffffff87166020850152606060408501528185835260808501905060808660051b86010192508660005b87811015612075577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8087860301835281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18a360301811261202b57600080fd5b8901848101903567ffffffffffffffff81111561204757600080fd5b80360382131561205657600080fd5b612061878284611f3e565b965050509183019190830190600101611fca565b50929998505050505050505050565b805169ffffffffffffffffffff81168114611ba757600080fd5b600080600080600060a086880312156120b657600080fd5b6120bf86612084565b94506020860151935060408601519250606086015191506120e260808701612084565b90509295509295909350565b8082028115828204841417611f0857611f08611ec6565b60008261213b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b858152846020820152836040820152608060608201526000612166608083018486611f3e565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b818110156121c157602081860181015185830152016121a7565b506000920191825250919050565b8183823760009101908152919050565b81810381811115611f0857611f08611ec6565b60006020828403121561220457600080fd5b815160ff81168114611b8057600080fd5b600181815b8085111561226e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561225457612254611ec6565b8085161561226157918102915b93841c939080029061221a565b509250929050565b60008261228557506001611f08565b8161229257506000611f08565b81600181146122a857600281146122b2576122ce565b6001915050611f08565b60ff8411156122c3576122c3611ec6565b50506001821b611f08565b5060208310610133831016604e8410600b84101617156122f1575081810a611f08565b6122fb8383612215565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561232d5761232d611ec6565b029392505050565b6000611b808383612276565b60006020828403121561235357600080fd5b8151611b8081611d0056fea2646970667358221220c993a6a40abeda1a7e4045e6beba5fd24fe864f9c4222670c5683dceb1ab966764736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.