Overview
S Balance
0 S
S Value
-More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 48 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Buy Exact In | 1199784 | 7 days ago | IN | 1 S | 0.00026639 | ||||
Buy Exact In | 1051495 | 8 days ago | IN | 0.1 S | 0.00027048 | ||||
Buy Exact In | 1043940 | 8 days ago | IN | 2 S | 0.00027048 | ||||
Migrate | 1038186 | 8 days ago | IN | 0 S | 0.00047642 | ||||
Sell Exact In | 987737 | 9 days ago | IN | 0 S | 0.00031827 | ||||
Buy Exact In | 917423 | 9 days ago | IN | 200 S | 0.02718344 | ||||
Buy Exact In | 916473 | 9 days ago | IN | 200 S | 0.02718344 | ||||
Buy Exact In | 915233 | 9 days ago | IN | 1 S | 0.00027048 | ||||
Buy Exact In | 914740 | 9 days ago | IN | 1 S | 0.00027048 | ||||
Buy Exact In | 914734 | 9 days ago | IN | 10 S | 0.00027048 | ||||
Sell Exact In | 914694 | 9 days ago | IN | 0 S | 0.00031827 | ||||
Buy Exact In | 914633 | 9 days ago | IN | 10 S | 0.00027048 | ||||
Buy Exact In | 914608 | 9 days ago | IN | 1 S | 0.00027048 | ||||
Buy Exact In | 914606 | 9 days ago | IN | 200 S | 0.02718344 | ||||
Buy Exact In | 914534 | 9 days ago | IN | 200 S | 0.00027048 | ||||
Buy Exact In | 914477 | 9 days ago | IN | 200 S | 0.00027048 | ||||
Buy Exact In | 914395 | 9 days ago | IN | 200 S | 0.00027048 | ||||
Buy Exact In | 914376 | 9 days ago | IN | 100 S | 0.00042083 | ||||
Buy Exact In | 914200 | 9 days ago | IN | 100 S | 0.0003736 | ||||
Buy Exact In | 914166 | 9 days ago | IN | 100 S | 0.0003736 | ||||
Buy Exact In | 914163 | 9 days ago | IN | 100 S | 0.00040438 | ||||
Buy Exact In | 914151 | 9 days ago | IN | 150 S | 0.0003736 | ||||
Buy Exact In | 914126 | 9 days ago | IN | 100 S | 0.00040438 | ||||
Buy Exact In | 914105 | 9 days ago | IN | 150 S | 0.00040438 | ||||
Buy Exact In | 914100 | 9 days ago | IN | 100 S | 0.00040438 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
1199784 | 7 days ago | 1 S | ||||
1051495 | 8 days ago | 0.1 S | ||||
1043940 | 8 days ago | 2 S | ||||
917423 | 9 days ago | 200 S | ||||
916473 | 9 days ago | 200 S | ||||
915233 | 9 days ago | 1 S | ||||
914740 | 9 days ago | 1 S | ||||
914734 | 9 days ago | 10 S | ||||
914633 | 9 days ago | 10 S | ||||
914608 | 9 days ago | 1 S | ||||
914606 | 9 days ago | 200 S | ||||
914534 | 9 days ago | 200 S | ||||
914477 | 9 days ago | 200 S | ||||
914395 | 9 days ago | 200 S | ||||
914376 | 9 days ago | 100 S | ||||
914200 | 9 days ago | 100 S | ||||
914166 | 9 days ago | 100 S | ||||
914163 | 9 days ago | 100 S | ||||
914151 | 9 days ago | 150 S | ||||
914126 | 9 days ago | 100 S | ||||
914105 | 9 days ago | 150 S | ||||
914100 | 9 days ago | 100 S | ||||
914087 | 9 days ago | 200 S | ||||
914061 | 9 days ago | 0.9801 S | ||||
914061 | 9 days ago | 0.9801 S |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
MoonshotFactory
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.23; import {MoonshotToken} from "./MoonshotToken.sol"; import {IMoonshotFactory} from "./interfaces/IMoonshotFactory.sol"; import {IMoonshotToken} from "./interfaces/IMoonshotToken.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import {IRouter03} from "./interfaces/IRouter03.sol"; import {IPairFactory} from "./interfaces/IPairFactory.sol"; contract MoonshotFactory is IMoonshotFactory, Ownable, ReentrancyGuard { uint256 public totalSupply; uint256 public virtualTokenReserves; uint256 public virtualCollateralReserves; uint256 public feeBasisPoints; uint256 public mcUpperLimit; uint256 public mcLowerLimit; uint256 public tokensMigrationThreshold; uint256 public migrationFeeFixed; uint256 public poolCreationFee; uint256 public dexFeeBasisPoints; address public dexTreasury; address public treasury; address public immutable ROUTER_03; address public signer; mapping(bytes32 => bool) public usedSignatures; mapping(address => bool) public readyForMigration; address[] public moonshotTokens; uint256 private constant MAX_BPS = 2_500; constructor( uint256 _totalSupply, uint256 _virtualTokenReserves, uint256 _virtualCollateralReserves, uint256 _feeBasisPoints, uint256 _dexFeeBasisPoints, uint256 _migrationFeeFixed, uint256 _poolCreationFee, uint256 _mcUpperLimit, uint256 _mcLowerLimit, uint256 _tokensMigrationThreshold, address _treasury, address _dexTreasury, address _solidlyRouter, address _signer ) Ownable(msg.sender) { _setConfig( _totalSupply, _virtualTokenReserves, _virtualCollateralReserves, _feeBasisPoints, _dexFeeBasisPoints, _migrationFeeFixed, _poolCreationFee, _mcUpperLimit, _mcLowerLimit, _tokensMigrationThreshold, _treasury, _dexTreasury, _signer ); ROUTER_03 = _solidlyRouter; } function setConfig( uint256 _totalSupply, uint256 _virtualTokenReserves, uint256 _virtualCollateralReserves, uint256 _feeBasisPoints, uint256 _dexFeeBasisPoints, uint256 _migrationFeeFixed, uint256 _poolCreationFee, uint256 _mcUpperLimit, uint256 _mcLowerLimit, uint256 _tokensMigrationThreshold, address _treasury, address _dexTreasury, address _signer ) external onlyOwner { _setConfig( _totalSupply, _virtualTokenReserves, _virtualCollateralReserves, _feeBasisPoints, _dexFeeBasisPoints, _migrationFeeFixed, _poolCreationFee, _mcUpperLimit, _mcLowerLimit, _tokensMigrationThreshold, _treasury, _dexTreasury, _signer ); } function createMoonshotToken( string memory _name, string memory _symbol, uint256 _nonce, bytes memory _signature ) external onlyOwner returns (address) { MoonshotToken token = new MoonshotToken( IMoonshotToken.ConstructorParams( _name, _symbol, msg.sender, // creator totalSupply, virtualTokenReserves, virtualCollateralReserves, feeBasisPoints, dexFeeBasisPoints, migrationFeeFixed, poolCreationFee, mcLowerLimit, mcUpperLimit, tokensMigrationThreshold, treasury, ROUTER_03, dexTreasury ) ); moonshotTokens.push(address(token)); IRouter03 router = IRouter03(ROUTER_03); address wethAddress = router.weth(); IPairFactory factory = IPairFactory(router.factory()); address pair = factory.createPair(address(token), wethAddress, false); emit NewMoonshotToken(address(token), msg.sender, pair); return address(token); } function createMoonshotTokenAndBuy( string memory _name, string memory _symbol, uint256 _nonce, uint256 _tokenAmountMin, bytes memory _signature ) external payable nonReentrant onlyOwner returns (address) { MoonshotToken token = new MoonshotToken( IMoonshotToken.ConstructorParams( _name, _symbol, msg.sender, // creator totalSupply, virtualTokenReserves, virtualCollateralReserves, feeBasisPoints, dexFeeBasisPoints, migrationFeeFixed, poolCreationFee, mcLowerLimit, mcUpperLimit, tokensMigrationThreshold, treasury, ROUTER_03, dexTreasury ) ); uint256 valueBuy = msg.value / 2; uint256 remainingValue = msg.value - valueBuy; (uint256 collateralToPayWithFee, uint256 helioFee, uint256 dexFee) = token.buyExactIn{value: valueBuy}( _tokenAmountMin ); uint256 tokenAmount = token.balanceOf(address(this)); // token.transfer(msg.sender, tokenAmount); IRouter03 router = IRouter03(ROUTER_03); (, , uint256 liquidity) = router.addLiquidityETH{value: remainingValue}( address(token), false, tokenAmount, tokenAmount, remainingValue, address(this), block.timestamp + 120 // 2 minutes ); address pair = IPairFactory(router.factory()).getPair(address(token), router.weth(), false); moonshotTokens.push(address(token)); emit NewMoonshotTokenAndBuy( address(token), msg.sender, pair, tokenAmount, collateralToPayWithFee, helioFee, dexFee, token.getCurveProgressBps() ); return address(token); } function buyExactOut( address _token, uint256 _tokenAmount, uint256 _maxCollateralAmount ) external payable nonReentrant { (uint256 collateralToPayWithFee, uint256 helioFee, uint256 dexFee) = IMoonshotToken(_token).buyExactOut{ value: msg.value }(_tokenAmount, _maxCollateralAmount); IMoonshotToken(_token).transfer(msg.sender, _tokenAmount); uint256 refund = address(this).balance; if (refund > 0) { (bool sent, ) = msg.sender.call{value: refund}(""); if (!sent) revert FailedToSendETH(); } emit BuyExactOut( msg.sender, _token, _tokenAmount, MoonshotToken(_token).totalSupply() - IMoonshotToken(_token).balanceOf(address(_token)), collateralToPayWithFee, refund, helioFee, dexFee, IMoonshotToken(_token).getCurveProgressBps() ); if (MoonshotToken(_token).tradingStopped()) { readyForMigration[_token] = true; emit MarketcapReached(_token); } } function buyExactIn(address _token, uint256 _amountOutMin) external payable nonReentrant { (uint256 collateralToPayWithFee, uint256 helioFee, uint256 dexFee) = IMoonshotToken(_token).buyExactIn{ value: msg.value }(_amountOutMin); uint256 tokensOut = IMoonshotToken(_token).balanceOf(address(this)); IMoonshotToken(_token).transfer(msg.sender, tokensOut); uint256 refund = address(this).balance; if (refund > 0) { (bool sent, ) = msg.sender.call{value: refund}(""); if (!sent) revert FailedToSendETH(); } emit BuyExactIn( msg.sender, _token, tokensOut, MoonshotToken(_token).totalSupply() - IMoonshotToken(_token).balanceOf(address(_token)), collateralToPayWithFee, helioFee, dexFee, IMoonshotToken(_token).getCurveProgressBps() ); if (MoonshotToken(_token).tradingStopped()) { readyForMigration[_token] = true; emit MarketcapReached(_token); } } function sellExactIn(address _token, uint256 _tokenAmount, uint256 _amountCollateralMin) external nonReentrant { MoonshotToken(_token).transferFrom(msg.sender, address(this), _tokenAmount); (uint256 collateralToReceiveMinusFee, uint256 helioFee, uint256 dexFee) = MoonshotToken(_token).sellExactIn( _tokenAmount, _amountCollateralMin ); (bool sent, ) = msg.sender.call{value: address(this).balance}(""); if (!sent) revert FailedToSendETH(); emit SellExactIn( msg.sender, _token, _tokenAmount, MoonshotToken(_token).totalSupply() - MoonshotToken(_token).balanceOf(address(_token)), collateralToReceiveMinusFee, helioFee, dexFee, IMoonshotToken(_token).getCurveProgressBps() ); } function sellExactOut(address _token, uint256 _tokenAmountMax, uint256 _amountCollateral) external nonReentrant { MoonshotToken(_token).transferFrom(msg.sender, address(this), _tokenAmountMax); (uint256 collateralToReceiveMinusFee, uint256 tokensOut, uint256 helioFee, uint256 dexFee) = MoonshotToken( _token ).sellExactOut(_tokenAmountMax, _amountCollateral); (bool sent, ) = msg.sender.call{value: address(this).balance}(""); if (!sent) revert FailedToSendETH(); emit SellExactOut( msg.sender, _token, tokensOut, MoonshotToken(_token).totalSupply() - MoonshotToken(_token).balanceOf(address(_token)), collateralToReceiveMinusFee, helioFee, dexFee, IMoonshotToken(_token).getCurveProgressBps() ); } function migrate(address _token) external { if (!readyForMigration[_token]) revert NotReadyForMigration(); (uint256 tokensToMigrate, uint256 tokensToBurn, uint256 collateralAmount, address pair) = MoonshotToken(_token) .migrate(); emit Migrated( _token, tokensToMigrate, tokensToBurn, collateralAmount, MoonshotToken(_token).fixedMigrationFee() + MoonshotToken(_token).poolCreationFee(), pair ); } function _setConfig( uint256 _totalSupply, uint256 _virtualTokenReserves, uint256 _virtualCollateralReserves, uint256 _feeBasisPoints, uint256 _dexFeeBasisPoints, uint256 _migrationFeeFixed, uint256 _poolCreationFee, uint256 _mcUpperLimit, uint256 _mcLowerLimit, uint256 _tokensMigrationThreshold, address _treasury, address _dexTreasury, address _signer ) internal { if (_totalSupply == 0) revert TotalSupplyZeroValue(); if (_virtualTokenReserves == 0) revert VirtualTokenReservesZeroValue(); if (_virtualCollateralReserves == 0) revert VirtualCollateralReservesZeroValue(); if (_mcLowerLimit == 0) revert McUpperLimitZeroValue(); if (_mcUpperLimit == 0) revert McLowerLimitZeroValue(); if (_tokensMigrationThreshold == 0) revert TokensMigrationThresholdZeroValue(); if (_treasury == address(0)) revert TreasuryZeroValue(); if (_dexTreasury == address(0)) revert DexTreasuryZeroValue(); if (_signer == address(0)) revert SignerZeroValue(); if (_mcLowerLimit >= _mcUpperLimit) revert McLowerLimitGreaterThanUpperLimit(); if (dexFeeBasisPoints >= 10_000) revert FeeBPSCheckFailed(); if (feeBasisPoints >= MAX_BPS) revert FeeBPSCheckFailed(); totalSupply = _totalSupply; virtualTokenReserves = _virtualTokenReserves; virtualCollateralReserves = _virtualCollateralReserves; feeBasisPoints = _feeBasisPoints; dexFeeBasisPoints = _dexFeeBasisPoints; migrationFeeFixed = _migrationFeeFixed; poolCreationFee = _poolCreationFee; mcUpperLimit = _mcUpperLimit; mcLowerLimit = _mcLowerLimit; tokensMigrationThreshold = _tokensMigrationThreshold; treasury = _treasury; dexTreasury = _dexTreasury; signer = _signer; emit SetConfig( totalSupply, virtualTokenReserves, virtualCollateralReserves, feeBasisPoints, dexFeeBasisPoints, migrationFeeFixed, poolCreationFee, mcUpperLimit, mcLowerLimit, tokensMigrationThreshold, treasury, dexTreasury, signer ); } receive() external payable {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1271.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol) pragma solidity ^0.8.20; import {ERC20} from "../ERC20.sol"; import {Context} from "../../../utils/Context.sol"; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys a `value` amount of tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 value) public virtual { _burn(_msgSender(), value); } /** * @dev Destroys a `value` amount of tokens from `account`, deducting from * the caller's allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `value`. */ function burnFrom(address account, uint256 value) public virtual { _spendAllowance(account, _msgSender(), value); _burn(account, value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// 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/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "../Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/SignatureChecker.sol) pragma solidity ^0.8.20; import {ECDSA} from "./ECDSA.sol"; import {IERC1271} from "../../interfaces/IERC1271.sol"; /** * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like * Argent and Safe Wallet (previously Gnosis Safe). */ library SignatureChecker { /** * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) { (address recovered, ECDSA.RecoverError error, ) = ECDSA.tryRecover(hash, signature); return (error == ECDSA.RecoverError.NoError && recovered == signer) || isValidERC1271SignatureNow(signer, hash, signature); } /** * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated * against the signer smart contract using ERC1271. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidERC1271SignatureNow( address signer, bytes32 hash, bytes memory signature ) internal view returns (bool) { (bool success, bytes memory result) = signer.staticcall( abi.encodeCall(IERC1271.isValidSignature, (hash, signature)) ); return (success && result.length >= 32 && abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.23; interface IMoonshotFactory { error InvalidSignature(); error SignatureIsUsed(); error FailedToSendETH(); error NotReadyForMigration(); error TotalSupplyZeroValue(); error VirtualTokenReservesZeroValue(); error VirtualCollateralReservesZeroValue(); error McUpperLimitZeroValue(); error McLowerLimitZeroValue(); error TokensMigrationThresholdZeroValue(); error TreasuryZeroValue(); error DexTreasuryZeroValue(); error SignerZeroValue(); error McLowerLimitGreaterThanUpperLimit(); error FeeBPSCheckFailed(); event SetConfig( uint256 totalSupply, uint256 virtualTokenReserves, uint256 virtualCollateralReserves, uint256 feeBasisPoints, uint256 dexFeeBasisPoints, uint256 migrationFeeFixed, uint256 poolCreationFee, uint256 mcUpperLimit, uint256 mcLowerLimit, uint256 tokensMigrationThreshold, address treasury, address dexTreasury, address signer ); event NewMoonshotToken(address addr, address creator, address pair); event NewMoonshotTokenAndBuy( address addr, address creator, address pair, uint256 tokenAmount, uint256 collateralAmount, uint256 fee, uint256 dexFee, uint256 curveProgressBps ); event MarketcapReached(address token); event Migrated( address token, uint256 tokensToMigrate, uint256 tokensToBurn, uint256 collateralToMigrate, uint256 migrationFee, address pair ); event BuyExactOut( address indexed buyer, address indexed token, uint256 tokenAmount, uint256 curvePositionAfterTrade, uint256 collateralAmount, uint256 refund, uint256 fee, uint256 dexFee, uint256 curveProgressBps ); event BuyExactIn( address indexed buyer, address indexed token, uint256 tokenAmount, uint256 curvePositionAfterTrade, uint256 collateralAmount, uint256 fee, uint256 dexFee, uint256 curveProgressBps ); event SellExactIn( address indexed seller, address indexed token, uint256 tokenAmount, uint256 curvePositionAfterTrade, uint256 collateralAmount, uint256 fee, uint256 dexFee, uint256 curveProgressBps ); event SellExactOut( address indexed seller, address indexed token, uint256 tokenAmount, uint256 curvePositionAfterTrade, uint256 collateralAmount, uint256 fee, uint256 dexFee, uint256 curveProgressBps ); function buyExactOut(address _token, uint256 _tokenAmount, uint256 _maxCollateralAmount) external payable; function buyExactIn(address _token, uint256 _amountOutMin) external payable; function sellExactIn(address _token, uint256 _tokenAmount, uint256 _amountCollateralMin) external; function sellExactOut(address _token, uint256 _tokenAmountMax, uint256 _amountCollateral) external; function setConfig( uint256 _totalSupply, uint256 _virtualTokenReserves, uint256 _virtualCollateralReserves, uint256 _feeBasisPoints, uint256 _dexFeeBasisPoints, uint256 _migrationFeeFixed, uint256 _poolCreationFee, uint256 _mcUpperLimit, uint256 _mcLowerLimit, uint256 _tokensMigrationThreshold, address _treasury, address _dexTreasury, address _signer ) external; function createMoonshotToken( string memory _name, string memory _symbol, uint256 _nonce, bytes memory _signature ) external returns (address); function createMoonshotTokenAndBuy( string memory _name, string memory _symbol, uint256 _nonce, uint256 _tokenAmountMin, bytes memory _signature ) external payable returns (address); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.23; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IMoonshotToken is IERC20 { enum CurveType { ConstantProductV1 } struct ConstructorParams { string name; string symbol; address creator; uint256 totalSupply; uint256 virtualTokenReserves; uint256 virtualCollateralReserves; uint256 feeBasisPoints; uint256 dexFeeBasisPoints; uint256 migrationFeeFixed; uint256 poolCreationFee; uint256 mcLowerLimit; uint256 mcUpperLimit; uint256 tokensMigrationThreshold; address treasury; address solidlyRouter; address dexTreasury; } error NotEnoughETHReserves(); error InsufficientTokenReserves(); error FailedToSendETH(); error NotEnoughtETHToBuyTokens(); error SlippageCheckFailed(); error MarketcapThresholdReached(); error SendingToPairIsNotAllowedBeforeMigration(); error PairNotCreated(); error TradingStopped(); error OnlyFactory(); function buyExactOut( uint256 _tokenAmount, uint256 _maxCollateralAmount ) external payable returns (uint256 collateralToPayWithFee, uint256 helioFee, uint256 dexFee); function buyExactIn( uint256 _amountOutMin ) external payable returns (uint256 collateralToPayWithFee, uint256 helioFee, uint256 dexFee); function sellExactIn( uint256 _tokenAmount, uint256 _amountOutMin ) external payable returns (uint256 collateralToReceiveMinusFee, uint256 helioFee, uint256 dexFee); function sellExactOut( uint256 _tokenAmountMax, uint256 _amountCollateral ) external payable returns (uint256 collateralToReceiveMinusFee, uint256 tokensOut, uint256 helioFee, uint256 dexFee); function getAmountOutAndFee( uint256 _amountIn, uint256 _reserveIn, uint256 _reserveOut, bool _paymentTokenIsIn ) external view returns (uint256 amountOut, uint256 fee); function getAmountInAndFee( uint256 _amountOut, uint256 _reserveIn, uint256 _reserveOut, bool _paymentTokenIsOut ) external view returns (uint256 amountIn, uint256 fee); function migrate() external returns (uint256 tokensToMigrate, uint256 tokensToBurn, uint256 collateralAmount, address pair); function getCurveProgressBps() external view returns (uint256); function getMarketCap() external view returns (uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.23; interface IPairFactory { function allPairsLength() external view returns (uint); function isPair(address pair) external view returns (bool); function isPaused() external view returns (bool); function pairCodeHash() external pure returns (bytes32); function getPair(address tokenA, address token, bool stable) external view returns (address); function getInitializable() external view returns (address, address, bool); function createPair(address tokenA, address tokenB, bool stable) external returns (address pair); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; interface IRouter03 { struct Route { address from; address to; bool stable; } function factory() external view returns (address); function weth() external view returns (address); function pairCodeHash() external view returns (bytes32); function voter() external view returns (address); function pairFor(address tokenA, address tokenB, bool stable) external view returns (address pair); function getReserves( address tokenA, address tokenB, bool stable ) external view returns (uint reserveA, uint reserveB); function getAmountOut( uint amountIn, address tokenIn, address tokenOut ) external view returns (uint amount, bool stable); function getAmountOut( uint amountIn, address tokenIn, address tokenOut, bool stable ) external view returns (uint amount); function getAmountsOut(uint amountIn, Route[] memory routes) external view returns (uint[] memory amounts); function isPair(address pair) external view returns (bool); function quoteAddLiquidity( address tokenA, address tokenB, bool stable, uint amountADesired, uint amountBDesired ) external view returns (uint amountA, uint amountB, uint liquidity); function quoteRemoveLiquidity( address tokenA, address tokenB, bool stable, uint liquidity ) external view returns (uint amountA, uint amountB); function addLiquidity( address tokenA, address tokenB, bool stable, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, bool stable, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, bool stable, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, bool stable, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, bool stable, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, bool stable, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function removeLiquidityETHSupportingFeeOnTransferTokens( address token, bool stable, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, bool stable, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokensSimple( uint amountIn, uint amountOutMin, address tokenFrom, address tokenTo, bool stable, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, Route[] calldata routes, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens( uint amountOutMin, Route[] calldata routes, address to, uint deadline ) external payable returns (uint[] memory amounts); function swapExactTokensForETH( uint amountIn, uint amountOutMin, Route[] calldata routes, address to, uint deadline ) external returns (uint[] memory amounts); function UNSAFE_swapExactTokensForTokens( uint[] memory amounts, Route[] calldata routes, address to, uint deadline ) external returns (uint[] memory); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, Route[] calldata routes, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, Route[] calldata routes, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, Route[] calldata routes, address to, uint deadline ) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.23; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import {IRouter03} from "./interfaces/IRouter03.sol"; import {IPairFactory} from "./interfaces/IPairFactory.sol"; import {IMoonshotToken} from "./interfaces/IMoonshotToken.sol"; contract MoonshotToken is ERC20Burnable, IMoonshotToken, ReentrancyGuard { CurveType public constant curveType = CurveType.ConstantProductV1; uint256 public initalTokenSupply; uint256 public virtualTokenReserves; uint256 public virtualCollateralReserves; uint256 public immutable virtualCollateralReservesInitial; uint256 public immutable feeBPS; uint256 public immutable dexFeeBPS; uint256 public immutable mcLowerLimit; uint256 public immutable mcUpperLimit; uint256 public immutable tokensMigrationThreshold; uint256 public immutable fixedMigrationFee; uint256 public immutable poolCreationFee; address public immutable creator; address public immutable treasury; address public immutable dexTreasury; address public immutable factory; bool public tradingStopped; bool public sendingToPairNotAllowed = true; uint256 public constant MAX_BPS = 10_000; IRouter03 public immutable solidlyRouter; modifier buyChecks() { if (tradingStopped) revert TradingStopped(); _; _checkMcLower(); _checkMcUpperLimit(); } modifier sellChecks() { if (tradingStopped) revert TradingStopped(); _; } modifier onlyFactory() { if (msg.sender != factory) revert OnlyFactory(); _; } constructor(ConstructorParams memory _params) ERC20(_params.name, _params.symbol) { _mint(address(this), _params.totalSupply); initalTokenSupply = _params.totalSupply; virtualCollateralReserves = _params.virtualCollateralReserves; virtualCollateralReservesInitial = _params.virtualCollateralReserves; virtualTokenReserves = _params.virtualTokenReserves; creator = _params.creator; feeBPS = _params.feeBasisPoints; dexFeeBPS = _params.dexFeeBasisPoints; treasury = _params.treasury; dexTreasury = _params.dexTreasury; fixedMigrationFee = _params.migrationFeeFixed; poolCreationFee = _params.poolCreationFee; mcLowerLimit = _params.mcLowerLimit; mcUpperLimit = _params.mcUpperLimit; tokensMigrationThreshold = _params.tokensMigrationThreshold; solidlyRouter = IRouter03(_params.solidlyRouter); factory = msg.sender; } /** * @dev Buys tokenAmount of tokens for eth, refunding excess eth * * @param _tokenAmount - amount of tokens to buy * @param _maxCollateralAmount - maximum amount of collateral a caller is willing to spend */ function buyExactOut( uint256 _tokenAmount, uint256 _maxCollateralAmount ) external payable onlyFactory buyChecks returns (uint256 collateralToPayWithFee, uint256 helioFee, uint256 dexFee) { if (balanceOf(address(this)) <= _tokenAmount) revert InsufficientTokenReserves(); uint256 collateralToSpend = (_tokenAmount * virtualCollateralReserves) / (virtualTokenReserves - _tokenAmount); (helioFee, dexFee) = _calculateFee(collateralToSpend); collateralToPayWithFee = collateralToSpend + helioFee + dexFee; if (collateralToPayWithFee > _maxCollateralAmount) revert SlippageCheckFailed(); _transferCollateral(treasury, helioFee); _transferCollateral(dexTreasury, dexFee); virtualTokenReserves -= _tokenAmount; virtualCollateralReserves += collateralToSpend; uint256 refund; if (msg.value > collateralToPayWithFee) { // refund the user refund = msg.value - collateralToPayWithFee; _transferCollateral(msg.sender, refund); } else if (msg.value < collateralToPayWithFee) { revert NotEnoughtETHToBuyTokens(); } _transfer(address(this), msg.sender, _tokenAmount); } /** * @dev Buys tokens specifing minimal amount of tokens a caller gets * * @param _amountOutMin - minimal amount of tokens a caller will get */ function buyExactIn( uint256 _amountOutMin ) external payable onlyFactory buyChecks returns (uint256 collateralToPayWithFee, uint256 helioFee, uint256 dexFee) { if (balanceOf(address(this)) <= _amountOutMin) revert InsufficientTokenReserves(); collateralToPayWithFee = msg.value; (helioFee, dexFee) = _calculateFee(collateralToPayWithFee); uint256 collateralToSpendMinusFee = collateralToPayWithFee - helioFee - dexFee; _transferCollateral(treasury, helioFee); _transferCollateral(dexTreasury, dexFee); uint256 tokensOut = (collateralToSpendMinusFee * virtualTokenReserves) / (virtualCollateralReserves + collateralToSpendMinusFee); if (tokensOut < _amountOutMin) revert SlippageCheckFailed(); virtualTokenReserves -= tokensOut; virtualCollateralReserves += collateralToSpendMinusFee; _transfer(address(this), msg.sender, tokensOut); } /** * @dev Sells given amount of tokens for eth * * @param _tokenAmount - amount of tokens a caller wants to sell * @param _amountCollateralMin - minimum amount of collateral a seller will get */ function sellExactIn( uint256 _tokenAmount, uint256 _amountCollateralMin ) external payable onlyFactory sellChecks returns (uint256 collateralToReceiveMinusFee, uint256 helioFee, uint256 dexFee) { uint256 collaterallToReceive = (_tokenAmount * virtualCollateralReserves) / (virtualTokenReserves + _tokenAmount); (helioFee, dexFee) = _calculateFee(collaterallToReceive); collateralToReceiveMinusFee = collaterallToReceive - helioFee - dexFee; _transferCollateral(treasury, helioFee); _transferCollateral(dexTreasury, dexFee); if (collateralToReceiveMinusFee < _amountCollateralMin) revert SlippageCheckFailed(); virtualTokenReserves += _tokenAmount; virtualCollateralReserves -= collaterallToReceive; _transferCollateral(msg.sender, collateralToReceiveMinusFee); _transfer(msg.sender, address(this), _tokenAmount); } /** * @dev Sells given amount of tokens for eth * * @param _tokenAmountMax - max amount of tokens a caller wants to sell */ function sellExactOut( uint256 _tokenAmountMax, uint256 _amountCollateral ) external payable onlyFactory sellChecks returns (uint256 collateralToReceiveMinusFee, uint256 tokensOut, uint256 helioFee, uint256 dexFee) { (helioFee, dexFee) = _calculateFee(_amountCollateral); collateralToReceiveMinusFee = _amountCollateral - helioFee - dexFee; _transferCollateral(treasury, helioFee); _transferCollateral(dexTreasury, dexFee); tokensOut = (_amountCollateral * virtualTokenReserves) / (virtualCollateralReserves - _amountCollateral); if (tokensOut > _tokenAmountMax) revert SlippageCheckFailed(); _transfer(msg.sender, address(this), tokensOut); virtualTokenReserves += tokensOut; virtualCollateralReserves -= _amountCollateral; _transferCollateral(msg.sender, collateralToReceiveMinusFee); } /** * @dev Calculates amountOut for a given amountIn * * @param _amountIn - amount in which will be transfered to the contract * @param _reserveIn - reserve in * @param _reserveOut - reserve out * @param _paymentTokenIsIn - if token in is a collateral token */ function getAmountOutAndFee( uint256 _amountIn, uint256 _reserveIn, uint256 _reserveOut, bool _paymentTokenIsIn ) external view returns (uint256 amountOut, uint256 fee) { if (_paymentTokenIsIn) { (uint256 helioFee, uint256 dexFee) = _calculateFee(_amountIn); fee = helioFee + dexFee; amountOut = (_amountIn * _reserveOut) / (_reserveIn + _amountIn); } else { amountOut = (_amountIn * _reserveOut) / (_reserveIn + _amountIn); (uint256 helioFee, uint256 dexFee) = _calculateFee(amountOut); fee = helioFee + dexFee; } } /** * @dev Calculates amountIn for a given amountOut * * @param _amountOut - amount out which will be transfered from the contract * @param _reserveIn - reserve in * @param _reserveOut - reserve out * @param _paymentTokenIsOut - if token out is a payment token */ function getAmountInAndFee( uint256 _amountOut, uint256 _reserveIn, uint256 _reserveOut, bool _paymentTokenIsOut ) external view returns (uint256 amountIn, uint256 fee) { if (_paymentTokenIsOut) { (uint256 helioFee, uint256 dexFee) = _calculateFee(_amountOut); fee = helioFee + dexFee; amountIn = (_amountOut * _reserveIn) / (_reserveOut - _amountOut); } else { amountIn = (_amountOut * _reserveIn) / (_reserveOut - _amountOut); (uint256 helioFee, uint256 dexFee) = _calculateFee(amountIn); fee = helioFee + dexFee; } } /** * @dev migrates tokens and collateral to uniswap-v2 and burns LP tokens */ function migrate() external onlyFactory returns (uint256 tokensToMigrate, uint256 tokensToBurn, uint256 collateralAmount, address pair) { sendingToPairNotAllowed = false; uint256 tokensRemaining = balanceOf(address(this)); this.approve(address(solidlyRouter), tokensRemaining); tokensToMigrate = _tokensToMigrate(); tokensToBurn = tokensRemaining - tokensToMigrate; _burn(address(this), tokensToBurn); (uint256 treasuryFee, uint256 dexFee) = _splitFee(fixedMigrationFee); _transferCollateral(treasury, treasuryFee + poolCreationFee); _transferCollateral(dexTreasury, dexFee); collateralAmount = virtualCollateralReserves - virtualCollateralReservesInitial - treasuryFee - dexFee - poolCreationFee; (, , uint256 liquidity) = solidlyRouter.addLiquidityETH{value: collateralAmount}( address(this), false, tokensToMigrate, tokensToMigrate, collateralAmount, address(this), block.timestamp + 120 // 2 minutes ); pair = IPairFactory(solidlyRouter.factory()).getPair(address(this), solidlyRouter.weth(), false); if (pair == address(0)) revert PairNotCreated(); if (address(this).balance > 0) { _transferCollateral(treasury, address(this).balance); } IERC20(pair).transfer(address(0), liquidity); } function getMarketCap() public view returns (uint256) { uint256 mc = (virtualCollateralReserves * 10 ** 18 * totalSupply()) / virtualTokenReserves; return mc / 10 ** 18; } function getCurveProgressBps() external view returns (uint256) { uint256 progress = ((initalTokenSupply - balanceOf(address(this))) * MAX_BPS) / tokensMigrationThreshold; return progress < 100 ? 100 : (progress > MAX_BPS ? MAX_BPS : progress); } function _tokensToMigrate() internal view returns (uint256) { uint256 collateralDeductedFee = address(this).balance - fixedMigrationFee - poolCreationFee; return (virtualTokenReserves * collateralDeductedFee) / virtualCollateralReserves; } function _calculateFee(uint256 _amount) internal view returns (uint256 treasuryFee, uint256 dexFee) { treasuryFee = (_amount * feeBPS) / MAX_BPS; dexFee = (treasuryFee * dexFeeBPS) / MAX_BPS; treasuryFee -= dexFee; } function _splitFee(uint256 _feeAmount) internal view returns (uint256 treasuryFee, uint256 dexFee) { dexFee = (_feeAmount * dexFeeBPS) / MAX_BPS; treasuryFee = _feeAmount - dexFee; } function _transferCollateral(address _to, uint256 _amount) internal { (bool sent, ) = _to.call{value: _amount}(""); if (!sent) revert FailedToSendETH(); } function _checkMcUpperLimit() internal view { uint256 mc = getMarketCap(); if (mc > mcUpperLimit) revert MarketcapThresholdReached(); } function _checkMcLower() internal { uint256 mc = getMarketCap(); if (mc > mcLowerLimit) { tradingStopped = true; } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "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":"uint256","name":"_totalSupply","type":"uint256"},{"internalType":"uint256","name":"_virtualTokenReserves","type":"uint256"},{"internalType":"uint256","name":"_virtualCollateralReserves","type":"uint256"},{"internalType":"uint256","name":"_feeBasisPoints","type":"uint256"},{"internalType":"uint256","name":"_dexFeeBasisPoints","type":"uint256"},{"internalType":"uint256","name":"_migrationFeeFixed","type":"uint256"},{"internalType":"uint256","name":"_poolCreationFee","type":"uint256"},{"internalType":"uint256","name":"_mcUpperLimit","type":"uint256"},{"internalType":"uint256","name":"_mcLowerLimit","type":"uint256"},{"internalType":"uint256","name":"_tokensMigrationThreshold","type":"uint256"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_dexTreasury","type":"address"},{"internalType":"address","name":"_solidlyRouter","type":"address"},{"internalType":"address","name":"_signer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DexTreasuryZeroValue","type":"error"},{"inputs":[],"name":"FailedToSendETH","type":"error"},{"inputs":[],"name":"FeeBPSCheckFailed","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"McLowerLimitGreaterThanUpperLimit","type":"error"},{"inputs":[],"name":"McLowerLimitZeroValue","type":"error"},{"inputs":[],"name":"McUpperLimitZeroValue","type":"error"},{"inputs":[],"name":"NotReadyForMigration","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"SignatureIsUsed","type":"error"},{"inputs":[],"name":"SignerZeroValue","type":"error"},{"inputs":[],"name":"TokensMigrationThresholdZeroValue","type":"error"},{"inputs":[],"name":"TotalSupplyZeroValue","type":"error"},{"inputs":[],"name":"TreasuryZeroValue","type":"error"},{"inputs":[],"name":"VirtualCollateralReservesZeroValue","type":"error"},{"inputs":[],"name":"VirtualTokenReservesZeroValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"curvePositionAfterTrade","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dexFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"curveProgressBps","type":"uint256"}],"name":"BuyExactIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"curvePositionAfterTrade","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"refund","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dexFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"curveProgressBps","type":"uint256"}],"name":"BuyExactOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"MarketcapReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokensToMigrate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensToBurn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralToMigrate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"migrationFee","type":"uint256"},{"indexed":false,"internalType":"address","name":"pair","type":"address"}],"name":"Migrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"}],"name":"NewMoonshotToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dexFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"curveProgressBps","type":"uint256"}],"name":"NewMoonshotTokenAndBuy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"curvePositionAfterTrade","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dexFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"curveProgressBps","type":"uint256"}],"name":"SellExactIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"curvePositionAfterTrade","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dexFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"curveProgressBps","type":"uint256"}],"name":"SellExactOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"virtualTokenReserves","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"virtualCollateralReserves","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeBasisPoints","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dexFeeBasisPoints","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"migrationFeeFixed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"poolCreationFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mcUpperLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mcLowerLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensMigrationThreshold","type":"uint256"},{"indexed":false,"internalType":"address","name":"treasury","type":"address"},{"indexed":false,"internalType":"address","name":"dexTreasury","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"SetConfig","type":"event"},{"inputs":[],"name":"ROUTER_03","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amountOutMin","type":"uint256"}],"name":"buyExactIn","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"},{"internalType":"uint256","name":"_maxCollateralAmount","type":"uint256"}],"name":"buyExactOut","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"createMoonshotToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"uint256","name":"_tokenAmountMin","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"createMoonshotTokenAndBuy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"dexFeeBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dexTreasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mcLowerLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mcUpperLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"migrationFeeFixed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"moonshotTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolCreationFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"readyForMigration","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"},{"internalType":"uint256","name":"_amountCollateralMin","type":"uint256"}],"name":"sellExactIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenAmountMax","type":"uint256"},{"internalType":"uint256","name":"_amountCollateral","type":"uint256"}],"name":"sellExactOut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalSupply","type":"uint256"},{"internalType":"uint256","name":"_virtualTokenReserves","type":"uint256"},{"internalType":"uint256","name":"_virtualCollateralReserves","type":"uint256"},{"internalType":"uint256","name":"_feeBasisPoints","type":"uint256"},{"internalType":"uint256","name":"_dexFeeBasisPoints","type":"uint256"},{"internalType":"uint256","name":"_migrationFeeFixed","type":"uint256"},{"internalType":"uint256","name":"_poolCreationFee","type":"uint256"},{"internalType":"uint256","name":"_mcUpperLimit","type":"uint256"},{"internalType":"uint256","name":"_mcLowerLimit","type":"uint256"},{"internalType":"uint256","name":"_tokensMigrationThreshold","type":"uint256"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_dexTreasury","type":"address"},{"internalType":"address","name":"_signer","type":"address"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensMigrationThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"usedSignatures","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"virtualCollateralReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"virtualTokenReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
346200038c5762004a1b3881900360a0601f8201601f19168101906001600160401b0382119082101762000391576101c092829160405260a039126200038c5760a05160c05160e05161010051610120516101405161016051610180516101a0516101c0519498969796959491620000796101e0620003a7565b9362000087610200620003a7565b9562000095610220620003a7565b9b620000a3610240620003a7565b983315620003735760008054336001600160a01b03198216811783556040519290916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3600180558b156200036457508b1562000352578c15620003405785156200032e5784156200031c5786156200030a576001600160a01b03881615620002f8576001600160a01b03891615620002e6576001600160a01b038a1615620002d45784861015620002c257612710600b541015620002ad576109c46005541015620002ad577fd36fa963ad16d3473577f6f3c68e0c369c04f095bedb1f1e0163d11f5785f2fd9c6101a09c8c60025580600355816004558260055583600b558460095585600a5586600655876007558860085560018060a01b038a1660018060a01b0319600d541617600d5560018060a01b038b1660018060a01b0319600c541617600c5560018060a01b038c1660018060a01b0319600e541617600e556040519c8d5260208d015260408c015260608b015260808a015260a089015260c088015260e087015261010086015261012085015260018060a01b031661014084015260018060a01b031661016083015260018060a01b0316610180820152a160805260405161465e9081620003bd8239608051818181610282015281816103fa015281816105540152818161059a015281816105eb0152610a3a0152f35b60405160016251ee6960e01b03198152600490fd5b60405163cb0e875d60e01b8152600490fd5b60405163598e40c360e11b8152600490fd5b60405163c764c12360e01b8152600490fd5b604051630172f23760e11b8152600490fd5b604051630c7a88c360e21b8152600490fd5b604051632136548960e21b8152600490fd5b60405163870e604160e01b8152600490fd5b6040516307b4f43d60e11b8152600490fd5b6040516306bb2a0d60e31b8152600490fd5b63ef7facc160e01b8152600490fd5b604051631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036200038c5756fe60808060405260043610156200001f575b5036156200001d57600080fd5b005b60003560e01c908163095b710d1462001f6f5750806315c088b31462001cd25780631655bc621462001cb257806318160ddd1462001c92578063238ac9331462001c6757806330a2aa2014620019dc5780634c7766b514620019bc57806361d027b3146200199157806365e5968d14620019335780636bb922dd14620019135780636d04eb9f14620018f3578063715018a61462001896578063758b647a146200155457806385f377ca14620015295780638da5cb5b14620014fe57806394b6c1601462001244578063ace1bfab1462001201578063b8606eef14620011e1578063be74615f14620011c1578063c68255a51462000e84578063ce5494bb1462000ca1578063d72b905e1462000915578063e7a1aeb714620002d1578063e8e70c4c14620002b1578063e9977985146200026a578063f2fde38b14620001d5578063f978fd6114620001a25763fe94c269146200017d573862000010565b346200019d5760003660031901126200019d576020600854604051908152f35b600080fd5b346200019d5760203660031901126200019d57600435600052600f602052602060ff604060002054166040519015158152f35b346200019d5760203660031901126200019d57620001f262001f8c565b620001fc620022ac565b6001600160a01b039081169081156200025157600054826bffffffffffffffffffffffff60a01b821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b604051631e4fbdf760e01b815260006004820152602490fd5b346200019d5760003660031901126200019d576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346200019d5760003660031901126200019d576020600454604051908152f35b60a03660031901126200019d5760043567ffffffffffffffff81116200019d57620003019036906004016200202d565b60243567ffffffffffffffff81116200019d57620003249036906004016200202d565b60843567ffffffffffffffff81116200019d57620003479036906004016200202d565b5062000352620022d9565b6200035c620022ac565b600254600354600454600554600b54600954600a549160075493600654956008549760018060a01b03600d54169960018060a01b03600c54169b60206040519e8f90620003a98262001fcf565b815201528c60403391015260608d015260808c015260a08b015260c08a015260e08901526101008801526101208701526101408601526101608501526101808401526101a083015260018060a01b037f0000000000000000000000000000000000000000000000000000000000000000166101c08301526101e08201526040519061232b8083019183831067ffffffffffffffff841117620008ff5783926200045892620022fe85396200214a565b03906000f0801562000778576024903460011c6060620004798234620020e5565b604051634fb3fbe760e01b8152606435600482015294909285919082906001600160a01b0387165af19081156200077857600091600094600091620008d4575b506040516370a0823160e01b8152306004820152916020836024816001600160a01b0389165afa92831562000778576000936200089a575b5060784201421162000884576040516302df835360e61b81526001600160a01b038681166004830152600060248301526044820185905260648201859052608482018390523060a48301524260780160c48301529091606091839160e4918391907f0000000000000000000000000000000000000000000000000000000000000000165af1801562000778576200084e575b5060405163c45a015560e01b8152926020846004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa93841562000778576000946200080a575b50604051633fc8cef360e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156200077857600090620007c8575b6040516306801cc360e41b81526001600160a01b038881166004830152918216602482015260006044820152956020925086916064918391165afa938415620007785760009462000784575b50620006866001600160a01b0386166200222b565b6040516311b46d1960e11b8152926020846004816001600160a01b038a165afa938415620007785760009462000735575b509160209661010094927f7b713ba130bc5c5c64aa56a986de7cf9da47b6138d0099aef4381e9de468138096946040519560018060a01b038a168752338b88015260018060a01b031660408701526060860152608085015260a084015260c083015260e0820152a1600180556040516001600160a01b039091168152f35b93509093916020843d6020116200076f575b81620007566020938362001fed565b810103126200019d5792519193919291906020620006b7565b3d915062000747565b6040513d6000823e3d90fd5b9093506020813d602011620007bf575b81620007a36020938362001fed565b810103126200019d57620007b790620020f3565b928662000671565b3d915062000794565b506020813d60201162000801575b81620007e56020938362001fed565b810103126200019d57620007fb602091620020f3565b62000625565b3d9150620007d6565b9093506020813d60201162000845575b81620008296020938362001fed565b810103126200019d576200083d90620020f3565b9286620005d5565b3d91506200081a565b620008749060603d6060116200087c575b6200086b818362001fed565b81019062002094565b505062000583565b503d6200085f565b634e487b7160e01b600052601160045260246000fd5b9092506020813d602011620008cb575b81620008b96020938362001fed565b810103126200019d57519186620004f1565b3d9150620008aa565b91945050620008f5915060603d6060116200087c576200086b818362001fed565b93909385620004b9565b634e487b7160e01b600052604160045260246000fd5b346200019d5760803660031901126200019d5760043567ffffffffffffffff81116200019d576200094b9036906004016200202d565b60243567ffffffffffffffff81116200019d576200096e9036906004016200202d565b6064359067ffffffffffffffff82116200019d5762000996620009e79236906004016200202d565b50620009a1620022ac565b600254600354600454600554600b5460095490600a549260075494600654966008549860018060a01b03600d54169a60018060a01b03600c54169d6040519d8e62001fcf565b8d5260208d01523360408d015260608c015260808b015260a08a015260c089015260e08801526101008701526101208601526101408501526101608401526101808301526101a082015260018060a01b037f00000000000000000000000000000000000000000000000000000000000000001691826101c08301526101e08201526040519061232b8083019183831067ffffffffffffffff841117620008ff57839262000a9a92620022fe85396200214a565b03906000f0801562000778576001600160a01b031662000aba816200222b565b604051633fc8cef360e01b815291602083600481845afa928315620007785760009362000c58575b5060206004916040519283809263c45a015560e01b82525afa908115620007785760009162000c0c575b506040516320b7f73960e21b8152600481018390526001600160a01b039384166024820152600060448201819052909360209285926064928492165af1918215620007785760009262000ba3575b507ff2fd526617507d454f774c90ef1d86c7788a2c9a36e0ad9aa1e51ed4ea67758f606060209360405190848252338683015260018060a01b03166040820152a1604051908152f35b91506020823d60201162000c03575b8162000bc16020938362001fed565b810103126200019d577ff2fd526617507d454f774c90ef1d86c7788a2c9a36e0ad9aa1e51ed4ea67758f606062000bfa602094620020f3565b93505062000b5a565b3d915062000bb2565b90506020813d60201162000c4f575b8162000c2a6020938362001fed565b810103126200019d57600092606462000c45602093620020f3565b9250509262000b0c565b3d915062000c1b565b9092506020813d60201162000c98575b8162000c776020938362001fed565b810103126200019d57602062000c8f600492620020f3565b93915062000ae2565b3d915062000c68565b346200019d576020806003193601126200019d576001600160a01b03908162000cc962001f8c565b16806000526010825260ff604060002054161562000e725760405163011fa75760e71b8152926080846004816000865af18015620007785760009460009060009060009362000e1b575b506040516362457f0b60e11b8152918683600481895afa928315620007785760009362000de6575b5060405163be74615f60e01b815287816004818a5afa908115620007785760009162000db3575b50830180931162000884577fa11672d49fffe086a179ad90e93d275d6298008a4b74d8a6cb2eff5bf5a9fe999760c0976040519788528701526040860152606085015260808401521660a0820152a1005b90508781813d831162000dde575b62000dcd818362001fed565b810103126200019d57518962000d62565b503d62000dc1565b9092508681813d831162000e13575b62000e01818362001fed565b810103126200019d5751918862000d3b565b503d62000df5565b96505050506080843d60801162000e69575b8162000e3c6080938362001fed565b810103126200019d578351838501519462000e5f606060408301519201620020f3565b9195908762000d13565b3d915062000e2d565b604051633f7a101960e01b8152600490fd5b62000e8f3662001fa3565b9162000e9a620022d9565b6040516325e17b5760e01b81526004810183905260248101939093526001600160a01b03169160608160448134875af1918215620007785760009160009060009462001197575b5060405163a9059cbb60e01b81523360048201526024810183905260209490858160448160008b5af18015620007785762001175575b5047918262001149575b6040516318160ddd60e01b815286816004818b5afa908115620007785760009162001116575b506040516370a0823160e01b8152600481018990529087826024818c5afa9081156200077857600091620010de575b62000f829250620020e5565b92604051956311b46d1960e11b875287876004818c5afa94851562000778578997600096620010a6575b506040519687528887015260408601526060850152608084015260a083015260c08201527ff6610dda82cea0160b2deaaf7dcfd1da470601afde9e3e90ec9777f07a71c8f160e03392a360405163fd62bcd760e01b81528181600481865afa908115620007785760009162001072575b5062001029575b60018055005b817f5a559a9a4be3dacfba7a0da0a570245e186e11f99ddfc652c6d2c971d9efbb4992600052601082526040600020600160ff19825416179055604051908152a1808062001023565b620010979150823d84116200109e575b6200108e818362001fed565b8101906200207a565b836200101c565b503d62001082565b975094508787813d8111620010d6575b620010c2818362001fed565b810103126200019d57889651948a62000fac565b503d620010b6565b90508782813d83116200110e575b620010f8818362001fed565b810103126200019d5762000f8291519062000f76565b503d620010ec565b90508681813d831162001141575b62001130818362001fed565b810103126200019d57518862000f47565b503d62001124565b600080808086335af16200115c620020b0565b5062000f21575b6040516338822c1360e11b8152600490fd5b6200118f90863d88116200109e576200108e818362001fed565b508662000f17565b91935050620011b8915060603d6060116200087c576200086b818362001fed565b92908562000ee1565b346200019d5760003660031901126200019d576020600a54604051908152f35b346200019d5760003660031901126200019d576020600554604051908152f35b346200019d5760203660031901126200019d576001600160a01b036200122662001f8c565b166000526010602052602060ff604060002054166040519015158152f35b346200019d57620012553662001fa3565b909162001261620022d9565b6040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b039190911692602092909183816064816000895af180156200077857620014dc575b5060405191630e30ec6360e31b8352600483015260248201526080816044816000875af190811562000778576000906000936000916000946200148c575b50600080808047335af1620012fc620020b0565b501562001163576040516318160ddd60e01b815281816004818a5afa908115620007785760009162001459575b506040516370a0823160e01b8152600481018890529082826024818b5afa908115620007785760009162001421575b620013649250620020e5565b916040516311b46d1960e11b815282816004818b5afa9283156200077857600093620013e8575b5050604080519687526020870193909352918501929092526060840152608083019190915260a082015233907f7811ffe97d7272ed69f2ebe0eb5b684cbcaa5dbd3500f11a5e457d1880aa4dd6908060c081015b0390a360018055005b90809350813d831162001419575b62001402818362001fed565b810103126200019d5790519084620013df6200138b565b503d620013f6565b90508282813d831162001451575b6200143b818362001fed565b810103126200019d576200136491519062001358565b503d6200142f565b90508181813d831162001484575b62001473818362001fed565b810103126200019d57518762001329565b503d62001467565b9450925050506080823d608011620014d3575b81620014ae6080938362001fed565b810103126200019d5781518183015160408401516060909401519093909286620012e8565b3d91506200149f565b620014f690843d86116200109e576200108e818362001fed565b5084620012aa565b346200019d5760003660031901126200019d576000546040516001600160a01b039091168152602090f35b346200019d5760003660031901126200019d57600c546040516001600160a01b039091168152602090f35b60403660031901126200019d576200156b62001f8c565b62001575620022d9565b60018060a01b0316604051634fb3fbe760e01b8152602435600482015260608160248134865af190811562000778576000916000916000916200186f575b506040516370a0823160e01b8082523060048301526020949085836024818a5afa92831562000778576000936200183a575b5060405163a9059cbb60e01b815233600482015260248101849052868160448160008c5af18015620007785762001818575b504780620017f7575b506040516318160ddd60e01b815286816004818b5afa9081156200077857600091620017c4575b5060405191825287600483015286826024818b5afa90811562000778576000916200178c575b620016799250620020e5565b6040516311b46d1960e11b81529386856004818b5afa9081156200077857889560009262001732575b5090620016fe917f808fdde3ed072c1c71e9531614f79dbafd5a4e3e3c8e3eb605d847578aa9b4999596976040519586953399879260a094919796959260c0850198855260208501526040840152606083015260808201520152565b0390a360405163fd62bcd760e01b81528181600481865afa9081156200077857600091620010725750620010295760018055005b8880929697508193503d831162001784575b62001750818362001fed565b810103126200019d57518794937f808fdde3ed072c1c71e9531614f79dbafd5a4e3e3c8e3eb605d847578aa9b499620016a2565b503d62001744565b90508682813d8311620017bc575b620017a6818362001fed565b810103126200019d57620016799151906200166d565b503d6200179a565b90508681813d8311620017ef575b620017de818362001fed565b810103126200019d57518862001647565b503d620017d2565b600080808093335af16200180a620020b0565b501562001163578762001620565b6200183290873d89116200109e576200108e818362001fed565b508762001617565b9092508581813d831162001867575b62001855818362001fed565b810103126200019d57519187620015e5565b503d62001849565b9150506200188f915060603d6060116200087c576200086b818362001fed565b84620015b3565b346200019d5760003660031901126200019d57620018b3620022ac565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346200019d5760003660031901126200019d576020600754604051908152f35b346200019d5760003660031901126200019d576020600954604051908152f35b346200019d5760203660031901126200019d576004356011548110156200019d5760116000527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6801546040516001600160a01b039091168152602090f35b346200019d5760003660031901126200019d57600d546040516001600160a01b039091168152602090f35b346200019d5760003660031901126200019d576020600654604051908152f35b346200019d57620019ed3662001fa3565b91620019f8620022d9565b6040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b0391909116929060209081816064816000895af18015620007785762001c45575b506040519163e98d5cd560e01b835283600484015260248301526060826044816000885af1918215620007785760009160009160009462001c1c575b50600080808047335af162001a90620020b0565b501562001163576040516318160ddd60e01b815281816004818a5afa908115620007785760009162001be9575b506040516370a0823160e01b8152600481018890529082826024818b5afa908115620007785760009162001bb1575b62001af89250620020e5565b916040516311b46d1960e11b815282816004818b5afa928315620007785760009362001b78575b5050604080519687526020870193909352918501929092526060840152608083019190915260a082015233907f17f90346238171af1d19cb32cdbf0a10b0c9ddd9ed2928cb2a3729d6c7b3dc45908060c08101620013df565b90809350813d831162001ba9575b62001b92818362001fed565b810103126200019d5790519084620013df62001b1f565b503d62001b86565b90508282813d831162001be1575b62001bcb818362001fed565b810103126200019d5762001af891519062001aec565b503d62001bbf565b90508181813d831162001c14575b62001c03818362001fed565b810103126200019d57518762001abd565b503d62001bf7565b9150925062001c3d915060603d6060116200087c576200086b818362001fed565b928662001a7c565b62001c5f90823d84116200109e576200108e818362001fed565b508462001a40565b346200019d5760003660031901126200019d57600e546040516001600160a01b039091168152602090f35b346200019d5760003660031901126200019d576020600254604051908152f35b346200019d5760003660031901126200019d576020600354604051908152f35b346200019d576101a03660031901126200019d576001600160a01b036101443581811681036200019d57610164359082821682036200019d57610184359280841684036200019d5762001d24620022ac565b6004351562001f5d576024351562001f4b576044351562001f3957610104351562001f275760e4351562001f1557610124351562001f03578082161562001ef1578083161562001edf578084161562001ecd5760e43561010435101562001ebb57612710600b54101562001ea6576109c4600554101562001ea6577fd36fa963ad16d3473577f6f3c68e0c369c04f095bedb1f1e0163d11f5785f2fd93816101a094600435600255602435600355604435600455606435600555608435600b5560a43560095560c435600a5560e43560065561010435600755610124356008556bffffffffffffffffffffffff60a01b82861681600d541617600d5582821681600c541617600c5582841690600e541617600e5581604051956004358752602435602088015260443560408801526064356060880152608435608088015260a43560a088015260c43560c088015260e43560e08801526101043561010088015261012435610120880152166101408601521661016084015216610180820152a1005b60405160016251ee6960e01b03198152600490fd5b60405163cb0e875d60e01b8152600490fd5b60405163598e40c360e11b8152600490fd5b60405163c764c12360e01b8152600490fd5b604051630172f23760e11b8152600490fd5b604051630c7a88c360e21b8152600490fd5b604051632136548960e21b8152600490fd5b60405163870e604160e01b8152600490fd5b6040516307b4f43d60e11b8152600490fd5b6040516306bb2a0d60e31b8152600490fd5b60405163ef7facc160e01b8152600490fd5b346200019d5760003660031901126200019d57602090600b548152f35b600435906001600160a01b03821682036200019d57565b60609060031901126200019d576004356001600160a01b03811681036200019d57906024359060443590565b610200810190811067ffffffffffffffff821117620008ff57604052565b90601f8019910116810190811067ffffffffffffffff821117620008ff57604052565b67ffffffffffffffff8111620008ff57601f01601f191660200190565b81601f820112156200019d57803590620020478262002010565b9262002057604051948562001fed565b828452602083830101116200019d57816000926020809301838601378301015290565b908160209103126200019d575180151581036200019d5790565b908160609103126200019d578051916040602083015192015190565b3d15620020e0573d90620020c48262002010565b91620020d4604051938462001fed565b82523d6000602084013e565b606090565b919082039182116200088457565b51906001600160a01b03821682036200019d57565b919082519283825260005b84811062002135575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520162002113565b602081528151620021856200216e6102009283602086015261022085019062002108565b6020850151848203601f1901604086015262002108565b9260408101519060018060a01b03809216606085015260608101516080850152608081015160a085015260a081015160c085015260c081015160e085015260e0810151610100908186015281015161012090818601528101516101409081860152810151610160908186015281015161018090818601528101516101a09081860152810151826101c091168186015281015190826101e092168286015201511691015290565b60115468010000000000000000811015620008ff576001810180601155811015620022965760116000527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c680180546001600160a01b0319166001600160a01b03909216919091179055565b634e487b7160e01b600052603260045260246000fd5b6000546001600160a01b03163303620022c157565b60405163118cdaa760e01b8152336004820152602490fd5b600260015414620022eb576002600155565b604051633ee5aeb560e01b8152600490fdfe610220604052346200071d576200232b803803806200001e8162000722565b92833981016020828203126200071d5781516001600160401b0381116200071d576102008184018303126200071d576040519161020083016001600160401b03811184821017620005fc57604052838201516001600160401b0381116200071d57816200008f918487010162000748565b835283820160200151916001600160401b0383116200071d57620000bf6101e0926200017b948388010162000748565b94856020860152620000d6604083830101620007ba565b6040860152808201606081810151908701526080808201519087015260a0808201519087015260c0808201519087015260e080820151908701526101008082015190870152610120808201519087015261014080820151908701526101608082015190870152610180808201519087015262000156906101a001620007ba565b6101a08601526200016d6101c083830101620007ba565b6101c08601520101620007ba565b6101e0820152805180519092906001600160401b038111620005fc57600354600181811c9116801562000712575b6020821014620005db57601f8111620006a8575b506020601f82116001146200061e578192939460009262000612575b50508160011b916000199060031b1c1916176003555b8051906001600160401b038211620005fc5760045490600182811c92168015620005f1575b6020831014620005db5781601f84931162000569575b50602090601f8311600114620004da57600092620004ce575b50508160011b916000199060031b1c1916176004555b600160055561010061ff0019600954161760095560608101513015620004b55760025481810181116200049f578101600255306000526000602052604060002081815401905560405190815260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60203093a3606081015160065560a08101518060085560805260808101516007556101c060018060a01b0391826040820151166101805260c081015160a05260e081015160c052826101a0820151166101a052826101e0820151168252610100810151610140526101208101516101605261014081015160e052610160810151610100526101808101516101205201511661020052336101e052604051611b5b9081620007d0823960805181818161055901526108ac015260a0518181816113210152611782015260c05181818161081301528181610bf001526117ae015260e051818181610da30152611999015261010051818181610fca01526119d80152610120518181816101f301526112a201526101405181818161049f015261078001526101605181818161051e01526107bc0152610180518161158001526101a0518181816102e60152818161084601528181610c7b01528181610ddb01528181610ecd015261114301526101c0518181816103100152818161088001528181610b7301528181610ca501528181610ef7015261116d01526101e051818181610266015281816104d7015281816106ee01528181610c2201528181610e6201526110ad0152610200518181816107310152610e1f0152f35b634e487b7160e01b600052601160045260246000fd5b60405163ec442f0560e01b815260006004820152602490fd5b01519050388062000243565b6004600090815293507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b91905b601f19841685106200054d576001945083601f1981161062000533575b505050811b0160045562000259565b015160001960f88460031b161c1916905538808062000524565b8181015183556020948501946001909301929091019062000507565b60046000529091507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f840160051c810160208510620005d3575b90849392915b601f830160051c82018110620005c35750506200022a565b60008155859450600101620005ab565b5080620005a5565b634e487b7160e01b600052602260045260246000fd5b91607f169162000214565b634e487b7160e01b600052604160045260246000fd5b015190503880620001d9565b600360009081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9190601f198416905b8181106200068f5750958360019596971062000675575b505050811b01600355620001ef565b015160001960f88460031b161c1916905538808062000666565b9192602060018192868b0151815501940192016200064f565b60036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f830160051c8101916020841062000707575b601f0160051c01905b818110620006fa5750620001bd565b60008155600101620006eb565b9091508190620006e2565b90607f1690620001a9565b600080fd5b6040519190601f01601f191682016001600160401b03811183821017620005fc57604052565b919080601f840112156200071d5782516001600160401b038111620005fc576020906200077e601f8201601f1916830162000722565b928184528282870101116200071d5760005b818110620007a657508260009394955001015290565b858101830151848201840152820162000790565b51906001600160a01b03821682036200071d5756fe608060408181526004918236101561001657600080fd5b600092833560e01c91826302d05d3f1461156c5750816306fdde0314611475578163095ea7b3146113cb57816315204481146113825781631655bc621461136357816318160ddd146113445781631a1c6e53146113095781632368da321461125957816323b872dd1461121c57816325e17b571461109b578163313ce5671461107f57816342966c681461106157816349a3024614610fed5781634c7766b514610fb25781634fb3fbe714610e4e57816361b3815514610e0a57816361d027b314610dc65781636d04eb9f14610d8b57816370a0823114610d545781637187631814610c1357816371ea0d8e14610bd857816379cc679014610ba257816385f377ca14610b5e5781638fd3ab80146106d257816390825c28146106ae57816395d89b41146105ad578163a9059cbb1461057c578163b026a12114610541578163be74615f14610506578163c45a0155146104c2578163c48afe1614610487578163c6d8b77814610460578163c78d0b0e14610441578163d3728de414610426578163dd62ed3e146103dd578163e8e70c4c146103be578163e98d5cd51461025957508063fd62bcd714610236578063fd967f471461021a5763fe94c269146101dd57600080fd5b34610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5080fd5b5034610216578160031936011261021657602090516127108152f35b503461021657816003193601126102165760209060ff6009541690519015158152f35b8261026336611650565b917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633036103af5760ff600954166103a0576102bf6102ad6008548461169e565b6102b9846007546116c7565b906116d4565b916102c983611773565b9390956102df856102da89856116f4565b6116f4565b9561030a887f0000000000000000000000000000000000000000000000000000000000000000611a10565b610334867f0000000000000000000000000000000000000000000000000000000000000000611a10565b861061039257508161035f6103739261035461038e9796956007546116c7565b6007556008546116f4565b60085561036c8633611a10565b30336118b1565b51938493846040919493926060820195825260208201520152565b0390f35b8351630a1c173f60e41b8152fd5b5163058aab2d60e21b81528390fd5b51630636a15760e11b81528390fd5b5050346102165781600319360112610216576020906008549051908152f35b505034610216578060031936011261021657806020926103fb6115f8565b610403611613565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b50503461021657816003193601126102165751908152602090f35b5050346102165781600319360112610216576020906006549051908152f35b50503461021657816003193601126102165760209060ff60095460081c1690519015158152f35b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b505034610216578160031936011261021657517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5050346102165780600319360112610216576020906105a661059c6115f8565b60243590336118b1565b5160018152f35b83833461021657816003193601126102165780519180938054916001908360011c92600185169485156106a4575b60209586861081146106915785895290811561066d5750600114610615575b61038e878761060b828c0383611666565b51918291826115af565b81529295507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b82841061065a575050508261038e9461060b928201019486806105fa565b805486850188015292860192810161063c565b60ff19168887015250505050151560051b830101925061060b8261038e86806105fa565b634e487b7160e01b845260228352602484fd5b93607f16936105db565b5050346102165781600319360112610216576020906106cb611738565b9051908152f35b905034610b5a5782600319360112610b5a576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081163303610b4b5761ff0019600954166009553084526020928484528085205493827f00000000000000000000000000000000000000000000000000000000000000001690825163095ea7b360e01b8152828682015286602482015281816044818b305af18015610a3157610b2e575b507f0000000000000000000000000000000000000000000000000000000000000000946107aa86476116f4565b926108d16107fa6107f36107ea6107e27f000000000000000000000000000000000000000000000000000000000000000080996116f4565b60075461169e565b600854906116d4565b809a6116f4565b946108058630611a86565b6102da6108406127106108387f00000000000000000000000000000000000000000000000000000000000000008d61169e565b04809b6116f4565b996102da7f00000000000000000000000000000000000000000000000000000000000000009b61087a8d61087487846116c7565b90611a10565b6108a4837f0000000000000000000000000000000000000000000000000000000000000000611a10565b6102da6008547f0000000000000000000000000000000000000000000000000000000000000000906116f4565b956078420191824211610b1b578a908751936302df835360e61b855230868601528260248601528b60448601528b60648601528960848601523060a486015260c485015260608460e4818c855af1938415610b11578294610adb575b50875163c45a015560e01b81529086828781845afa918215610ab25786929188918593610abc575b508a51633fc8cef360e01b815293849182905afa918215610ab25787928580936064938793610a93575b508c5196879586946306801cc360e41b8652308d8701521660248501526044840152165afa908115610a89578b91610a5c575b5016968715610a4c5747610a3b575b50845163a9059cbb60e01b8152918201899052602482015281816044818b8a5af18015610a315760809850610a04575b5082519586528501528301526060820152f35b610a2390823d8411610a2a575b610a1b8183611666565b810190611701565b50386109f1565b503d610a11565b84513d8a823e3d90fd5b610a46904790611a10565b386109c1565b855163c6bcf59960e01b81528390fd5b610a7c9150853d8711610a82575b610a748183611666565b810190611719565b386109b2565b503d610a6a565b87513d8d823e3d90fd5b610aab919350863d8811610a8257610a748183611666565b913861097f565b89513d85823e3d90fd5b610ad4919350823d8411610a8257610a748183611666565b9138610955565b9093506060813d606011610b09575b81610af760609383611666565b8101031261021657870151923861092d565b3d9150610aea565b88513d84823e3d90fd5b634e487b7160e01b8b526011845260248bfd5b610b4490823d8411610a2a57610a1b8183611666565b503861077d565b509051630636a15760e11b8152fd5b8280fd5b505034610216578160031936011261021657517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50503461021657366003190112610bd557610bd2610bbe6115f8565b60243590610bcd8233836117de565b611a86565b80f35b80fd5b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b9050610c1e36611650565b92907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610d465760ff60095416610d3857610c6384611773565b929091610c74846102da85896116f4565b94610c9f847f0000000000000000000000000000000000000000000000000000000000000000611a10565b610cc9857f0000000000000000000000000000000000000000000000000000000000000000611a10565b610ce4610cd86007548961169e565b6102b9896008546116f4565b918211610d2a5750610d09608096610cfd8330336118b1565b610354836007546116c7565b600855610d168533611a10565b815194855260208501528301526060820152f35b8251630a1c173f60e41b8152fd5b505163058aab2d60e21b8152fd5b5051630636a15760e11b8152fd5b5050346102165760203660031901126102165760209181906001600160a01b03610d7c6115f8565b16815280845220549051908152f35b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b505034610216578160031936011261021657517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b505034610216578160031936011261021657517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b9190506020366003190112610b5a578135927f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610d465760ff60095416610d38578184913081528060205220541115610fa557610eb534611773565b939092610ec6856102da86346116f4565b90610ef1857f0000000000000000000000000000000000000000000000000000000000000000611a10565b610f1b867f0000000000000000000000000000000000000000000000000000000000000000611a10565b600754610f28818461169e565b91610f3a600854936102b986866116c7565b948510610f975750610f6b928492610f5961038e9796610f61946116f4565b6007556116c7565b60085533306118b1565b610f7361198f565b610f7b6119ce565b5192839234846040919493926060820195825260208201520152565b8551630a1c173f60e41b8152fd5b5163904db1ff60e01b8152fd5b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b828434610bd557610ffd36611629565b91935091901561103f57906102b98261102b61102461101e61103196611773565b906116c7565b958261169e565b926116f4565b905b82519182526020820152f35b8061102b611050946102b99361169e565b61105c61101e82611773565b611033565b83903461021657602036600319011261021657610bd2903533611a86565b5050346102165781600319360112610216576020905160128152f35b90506110a636611650565b90939092907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610d465760ff60095416610d38578185913081528060205220541115610fa5576111126111066008548661169e565b6102b9866007546116f4565b9361111c85611773565b9390956111328561112d89846116c7565b6116c7565b95861161120d576111a890611167887f0000000000000000000000000000000000000000000000000000000000000000611a10565b611191867f0000000000000000000000000000000000000000000000000000000000000000611a10565b61119d846007546116f4565b6007556008546116c7565b6008558434116000146111e95750906111d961038e93926111d26111cc87346116f4565b33611a10565b33306118b1565b6111e161198f565b6103736119ce565b8434106111ff5750906111d961038e93926111d2565b82516367c45b4f60e11b8152fd5b508251630a1c173f60e41b8152fd5b505034610216576060366003190112610216576020906105a661123d6115f8565b611245611613565b604435916112548333836117de565b6118b1565b828434610bd55780600319360112610bd5576112826006543083528260205283832054906116f4565b9061271091828102908082048414901517156112f657602094506112c7907f0000000000000000000000000000000000000000000000000000000000000000906116d4565b9060648210156112de575050506064905b51908152f35b50818111156112ef57505b906112d8565b90506112e9565b634e487b7160e01b825260118552602482fd5b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5050346102165781600319360112610216576020906002549051908152f35b5050346102165781600319360112610216576020906007549051908152f35b828434610bd55761139236611629565b909350909190156113ba57906102b9826113b461102461101e61103196611773565b926116c7565b806113b4611050946102b99361169e565b905034610b5a5781600319360112610b5a576113e56115f8565b60243590331561145e576001600160a01b031691821561144757508083602095338152600187528181208582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b8351634a1406b160e11b8152908101859052602490fd5b835163e602df0560e01b8152808401869052602490fd5b91905034610b5a5782600319360112610b5a5780519183600354906001908260011c92600181168015611562575b602095868610821461154f575084885290811561152d57506001146114d4575b61038e868661060b828b0383611666565b929550600383527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b82841061151a575050508261038e9461060b9282010194386114c3565b80548685018801529286019281016114fd565b60ff191687860152505050151560051b830101925061060b8261038e386114c3565b634e487b7160e01b845260229052602483fd5b93607f16936114a3565b8490346102165781600319360112610216577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b6020808252825181830181905290939260005b8281106115e457505060409293506000838284010152601f8019910116010190565b8181018601518482016040015285016115c2565b600435906001600160a01b038216820361160e57565b600080fd5b602435906001600160a01b038216820361160e57565b608090600319011261160e57600435906024359060443590606435801515810361160e5790565b604090600319011261160e576004359060243590565b90601f8019910116810190811067ffffffffffffffff82111761168857604052565b634e487b7160e01b600052604160045260246000fd5b818102929181159184041417156116b157565b634e487b7160e01b600052601160045260246000fd5b919082018092116116b157565b81156116de570490565b634e487b7160e01b600052601260045260246000fd5b919082039182116116b157565b9081602091031261160e5751801515810361160e5790565b9081602091031261160e57516001600160a01b038116810361160e5790565b600854670de0b6b3a764000090818102908082048314901517156116b15761176661176f916002549061169e565b600754906116d4565b0490565b6117db6117a7916127109283917f00000000000000000000000000000000000000000000000000000000000000009061169e565b04916117d37f00000000000000000000000000000000000000000000000000000000000000008461169e565b0480926116f4565b91565b9160018060a01b03809316916000938385526001602052604093848620918316918287526020528486205492600019840361181d575b50505050505050565b8484106118815750801561186957811561185157855260016020528385209085526020520391205538808080808080611814565b8451634a1406b160e11b815260048101879052602490fd5b845163e602df0560e01b815260048101879052602490fd5b8551637dc7a0d960e11b81526001600160a01b039190911660048201526024810184905260448101859052606490fd5b916001600160a01b03808416928315611976571692831561195d576000908382528160205260408220549083821061192b575091604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fd5b611997611738565b7f0000000000000000000000000000000000000000000000000000000000000000106119bf57565b600160ff196009541617600955565b6119d6611738565b7f0000000000000000000000000000000000000000000000000000000000000000106119fe57565b6040516353dfa97560e01b8152600490fd5b60008080809481945af1903d15611a80573d9067ffffffffffffffff8211611a6c5760405191611a4a601f8201601f191660200184611666565b825260203d92013e5b15611a5a57565b6040516338822c1360e11b8152600490fd5b634e487b7160e01b81526041600452602490fd5b50611a53565b906001600160a01b0382169081156119765760009282845283602052604084205490828210611af35750817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef926020928587528684520360408620558060025403600255604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101829052606490fdfea26469706673582212205c7701526c567d41e360a9217898a429269a3823cc13033e1a59a5f3ac2e251364736f6c63430008170033a26469706673582212209554b1e3e7c647dec29fc7a0d952f38ccf91457062ac28813be962a00ec6d0fd64736f6c634300081700330000000000000000000000000000000000000000033b2e3c9fd0803ce80000000000000000000000000000000000000000000000036ccfbb244887eea40000000000000000000000000000000000000000000000000001043561a882930000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000177000000000000000000000000000000000000000000000001043561a88293000000000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000000000000000000000000010f0cf064dd5920000000000000000000000000000000000000000000000000001969368974c05b00000000000000000000000000000000000000000000000c380f8e0bc1c7ed0d305ab00000000000000000000000056c4f0504f577a283073ab780b6850fec4121389000000000000000000000000377cee6040c7300c6b31ab0f17d3a6e5d8059032000000000000000000000000cc6169aa1e879d3a4227536671f85afdb2d23fad000000000000000000000000ef4d642140b89fc0eaac3d3dfff0632e4469aa12
Deployed Bytecode
0x60808060405260043610156200001f575b5036156200001d57600080fd5b005b60003560e01c908163095b710d1462001f6f5750806315c088b31462001cd25780631655bc621462001cb257806318160ddd1462001c92578063238ac9331462001c6757806330a2aa2014620019dc5780634c7766b514620019bc57806361d027b3146200199157806365e5968d14620019335780636bb922dd14620019135780636d04eb9f14620018f3578063715018a61462001896578063758b647a146200155457806385f377ca14620015295780638da5cb5b14620014fe57806394b6c1601462001244578063ace1bfab1462001201578063b8606eef14620011e1578063be74615f14620011c1578063c68255a51462000e84578063ce5494bb1462000ca1578063d72b905e1462000915578063e7a1aeb714620002d1578063e8e70c4c14620002b1578063e9977985146200026a578063f2fde38b14620001d5578063f978fd6114620001a25763fe94c269146200017d573862000010565b346200019d5760003660031901126200019d576020600854604051908152f35b600080fd5b346200019d5760203660031901126200019d57600435600052600f602052602060ff604060002054166040519015158152f35b346200019d5760203660031901126200019d57620001f262001f8c565b620001fc620022ac565b6001600160a01b039081169081156200025157600054826bffffffffffffffffffffffff60a01b821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b604051631e4fbdf760e01b815260006004820152602490fd5b346200019d5760003660031901126200019d576040517f000000000000000000000000cc6169aa1e879d3a4227536671f85afdb2d23fad6001600160a01b03168152602090f35b346200019d5760003660031901126200019d576020600454604051908152f35b60a03660031901126200019d5760043567ffffffffffffffff81116200019d57620003019036906004016200202d565b60243567ffffffffffffffff81116200019d57620003249036906004016200202d565b60843567ffffffffffffffff81116200019d57620003479036906004016200202d565b5062000352620022d9565b6200035c620022ac565b600254600354600454600554600b54600954600a549160075493600654956008549760018060a01b03600d54169960018060a01b03600c54169b60206040519e8f90620003a98262001fcf565b815201528c60403391015260608d015260808c015260a08b015260c08a015260e08901526101008801526101208701526101408601526101608501526101808401526101a083015260018060a01b037f000000000000000000000000cc6169aa1e879d3a4227536671f85afdb2d23fad166101c08301526101e08201526040519061232b8083019183831067ffffffffffffffff841117620008ff5783926200045892620022fe85396200214a565b03906000f0801562000778576024903460011c6060620004798234620020e5565b604051634fb3fbe760e01b8152606435600482015294909285919082906001600160a01b0387165af19081156200077857600091600094600091620008d4575b506040516370a0823160e01b8152306004820152916020836024816001600160a01b0389165afa92831562000778576000936200089a575b5060784201421162000884576040516302df835360e61b81526001600160a01b038681166004830152600060248301526044820185905260648201859052608482018390523060a48301524260780160c48301529091606091839160e4918391907f000000000000000000000000cc6169aa1e879d3a4227536671f85afdb2d23fad165af1801562000778576200084e575b5060405163c45a015560e01b8152926020846004817f000000000000000000000000cc6169aa1e879d3a4227536671f85afdb2d23fad6001600160a01b03165afa93841562000778576000946200080a575b50604051633fc8cef360e01b81526020816004817f000000000000000000000000cc6169aa1e879d3a4227536671f85afdb2d23fad6001600160a01b03165afa80156200077857600090620007c8575b6040516306801cc360e41b81526001600160a01b038881166004830152918216602482015260006044820152956020925086916064918391165afa938415620007785760009462000784575b50620006866001600160a01b0386166200222b565b6040516311b46d1960e11b8152926020846004816001600160a01b038a165afa938415620007785760009462000735575b509160209661010094927f7b713ba130bc5c5c64aa56a986de7cf9da47b6138d0099aef4381e9de468138096946040519560018060a01b038a168752338b88015260018060a01b031660408701526060860152608085015260a084015260c083015260e0820152a1600180556040516001600160a01b039091168152f35b93509093916020843d6020116200076f575b81620007566020938362001fed565b810103126200019d5792519193919291906020620006b7565b3d915062000747565b6040513d6000823e3d90fd5b9093506020813d602011620007bf575b81620007a36020938362001fed565b810103126200019d57620007b790620020f3565b928662000671565b3d915062000794565b506020813d60201162000801575b81620007e56020938362001fed565b810103126200019d57620007fb602091620020f3565b62000625565b3d9150620007d6565b9093506020813d60201162000845575b81620008296020938362001fed565b810103126200019d576200083d90620020f3565b9286620005d5565b3d91506200081a565b620008749060603d6060116200087c575b6200086b818362001fed565b81019062002094565b505062000583565b503d6200085f565b634e487b7160e01b600052601160045260246000fd5b9092506020813d602011620008cb575b81620008b96020938362001fed565b810103126200019d57519186620004f1565b3d9150620008aa565b91945050620008f5915060603d6060116200087c576200086b818362001fed565b93909385620004b9565b634e487b7160e01b600052604160045260246000fd5b346200019d5760803660031901126200019d5760043567ffffffffffffffff81116200019d576200094b9036906004016200202d565b60243567ffffffffffffffff81116200019d576200096e9036906004016200202d565b6064359067ffffffffffffffff82116200019d5762000996620009e79236906004016200202d565b50620009a1620022ac565b600254600354600454600554600b5460095490600a549260075494600654966008549860018060a01b03600d54169a60018060a01b03600c54169d6040519d8e62001fcf565b8d5260208d01523360408d015260608c015260808b015260a08a015260c089015260e08801526101008701526101208601526101408501526101608401526101808301526101a082015260018060a01b037f000000000000000000000000cc6169aa1e879d3a4227536671f85afdb2d23fad1691826101c08301526101e08201526040519061232b8083019183831067ffffffffffffffff841117620008ff57839262000a9a92620022fe85396200214a565b03906000f0801562000778576001600160a01b031662000aba816200222b565b604051633fc8cef360e01b815291602083600481845afa928315620007785760009362000c58575b5060206004916040519283809263c45a015560e01b82525afa908115620007785760009162000c0c575b506040516320b7f73960e21b8152600481018390526001600160a01b039384166024820152600060448201819052909360209285926064928492165af1918215620007785760009262000ba3575b507ff2fd526617507d454f774c90ef1d86c7788a2c9a36e0ad9aa1e51ed4ea67758f606060209360405190848252338683015260018060a01b03166040820152a1604051908152f35b91506020823d60201162000c03575b8162000bc16020938362001fed565b810103126200019d577ff2fd526617507d454f774c90ef1d86c7788a2c9a36e0ad9aa1e51ed4ea67758f606062000bfa602094620020f3565b93505062000b5a565b3d915062000bb2565b90506020813d60201162000c4f575b8162000c2a6020938362001fed565b810103126200019d57600092606462000c45602093620020f3565b9250509262000b0c565b3d915062000c1b565b9092506020813d60201162000c98575b8162000c776020938362001fed565b810103126200019d57602062000c8f600492620020f3565b93915062000ae2565b3d915062000c68565b346200019d576020806003193601126200019d576001600160a01b03908162000cc962001f8c565b16806000526010825260ff604060002054161562000e725760405163011fa75760e71b8152926080846004816000865af18015620007785760009460009060009060009362000e1b575b506040516362457f0b60e11b8152918683600481895afa928315620007785760009362000de6575b5060405163be74615f60e01b815287816004818a5afa908115620007785760009162000db3575b50830180931162000884577fa11672d49fffe086a179ad90e93d275d6298008a4b74d8a6cb2eff5bf5a9fe999760c0976040519788528701526040860152606085015260808401521660a0820152a1005b90508781813d831162000dde575b62000dcd818362001fed565b810103126200019d57518962000d62565b503d62000dc1565b9092508681813d831162000e13575b62000e01818362001fed565b810103126200019d5751918862000d3b565b503d62000df5565b96505050506080843d60801162000e69575b8162000e3c6080938362001fed565b810103126200019d578351838501519462000e5f606060408301519201620020f3565b9195908762000d13565b3d915062000e2d565b604051633f7a101960e01b8152600490fd5b62000e8f3662001fa3565b9162000e9a620022d9565b6040516325e17b5760e01b81526004810183905260248101939093526001600160a01b03169160608160448134875af1918215620007785760009160009060009462001197575b5060405163a9059cbb60e01b81523360048201526024810183905260209490858160448160008b5af18015620007785762001175575b5047918262001149575b6040516318160ddd60e01b815286816004818b5afa908115620007785760009162001116575b506040516370a0823160e01b8152600481018990529087826024818c5afa9081156200077857600091620010de575b62000f829250620020e5565b92604051956311b46d1960e11b875287876004818c5afa94851562000778578997600096620010a6575b506040519687528887015260408601526060850152608084015260a083015260c08201527ff6610dda82cea0160b2deaaf7dcfd1da470601afde9e3e90ec9777f07a71c8f160e03392a360405163fd62bcd760e01b81528181600481865afa908115620007785760009162001072575b5062001029575b60018055005b817f5a559a9a4be3dacfba7a0da0a570245e186e11f99ddfc652c6d2c971d9efbb4992600052601082526040600020600160ff19825416179055604051908152a1808062001023565b620010979150823d84116200109e575b6200108e818362001fed565b8101906200207a565b836200101c565b503d62001082565b975094508787813d8111620010d6575b620010c2818362001fed565b810103126200019d57889651948a62000fac565b503d620010b6565b90508782813d83116200110e575b620010f8818362001fed565b810103126200019d5762000f8291519062000f76565b503d620010ec565b90508681813d831162001141575b62001130818362001fed565b810103126200019d57518862000f47565b503d62001124565b600080808086335af16200115c620020b0565b5062000f21575b6040516338822c1360e11b8152600490fd5b6200118f90863d88116200109e576200108e818362001fed565b508662000f17565b91935050620011b8915060603d6060116200087c576200086b818362001fed565b92908562000ee1565b346200019d5760003660031901126200019d576020600a54604051908152f35b346200019d5760003660031901126200019d576020600554604051908152f35b346200019d5760203660031901126200019d576001600160a01b036200122662001f8c565b166000526010602052602060ff604060002054166040519015158152f35b346200019d57620012553662001fa3565b909162001261620022d9565b6040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b039190911692602092909183816064816000895af180156200077857620014dc575b5060405191630e30ec6360e31b8352600483015260248201526080816044816000875af190811562000778576000906000936000916000946200148c575b50600080808047335af1620012fc620020b0565b501562001163576040516318160ddd60e01b815281816004818a5afa908115620007785760009162001459575b506040516370a0823160e01b8152600481018890529082826024818b5afa908115620007785760009162001421575b620013649250620020e5565b916040516311b46d1960e11b815282816004818b5afa9283156200077857600093620013e8575b5050604080519687526020870193909352918501929092526060840152608083019190915260a082015233907f7811ffe97d7272ed69f2ebe0eb5b684cbcaa5dbd3500f11a5e457d1880aa4dd6908060c081015b0390a360018055005b90809350813d831162001419575b62001402818362001fed565b810103126200019d5790519084620013df6200138b565b503d620013f6565b90508282813d831162001451575b6200143b818362001fed565b810103126200019d576200136491519062001358565b503d6200142f565b90508181813d831162001484575b62001473818362001fed565b810103126200019d57518762001329565b503d62001467565b9450925050506080823d608011620014d3575b81620014ae6080938362001fed565b810103126200019d5781518183015160408401516060909401519093909286620012e8565b3d91506200149f565b620014f690843d86116200109e576200108e818362001fed565b5084620012aa565b346200019d5760003660031901126200019d576000546040516001600160a01b039091168152602090f35b346200019d5760003660031901126200019d57600c546040516001600160a01b039091168152602090f35b60403660031901126200019d576200156b62001f8c565b62001575620022d9565b60018060a01b0316604051634fb3fbe760e01b8152602435600482015260608160248134865af190811562000778576000916000916000916200186f575b506040516370a0823160e01b8082523060048301526020949085836024818a5afa92831562000778576000936200183a575b5060405163a9059cbb60e01b815233600482015260248101849052868160448160008c5af18015620007785762001818575b504780620017f7575b506040516318160ddd60e01b815286816004818b5afa9081156200077857600091620017c4575b5060405191825287600483015286826024818b5afa90811562000778576000916200178c575b620016799250620020e5565b6040516311b46d1960e11b81529386856004818b5afa9081156200077857889560009262001732575b5090620016fe917f808fdde3ed072c1c71e9531614f79dbafd5a4e3e3c8e3eb605d847578aa9b4999596976040519586953399879260a094919796959260c0850198855260208501526040840152606083015260808201520152565b0390a360405163fd62bcd760e01b81528181600481865afa9081156200077857600091620010725750620010295760018055005b8880929697508193503d831162001784575b62001750818362001fed565b810103126200019d57518794937f808fdde3ed072c1c71e9531614f79dbafd5a4e3e3c8e3eb605d847578aa9b499620016a2565b503d62001744565b90508682813d8311620017bc575b620017a6818362001fed565b810103126200019d57620016799151906200166d565b503d6200179a565b90508681813d8311620017ef575b620017de818362001fed565b810103126200019d57518862001647565b503d620017d2565b600080808093335af16200180a620020b0565b501562001163578762001620565b6200183290873d89116200109e576200108e818362001fed565b508762001617565b9092508581813d831162001867575b62001855818362001fed565b810103126200019d57519187620015e5565b503d62001849565b9150506200188f915060603d6060116200087c576200086b818362001fed565b84620015b3565b346200019d5760003660031901126200019d57620018b3620022ac565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346200019d5760003660031901126200019d576020600754604051908152f35b346200019d5760003660031901126200019d576020600954604051908152f35b346200019d5760203660031901126200019d576004356011548110156200019d5760116000527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6801546040516001600160a01b039091168152602090f35b346200019d5760003660031901126200019d57600d546040516001600160a01b039091168152602090f35b346200019d5760003660031901126200019d576020600654604051908152f35b346200019d57620019ed3662001fa3565b91620019f8620022d9565b6040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b0391909116929060209081816064816000895af18015620007785762001c45575b506040519163e98d5cd560e01b835283600484015260248301526060826044816000885af1918215620007785760009160009160009462001c1c575b50600080808047335af162001a90620020b0565b501562001163576040516318160ddd60e01b815281816004818a5afa908115620007785760009162001be9575b506040516370a0823160e01b8152600481018890529082826024818b5afa908115620007785760009162001bb1575b62001af89250620020e5565b916040516311b46d1960e11b815282816004818b5afa928315620007785760009362001b78575b5050604080519687526020870193909352918501929092526060840152608083019190915260a082015233907f17f90346238171af1d19cb32cdbf0a10b0c9ddd9ed2928cb2a3729d6c7b3dc45908060c08101620013df565b90809350813d831162001ba9575b62001b92818362001fed565b810103126200019d5790519084620013df62001b1f565b503d62001b86565b90508282813d831162001be1575b62001bcb818362001fed565b810103126200019d5762001af891519062001aec565b503d62001bbf565b90508181813d831162001c14575b62001c03818362001fed565b810103126200019d57518762001abd565b503d62001bf7565b9150925062001c3d915060603d6060116200087c576200086b818362001fed565b928662001a7c565b62001c5f90823d84116200109e576200108e818362001fed565b508462001a40565b346200019d5760003660031901126200019d57600e546040516001600160a01b039091168152602090f35b346200019d5760003660031901126200019d576020600254604051908152f35b346200019d5760003660031901126200019d576020600354604051908152f35b346200019d576101a03660031901126200019d576001600160a01b036101443581811681036200019d57610164359082821682036200019d57610184359280841684036200019d5762001d24620022ac565b6004351562001f5d576024351562001f4b576044351562001f3957610104351562001f275760e4351562001f1557610124351562001f03578082161562001ef1578083161562001edf578084161562001ecd5760e43561010435101562001ebb57612710600b54101562001ea6576109c4600554101562001ea6577fd36fa963ad16d3473577f6f3c68e0c369c04f095bedb1f1e0163d11f5785f2fd93816101a094600435600255602435600355604435600455606435600555608435600b5560a43560095560c435600a5560e43560065561010435600755610124356008556bffffffffffffffffffffffff60a01b82861681600d541617600d5582821681600c541617600c5582841690600e541617600e5581604051956004358752602435602088015260443560408801526064356060880152608435608088015260a43560a088015260c43560c088015260e43560e08801526101043561010088015261012435610120880152166101408601521661016084015216610180820152a1005b60405160016251ee6960e01b03198152600490fd5b60405163cb0e875d60e01b8152600490fd5b60405163598e40c360e11b8152600490fd5b60405163c764c12360e01b8152600490fd5b604051630172f23760e11b8152600490fd5b604051630c7a88c360e21b8152600490fd5b604051632136548960e21b8152600490fd5b60405163870e604160e01b8152600490fd5b6040516307b4f43d60e11b8152600490fd5b6040516306bb2a0d60e31b8152600490fd5b60405163ef7facc160e01b8152600490fd5b346200019d5760003660031901126200019d57602090600b548152f35b600435906001600160a01b03821682036200019d57565b60609060031901126200019d576004356001600160a01b03811681036200019d57906024359060443590565b610200810190811067ffffffffffffffff821117620008ff57604052565b90601f8019910116810190811067ffffffffffffffff821117620008ff57604052565b67ffffffffffffffff8111620008ff57601f01601f191660200190565b81601f820112156200019d57803590620020478262002010565b9262002057604051948562001fed565b828452602083830101116200019d57816000926020809301838601378301015290565b908160209103126200019d575180151581036200019d5790565b908160609103126200019d578051916040602083015192015190565b3d15620020e0573d90620020c48262002010565b91620020d4604051938462001fed565b82523d6000602084013e565b606090565b919082039182116200088457565b51906001600160a01b03821682036200019d57565b919082519283825260005b84811062002135575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520162002113565b602081528151620021856200216e6102009283602086015261022085019062002108565b6020850151848203601f1901604086015262002108565b9260408101519060018060a01b03809216606085015260608101516080850152608081015160a085015260a081015160c085015260c081015160e085015260e0810151610100908186015281015161012090818601528101516101409081860152810151610160908186015281015161018090818601528101516101a09081860152810151826101c091168186015281015190826101e092168286015201511691015290565b60115468010000000000000000811015620008ff576001810180601155811015620022965760116000527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c680180546001600160a01b0319166001600160a01b03909216919091179055565b634e487b7160e01b600052603260045260246000fd5b6000546001600160a01b03163303620022c157565b60405163118cdaa760e01b8152336004820152602490fd5b600260015414620022eb576002600155565b604051633ee5aeb560e01b8152600490fdfe610220604052346200071d576200232b803803806200001e8162000722565b92833981016020828203126200071d5781516001600160401b0381116200071d576102008184018303126200071d576040519161020083016001600160401b03811184821017620005fc57604052838201516001600160401b0381116200071d57816200008f918487010162000748565b835283820160200151916001600160401b0383116200071d57620000bf6101e0926200017b948388010162000748565b94856020860152620000d6604083830101620007ba565b6040860152808201606081810151908701526080808201519087015260a0808201519087015260c0808201519087015260e080820151908701526101008082015190870152610120808201519087015261014080820151908701526101608082015190870152610180808201519087015262000156906101a001620007ba565b6101a08601526200016d6101c083830101620007ba565b6101c08601520101620007ba565b6101e0820152805180519092906001600160401b038111620005fc57600354600181811c9116801562000712575b6020821014620005db57601f8111620006a8575b506020601f82116001146200061e578192939460009262000612575b50508160011b916000199060031b1c1916176003555b8051906001600160401b038211620005fc5760045490600182811c92168015620005f1575b6020831014620005db5781601f84931162000569575b50602090601f8311600114620004da57600092620004ce575b50508160011b916000199060031b1c1916176004555b600160055561010061ff0019600954161760095560608101513015620004b55760025481810181116200049f578101600255306000526000602052604060002081815401905560405190815260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60203093a3606081015160065560a08101518060085560805260808101516007556101c060018060a01b0391826040820151166101805260c081015160a05260e081015160c052826101a0820151166101a052826101e0820151168252610100810151610140526101208101516101605261014081015160e052610160810151610100526101808101516101205201511661020052336101e052604051611b5b9081620007d0823960805181818161055901526108ac015260a0518181816113210152611782015260c05181818161081301528181610bf001526117ae015260e051818181610da30152611999015261010051818181610fca01526119d80152610120518181816101f301526112a201526101405181818161049f015261078001526101605181818161051e01526107bc0152610180518161158001526101a0518181816102e60152818161084601528181610c7b01528181610ddb01528181610ecd015261114301526101c0518181816103100152818161088001528181610b7301528181610ca501528181610ef7015261116d01526101e051818181610266015281816104d7015281816106ee01528181610c2201528181610e6201526110ad0152610200518181816107310152610e1f0152f35b634e487b7160e01b600052601160045260246000fd5b60405163ec442f0560e01b815260006004820152602490fd5b01519050388062000243565b6004600090815293507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b91905b601f19841685106200054d576001945083601f1981161062000533575b505050811b0160045562000259565b015160001960f88460031b161c1916905538808062000524565b8181015183556020948501946001909301929091019062000507565b60046000529091507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f840160051c810160208510620005d3575b90849392915b601f830160051c82018110620005c35750506200022a565b60008155859450600101620005ab565b5080620005a5565b634e487b7160e01b600052602260045260246000fd5b91607f169162000214565b634e487b7160e01b600052604160045260246000fd5b015190503880620001d9565b600360009081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9190601f198416905b8181106200068f5750958360019596971062000675575b505050811b01600355620001ef565b015160001960f88460031b161c1916905538808062000666565b9192602060018192868b0151815501940192016200064f565b60036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f830160051c8101916020841062000707575b601f0160051c01905b818110620006fa5750620001bd565b60008155600101620006eb565b9091508190620006e2565b90607f1690620001a9565b600080fd5b6040519190601f01601f191682016001600160401b03811183821017620005fc57604052565b919080601f840112156200071d5782516001600160401b038111620005fc576020906200077e601f8201601f1916830162000722565b928184528282870101116200071d5760005b818110620007a657508260009394955001015290565b858101830151848201840152820162000790565b51906001600160a01b03821682036200071d5756fe608060408181526004918236101561001657600080fd5b600092833560e01c91826302d05d3f1461156c5750816306fdde0314611475578163095ea7b3146113cb57816315204481146113825781631655bc621461136357816318160ddd146113445781631a1c6e53146113095781632368da321461125957816323b872dd1461121c57816325e17b571461109b578163313ce5671461107f57816342966c681461106157816349a3024614610fed5781634c7766b514610fb25781634fb3fbe714610e4e57816361b3815514610e0a57816361d027b314610dc65781636d04eb9f14610d8b57816370a0823114610d545781637187631814610c1357816371ea0d8e14610bd857816379cc679014610ba257816385f377ca14610b5e5781638fd3ab80146106d257816390825c28146106ae57816395d89b41146105ad578163a9059cbb1461057c578163b026a12114610541578163be74615f14610506578163c45a0155146104c2578163c48afe1614610487578163c6d8b77814610460578163c78d0b0e14610441578163d3728de414610426578163dd62ed3e146103dd578163e8e70c4c146103be578163e98d5cd51461025957508063fd62bcd714610236578063fd967f471461021a5763fe94c269146101dd57600080fd5b34610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5080fd5b5034610216578160031936011261021657602090516127108152f35b503461021657816003193601126102165760209060ff6009541690519015158152f35b8261026336611650565b917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633036103af5760ff600954166103a0576102bf6102ad6008548461169e565b6102b9846007546116c7565b906116d4565b916102c983611773565b9390956102df856102da89856116f4565b6116f4565b9561030a887f0000000000000000000000000000000000000000000000000000000000000000611a10565b610334867f0000000000000000000000000000000000000000000000000000000000000000611a10565b861061039257508161035f6103739261035461038e9796956007546116c7565b6007556008546116f4565b60085561036c8633611a10565b30336118b1565b51938493846040919493926060820195825260208201520152565b0390f35b8351630a1c173f60e41b8152fd5b5163058aab2d60e21b81528390fd5b51630636a15760e11b81528390fd5b5050346102165781600319360112610216576020906008549051908152f35b505034610216578060031936011261021657806020926103fb6115f8565b610403611613565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b50503461021657816003193601126102165751908152602090f35b5050346102165781600319360112610216576020906006549051908152f35b50503461021657816003193601126102165760209060ff60095460081c1690519015158152f35b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b505034610216578160031936011261021657517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5050346102165780600319360112610216576020906105a661059c6115f8565b60243590336118b1565b5160018152f35b83833461021657816003193601126102165780519180938054916001908360011c92600185169485156106a4575b60209586861081146106915785895290811561066d5750600114610615575b61038e878761060b828c0383611666565b51918291826115af565b81529295507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b82841061065a575050508261038e9461060b928201019486806105fa565b805486850188015292860192810161063c565b60ff19168887015250505050151560051b830101925061060b8261038e86806105fa565b634e487b7160e01b845260228352602484fd5b93607f16936105db565b5050346102165781600319360112610216576020906106cb611738565b9051908152f35b905034610b5a5782600319360112610b5a576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081163303610b4b5761ff0019600954166009553084526020928484528085205493827f00000000000000000000000000000000000000000000000000000000000000001690825163095ea7b360e01b8152828682015286602482015281816044818b305af18015610a3157610b2e575b507f0000000000000000000000000000000000000000000000000000000000000000946107aa86476116f4565b926108d16107fa6107f36107ea6107e27f000000000000000000000000000000000000000000000000000000000000000080996116f4565b60075461169e565b600854906116d4565b809a6116f4565b946108058630611a86565b6102da6108406127106108387f00000000000000000000000000000000000000000000000000000000000000008d61169e565b04809b6116f4565b996102da7f00000000000000000000000000000000000000000000000000000000000000009b61087a8d61087487846116c7565b90611a10565b6108a4837f0000000000000000000000000000000000000000000000000000000000000000611a10565b6102da6008547f0000000000000000000000000000000000000000000000000000000000000000906116f4565b956078420191824211610b1b578a908751936302df835360e61b855230868601528260248601528b60448601528b60648601528960848601523060a486015260c485015260608460e4818c855af1938415610b11578294610adb575b50875163c45a015560e01b81529086828781845afa918215610ab25786929188918593610abc575b508a51633fc8cef360e01b815293849182905afa918215610ab25787928580936064938793610a93575b508c5196879586946306801cc360e41b8652308d8701521660248501526044840152165afa908115610a89578b91610a5c575b5016968715610a4c5747610a3b575b50845163a9059cbb60e01b8152918201899052602482015281816044818b8a5af18015610a315760809850610a04575b5082519586528501528301526060820152f35b610a2390823d8411610a2a575b610a1b8183611666565b810190611701565b50386109f1565b503d610a11565b84513d8a823e3d90fd5b610a46904790611a10565b386109c1565b855163c6bcf59960e01b81528390fd5b610a7c9150853d8711610a82575b610a748183611666565b810190611719565b386109b2565b503d610a6a565b87513d8d823e3d90fd5b610aab919350863d8811610a8257610a748183611666565b913861097f565b89513d85823e3d90fd5b610ad4919350823d8411610a8257610a748183611666565b9138610955565b9093506060813d606011610b09575b81610af760609383611666565b8101031261021657870151923861092d565b3d9150610aea565b88513d84823e3d90fd5b634e487b7160e01b8b526011845260248bfd5b610b4490823d8411610a2a57610a1b8183611666565b503861077d565b509051630636a15760e11b8152fd5b8280fd5b505034610216578160031936011261021657517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50503461021657366003190112610bd557610bd2610bbe6115f8565b60243590610bcd8233836117de565b611a86565b80f35b80fd5b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b9050610c1e36611650565b92907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610d465760ff60095416610d3857610c6384611773565b929091610c74846102da85896116f4565b94610c9f847f0000000000000000000000000000000000000000000000000000000000000000611a10565b610cc9857f0000000000000000000000000000000000000000000000000000000000000000611a10565b610ce4610cd86007548961169e565b6102b9896008546116f4565b918211610d2a5750610d09608096610cfd8330336118b1565b610354836007546116c7565b600855610d168533611a10565b815194855260208501528301526060820152f35b8251630a1c173f60e41b8152fd5b505163058aab2d60e21b8152fd5b5051630636a15760e11b8152fd5b5050346102165760203660031901126102165760209181906001600160a01b03610d7c6115f8565b16815280845220549051908152f35b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b505034610216578160031936011261021657517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b505034610216578160031936011261021657517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b9190506020366003190112610b5a578135927f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610d465760ff60095416610d38578184913081528060205220541115610fa557610eb534611773565b939092610ec6856102da86346116f4565b90610ef1857f0000000000000000000000000000000000000000000000000000000000000000611a10565b610f1b867f0000000000000000000000000000000000000000000000000000000000000000611a10565b600754610f28818461169e565b91610f3a600854936102b986866116c7565b948510610f975750610f6b928492610f5961038e9796610f61946116f4565b6007556116c7565b60085533306118b1565b610f7361198f565b610f7b6119ce565b5192839234846040919493926060820195825260208201520152565b8551630a1c173f60e41b8152fd5b5163904db1ff60e01b8152fd5b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b828434610bd557610ffd36611629565b91935091901561103f57906102b98261102b61102461101e61103196611773565b906116c7565b958261169e565b926116f4565b905b82519182526020820152f35b8061102b611050946102b99361169e565b61105c61101e82611773565b611033565b83903461021657602036600319011261021657610bd2903533611a86565b5050346102165781600319360112610216576020905160128152f35b90506110a636611650565b90939092907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610d465760ff60095416610d38578185913081528060205220541115610fa5576111126111066008548661169e565b6102b9866007546116f4565b9361111c85611773565b9390956111328561112d89846116c7565b6116c7565b95861161120d576111a890611167887f0000000000000000000000000000000000000000000000000000000000000000611a10565b611191867f0000000000000000000000000000000000000000000000000000000000000000611a10565b61119d846007546116f4565b6007556008546116c7565b6008558434116000146111e95750906111d961038e93926111d26111cc87346116f4565b33611a10565b33306118b1565b6111e161198f565b6103736119ce565b8434106111ff5750906111d961038e93926111d2565b82516367c45b4f60e11b8152fd5b508251630a1c173f60e41b8152fd5b505034610216576060366003190112610216576020906105a661123d6115f8565b611245611613565b604435916112548333836117de565b6118b1565b828434610bd55780600319360112610bd5576112826006543083528260205283832054906116f4565b9061271091828102908082048414901517156112f657602094506112c7907f0000000000000000000000000000000000000000000000000000000000000000906116d4565b9060648210156112de575050506064905b51908152f35b50818111156112ef57505b906112d8565b90506112e9565b634e487b7160e01b825260118552602482fd5b505034610216578160031936011261021657602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b5050346102165781600319360112610216576020906002549051908152f35b5050346102165781600319360112610216576020906007549051908152f35b828434610bd55761139236611629565b909350909190156113ba57906102b9826113b461102461101e61103196611773565b926116c7565b806113b4611050946102b99361169e565b905034610b5a5781600319360112610b5a576113e56115f8565b60243590331561145e576001600160a01b031691821561144757508083602095338152600187528181208582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b8351634a1406b160e11b8152908101859052602490fd5b835163e602df0560e01b8152808401869052602490fd5b91905034610b5a5782600319360112610b5a5780519183600354906001908260011c92600181168015611562575b602095868610821461154f575084885290811561152d57506001146114d4575b61038e868661060b828b0383611666565b929550600383527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b82841061151a575050508261038e9461060b9282010194386114c3565b80548685018801529286019281016114fd565b60ff191687860152505050151560051b830101925061060b8261038e386114c3565b634e487b7160e01b845260229052602483fd5b93607f16936114a3565b8490346102165781600319360112610216577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b6020808252825181830181905290939260005b8281106115e457505060409293506000838284010152601f8019910116010190565b8181018601518482016040015285016115c2565b600435906001600160a01b038216820361160e57565b600080fd5b602435906001600160a01b038216820361160e57565b608090600319011261160e57600435906024359060443590606435801515810361160e5790565b604090600319011261160e576004359060243590565b90601f8019910116810190811067ffffffffffffffff82111761168857604052565b634e487b7160e01b600052604160045260246000fd5b818102929181159184041417156116b157565b634e487b7160e01b600052601160045260246000fd5b919082018092116116b157565b81156116de570490565b634e487b7160e01b600052601260045260246000fd5b919082039182116116b157565b9081602091031261160e5751801515810361160e5790565b9081602091031261160e57516001600160a01b038116810361160e5790565b600854670de0b6b3a764000090818102908082048314901517156116b15761176661176f916002549061169e565b600754906116d4565b0490565b6117db6117a7916127109283917f00000000000000000000000000000000000000000000000000000000000000009061169e565b04916117d37f00000000000000000000000000000000000000000000000000000000000000008461169e565b0480926116f4565b91565b9160018060a01b03809316916000938385526001602052604093848620918316918287526020528486205492600019840361181d575b50505050505050565b8484106118815750801561186957811561185157855260016020528385209085526020520391205538808080808080611814565b8451634a1406b160e11b815260048101879052602490fd5b845163e602df0560e01b815260048101879052602490fd5b8551637dc7a0d960e11b81526001600160a01b039190911660048201526024810184905260448101859052606490fd5b916001600160a01b03808416928315611976571692831561195d576000908382528160205260408220549083821061192b575091604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fd5b611997611738565b7f0000000000000000000000000000000000000000000000000000000000000000106119bf57565b600160ff196009541617600955565b6119d6611738565b7f0000000000000000000000000000000000000000000000000000000000000000106119fe57565b6040516353dfa97560e01b8152600490fd5b60008080809481945af1903d15611a80573d9067ffffffffffffffff8211611a6c5760405191611a4a601f8201601f191660200184611666565b825260203d92013e5b15611a5a57565b6040516338822c1360e11b8152600490fd5b634e487b7160e01b81526041600452602490fd5b50611a53565b906001600160a01b0382169081156119765760009282845283602052604084205490828210611af35750817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef926020928587528684520360408620558060025403600255604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101829052606490fdfea26469706673582212205c7701526c567d41e360a9217898a429269a3823cc13033e1a59a5f3ac2e251364736f6c63430008170033a26469706673582212209554b1e3e7c647dec29fc7a0d952f38ccf91457062ac28813be962a00ec6d0fd64736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000033b2e3c9fd0803ce80000000000000000000000000000000000000000000000036ccfbb244887eea40000000000000000000000000000000000000000000000000001043561a882930000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000177000000000000000000000000000000000000000000000001043561a88293000000000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000000000000000000000000010f0cf064dd5920000000000000000000000000000000000000000000000000001969368974c05b00000000000000000000000000000000000000000000000c380f8e0bc1c7ed0d305ab00000000000000000000000056c4f0504f577a283073ab780b6850fec4121389000000000000000000000000377cee6040c7300c6b31ab0f17d3a6e5d8059032000000000000000000000000cc6169aa1e879d3a4227536671f85afdb2d23fad000000000000000000000000ef4d642140b89fc0eaac3d3dfff0632e4469aa12
-----Decoded View---------------
Arg [0] : _totalSupply (uint256): 1000000000000000000000000000
Arg [1] : _virtualTokenReserves (uint256): 1060000000000000000000000000
Arg [2] : _virtualCollateralReserves (uint256): 4800000000000000000000
Arg [3] : _feeBasisPoints (uint256): 100
Arg [4] : _dexFeeBasisPoints (uint256): 6000
Arg [5] : _migrationFeeFixed (uint256): 300000000000000000000
Arg [6] : _poolCreationFee (uint256): 100000000000000000000
Arg [7] : _mcUpperLimit (uint256): 80000000000000000000000
Arg [8] : _mcLowerLimit (uint256): 7500000000000000000000
Arg [9] : _tokensMigrationThreshold (uint256): 236349588721039974736266667
Arg [10] : _treasury (address): 0x56C4f0504f577a283073AB780b6850feC4121389
Arg [11] : _dexTreasury (address): 0x377Cee6040C7300c6B31AB0f17d3a6e5d8059032
Arg [12] : _solidlyRouter (address): 0xcC6169aA1E879d3a4227536671F85afdb2d23fAD
Arg [13] : _signer (address): 0xEF4d642140B89FC0Eaac3D3DfFF0632E4469aa12
-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000
Arg [1] : 0000000000000000000000000000000000000000036ccfbb244887eea4000000
Arg [2] : 0000000000000000000000000000000000000000000001043561a88293000000
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000064
Arg [4] : 0000000000000000000000000000000000000000000000000000000000001770
Arg [5] : 00000000000000000000000000000000000000000000001043561a8829300000
Arg [6] : 0000000000000000000000000000000000000000000000056bc75e2d63100000
Arg [7] : 0000000000000000000000000000000000000000000010f0cf064dd592000000
Arg [8] : 0000000000000000000000000000000000000000000001969368974c05b00000
Arg [9] : 000000000000000000000000000000000000000000c380f8e0bc1c7ed0d305ab
Arg [10] : 00000000000000000000000056c4f0504f577a283073ab780b6850fec4121389
Arg [11] : 000000000000000000000000377cee6040c7300c6b31ab0f17d3a6e5d8059032
Arg [12] : 000000000000000000000000cc6169aa1e879d3a4227536671f85afdb2d23fad
Arg [13] : 000000000000000000000000ef4d642140b89fc0eaac3d3dfff0632e4469aa12
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.