Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x9a716fe537e47baf275cb939461e69a6d84341bdc4be5488f037ccc848c381e6 | Deposit Coin | (pending) | 6 hrs ago | IN | 0.001 ETH | (Pending) | |||
0xcb8179c22512aaf3d8869b422e484aacb4985416251cce804fe8e5ede410faaf | Deposit Coin | (pending) | 6 hrs ago | IN | 0.001 ETH | (Pending) | |||
Deposit Coin | 21506756 | 38 mins ago | IN | 0.008 ETH | 0.00035467 | ||||
Deposit Coin | 21506470 | 1 hr ago | IN | 0.0013 ETH | 0.00036123 | ||||
Deposit Coin | 21506422 | 1 hr ago | IN | 0.01449 ETH | 0.00027959 | ||||
Deposit Coin | 21506404 | 1 hr ago | IN | 0.03 ETH | 0.00037642 | ||||
Deposit Coin | 21506373 | 1 hr ago | IN | 0.00264 ETH | 0.00041238 | ||||
Deposit Coin | 21506282 | 2 hrs ago | IN | 0.029 ETH | 0.00031631 | ||||
Deposit Coin | 21506276 | 2 hrs ago | IN | 0.01 ETH | 0.00040947 | ||||
Deposit Coin | 21506257 | 2 hrs ago | IN | 0.013 ETH | 0.00042228 | ||||
Deposit Coin | 21506246 | 2 hrs ago | IN | 0.09 ETH | 0.00044845 | ||||
Deposit Coin | 21506210 | 2 hrs ago | IN | 0.035 ETH | 0.00047405 | ||||
Deposit Coin | 21506182 | 2 hrs ago | IN | 0.0192182 ETH | 0.00031594 | ||||
Deposit Coin | 21506151 | 2 hrs ago | IN | 0.0022 ETH | 0.00043318 | ||||
Deposit Coin | 21506129 | 2 hrs ago | IN | 0.0003 ETH | 0.00034489 | ||||
Deposit Coin | 21506104 | 2 hrs ago | IN | 0.029 ETH | 0.00029872 | ||||
Deposit USDC | 21506078 | 2 hrs ago | IN | 0 ETH | 0.00033803 | ||||
Deposit Coin | 21506061 | 2 hrs ago | IN | 0.0004 ETH | 0.00035372 | ||||
Deposit Coin | 21505909 | 3 hrs ago | IN | 0.0043 ETH | 0.00028759 | ||||
Deposit Coin | 21505879 | 3 hrs ago | IN | 0.031 ETH | 0.00044549 | ||||
Deposit Coin | 21505833 | 3 hrs ago | IN | 0.1 ETH | 0.00055111 | ||||
Deposit Coin | 21505776 | 3 hrs ago | IN | 0.0623 ETH | 0.00044582 | ||||
Deposit Coin | 21505735 | 4 hrs ago | IN | 0.00038 ETH | 0.00037404 | ||||
Deposit Coin | 21505714 | 4 hrs ago | IN | 0.0022 ETH | 0.00029574 | ||||
Deposit Coin | 21505680 | 4 hrs ago | IN | 0.006 ETH | 0.00031321 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21506756 | 38 mins ago | 0.00000005 ETH | ||||
21506756 | 38 mins ago | 0.00799994 ETH | ||||
21506470 | 1 hr ago | 0.00000011 ETH | ||||
21506470 | 1 hr ago | 0.00129988 ETH | ||||
21506422 | 1 hr ago | 0.00000001 ETH | ||||
21506422 | 1 hr ago | 0.01448998 ETH | ||||
21506404 | 1 hr ago | 0 ETH | ||||
21506404 | 1 hr ago | 0.02999999 ETH | ||||
21506373 | 1 hr ago | 0.00000007 ETH | ||||
21506373 | 1 hr ago | 0.00263992 ETH | ||||
21506282 | 2 hrs ago | 0.00000016 ETH | ||||
21506282 | 2 hrs ago | 0.02899983 ETH | ||||
21506276 | 2 hrs ago | 0 ETH | ||||
21506276 | 2 hrs ago | 0.00999999 ETH | ||||
21506257 | 2 hrs ago | 0.00000012 ETH | ||||
21506257 | 2 hrs ago | 0.01299987 ETH | ||||
21506246 | 2 hrs ago | 0 ETH | ||||
21506246 | 2 hrs ago | 0.08999999 ETH | ||||
21506210 | 2 hrs ago | 0 ETH | ||||
21506210 | 2 hrs ago | 0.03499999 ETH | ||||
21506182 | 2 hrs ago | 0.00000003 ETH | ||||
21506182 | 2 hrs ago | 0.01921816 ETH | ||||
21506151 | 2 hrs ago | 0.00000016 ETH | ||||
21506151 | 2 hrs ago | 0.00219983 ETH | ||||
21506129 | 2 hrs ago | 0.0000001 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Presale
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 { IERC20, SafeERC20 } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol"; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "./interfaces/IPresale.sol"; contract Presale is IPresale, AccessControl, Pausable { using SafeERC20 for IERC20; bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE"); uint256 public constant DEFAULT_DELAY = 12 hours; int32 public constant STABLETOKEN_PRICE = 1e8; uint8 public constant STABLE_TOKEN_DECIMALS = 6; uint8 public constant PRICEFEED_DECIMALS = 8; uint8 public constant TOKEN_PRECISION = 18; AggregatorV3Interface public immutable COIN_PRICE_FEED; IERC20 public immutable usdcToken; IERC20 public immutable usdtToken; address public protocolWallet; uint256 public totalTokensSold; uint256 public totalSoldInUSD; // Precision is 8 decimals uint256 public stageIterator; StageData[] public stages; mapping(address user => uint256 balance) public balances; mapping(bytes4 selector => uint256 timestamp) private _timestamps; constructor( AggregatorV3Interface COIN_PRICE_FEED_, IERC20 usdcToken_, IERC20 usdtToken_, address protocolWallet_, address DAO, address operator ) { COIN_PRICE_FEED = COIN_PRICE_FEED_; usdcToken = usdcToken_; usdtToken = usdtToken_; protocolWallet = protocolWallet_; stages.push(StageData(2e4, 150000000)); // 0.00020000 stages.push(StageData(4e4, 125000000)); // 0.00040000 stages.push(StageData(5e4, 240000000)); // 0.00050000 stages.push(StageData(6e4, 500000000)); // 0.00060000 stages.push(StageData(7e4, 928571429)); // 0.00070000 stages.push(StageData(8e4, 812500000)); // 0.00080000 stages.push(StageData(9e4, 722222222)); // 0.00090000 stages.push(StageData(10e4, 650000000)); // 0.00100000 stages.push(StageData(11e4, 590909091)); // 0.00110000 stages.push(StageData(12e4, 541666667)); // 0.00120000 stages.push(StageData(13e4, 246153846)); // 0.00130000 stages.push(StageData(14e4, 142857143)); // 0.00140000 stages.push(StageData(15e4, 33333333)); // 0.00150000 stages.push(StageData(16e4, 18750000)); // 0.00160000 stages.push(StageData(0, 0)); // End _grantRole(DEFAULT_ADMIN_ROLE, DAO); _grantRole(OPERATOR_ROLE, operator); } //NOTE function selector is: 0xe308a099 function updateProtocolWallet(address wallet) external onlyRole(DEFAULT_ADMIN_ROLE) { uint256 delayedTill = _timestamps[0xe308a099]; if(delayedTill > 0 && delayedTill <= block.timestamp) { protocolWallet = wallet; _timestamps[0xe308a099] = 0; } else { _timestamps[0xe308a099] = block.timestamp + DEFAULT_DELAY; } } function setStage(uint256 stageIterator_) external onlyRole(OPERATOR_ROLE) { require(stageIterator_ < stages.length, "Presale: Wrong iterator"); stageIterator = stageIterator_; emit StageUpdated(stageIterator); } //NOTE function selector is: 0x76aa28fc function updateTotalSold(uint256 amount) external onlyRole(OPERATOR_ROLE) { uint256 delayedTill = _timestamps[0x76aa28fc]; if(delayedTill > 0 && delayedTill <= block.timestamp) { totalTokensSold = amount; _timestamps[0xe308a099] = 0; } else { _timestamps[0x76aa28fc] = block.timestamp + DEFAULT_DELAY; } } function pause() external onlyRole(OPERATOR_ROLE) { _pause(); } function unpause() external onlyRole(OPERATOR_ROLE) { _unpause(); } function rescueFunds(IERC20 token, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE) { uint256 delayedTill = _timestamps[0x78e3214f]; if(delayedTill > 0 && delayedTill <= block.timestamp) { if (address(token) == address(0)) { require(amount <= address(this).balance, "Presale: Wrong amount"); (bool success, ) = payable(msg.sender).call{value: amount}(""); require(success, "Payout: Transfer coin failed"); } else { require(amount <= token.balanceOf(address(this)), "Presale: Wrong amount"); token.safeTransfer(protocolWallet, amount); } _timestamps[0x78e3214f] = 0; } else { _timestamps[0x78e3214f] = block.timestamp + DEFAULT_DELAY; } } function depositUSDCTo(address to, uint256 amount, address referrer) external whenNotPaused { (uint256 chargeBack, uint256 spendedValue) = _depositChecksAndEffects(usdcToken, to, amount, true); _depositInteractions(usdcToken, amount, chargeBack, spendedValue); emit TokensBought(address(usdcToken), to, referrer, spendedValue); } function depositUSDC(uint256 amount, address referrer) external whenNotPaused { (uint256 chargeBack, uint256 spendedValue) = _depositChecksAndEffects(usdcToken, msg.sender, amount, true); _depositInteractions(usdcToken, amount, chargeBack, spendedValue); emit TokensBought(address(usdcToken), msg.sender, referrer, spendedValue); } function depositUSDTTo(address to, uint256 amount, address referrer) external whenNotPaused { (uint256 chargeBack, uint256 spendedValue) = _depositChecksAndEffects(usdtToken, to, amount, true); _depositInteractions(usdtToken, amount, chargeBack, spendedValue); emit TokensBought(address(usdtToken), to, referrer, spendedValue); } function depositUSDT(uint256 amount, address referrer) external whenNotPaused { (uint256 chargeBack, uint256 spendedValue) = _depositChecksAndEffects(usdtToken, msg.sender, amount, true); _depositInteractions(usdtToken, amount, chargeBack, spendedValue); emit TokensBought(address(usdtToken), msg.sender, referrer, spendedValue); } function depositCoinTo(address to, address referrer) public payable whenNotPaused { (uint256 chargeBack, uint256 spendedValue) = _depositChecksAndEffects(IERC20(address(0)), to, msg.value, false); (bool success, ) = payable(protocolWallet).call{value: spendedValue}(""); require(success, "Presale: Coin transfer failed"); if(chargeBack > 0) { (success, ) = payable(msg.sender).call{value: chargeBack}(""); require(success, "Presale: Coin transfer failed"); } emit TokensBought(address(0), to, referrer, spendedValue); } function depositCoin(address referrer) public payable whenNotPaused { (uint256 chargeBack, uint256 spendedValue) = _depositChecksAndEffects(IERC20(address(0)), msg.sender, msg.value, false); (bool success, ) = payable(protocolWallet).call{value: spendedValue}(""); require(success, "Presale: Coin transfer failed"); if(chargeBack > 0) { (success, ) = payable(msg.sender).call{value: chargeBack}(""); require(success, "Presale: Coin transfer failed"); } emit TokensBought(address(0), msg.sender, referrer, spendedValue); } function _depositChecksAndEffects( IERC20 token, address to, uint256 value, bool isStableToken ) internal virtual returns (uint256 chargeBack, uint256 spendedValue) { require(stages[stageIterator].amount != 0, "PreSale: is ended"); (uint256 tokensToTransfer, uint256 coinPrice) = _calculateAmount(isStableToken, value); (chargeBack, spendedValue) = _purchase(token, to, coinPrice, tokensToTransfer, value); } function _depositInteractions( IERC20 token, uint256 amount, uint256 chargeBack, uint256 spendedValue ) internal virtual { token.safeTransferFrom(msg.sender, address(this), amount); token.safeTransfer(protocolWallet, spendedValue); if(chargeBack > 0) token.safeTransfer(msg.sender, chargeBack); } function _calculateAmount(bool isStableToken, uint256 value) internal virtual returns (uint256 amount, uint256 price) { int256 coinPrice; uint256 PRECISION; if (isStableToken) { coinPrice = STABLETOKEN_PRICE; PRECISION = STABLE_TOKEN_DECIMALS; } else { (, coinPrice, , , ) = COIN_PRICE_FEED.latestRoundData(); PRECISION = TOKEN_PRECISION; } uint256 expectedAmount = uint(coinPrice) * value / uint(stages[stageIterator].cost); emit AmountAndUSD(msg.sender, expectedAmount, coinPrice); return (expectedAmount / 10 ** (PRECISION), uint(coinPrice)); } function _purchase( IERC20 token, address to, uint256 coinPrice, uint256 amount, uint256 value ) internal virtual returns (uint256 tokensToChargeBack, uint256 spendedValue) { StageData storage crtStage = stages[stageIterator]; if (uint(crtStage.amount) <= amount) { spendedValue = crtStage.amount * crtStage.cost; } else { spendedValue = amount * crtStage.cost; } totalSoldInUSD += spendedValue; if(address(token) == address(0)) { uint256 usdInEth = 1 ether / coinPrice; spendedValue *= usdInEth; } else { spendedValue /= 10 ** (PRICEFEED_DECIMALS - STABLE_TOKEN_DECIMALS); } tokensToChargeBack = value - spendedValue; if (uint(crtStage.amount) <= amount) { balances[to] += crtStage.amount; totalTokensSold += crtStage.amount; crtStage.amount = 0; stageIterator++; emit StageUpdated(stageIterator); } else { balances[to] += amount; totalTokensSold += amount; crtStage.amount -= uint160(amount); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IDaiLikePermit { function permit( address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IPermit2 { struct PermitDetails { // ERC20 token address address token; // the maximum amount allowed to spend uint160 amount; // timestamp at which a spender's token allowances become invalid uint48 expiration; // an incrementing value indexed per owner,token,and spender for each signature uint48 nonce; } /// @notice The permit message signed for a single token allownce struct PermitSingle { // the permit data for a single token alownce PermitDetails details; // address permissioned on the allowed tokens address spender; // deadline on the permit signature uint256 sigDeadline; } /// @notice Packed allowance struct PackedAllowance { // amount allowed uint160 amount; // permission expiry uint48 expiration; // an incrementing value indexed per owner,token,and spender for each signature uint48 nonce; } function transferFrom(address user, address spender, uint160 amount, address token) external; function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external; function allowance(address user, address token, address spender) external view returns (PackedAllowance memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH is IERC20 { event Deposit(address indexed dst, uint256 wad); event Withdrawal(address indexed src, uint256 wad); function deposit() external payable; function withdraw(uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Revert reason forwarder. library RevertReasonForwarder { /// @dev Forwards latest externall call revert. function reRevert() internal pure { // bubble up revert reason from latest external call assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } /// @dev Returns latest external call revert reason. function reReason() internal pure returns (bytes memory reason) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly reason := mload(0x40) let length := returndatasize() mstore(reason, length) returndatacopy(add(reason, 0x20), 0, length) mstore(0x40, add(reason, add(0x20, length))) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; import "../interfaces/IDaiLikePermit.sol"; import "../interfaces/IPermit2.sol"; import "../interfaces/IWETH.sol"; import "../libraries/RevertReasonForwarder.sol"; /** * @title Implements efficient safe methods for ERC20 interface. * @notice Compared to the standard ERC20, this implementation offers several enhancements: * 1. more gas-efficient, providing significant savings in transaction costs. * 2. support for different permit implementations * 3. forceApprove functionality * 4. support for WETH deposit and withdraw */ library SafeERC20 { error SafeTransferFailed(); error SafeTransferFromFailed(); error ForceApproveFailed(); error SafeIncreaseAllowanceFailed(); error SafeDecreaseAllowanceFailed(); error SafePermitBadLength(); error Permit2TransferAmountTooHigh(); // Uniswap Permit2 address address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; bytes4 private constant _PERMIT_LENGTH_ERROR = 0x68275857; // SafePermitBadLength.selector uint256 private constant _RAW_CALL_GAS_LIMIT = 5000; /** * @notice Fetches the balance of a specific ERC20 token held by an account. * Consumes less gas then regular `ERC20.balanceOf`. * @dev Note that the implementation does not perform dirty bits cleaning, so it is the * responsibility of the caller to make sure that the higher 96 bits of the `account` parameter are clean. * @param token The IERC20 token contract for which the balance will be fetched. * @param account The address of the account whose token balance will be fetched. * @return tokenBalance The balance of the specified ERC20 token held by the account. */ function safeBalanceOf( IERC20 token, address account ) internal view returns(uint256 tokenBalance) { bytes4 selector = IERC20.balanceOf.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0x00, selector) mstore(0x04, account) let success := staticcall(gas(), token, 0x00, 0x24, 0x00, 0x20) tokenBalance := mload(0) if or(iszero(success), lt(returndatasize(), 0x20)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } /** * @notice Attempts to safely transfer tokens from one address to another. * @dev If permit2 is true, uses the Permit2 standard; otherwise uses the standard ERC20 transferFrom. * Either requires `true` in return data, or requires target to be smart-contract and empty return data. * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of * the caller to make sure that the higher 96 bits of the `from` and `to` parameters are clean. * @param token The IERC20 token contract from which the tokens will be transferred. * @param from The address from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param amount The amount of tokens to transfer. * @param permit2 If true, uses the Permit2 standard for the transfer; otherwise uses the standard ERC20 transferFrom. */ function safeTransferFromUniversal( IERC20 token, address from, address to, uint256 amount, bool permit2 ) internal { if (permit2) { safeTransferFromPermit2(token, from, to, amount); } else { safeTransferFrom(token, from, to, amount); } } /** * @notice Attempts to safely transfer tokens from one address to another using the ERC20 standard. * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data. * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of * the caller to make sure that the higher 96 bits of the `from` and `to` parameters are clean. * @param token The IERC20 token contract from which the tokens will be transferred. * @param from The address from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param amount The amount of tokens to transfer. */ function safeTransferFrom( IERC20 token, address from, address to, uint256 amount ) internal { bytes4 selector = token.transferFrom.selector; bool success; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), from) mstore(add(data, 0x24), to) mstore(add(data, 0x44), amount) success := call(gas(), token, 0, data, 100, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } if (!success) revert SafeTransferFromFailed(); } /** * @notice Attempts to safely transfer tokens from one address to another using the Permit2 standard. * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data. * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of * the caller to make sure that the higher 96 bits of the `from` and `to` parameters are clean. * @param token The IERC20 token contract from which the tokens will be transferred. * @param from The address from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param amount The amount of tokens to transfer. */ function safeTransferFromPermit2( IERC20 token, address from, address to, uint256 amount ) internal { if (amount > type(uint160).max) revert Permit2TransferAmountTooHigh(); bytes4 selector = IPermit2.transferFrom.selector; bool success; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), from) mstore(add(data, 0x24), to) mstore(add(data, 0x44), amount) mstore(add(data, 0x64), token) success := call(gas(), _PERMIT2, 0, data, 0x84, 0x0, 0x0) if success { success := gt(extcodesize(_PERMIT2), 0) } } if (!success) revert SafeTransferFromFailed(); } /** * @notice Attempts to safely transfer tokens to another address. * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data. * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of * the caller to make sure that the higher 96 bits of the `to` parameter are clean. * @param token The IERC20 token contract from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param value The amount of tokens to transfer. */ function safeTransfer( IERC20 token, address to, uint256 value ) internal { if (!_makeCall(token, token.transfer.selector, to, value)) { revert SafeTransferFailed(); } } /** * @notice Attempts to approve a spender to spend a certain amount of tokens. * @dev If `approve(from, to, amount)` fails, it tries to set the allowance to zero, and retries the `approve` call. * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of * the caller to make sure that the higher 96 bits of the `spender` parameter are clean. * @param token The IERC20 token contract on which the call will be made. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. */ function forceApprove( IERC20 token, address spender, uint256 value ) internal { if (!_makeCall(token, token.approve.selector, spender, value)) { if ( !_makeCall(token, token.approve.selector, spender, 0) || !_makeCall(token, token.approve.selector, spender, value) ) { revert ForceApproveFailed(); } } } /** * @notice Safely increases the allowance of a spender. * @dev Increases with safe math check. Checks if the increased allowance will overflow, if yes, then it reverts the transaction. * Then uses `forceApprove` to increase the allowance. * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of * the caller to make sure that the higher 96 bits of the `spender` parameter are clean. * @param token The IERC20 token contract on which the call will be made. * @param spender The address which will spend the funds. * @param value The amount of tokens to increase the allowance by. */ function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 allowance = token.allowance(address(this), spender); if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed(); forceApprove(token, spender, allowance + value); } /** * @notice Safely decreases the allowance of a spender. * @dev Decreases with safe math check. Checks if the decreased allowance will underflow, if yes, then it reverts the transaction. * Then uses `forceApprove` to increase the allowance. * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of * the caller to make sure that the higher 96 bits of the `spender` parameter are clean. * @param token The IERC20 token contract on which the call will be made. * @param spender The address which will spend the funds. * @param value The amount of tokens to decrease the allowance by. */ function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 allowance = token.allowance(address(this), spender); if (value > allowance) revert SafeDecreaseAllowanceFailed(); forceApprove(token, spender, allowance - value); } /** * @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters. * Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2). * @dev Wraps `tryPermit` function and forwards revert reason if permit fails. * @param token The IERC20 token to execute the permit function on. * @param permit The permit data to be used in the function call. */ function safePermit(IERC20 token, bytes calldata permit) internal { if (!tryPermit(token, msg.sender, address(this), permit)) RevertReasonForwarder.reRevert(); } /** * @notice Attempts to execute the `permit` function on the provided token with custom owner and spender parameters. * Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2). * @dev Wraps `tryPermit` function and forwards revert reason if permit fails. * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of * the caller to make sure that the higher 96 bits of the `owner` and `spender` parameters are clean. * @param token The IERC20 token to execute the permit function on. * @param owner The owner of the tokens for which the permit is made. * @param spender The spender allowed to spend the tokens by the permit. * @param permit The permit data to be used in the function call. */ function safePermit(IERC20 token, address owner, address spender, bytes calldata permit) internal { if (!tryPermit(token, owner, spender, permit)) RevertReasonForwarder.reRevert(); } /** * @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters. * @dev Invokes `tryPermit` with sender as owner and contract as spender. * @param token The IERC20 token to execute the permit function on. * @param permit The permit data to be used in the function call. * @return success Returns true if the permit function was successfully executed, false otherwise. */ function tryPermit(IERC20 token, bytes calldata permit) internal returns(bool success) { return tryPermit(token, msg.sender, address(this), permit); } /** * @notice The function attempts to call the permit function on a given ERC20 token. * @dev The function is designed to support a variety of permit functions, namely: IERC20Permit, IDaiLikePermit, and IPermit2. * It accommodates both Compact and Full formats of these permit types. * Please note, it is expected that the `expiration` parameter for the compact Permit2 and the `deadline` parameter * for the compact Permit are to be incremented by one before invoking this function. This approach is motivated by * gas efficiency considerations; as the unlimited expiration period is likely to be the most common scenario, and * zeros are cheaper to pass in terms of gas cost. Thus, callers should increment the expiration or deadline by one * before invocation for optimized performance. * Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of * the caller to make sure that the higher 96 bits of the `owner` and `spender` parameters are clean. * @param token The address of the ERC20 token on which to call the permit function. * @param owner The owner of the tokens. This address should have signed the off-chain permit. * @param spender The address which will be approved for transfer of tokens. * @param permit The off-chain permit data, containing different fields depending on the type of permit function. * @return success A boolean indicating whether the permit call was successful. */ function tryPermit(IERC20 token, address owner, address spender, bytes calldata permit) internal returns(bool success) { // load function selectors for different permit standards bytes4 permitSelector = IERC20Permit.permit.selector; bytes4 daiPermitSelector = IDaiLikePermit.permit.selector; bytes4 permit2Selector = IPermit2.permit.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) // Switch case for different permit lengths, indicating different permit standards switch permit.length // Compact IERC20Permit case 100 { mstore(ptr, permitSelector) // store selector mstore(add(ptr, 0x04), owner) // store owner mstore(add(ptr, 0x24), spender) // store spender // Compact IERC20Permit.permit(uint256 value, uint32 deadline, uint256 r, uint256 vs) { // stack too deep let deadline := shr(224, calldataload(add(permit.offset, 0x20))) // loads permit.offset 0x20..0x23 let vs := calldataload(add(permit.offset, 0x44)) // loads permit.offset 0x44..0x63 calldatacopy(add(ptr, 0x44), permit.offset, 0x20) // store value = copy permit.offset 0x00..0x19 mstore(add(ptr, 0x64), sub(deadline, 1)) // store deadline = deadline - 1 mstore(add(ptr, 0x84), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28) calldatacopy(add(ptr, 0xa4), add(permit.offset, 0x24), 0x20) // store r = copy permit.offset 0x24..0x43 mstore(add(ptr, 0xc4), shr(1, shl(1, vs))) // store s = vs without most significant bit } // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0xe4, 0, 0) } // Compact IDaiLikePermit case 72 { mstore(ptr, daiPermitSelector) // store selector mstore(add(ptr, 0x04), owner) // store owner mstore(add(ptr, 0x24), spender) // store spender // Compact IDaiLikePermit.permit(uint32 nonce, uint32 expiry, uint256 r, uint256 vs) { // stack too deep let expiry := shr(224, calldataload(add(permit.offset, 0x04))) // loads permit.offset 0x04..0x07 let vs := calldataload(add(permit.offset, 0x28)) // loads permit.offset 0x28..0x47 mstore(add(ptr, 0x44), shr(224, calldataload(permit.offset))) // store nonce = copy permit.offset 0x00..0x03 mstore(add(ptr, 0x64), sub(expiry, 1)) // store expiry = expiry - 1 mstore(add(ptr, 0x84), true) // store allowed = true mstore(add(ptr, 0xa4), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28) calldatacopy(add(ptr, 0xc4), add(permit.offset, 0x08), 0x20) // store r = copy permit.offset 0x08..0x27 mstore(add(ptr, 0xe4), shr(1, shl(1, vs))) // store s = vs without most significant bit } // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0x104, 0, 0) } // IERC20Permit case 224 { mstore(ptr, permitSelector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0xe4, 0, 0) } // IDaiLikePermit case 256 { mstore(ptr, daiPermitSelector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0x104, 0, 0) } // Compact IPermit2 case 96 { // Compact IPermit2.permit(uint160 amount, uint32 expiration, uint32 nonce, uint32 sigDeadline, uint256 r, uint256 vs) mstore(ptr, permit2Selector) // store selector mstore(add(ptr, 0x04), owner) // store owner mstore(add(ptr, 0x24), token) // store token calldatacopy(add(ptr, 0x50), permit.offset, 0x14) // store amount = copy permit.offset 0x00..0x13 // and(0xffffffffffff, ...) - conversion to uint48 mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // store expiration = ((permit.offset 0x14..0x17 - 1) & 0xffffffffffff) mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // store nonce = copy permit.offset 0x18..0x1b mstore(add(ptr, 0xa4), spender) // store spender // and(0xffffffffffff, ...) - conversion to uint48 mstore(add(ptr, 0xc4), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x1c))), 1))) // store sigDeadline = ((permit.offset 0x1c..0x1f - 1) & 0xffffffffffff) mstore(add(ptr, 0xe4), 0x100) // store offset = 256 mstore(add(ptr, 0x104), 0x40) // store length = 64 calldatacopy(add(ptr, 0x124), add(permit.offset, 0x20), 0x20) // store r = copy permit.offset 0x20..0x3f calldatacopy(add(ptr, 0x144), add(permit.offset, 0x40), 0x20) // store vs = copy permit.offset 0x40..0x5f // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature) success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0) } // IPermit2 case 352 { mstore(ptr, permit2Selector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature) success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0) } // Unknown default { mstore(ptr, _PERMIT_LENGTH_ERROR) revert(ptr, 4) } } } /** * @dev Executes a low level call to a token contract, making it resistant to reversion and erroneous boolean returns. * @param token The IERC20 token contract on which the call will be made. * @param selector The function signature that is to be called on the token contract. * @param to The address to which the token amount will be transferred. * @param amount The token amount to be transferred. * @return success A boolean indicating if the call was successful. Returns 'true' on success and 'false' on failure. * In case of success but no returned data, validates that the contract code exists. * In case of returned data, ensures that it's a boolean `true`. */ function _makeCall( IERC20 token, bytes4 selector, address to, uint256 amount ) private returns (bool success) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), to) mstore(add(data, 0x24), amount) success := call(gas(), token, 0, data, 0x44, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } } /** * @notice Safely deposits a specified amount of Ether into the IWETH contract. Consumes less gas then regular `IWETH.deposit`. * @param weth The IWETH token contract. * @param amount The amount of Ether to deposit into the IWETH contract. */ function safeDeposit(IWETH weth, uint256 amount) internal { if (amount > 0) { bytes4 selector = IWETH.deposit.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0, selector) if iszero(call(gas(), weth, amount, 0, 4, 0, 0)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } } /** * @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract. Consumes less gas then regular `IWETH.withdraw`. * @dev Uses inline assembly to interact with the IWETH contract. * @param weth The IWETH token contract. * @param amount The amount of wrapped Ether to withdraw from the IWETH contract. */ function safeWithdraw(IWETH weth, uint256 amount) internal { bytes4 selector = IWETH.withdraw.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0, selector) mstore(4, amount) if iszero(call(gas(), weth, 0, 0, 0x24, 0, 0)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } /** * @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract to a specified recipient. * Consumes less gas then regular `IWETH.withdraw`. * @param weth The IWETH token contract. * @param amount The amount of wrapped Ether to withdraw from the IWETH contract. * @param to The recipient of the withdrawn Ether. */ function safeWithdrawTo(IWETH weth, uint256 amount, address to) internal { safeWithdraw(weth, amount); if (to != address(this)) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly if iszero(call(_RAW_CALL_GAS_LIMIT, to, amount, 0, 0, 0, 0)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; 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/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.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 Pausable is Context { bool private _paused; /** * @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. */ constructor() { _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) { 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 { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
//SPDX-License-Identifier: MIT pragma solidity 0.8.24; interface IPresale { struct StageData { uint96 cost; uint160 amount; } event TokensBought(address indexed token, address indexed user, address indexed referrer, uint256 amount); event AmountAndUSD(address indexed user, uint256 amount, int256 usd); event StageUpdated(uint256 currentStage); function updateProtocolWallet(address wallet) external; function setStage(uint256 stageIterator_) external; function updateTotalSold(uint256 amount) external; function pause() external; function unpause() external; function depositUSDCTo(address to, uint256 amount, address referrer) external; function depositUSDTTo(address to, uint256 amount, address referrer) external; function depositUSDC(uint256 amount, address referrer) external; function depositUSDT(uint256 amount, address referrer) external; }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "viaIR": true, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract AggregatorV3Interface","name":"COIN_PRICE_FEED_","type":"address"},{"internalType":"contract IERC20","name":"usdcToken_","type":"address"},{"internalType":"contract IERC20","name":"usdtToken_","type":"address"},{"internalType":"address","name":"protocolWallet_","type":"address"},{"internalType":"address","name":"DAO","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"SafeTransferFailed","type":"error"},{"inputs":[],"name":"SafeTransferFromFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"int256","name":"usd","type":"int256"}],"name":"AmountAndUSD","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"currentStage","type":"uint256"}],"name":"StageUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"COIN_PRICE_FEED","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICEFEED_DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STABLETOKEN_PRICE","outputs":[{"internalType":"int32","name":"","type":"int32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STABLE_TOKEN_DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_PRECISION","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"balances","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"depositCoin","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"referrer","type":"address"}],"name":"depositCoinTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"name":"depositUSDC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"name":"depositUSDCTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"name":"depositUSDT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"name":"depositUSDTTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stageIterator_","type":"uint256"}],"name":"setStage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stageIterator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stages","outputs":[{"internalType":"uint96","name":"cost","type":"uint96"},{"internalType":"uint160","name":"amount","type":"uint160"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSoldInUSD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokensSold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"updateProtocolWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"updateTotalSold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdcToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdtToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60e0346200033057601f620027bc38819003918201601f19168301916001600160401b03831184841017620003355780849260c094604052833981010312620003305780516001600160a01b03811681036200033057620002da620002e192620002d46020620000718184016200036b565b9462000080604085016200036b565b6200008e606086016200036b565b90620000ab60a0620000a3608089016200036b565b97016200036b565b976001549360805260a05260c052610100600160a81b039060081b169060018060a81b03191617600155620000f7620000e36200034b565b614e2081526308f0d1808382015262000380565b62000119620001056200034b565b619c40815263077359408382015262000380565b6200013b620001276200034b565b61c3508152630e4e1c008382015262000380565b6200015d620001496200034b565b61ea608152631dcd65008382015262000380565b620001806200016b6200034b565b620111708152633758e0258382015262000380565b620001a36200018e6200034b565b62013880815263306dc4208382015262000380565b620001c6620001b16200034b565b62015f908152632b0c3c8e8382015262000380565b620001e9620001d46200034b565b620186a081526326be36808382015262000380565b6200020c620001f76200034b565b6201adb081526323388ea38382015262000380565b6200022f6200021a6200034b565b6201d4c081526320492d6b8382015262000380565b620002526200023d6200034b565b6201fbd08152630eac02768382015262000380565b62000275620002606200034b565b620222e08152630883d3b78382015262000380565b62000298620002836200034b565b620249f081526301fca0558382015262000380565b620002bb620002a66200034b565b62027100815263011e1a308382015262000380565b6000620002c76200034b565b9181835282015262000380565b6200040e565b506200048e565b5060405161226b90816200053182396080518181816106a90152611773015260a05181818161055801528181610e2b01526112c2015260c05181818161060101528181610c140152610d650152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b60408051919082016001600160401b038111838210176200033557604052565b51906001600160a01b03821682036200033057565b6005546801000000000000000081101562000335576001810180600555811015620003f857600560005281516020929092015160601b6001600160601b0319166001600160601b0392909216919091177f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db09190910155565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b031660008181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604081205490919060ff166200048a57818052816020526040822081835260205260408220600160ff1982541617905533916000805160206200279c8339815191528180a4600190565b5090565b6001600160a01b031660008181527fee57cd81e84075558e8fcc182a1f4393f91fc97f963a136e66b7f949a62f319f60205260408120549091907f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9299060ff166200052b57808352826020526040832082845260205260408320600160ff198254161790556000805160206200279c833981519152339380a4600190565b50509056fe60806040908082526004908136101561001757600080fd5b600091823560e01c91826301ffc9a71461133c5750816306d6e63f146112e657816311eac855146112775781631c7e11af146111a3578163248a9ca31461115a57816327e235e3146110f85781632f2ff15d146110b057816336568abe146110265781633be00ab314610fec5781633eb1d77714610f195781633f4ba83a14610e595781633f63cf9714610dc257816345f5c0dc14610cfc5781635c975abb14610cba57816363b2011714610c7d578163659495a014610c425781636f6c2bd314610bd057816376aa28fc14610afc57816378e3214f146108b75781637f9aee991461087a5781638456cb59146107e4578163845ddcb21461077a57918093928263860956b61461073d57826391d14854146106cd5782639a6c59521461065e578263a217fddf14610625578263a98ad46c146105b6578263ad50d14214610514578263ba680e56146104d8578263c66168941461049e578263cbd6e8f4146103cc578263d434df7114610392578263d547741f14610333578263e308a0991461020757505063f5b541a6146101ac57600080fd5b3461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020357602090517f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9298152f35b5080fd5b8382913461032f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261032f576102416113f8565b610249611eb6565b7fe308a09900000000000000000000000000000000000000000000000000000000918285526007602052838520548015159081610324575b50156102da57507fffffffffffffffffffffff0000000000000000000000000000000000000000ff74ffffffffffffffffffffffffffffffffffffffff006001549260081b169116176001558252600760205281205580f35b93505061a8c04201928342116102f857508352600760205282205580f35b8460116024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b905042101587610281565b5050fd5b833461038e57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e5761038a91356103856001610374611420565b938387528660205286200154611ef0565b611fc0565b5080f35b8280fd5b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905160088152f35b508260207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576104006113f8565b906104096116dc565b6104133433611712565b92909173ffffffffffffffffffffffffffffffffffffffff9261044c86808080898960015460081c165af1610446611578565b506115d6565b8581610485575b5050519283521690827f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce60203393a480f35b80808061049794335af1610446611578565b8585610453565b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905160128152f35b83903461038e57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e5760209250549051908152f35b508234610203577f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce90602061054836611443565b6105569592959391936116dc565b7f000000000000000000000000000000000000000000000000000000000000000094610590610586868989611b4a565b9690879189612061565b5193845273ffffffffffffffffffffffffffffffffffffffff908116958116941692a480f35b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035751908152602090f35b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b83903461038e57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e578160209360ff9261070c611420565b9035825281865273ffffffffffffffffffffffffffffffffffffffff83832091168252855220541690519015158152f35b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020357602090516305f5e1008152f35b9050346102035760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035735906005548210156107e157506107c1906114a2565b50548151906bffffffffffffffffffffffff8116825260601c6020820152f35b80fd5b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035760207f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25891610840611e23565b6108486116dc565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154161760015551338152a180f35b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020906003549051908152f35b90503461020357827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020357803573ffffffffffffffffffffffffffffffffffffffff9182821692838303610af85760243590610916611eb6565b7f78e3214f000000000000000000000000000000000000000000000000000000009384875260209560078752888820548015159081610aed575b5015610a9f57806109ed57505050848080809361096f47821115611677565b335af161097a611578565b501561099157508293916007915b84525281205580f35b606490838651917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601c60248201527f5061796f75743a205472616e7366657220636f696e206661696c6564000000006044820152fd5b8689979560248a9b9896959851809481937f70a0823100000000000000000000000000000000000000000000000000000000835230908301525afa908115610a95578891610a5d575b5090600795610a4b8493610a58951115611677565b60015460081c1690612138565b610988565b929190508483813d8311610a8e575b610a768183611508565b81010312610a8a5791519091906007610a36565b8780fd5b503d610a6c565b87513d8a823e3d90fd5b5050505093909161a8c0420192834211610ac157845260079052822055905080f35b6024856011887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b905042101538610950565b8480fd5b829391503461032f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261032f57610b37611e23565b7f76aa28fc000000000000000000000000000000000000000000000000000000008084526007602052828420548015159081610bc5575b5015610ba75750356002557fe308a099000000000000000000000000000000000000000000000000000000008252600760205281205580f35b90925061a8c04201928342116102f857508352600760205282205580f35b905042101538610b6e565b828434610203577f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce906020610c0436611443565b610c129592959391936116dc565b7f000000000000000000000000000000000000000000000000000000000000000094610590610586868989611b4a565b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905161a8c08152f35b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020906002549051908152f35b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035760209060ff6001541690519015158152f35b8391503461038e57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e573590610d37611420565b91610d406116dc565b7f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce60207f000000000000000000000000000000000000000000000000000000000000000093610d9d610d93853388611b4a565b9590869188612061565b5192835273ffffffffffffffffffffffffffffffffffffffff9485169433941692a480f35b8391503461038e57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e573590610dfd611420565b91610e066116dc565b7f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce60207f000000000000000000000000000000000000000000000000000000000000000093610d9d610d93853388611b4a565b8391503461038e57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e57610e92611e23565b6001549060ff821615610ef257507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006020921660015551338152a180f35b82517f8dfc202b000000000000000000000000000000000000000000000000000000008152fd5b9050823461038e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e57813591610f56611e23565b600554831015610f905791602091817f34cf54504fd39ab670a54acbb37f686c5bd25e6eedfa39889cba899d360bc7d9945551908152a180f35b602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601760248201527f50726573616c653a2057726f6e67206974657261746f720000000000000000006044820152fd5b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905160068152f35b82843461020357807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035761105e611420565b903373ffffffffffffffffffffffffffffffffffffffff831603611088575061038a919235611fc0565b8390517f6697b232000000000000000000000000000000000000000000000000000000008152fd5b9050823461038e57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e5761038a91356110f36001610374611420565b611f16565b8284346102035760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203578060209273ffffffffffffffffffffffffffffffffffffffff61114a6113f8565b1681526006845220549051908152f35b8391503461038e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e57816020936001923581528085522001549051908152f35b8284807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576111d66113f8565b90827f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce6020611203611420565b9361120c6116dc565b6112163487611712565b9573ffffffffffffffffffffffffffffffffffffffff928392611249888080808d8960015460081c165af1610446611578565b878161125e575b50505196875216951693a480f35b80808061127094335af1610446611578565b8a87611250565b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035760209073ffffffffffffffffffffffffffffffffffffffff60015460081c169051908152f35b91503461038e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e57357fffffffff00000000000000000000000000000000000000000000000000000000811680910361038e57602092507f7965db0b0000000000000000000000000000000000000000000000000000000081149081156113ce575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014836113c7565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361141b57565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361141b57565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc606091011261141b5773ffffffffffffffffffffffffffffffffffffffff600435818116810361141b579160243591604435908116810361141b5790565b6005548110156114d95760056000527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761154957604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b3d156115d1573d9067ffffffffffffffff821161154957604051916115c560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184611508565b82523d6000602084013e565b606090565b156115dd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726573616c653a20436f696e207472616e73666572206661696c65640000006044820152fd5b9190820180921161164857565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b1561167e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f50726573616c653a2057726f6e6720616d6f756e7400000000000000000000006044820152fd5b60ff600154166116e857565b60046040517fd93c0665000000000000000000000000000000000000000000000000000000008152fd5b6004805491611720836114a2565b505490606091821c15611aec5773ffffffffffffffffffffffffffffffffffffffff6040928351927ffeaf968c00000000000000000000000000000000000000000000000000000000845260a0848781867f0000000000000000000000000000000000000000000000000000000000000000165afa938415611ae157600094611a92575b506117af88856121e9565b926117d56117bc896114a2565b50946bffffffffffffffffffffffff80965416906121fc565b86518181528660208201527fb80c9abe533e6358a5262b5e8e8d3aa6f8e4d2bb4ebab1e44efa024ee5cbb606883392a261181a670de0b6b3a7640000809204996114a2565b509586548681871c918c831115600014611a805716908482820216918183041490151715611a5257915b6118508360035461163b565b6003558115611a245790611866929104906121e9565b97888a03998a116119f6578554841c81106119415750906118ad92918554831c9116600052600660205261189f8660002091825461163b565b90558354901c60025461163b565b600255815416905581547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611913579160209160017f34cf54504fd39ab670a54acbb37f686c5bd25e6eedfa39889cba899d360bc7d9940180925551908152a19091565b6011837f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b9181979596919394508316600052600660205260002061196282825461163b565b90556119708160025461163b565b60025516908354901c039283116119c85750906119c491906bffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b9091565b6011907f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b6011887f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b60128a7f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b60118a7f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b611a8c9250168b6121e9565b91611844565b909360a0823d60a011611ad9575b81611aad60a09383611508565b810103126107e15750611abf816121d2565b50611ad16080602083015192016121d2565b5092386117a4565b3d9150611aa0565b85513d6000823e3d90fd5b6064836020604051917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601160248201527f50726553616c653a20697320656e6465640000000000000000000000000000006044820152fd5b600490815492611b59846114a2565b5054606090811c15611dc5576305f5e10091868302928084048803611d9757620f4240611bdf91611ba5611b8c8a6114a2565b50966bffffffffffffffffffffffff80985416906121fc565b906040519082825260208201527fb80c9abe533e6358a5262b5e8e8d3aa6f8e4d2bb4ebab1e44efa024ee5cbb60660403392a204966114a2565b509384548481851c9189831115600014611d8657169073ffffffffffffffffffffffffffffffffffffffff82820216918183041490151715611d4e575b611c288160035461163b565b60035573ffffffffffffffffffffffffffffffffffffffff918216611d7c576402540be40090818102918183041490151715611d4e57965b878903988911611d4e578554841c8110611d2e575090611c9992918554831c9116600052600660205261189f604060002091825461163b565b600255815416905580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611d00577f34cf54504fd39ab670a54acbb37f686c5bd25e6eedfa39889cba899d360bc7d991600160209201809155604051908152a19091565b6011827f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b90809694508092166000526006602052604060002061196282825461163b565b6011877f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b6064900496611c60565b611d92925016886121e9565b611c1c565b6011867f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b6064846020604051917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601160248201527f50726553616c653a20697320656e6465640000000000000000000000000000006044820152fd5b3360009081527fee57cd81e84075558e8fcc182a1f4393f91fc97f963a136e66b7f949a62f319f60205260409020547f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9299060ff1615611e7f5750565b604490604051907fe2517d3f0000000000000000000000000000000000000000000000000000000082523360048301526024820152fd5b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604081205460ff1615611e7f5750565b80600052600060205260406000203360005260205260ff6040600020541615611e7f5750565b906000918083528260205273ffffffffffffffffffffffffffffffffffffffff6040842092169182845260205260ff60408420541615600014611fbb5780835282602052604083208284526020526040832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d339380a4600190565b505090565b906000918083528260205273ffffffffffffffffffffffffffffffffffffffff6040842092169182845260205260ff604084205416600014611fbb578083528260205260408320828452602052604083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b339380a4600190565b92906020906064600091604051907f23b872dd000000000000000000000000000000000000000000000000000000008252336004830152306024830152604482015282875af180612118575b156120ee576120d89073ffffffffffffffffffffffffffffffffffffffff60015460081c1684612138565b806120e1575050565b6120ec913390612138565b565b60046040517ff4059071000000000000000000000000000000000000000000000000000000008152fd5b503d1561212f57600160005114601f3d11166120ad565b823b15156120ad565b916044602092600092604051917fa9059cbb0000000000000000000000000000000000000000000000000000000083526004830152602482015282855af190816121af575b501561218557565b60046040517ffb7f5079000000000000000000000000000000000000000000000000000000008152fd5b90503d156121ca5750600160005114601f3d11165b3861217d565b3b15156121c4565b519069ffffffffffffffffffff8216820361141b57565b8181029291811591840414171561164857565b8115612206570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea2646970667358221220aab25e6bc96e9535bf0fb07221a0d2c698f392a758bbfcba6a144a82a59c878164736f6c634300081800332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000004c2df47874a1d3eb46318509b0cec2a5f35024770000000000000000000000004c2df47874a1d3eb46318509b0cec2a5f35024770000000000000000000000004c316a33ef30d634a3002ca55561a8f084395e8b
Deployed Bytecode
0x60806040908082526004908136101561001757600080fd5b600091823560e01c91826301ffc9a71461133c5750816306d6e63f146112e657816311eac855146112775781631c7e11af146111a3578163248a9ca31461115a57816327e235e3146110f85781632f2ff15d146110b057816336568abe146110265781633be00ab314610fec5781633eb1d77714610f195781633f4ba83a14610e595781633f63cf9714610dc257816345f5c0dc14610cfc5781635c975abb14610cba57816363b2011714610c7d578163659495a014610c425781636f6c2bd314610bd057816376aa28fc14610afc57816378e3214f146108b75781637f9aee991461087a5781638456cb59146107e4578163845ddcb21461077a57918093928263860956b61461073d57826391d14854146106cd5782639a6c59521461065e578263a217fddf14610625578263a98ad46c146105b6578263ad50d14214610514578263ba680e56146104d8578263c66168941461049e578263cbd6e8f4146103cc578263d434df7114610392578263d547741f14610333578263e308a0991461020757505063f5b541a6146101ac57600080fd5b3461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020357602090517f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9298152f35b5080fd5b8382913461032f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261032f576102416113f8565b610249611eb6565b7fe308a09900000000000000000000000000000000000000000000000000000000918285526007602052838520548015159081610324575b50156102da57507fffffffffffffffffffffff0000000000000000000000000000000000000000ff74ffffffffffffffffffffffffffffffffffffffff006001549260081b169116176001558252600760205281205580f35b93505061a8c04201928342116102f857508352600760205282205580f35b8460116024927f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b905042101587610281565b5050fd5b833461038e57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e5761038a91356103856001610374611420565b938387528660205286200154611ef0565b611fc0565b5080f35b8280fd5b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905160088152f35b508260207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576104006113f8565b906104096116dc565b6104133433611712565b92909173ffffffffffffffffffffffffffffffffffffffff9261044c86808080898960015460081c165af1610446611578565b506115d6565b8581610485575b5050519283521690827f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce60203393a480f35b80808061049794335af1610446611578565b8585610453565b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905160128152f35b83903461038e57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e5760209250549051908152f35b508234610203577f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce90602061054836611443565b6105569592959391936116dc565b7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4894610590610586868989611b4a565b9690879189612061565b5193845273ffffffffffffffffffffffffffffffffffffffff908116958116941692a480f35b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7168152f35b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035751908152602090f35b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419168152f35b83903461038e57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e578160209360ff9261070c611420565b9035825281865273ffffffffffffffffffffffffffffffffffffffff83832091168252855220541690519015158152f35b50823461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020357602090516305f5e1008152f35b9050346102035760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035735906005548210156107e157506107c1906114a2565b50548151906bffffffffffffffffffffffff8116825260601c6020820152f35b80fd5b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035760207f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25891610840611e23565b6108486116dc565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154161760015551338152a180f35b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020906003549051908152f35b90503461020357827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020357803573ffffffffffffffffffffffffffffffffffffffff9182821692838303610af85760243590610916611eb6565b7f78e3214f000000000000000000000000000000000000000000000000000000009384875260209560078752888820548015159081610aed575b5015610a9f57806109ed57505050848080809361096f47821115611677565b335af161097a611578565b501561099157508293916007915b84525281205580f35b606490838651917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601c60248201527f5061796f75743a205472616e7366657220636f696e206661696c6564000000006044820152fd5b8689979560248a9b9896959851809481937f70a0823100000000000000000000000000000000000000000000000000000000835230908301525afa908115610a95578891610a5d575b5090600795610a4b8493610a58951115611677565b60015460081c1690612138565b610988565b929190508483813d8311610a8e575b610a768183611508565b81010312610a8a5791519091906007610a36565b8780fd5b503d610a6c565b87513d8a823e3d90fd5b5050505093909161a8c0420192834211610ac157845260079052822055905080f35b6024856011887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b905042101538610950565b8480fd5b829391503461032f5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261032f57610b37611e23565b7f76aa28fc000000000000000000000000000000000000000000000000000000008084526007602052828420548015159081610bc5575b5015610ba75750356002557fe308a099000000000000000000000000000000000000000000000000000000008252600760205281205580f35b90925061a8c04201928342116102f857508352600760205282205580f35b905042101538610b6e565b828434610203577f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce906020610c0436611443565b610c129592959391936116dc565b7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec794610590610586868989611b4a565b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905161a8c08152f35b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020906002549051908152f35b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035760209060ff6001541690519015158152f35b8391503461038e57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e573590610d37611420565b91610d406116dc565b7f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce60207f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec793610d9d610d93853388611b4a565b9590869188612061565b5192835273ffffffffffffffffffffffffffffffffffffffff9485169433941692a480f35b8391503461038e57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e573590610dfd611420565b91610e066116dc565b7f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce60207f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4893610d9d610d93853388611b4a565b8391503461038e57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e57610e92611e23565b6001549060ff821615610ef257507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006020921660015551338152a180f35b82517f8dfc202b000000000000000000000000000000000000000000000000000000008152fd5b9050823461038e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e57813591610f56611e23565b600554831015610f905791602091817f34cf54504fd39ab670a54acbb37f686c5bd25e6eedfa39889cba899d360bc7d9945551908152a180f35b602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601760248201527f50726573616c653a2057726f6e67206974657261746f720000000000000000006044820152fd5b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905160068152f35b82843461020357807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035761105e611420565b903373ffffffffffffffffffffffffffffffffffffffff831603611088575061038a919235611fc0565b8390517f6697b232000000000000000000000000000000000000000000000000000000008152fd5b9050823461038e57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e5761038a91356110f36001610374611420565b611f16565b8284346102035760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203578060209273ffffffffffffffffffffffffffffffffffffffff61114a6113f8565b1681526006845220549051908152f35b8391503461038e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e57816020936001923581528085522001549051908152f35b8284807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576111d66113f8565b90827f3bf78ceb2bec33367593d193d62ee0bab304fd3356e414656d746684d8c8d9ce6020611203611420565b9361120c6116dc565b6112163487611712565b9573ffffffffffffffffffffffffffffffffffffffff928392611249888080808d8960015460081c165af1610446611578565b878161125e575b50505196875216951693a480f35b80808061127094335af1610446611578565b8a87611250565b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610203576020905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48168152f35b82843461020357817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102035760209073ffffffffffffffffffffffffffffffffffffffff60015460081c169051908152f35b91503461038e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261038e57357fffffffff00000000000000000000000000000000000000000000000000000000811680910361038e57602092507f7965db0b0000000000000000000000000000000000000000000000000000000081149081156113ce575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014836113c7565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361141b57565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361141b57565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc606091011261141b5773ffffffffffffffffffffffffffffffffffffffff600435818116810361141b579160243591604435908116810361141b5790565b6005548110156114d95760056000527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761154957604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b3d156115d1573d9067ffffffffffffffff821161154957604051916115c560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184611508565b82523d6000602084013e565b606090565b156115dd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726573616c653a20436f696e207472616e73666572206661696c65640000006044820152fd5b9190820180921161164857565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b1561167e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f50726573616c653a2057726f6e6720616d6f756e7400000000000000000000006044820152fd5b60ff600154166116e857565b60046040517fd93c0665000000000000000000000000000000000000000000000000000000008152fd5b6004805491611720836114a2565b505490606091821c15611aec5773ffffffffffffffffffffffffffffffffffffffff6040928351927ffeaf968c00000000000000000000000000000000000000000000000000000000845260a0848781867f0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419165afa938415611ae157600094611a92575b506117af88856121e9565b926117d56117bc896114a2565b50946bffffffffffffffffffffffff80965416906121fc565b86518181528660208201527fb80c9abe533e6358a5262b5e8e8d3aa6f8e4d2bb4ebab1e44efa024ee5cbb606883392a261181a670de0b6b3a7640000809204996114a2565b509586548681871c918c831115600014611a805716908482820216918183041490151715611a5257915b6118508360035461163b565b6003558115611a245790611866929104906121e9565b97888a03998a116119f6578554841c81106119415750906118ad92918554831c9116600052600660205261189f8660002091825461163b565b90558354901c60025461163b565b600255815416905581547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611913579160209160017f34cf54504fd39ab670a54acbb37f686c5bd25e6eedfa39889cba899d360bc7d9940180925551908152a19091565b6011837f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b9181979596919394508316600052600660205260002061196282825461163b565b90556119708160025461163b565b60025516908354901c039283116119c85750906119c491906bffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000083549260601b169116179055565b9091565b6011907f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b6011887f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b60128a7f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b60118a7f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b611a8c9250168b6121e9565b91611844565b909360a0823d60a011611ad9575b81611aad60a09383611508565b810103126107e15750611abf816121d2565b50611ad16080602083015192016121d2565b5092386117a4565b3d9150611aa0565b85513d6000823e3d90fd5b6064836020604051917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601160248201527f50726553616c653a20697320656e6465640000000000000000000000000000006044820152fd5b600490815492611b59846114a2565b5054606090811c15611dc5576305f5e10091868302928084048803611d9757620f4240611bdf91611ba5611b8c8a6114a2565b50966bffffffffffffffffffffffff80985416906121fc565b906040519082825260208201527fb80c9abe533e6358a5262b5e8e8d3aa6f8e4d2bb4ebab1e44efa024ee5cbb60660403392a204966114a2565b509384548481851c9189831115600014611d8657169073ffffffffffffffffffffffffffffffffffffffff82820216918183041490151715611d4e575b611c288160035461163b565b60035573ffffffffffffffffffffffffffffffffffffffff918216611d7c576402540be40090818102918183041490151715611d4e57965b878903988911611d4e578554841c8110611d2e575090611c9992918554831c9116600052600660205261189f604060002091825461163b565b600255815416905580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611d00577f34cf54504fd39ab670a54acbb37f686c5bd25e6eedfa39889cba899d360bc7d991600160209201809155604051908152a19091565b6011827f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b90809694508092166000526006602052604060002061196282825461163b565b6011877f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b6064900496611c60565b611d92925016886121e9565b611c1c565b6011867f4e487b71000000000000000000000000000000000000000000000000000000006000525260246000fd5b6064846020604051917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601160248201527f50726553616c653a20697320656e6465640000000000000000000000000000006044820152fd5b3360009081527fee57cd81e84075558e8fcc182a1f4393f91fc97f963a136e66b7f949a62f319f60205260409020547f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9299060ff1615611e7f5750565b604490604051907fe2517d3f0000000000000000000000000000000000000000000000000000000082523360048301526024820152fd5b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604081205460ff1615611e7f5750565b80600052600060205260406000203360005260205260ff6040600020541615611e7f5750565b906000918083528260205273ffffffffffffffffffffffffffffffffffffffff6040842092169182845260205260ff60408420541615600014611fbb5780835282602052604083208284526020526040832060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d339380a4600190565b505090565b906000918083528260205273ffffffffffffffffffffffffffffffffffffffff6040842092169182845260205260ff604084205416600014611fbb578083528260205260408320828452602052604083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b339380a4600190565b92906020906064600091604051907f23b872dd000000000000000000000000000000000000000000000000000000008252336004830152306024830152604482015282875af180612118575b156120ee576120d89073ffffffffffffffffffffffffffffffffffffffff60015460081c1684612138565b806120e1575050565b6120ec913390612138565b565b60046040517ff4059071000000000000000000000000000000000000000000000000000000008152fd5b503d1561212f57600160005114601f3d11166120ad565b823b15156120ad565b916044602092600092604051917fa9059cbb0000000000000000000000000000000000000000000000000000000083526004830152602482015282855af190816121af575b501561218557565b60046040517ffb7f5079000000000000000000000000000000000000000000000000000000008152fd5b90503d156121ca5750600160005114601f3d11165b3861217d565b3b15156121c4565b519069ffffffffffffffffffff8216820361141b57565b8181029291811591840414171561164857565b8115612206570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea2646970667358221220aab25e6bc96e9535bf0fb07221a0d2c698f392a758bbfcba6a144a82a59c878164736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000004c2df47874a1d3eb46318509b0cec2a5f35024770000000000000000000000004c2df47874a1d3eb46318509b0cec2a5f35024770000000000000000000000004c316a33ef30d634a3002ca55561a8f084395e8b
-----Decoded View---------------
Arg [0] : COIN_PRICE_FEED_ (address): 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
Arg [1] : usdcToken_ (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [2] : usdtToken_ (address): 0xdAC17F958D2ee523a2206206994597C13D831ec7
Arg [3] : protocolWallet_ (address): 0x4C2DF47874a1d3Eb46318509b0cec2a5F3502477
Arg [4] : DAO (address): 0x4C2DF47874a1d3Eb46318509b0cec2a5F3502477
Arg [5] : operator (address): 0x4C316a33EF30d634A3002Ca55561A8F084395E8B
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419
Arg [1] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [2] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7
Arg [3] : 0000000000000000000000004c2df47874a1d3eb46318509b0cec2a5f3502477
Arg [4] : 0000000000000000000000004c2df47874a1d3eb46318509b0cec2a5f3502477
Arg [5] : 0000000000000000000000004c316a33ef30d634a3002ca55561a8f084395e8b
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.