Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 322 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Transfer | 20423552 | 36 days ago | IN | 0 ETH | 0.00015825 | ||||
Approve | 20108415 | 80 days ago | IN | 0 ETH | 0.00006909 | ||||
Transfer | 19935630 | 104 days ago | IN | 0 ETH | 0.00060305 | ||||
Approve | 19929162 | 105 days ago | IN | 0 ETH | 0.00029772 | ||||
Approve | 19927597 | 105 days ago | IN | 0 ETH | 0.00045523 | ||||
Approve | 19741562 | 131 days ago | IN | 0 ETH | 0.00026624 | ||||
Transfer | 19741557 | 131 days ago | IN | 0 ETH | 0.00017342 | ||||
Transfer | 19741551 | 131 days ago | IN | 0 ETH | 0.00027062 | ||||
Transfer | 19697126 | 137 days ago | IN | 0 ETH | 0.00040965 | ||||
Approve | 19670974 | 141 days ago | IN | 0 ETH | 0.00043057 | ||||
Approve | 19667858 | 142 days ago | IN | 0 ETH | 0.0005263 | ||||
Approve | 19600157 | 151 days ago | IN | 0 ETH | 0.00050893 | ||||
Transfer | 19584509 | 153 days ago | IN | 0 ETH | 0.00219189 | ||||
Approve | 19508106 | 164 days ago | IN | 0 ETH | 0.00064164 | ||||
Approve | 19491173 | 166 days ago | IN | 0 ETH | 0.00155715 | ||||
Approve | 19491165 | 166 days ago | IN | 0 ETH | 0.00142245 | ||||
Approve | 19481671 | 168 days ago | IN | 0 ETH | 0.00113147 | ||||
Transfer | 19481666 | 168 days ago | IN | 0 ETH | 0.00083379 | ||||
Transfer | 19481663 | 168 days ago | IN | 0 ETH | 0.00082065 | ||||
Approve | 19472549 | 169 days ago | IN | 0 ETH | 0.00124877 | ||||
Approve | 19465639 | 170 days ago | IN | 0 ETH | 0.00153456 | ||||
Approve | 19432038 | 175 days ago | IN | 0 ETH | 0.00224411 | ||||
Transfer | 19409560 | 178 days ago | IN | 0 ETH | 0.00147541 | ||||
Approve | 19407259 | 178 days ago | IN | 0 ETH | 0.00342846 | ||||
Transfer | 19375643 | 183 days ago | IN | 0 ETH | 0.00339319 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
Cheezburger
Compiler Version
v0.8.22+commit.4fc1097e
Contract Source Code (Solidity Multiple files format)
// SPDX-License-Identifier: UNLICENSED // // ████████████████████ // ██ ██ // ██ ██ ██ ██ // ██ ████ ████ ██ // ██ ████ ██ // ██ ██ // ████████████████████████████████████ // ██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██ // ████████████████████████████████ // ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ // ██░░██░░░░██████░░░░░░██░░░░████ // ████ ████ ██████ ████ ██ // ██ ██ // ████████████████████████████ // // Cheezburger enables frictionless creation of tokens for a wide // range of use cases, including DAOs, utility tokens, community projects, // memecoins, and more. It presents three revolutionary concepts: // // - Social Tokens: Enables permissionless, one-click launches for social profiles. // - Liquidity-Less Tokens: Auto-generated liquidity removes the need for initial capital. // - Factory Model: Enables free, fast, and gas-efficient deployments with configurable // settings, such as wallet caps, decaying premiums, and highly // customizable tokenomics for fair launches. // // Social and Liquidity-Less tokens will be available when the V3 pool is opened. // // ATTENTION: The only genuine deployer is chzb.eth. // Beware of scammers and follow official channels for more information. // // Read more on Cheezburger: https://cheezburger.lol // https://documentation.cheezburger.lol // pragma solidity ^0.8.22; import {SafeTransferLib} from "./SafeTransferLib.sol"; import {CheezburgerDeployerKit} from "./CheezburgerDeployerKit.sol"; import {ICheezburgerFactory} from "./ICheezburgerFactory.sol"; contract Cheezburger is CheezburgerDeployerKit { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ error TransferToZeroAddress(address from, address to); error TransferToToken(address to); error CannotReceiveEtherDirectly(); error EmptyAddressNotAllowed(); error SupplyAllocationExceeded(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ event GlobalSettingsChanged(); event SettingsChanged(); event PairingAmountsChanged(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ uint256 internal constant LIQUIDITY_FEE_WITHDRAWAL_ROLE = _ROLE_1; uint256 internal constant CREATION_FEE_WITHDRAWAL_ROLE = _ROLE_2; uint256 internal constant PAIRING_AMOUNT_SETTER_ROLE = _ROLE_3; uint256 internal constant SETTINGS_SETTER_ROLE = _ROLE_4; string private _name; string private _symbol; constructor( TokenCustomization memory _customization, address _factory, address _router ) { if (_factory == address(0) || _router == address(0)) { revert EmptyAddressNotAllowed(); } _name = _customization.name; _symbol = _customization.symbol; _website = _customization.website; _social = _customization.social; _initializeOwner(msg.sender); _mint(msg.sender, _customization.supply * (10 ** decimals())); changeSettings( SocialSettings({ pairingAmount: 0, leftSideSupply: 1_000_000, // 1 million supply for each social token openFeeWei: 0, // Zero fee at launch poolCreatorFeePercentage: 4, // 4% of the fees to pool creator at launch walletSettings: DynamicSettings({ duration: 14 days, // Max wallet duration 2 weeks for each Social token percentStart: 300, // 3% starting wallet cap percentEnd: 4900 // 49% ending wallet cap }), feeSettings: DynamicSettings({ duration: 1 days, // 1 day EAP duration for each Social token percentStart: 500, // 5% starting fee percentEnd: 200 // 2% ending fee }) }), TokenSettings({pairingAmount: 0, openFeeWei: 0}) ); changeGlobalSettings( GlobalSettings({ factory: ICheezburgerFactory(_factory), router: _router }) ); // Keep it disabled until launch // changePairingAmounts(totalSupply() / 33, totalSupply() / 33); // 3% mint for social and regular token launches } /// @dev Prevents direct Ether transfers to contract receive() external payable { revert CannotReceiveEtherDirectly(); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 METADATA */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function name() public view virtual override returns (string memory) { return _name; } function symbol() public view virtual override returns (string memory) { return _symbol; } function website() public view returns (string memory) { return _website; } function social() public view returns (string memory) { return _social; } /// @dev Returns the amount of tokens in existence minus liquidity pools burned tokens. /// The total supply with liquidity pools can be calculated with totalSupply() + outOfCirculationTokens. function totalSupply() public view override returns (uint256) { unchecked { return super.totalSupply() - outOfCirculationTokens; } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Burns `amount` tokens from the caller. function burn(uint256 amount) external { _burn(msg.sender, amount); } /// @dev Burns `amount` tokens from `account`, deducting from the caller's allowance. function burnFrom(address account, uint256 amount) external { _spendAllowance(account, msg.sender, amount); _burn(account, amount); } /// @dev Allows to withdraw creation liquidity fees to a customized contract function withdrawFeesOf( uint256 _userId, address _to ) external onlyRoles(LIQUIDITY_FEE_WITHDRAWAL_ROLE) returns (uint256) { return _withdrawFeesOf(_userId, _to); } /// @dev Allows to withdraw creation fees to a customized contract function withdrawCreationFees() external onlyRoles(CREATION_FEE_WITHDRAWAL_ROLE) { return SafeTransferLib.forceSafeTransferAllETH(msg.sender); } /// @dev Allow to change global settings by the owner only function changeGlobalSettings( GlobalSettings memory _globalSettings ) public onlyOwner { globalSettings = _globalSettings; emit GlobalSettingsChanged(); } /// @dev Allow to change settings by the owner only or an authorized address function changeSettings( SocialSettings memory _socialSettings, TokenSettings memory _tokenSettings ) public onlyOwnerOrRoles(SETTINGS_SETTER_ROLE) { // Pairing amounts cannot be changed here socialSettings.leftSideSupply = _socialSettings.leftSideSupply; socialSettings.openFeeWei = _socialSettings.openFeeWei; socialSettings.poolCreatorFeePercentage = _socialSettings .poolCreatorFeePercentage; socialSettings.walletSettings = _socialSettings.walletSettings; socialSettings.feeSettings = _socialSettings.feeSettings; tokenSettings.openFeeWei = _tokenSettings.openFeeWei; emit SettingsChanged(); } /// @dev Allow to change pairing amounts for token and social settings by the owner only or an authorized address function changePairingAmounts( uint256 _socialPairingAmount, uint256 _tokenPairingAmount ) public onlyOwnerOrRoles(PAIRING_AMOUNT_SETTER_ROLE) { uint256 maxSupplyPerCreation = totalSupply() / 25; // Capped to 4% of the supply if ( _socialPairingAmount > maxSupplyPerCreation || _tokenPairingAmount > maxSupplyPerCreation ) { revert SupplyAllocationExceeded(); } socialSettings.pairingAmount = _socialPairingAmount; tokenSettings.pairingAmount = _tokenPairingAmount; emit PairingAmountsChanged(); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual override { super._beforeTokenTransfer(from, to, amount); // Don't allow token transfers to the contract if (from != address(0) && to == address(this)) { revert TransferToToken(to); } } function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual override { super._afterTokenTransfer(from, to, amount); // Must use burn() to burn tokens if (to == address(0) && balanceOf(address(0)) > 0) { revert TransferToZeroAddress(from, to); } } }
// SPDX-License-Identifier: UNLICENSED // // ████████████████████ // ██ ██ // ██ ██ ██ ██ // ██ ████ ████ ██ // ██ ████ ██ // ██ ██ // ████████████████████████████████████ // ██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██ // ████████████████████████████████ // ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██ // ██░░██░░░░██████░░░░░░██░░░░████ // ████ ████ ██████ ████ ██ // ██ ██ // ████████████████████████████ // pragma solidity ^0.8.22; import {ERC20} from "./ERC20.sol"; import {LibString} from "./LibString.sol"; import {SafeTransferLib} from "./SafeTransferLib.sol"; import {OwnableRoles} from "./OwnableRoles.sol"; import {ReentrancyGuard} from "./ReentrancyGuard.sol"; import {ICheezburgerFactory} from "./ICheezburgerFactory.sol"; import {CheezburgerRegistry} from "./CheezburgerRegistry.sol"; abstract contract CheezburgerDeployerKit is ERC20, CheezburgerRegistry, ReentrancyGuard, OwnableRoles { using LibString for uint256; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ error EmptyNumericUserId(); error SocialNotOpened(); error UserIdNotFound(); error UserIdAlreadyExist(uint256 userId); error IncorrectPoolOpeningFee(uint256 value, uint256 expected); error SupplyOverflow(); error CannotUseCHZBNamespace(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCT */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ struct GlobalSettings { ICheezburgerFactory factory; address router; } struct SocialSettings { uint256 pairingAmount; uint256 leftSideSupply; uint256 openFeeWei; uint8 poolCreatorFeePercentage; DynamicSettings walletSettings; DynamicSettings feeSettings; } struct TokenSettings { uint256 pairingAmount; uint256 openFeeWei; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ event SocialTokenDeployed( uint256 indexed userId, address indexed token, uint256 indexed creationAmount, uint256 currentOutOfCirculationSupply ); event SocialTokenFeeWithdrawal( address indexed pair, address indexed to, uint256 indexed amount ); event LiquidityLessTokenDeployed( address indexed token, uint256 indexed creationAmount, uint256 currentOutOfCirculationSupply ); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ string internal _website; string internal _social; uint256 public outOfCirculationTokens; uint256 internal constant NAMESPACE_ROLE = _ROLE_5; GlobalSettings public globalSettings; SocialSettings public socialSettings; TokenSettings public tokenSettings; mapping(uint256 => Token) public socialTokens; mapping(address => uint256) public socialIds; /// @dev Deploy a new social token using bootstrapped CHZB liquidity /// @param userId User ID for the social token /// @dev Can be deployed from another contract but for gas reasons we'll let it here function deploySocialTokenWithCHZB( uint256 userId ) external payable nonReentrant returns (address) { // Ensure userId is valid if (userId == 0) { revert EmptyNumericUserId(); } // Ensure userId doesn't already exist if (socialTokens[userId].leftSide != address(0)) { revert UserIdAlreadyExist(userId); } // Half liquidity is burned // Half is kept in the contract as a custodial address[] memory feeAddresses = new address[](2); feeAddresses[0] = address(0); feeAddresses[1] = address(this); // 50/50 fees split uint8[] memory feePercentages = new uint8[](1); feePercentages[0] = 50; // Transform the user ID to string for name and symbol string memory userIdString = userId.toString(); Token memory token = _deployWithCHZB( TokenCustomization({ name: LibString.concat(userIdString, " (Social)"), symbol: LibString.concat("CHZB-X-", userIdString), website: _website, social: _social, supply: socialSettings.leftSideSupply }), LiquiditySettings({ feeThresholdPercent: 2, feeAddresses: feeAddresses, feePercentages: feePercentages }), socialSettings.feeSettings, socialSettings.walletSettings, socialSettings.poolCreatorFeePercentage > 0 ? ReferralSettings({ feeReceiver: msg.sender, feePercentage: socialSettings.poolCreatorFeePercentage }) : ReferralSettings({feeReceiver: address(0), feePercentage: 0}), socialSettings.pairingAmount, socialSettings.openFeeWei ); // Register ID socialTokens[userId] = token; socialIds[token.leftSide] = userId; emit SocialTokenDeployed( userId, token.leftSide, socialSettings.pairingAmount, outOfCirculationTokens ); return address(token.leftSide); } /// @dev Deploy a new customized token with bootstrapped CHZB liquidity function deployTokenWithCHZB( TokenCustomization memory _customization, LiquiditySettings memory _liquidity, DynamicSettings memory _fee, DynamicSettings memory _wallet, ReferralSettings memory _referral ) external payable nonReentrant returns (address) { if ( LibString.startsWith(_customization.symbol, "CHZB-") && !hasAnyRole(msg.sender, NAMESPACE_ROLE) ) { revert CannotUseCHZBNamespace(); } Token memory token = _deployWithCHZB( _customization, _liquidity, _fee, _wallet, _referral, tokenSettings.pairingAmount, tokenSettings.openFeeWei ); emit LiquidityLessTokenDeployed( token.leftSide, tokenSettings.pairingAmount, outOfCirculationTokens ); return address(token.leftSide); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function _deployWithCHZB( TokenCustomization memory _customization, LiquiditySettings memory _liquidity, DynamicSettings memory _fee, DynamicSettings memory _wallet, ReferralSettings memory _referral, uint256 _pairingAmount, uint256 _openingFee ) private returns (Token memory) { // Collect fee if any if (msg.value != _openingFee) { revert IncorrectPoolOpeningFee(msg.value, _openingFee); } // The tokens are used to pool with the token to give initial liquidity // This have no impact on price and they cannot be withdrawn as they are burned _mint(address(this), _pairingAmount); // Approve the Factory to use the created CHZB SafeTransferLib.safeApprove( address(this), address(globalSettings.factory), _pairingAmount ); // Create the token address tokenAddress = globalSettings.factory.deployWithToken( _customization, globalSettings.router, address(this), _pairingAmount, _liquidity, _fee, _wallet, _referral ); // Get token info Token memory token = getToken(globalSettings.factory, tokenAddress); // Burn liquidity SafeTransferLib.safeTransferAll(address(token.pair), address(0)); // Update out of circulating supply data unchecked { if (totalSupply() > totalSupply() + _pairingAmount) { revert SupplyOverflow(); } outOfCirculationTokens = outOfCirculationTokens + _pairingAmount; } return token; } /// @dev Allows to withdraw creation liquidity fees to a customized contract function _withdrawFeesOf( uint256 _userId, address _to ) internal returns (uint256) { address pair = address(socialTokens[_userId].pair); if (pair == address(0)) { revert UserIdNotFound(); } uint256 amount = SafeTransferLib.safeTransferAll(pair, _to); emit SocialTokenFeeWithdrawal(pair, _to, amount); return amount; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.22; import {ICheezburgerFactory} from "./ICheezburgerFactory.sol"; import {ICheezburger} from "./ICheezburger.sol"; import {CheezburgerStructs} from "./CheezburgerStructs.sol"; abstract contract CheezburgerRegistry is CheezburgerStructs { /// @dev Convert a socialTokens entry back to Token function getSocialToken( ICheezburger _chzb, uint256 _id ) internal view returns (Token memory) { ( address _uniswapFactory, address _uniswapRouter, address _uniswapPair, address _creator, address _leftSide, address _rightSide, LiquiditySettings memory _liquidity, DynamicSettings memory _fee, DynamicSettings memory _wallet, ReferralSettings memory _referral ) = _chzb.socialTokens(_id); return Token({ factory: _uniswapFactory, router: _uniswapRouter, pair: _uniswapPair, creator: _creator, leftSide: _leftSide, rightSide: _rightSide, liquidity: _liquidity, fee: _fee, wallet: _wallet, referral: _referral }); } /// @dev Convert a burgerRegistry entry back to Token function getToken( ICheezburgerFactory _factory, address _pairedToken ) internal view returns (Token memory) { ( address _uniswapFactory, address _uniswapRouter, address _uniswapPair, address _creator, address _leftSide, address _rightSide, LiquiditySettings memory _liquidity, DynamicSettings memory _fee, DynamicSettings memory _wallet, ReferralSettings memory _referral ) = _factory.burgerRegistry(_pairedToken); return Token({ factory: _uniswapFactory, router: _uniswapRouter, pair: _uniswapPair, creator: _creator, leftSide: _leftSide, rightSide: _rightSide, liquidity: _liquidity, fee: _fee, wallet: _wallet, referral: _referral }); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.22; interface CheezburgerStructs { /// @dev Settings and contracts for a token pair and its liquidity pool. struct Token { /// @dev The Uniswap factory contract address factory; /// @dev The Uniswap router contract address router; /// @dev The Uniswap pair contract address pair; /// @dev The token creator address creator; /// @dev The left side of the pair address leftSide; /// @dev The right side ERC20 token of the pair address rightSide; /// @dev Liquidity settings LiquiditySettings liquidity; /// @dev Dynamic fee settings DynamicSettings fee; /// @dev Dynamic wallet settings DynamicSettings wallet; /// @dev Referral settings ReferralSettings referral; } /// @dev Settings for customizing the token /// @param name The name of the token /// @param symbol The symbol for the token /// @param website The website associated with the token /// @param social A social media link associated with the token /// @param supply The max supply of the token struct TokenCustomization { string name; string symbol; string website; string social; uint256 supply; } /// @dev Settings for dynamic fees that change over time /// @param duration The duration over which the rate changes /// @param percentStart The starting percentage rate /// @param percentEnd The ending percentage rate struct DynamicSettings { uint256 duration; uint16 percentStart; uint16 percentEnd; } /// @dev Settings for liquidity pool fees distributed to addresses /// @param feeThresholdPercent The percentage threshold that triggers liquidity swaps /// @param feeAddresses The addresses receiving distributed fee amounts /// @param feePercentages The percentage fee amounts for each address struct LiquiditySettings { uint8 feeThresholdPercent; address[] feeAddresses; uint8[] feePercentages; } /// @dev Settings for referrals. Referrals get commissions from fees whenever people uses the factory to deploy their token. /// @param feeReceiver The addresses receiving commissions /// @param feePercentage The percentage fee struct ReferralSettings { address feeReceiver; uint8 feePercentage; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized ECDSA wrapper. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol) /// /// @dev Note: /// - The recovery functions use the ecrecover precompile (0x1). /// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure. /// This is for more safety by default. /// Use the `tryRecover` variants if you need to get the zero address back /// upon recovery failure instead. /// - As of Solady version 0.0.134, all `bytes signature` variants accept both /// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures. /// See: https://eips.ethereum.org/EIPS/eip-2098 /// This is for calldata efficiency on smart accounts prevalent on L2s. /// /// WARNING! Do NOT use signatures as unique identifiers: /// - Use a nonce in the digest to prevent replay attacks on the same contract. /// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts. /// EIP-712 also enables readable signing of typed data for better user safety. /// This implementation does NOT check if a signature is non-malleable. library ECDSA { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The signature is invalid. error InvalidSignature(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RECOVERY OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function recover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. for {} 1 {} { mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. if eq(mload(signature), 64) { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(mload(signature), 65) { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. break } result := 0 break } result := mload( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function recoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) for {} 1 {} { if eq(signature.length, 64) { let vs := calldataload(add(signature.offset, 0x20)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, calldataload(signature.offset)) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(signature.length, 65) { mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`. break } result := 0 break } result := mload( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) mstore(0x60, shr(1, shl(1, vs))) // `s`. result := mload( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the signature defined by `v`, `r`, `s`. function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) result := mload( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* TRY-RECOVER OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // WARNING! // These functions will NOT revert upon recovery failure. // Instead, they will return the zero address upon recovery failure. // It is critical that the returned address is NEVER compared against // a zero address (e.g. an uninitialized address variable). /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function tryRecover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. for {} 1 {} { mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. if eq(mload(signature), 64) { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(mload(signature), 65) { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. break } result := 0 break } pop( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function tryRecoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) for {} 1 {} { if eq(signature.length, 64) { let vs := calldataload(add(signature.offset, 0x20)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, calldataload(signature.offset)) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(signature.length, 65) { mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`. break } result := 0 break } pop( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) mstore(0x60, shr(1, shl(1, vs))) // `s`. pop( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the signature defined by `v`, `r`, `s`. function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) pop( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an Ethereum Signed Message, created from a `hash`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, hash) // Store into scratch space for keccak256. mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes. result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`. } } /// @dev Returns an Ethereum Signed Message, created from `s`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. /// Note: Supports lengths of `s` up to 999999 bytes. function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let sLength := mload(s) let o := 0x20 mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded. mstore(0x00, 0x00) // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`. for { let temp := sLength } 1 {} { o := sub(o, 1) mstore8(o, add(48, mod(temp, 10))) temp := div(temp, 10) if iszero(temp) { break } } let n := sub(0x3a, o) // Header length: `26 + 32 - o`. // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes. returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20)) mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header. result := keccak256(add(s, sub(0x20, n)), add(n, sLength)) mstore(s, sLength) // Restore the length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes. function emptySignature() internal pure returns (bytes calldata signature) { /// @solidity memory-safe-assembly assembly { signature.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple ERC20 + EIP-2612 implementation. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol) /// /// @dev Note: /// - The ERC20 standard allows minting and transferring to and from the zero address, /// minting and transferring zero tokens, as well as self-approvals. /// For performance, this implementation WILL NOT revert for such actions. /// Please add any checks with overrides if desired. /// - The `permit` function uses the ecrecover precompile (0x1). /// /// If you are overriding: /// - NEVER violate the ERC20 invariant: /// the total sum of all balances must be equal to `totalSupply()`. /// - Check that the overridden function is actually used in the function you want to /// change the behavior of. Much of the code has been manually inlined for performance. abstract contract ERC20 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The total supply has overflowed. error TotalSupplyOverflow(); /// @dev The allowance has overflowed. error AllowanceOverflow(); /// @dev The allowance has underflowed. error AllowanceUnderflow(); /// @dev Insufficient balance. error InsufficientBalance(); /// @dev Insufficient allowance. error InsufficientAllowance(); /// @dev The permit is invalid. error InvalidPermit(); /// @dev The permit has expired. error PermitExpired(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Emitted when `amount` tokens is transferred from `from` to `to`. event Transfer(address indexed from, address indexed to, uint256 amount); /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`. event Approval(address indexed owner, address indexed spender, uint256 amount); /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`. uint256 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`. uint256 private constant _APPROVAL_EVENT_SIGNATURE = 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The storage slot for the total supply. uint256 private constant _TOTAL_SUPPLY_SLOT = 0x05345cdf77eb68f44c; /// @dev The balance slot of `owner` is given by: /// ``` /// mstore(0x0c, _BALANCE_SLOT_SEED) /// mstore(0x00, owner) /// let balanceSlot := keccak256(0x0c, 0x20) /// ``` uint256 private constant _BALANCE_SLOT_SEED = 0x87a211a2; /// @dev The allowance slot of (`owner`, `spender`) is given by: /// ``` /// mstore(0x20, spender) /// mstore(0x0c, _ALLOWANCE_SLOT_SEED) /// mstore(0x00, owner) /// let allowanceSlot := keccak256(0x0c, 0x34) /// ``` uint256 private constant _ALLOWANCE_SLOT_SEED = 0x7f5e9f20; /// @dev The nonce slot of `owner` is given by: /// ``` /// mstore(0x0c, _NONCES_SLOT_SEED) /// mstore(0x00, owner) /// let nonceSlot := keccak256(0x0c, 0x20) /// ``` uint256 private constant _NONCES_SLOT_SEED = 0x38377508; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev `(_NONCES_SLOT_SEED << 16) | 0x1901`. uint256 private constant _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX = 0x383775081901; /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`. bytes32 private constant _DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; /// @dev `keccak256("1")`. bytes32 private constant _VERSION_HASH = 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6; /// @dev `keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")`. bytes32 private constant _PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 METADATA */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the name of the token. function name() public view virtual returns (string memory); /// @dev Returns the symbol of the token. function symbol() public view virtual returns (string memory); /// @dev Returns the decimals places of the token. function decimals() public view virtual returns (uint8) { return 18; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the amount of tokens in existence. function totalSupply() public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { result := sload(_TOTAL_SUPPLY_SLOT) } } /// @dev Returns the amount of tokens owned by `owner`. function balanceOf(address owner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, owner) result := sload(keccak256(0x0c, 0x20)) } } /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`. function allowance(address owner, address spender) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, spender) mstore(0x0c, _ALLOWANCE_SLOT_SEED) mstore(0x00, owner) result := sload(keccak256(0x0c, 0x34)) } } /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens. /// /// Emits a {Approval} event. function approve(address spender, uint256 amount) public virtual returns (bool) { /// @solidity memory-safe-assembly assembly { // Compute the allowance slot and store the amount. mstore(0x20, spender) mstore(0x0c, _ALLOWANCE_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x34), amount) // Emit the {Approval} event. mstore(0x00, amount) log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c))) } return true; } /// @dev Transfer `amount` tokens from the caller to `to`. /// /// Requirements: /// - `from` must at least have `amount`. /// /// Emits a {Transfer} event. function transfer(address to, uint256 amount) public virtual returns (bool) { _beforeTokenTransfer(msg.sender, to, amount); /// @solidity memory-safe-assembly assembly { // Compute the balance slot and load its value. mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, caller()) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Compute the balance slot of `to`. mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance of `to`. // Will not overflow because the sum of all user balances // cannot exceed the maximum uint256 value. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, caller(), shr(96, mload(0x0c))) } _afterTokenTransfer(msg.sender, to, amount); return true; } /// @dev Transfers `amount` tokens from `from` to `to`. /// /// Note: Does not update the allowance if it is the maximum uint256 value. /// /// Requirements: /// - `from` must at least have `amount`. /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`. /// /// Emits a {Transfer} event. function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) { _beforeTokenTransfer(from, to, amount); /// @solidity memory-safe-assembly assembly { let from_ := shl(96, from) // Compute the allowance slot and load its value. mstore(0x20, caller()) mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED)) let allowanceSlot := keccak256(0x0c, 0x34) let allowance_ := sload(allowanceSlot) // If the allowance is not the maximum uint256 value. if add(allowance_, 1) { // Revert if the amount to be transferred exceeds the allowance. if gt(amount, allowance_) { mstore(0x00, 0x13be252b) // `InsufficientAllowance()`. revert(0x1c, 0x04) } // Subtract and store the updated allowance. sstore(allowanceSlot, sub(allowance_, amount)) } // Compute the balance slot and load its value. mstore(0x0c, or(from_, _BALANCE_SLOT_SEED)) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Compute the balance slot of `to`. mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance of `to`. // Will not overflow because the sum of all user balances // cannot exceed the maximum uint256 value. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c))) } _afterTokenTransfer(from, to, amount); return true; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EIP-2612 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev For more performance, override to return the constant value /// of `keccak256(bytes(name()))` if `name()` will never change. function _constantNameHash() internal view virtual returns (bytes32 result) {} /// @dev Returns the current nonce for `owner`. /// This value is used to compute the signature for EIP-2612 permit. function nonces(address owner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the nonce slot and load its value. mstore(0x0c, _NONCES_SLOT_SEED) mstore(0x00, owner) result := sload(keccak256(0x0c, 0x20)) } } /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`, /// authorized by a signed approval by `owner`. /// /// Emits a {Approval} event. function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { bytes32 nameHash = _constantNameHash(); // We simply calculate it on-the-fly to allow for cases where the `name` may change. if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name())); /// @solidity memory-safe-assembly assembly { // Revert if the block timestamp is greater than `deadline`. if gt(timestamp(), deadline) { mstore(0x00, 0x1a15a3cc) // `PermitExpired()`. revert(0x1c, 0x04) } let m := mload(0x40) // Grab the free memory pointer. // Clean the upper 96 bits. owner := shr(96, shl(96, owner)) spender := shr(96, shl(96, spender)) // Compute the nonce slot and load its value. mstore(0x0e, _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX) mstore(0x00, owner) let nonceSlot := keccak256(0x0c, 0x20) let nonceValue := sload(nonceSlot) // Prepare the domain separator. mstore(m, _DOMAIN_TYPEHASH) mstore(add(m, 0x20), nameHash) mstore(add(m, 0x40), _VERSION_HASH) mstore(add(m, 0x60), chainid()) mstore(add(m, 0x80), address()) mstore(0x2e, keccak256(m, 0xa0)) // Prepare the struct hash. mstore(m, _PERMIT_TYPEHASH) mstore(add(m, 0x20), owner) mstore(add(m, 0x40), spender) mstore(add(m, 0x60), value) mstore(add(m, 0x80), nonceValue) mstore(add(m, 0xa0), deadline) mstore(0x4e, keccak256(m, 0xc0)) // Prepare the ecrecover calldata. mstore(0x00, keccak256(0x2c, 0x42)) mstore(0x20, and(0xff, v)) mstore(0x40, r) mstore(0x60, s) let t := staticcall(gas(), 1, 0, 0x80, 0x20, 0x20) // If the ecrecover fails, the returndatasize will be 0x00, // `owner` will be checked if it equals the hash at 0x00, // which evaluates to false (i.e. 0), and we will revert. // If the ecrecover succeeds, the returndatasize will be 0x20, // `owner` will be compared against the returned address at 0x20. if iszero(eq(mload(returndatasize()), owner)) { mstore(0x00, 0xddafbaef) // `InvalidPermit()`. revert(0x1c, 0x04) } // Increment and store the updated nonce. sstore(nonceSlot, add(nonceValue, t)) // `t` is 1 if ecrecover succeeds. // Compute the allowance slot and store the value. // The `owner` is already at slot 0x20. mstore(0x40, or(shl(160, _ALLOWANCE_SLOT_SEED), spender)) sstore(keccak256(0x2c, 0x34), value) // Emit the {Approval} event. log3(add(m, 0x60), 0x20, _APPROVAL_EVENT_SIGNATURE, owner, spender) mstore(0x40, m) // Restore the free memory pointer. mstore(0x60, 0) // Restore the zero pointer. } } /// @dev Returns the EIP-712 domain separator for the EIP-2612 permit. function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) { bytes32 nameHash = _constantNameHash(); // We simply calculate it on-the-fly to allow for cases where the `name` may change. if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name())); /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Grab the free memory pointer. mstore(m, _DOMAIN_TYPEHASH) mstore(add(m, 0x20), nameHash) mstore(add(m, 0x40), _VERSION_HASH) mstore(add(m, 0x60), chainid()) mstore(add(m, 0x80), address()) result := keccak256(m, 0xa0) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL MINT FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Mints `amount` tokens to `to`, increasing the total supply. /// /// Emits a {Transfer} event. function _mint(address to, uint256 amount) internal virtual { _beforeTokenTransfer(address(0), to, amount); /// @solidity memory-safe-assembly assembly { let totalSupplyBefore := sload(_TOTAL_SUPPLY_SLOT) let totalSupplyAfter := add(totalSupplyBefore, amount) // Revert if the total supply overflows. if lt(totalSupplyAfter, totalSupplyBefore) { mstore(0x00, 0xe5cfe957) // `TotalSupplyOverflow()`. revert(0x1c, 0x04) } // Store the updated total supply. sstore(_TOTAL_SUPPLY_SLOT, totalSupplyAfter) // Compute the balance slot and load its value. mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, 0, shr(96, mload(0x0c))) } _afterTokenTransfer(address(0), to, amount); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL BURN FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Burns `amount` tokens from `from`, reducing the total supply. /// /// Emits a {Transfer} event. function _burn(address from, uint256 amount) internal virtual { _beforeTokenTransfer(from, address(0), amount); /// @solidity memory-safe-assembly assembly { // Compute the balance slot and load its value. mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, from) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Subtract and store the updated total supply. sstore(_TOTAL_SUPPLY_SLOT, sub(sload(_TOTAL_SUPPLY_SLOT), amount)) // Emit the {Transfer} event. mstore(0x00, amount) log3(0x00, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, shl(96, from)), 0) } _afterTokenTransfer(from, address(0), amount); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL TRANSFER FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Moves `amount` of tokens from `from` to `to`. function _transfer(address from, address to, uint256 amount) internal virtual { _beforeTokenTransfer(from, to, amount); /// @solidity memory-safe-assembly assembly { let from_ := shl(96, from) // Compute the balance slot and load its value. mstore(0x0c, or(from_, _BALANCE_SLOT_SEED)) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Compute the balance slot of `to`. mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance of `to`. // Will not overflow because the sum of all user balances // cannot exceed the maximum uint256 value. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c))) } _afterTokenTransfer(from, to, amount); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL ALLOWANCE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Updates the allowance of `owner` for `spender` based on spent `amount`. function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { /// @solidity memory-safe-assembly assembly { // Compute the allowance slot and load its value. mstore(0x20, spender) mstore(0x0c, _ALLOWANCE_SLOT_SEED) mstore(0x00, owner) let allowanceSlot := keccak256(0x0c, 0x34) let allowance_ := sload(allowanceSlot) // If the allowance is not the maximum uint256 value. if add(allowance_, 1) { // Revert if the amount to be transferred exceeds the allowance. if gt(amount, allowance_) { mstore(0x00, 0x13be252b) // `InsufficientAllowance()`. revert(0x1c, 0x04) } // Subtract and store the updated allowance. sstore(allowanceSlot, sub(allowance_, amount)) } } } /// @dev Sets `amount` as the allowance of `spender` over the tokens of `owner`. /// /// Emits a {Approval} event. function _approve(address owner, address spender, uint256 amount) internal virtual { /// @solidity memory-safe-assembly assembly { let owner_ := shl(96, owner) // Compute the allowance slot and store the amount. mstore(0x20, spender) mstore(0x0c, or(owner_, _ALLOWANCE_SLOT_SEED)) sstore(keccak256(0x0c, 0x34), amount) // Emit the {Approval} event. mstore(0x00, amount) log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, shr(96, owner_), shr(96, mload(0x2c))) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HOOKS TO OVERRIDE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Hook that is called before any transfer of tokens. /// This includes minting and burning. function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /// @dev Hook that is called after any transfer of tokens. /// This includes minting and burning. function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.22; import {CheezburgerStructs} from "./CheezburgerStructs.sol"; interface ICheezburger is CheezburgerStructs { function socialTokens( uint256 id ) external view returns ( address, address, address, address, address, address, LiquiditySettings calldata, DynamicSettings calldata, DynamicSettings calldata, ReferralSettings calldata ); function withdrawFeesOf( uint256 _userId, address _to ) external returns (uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.22; import {CheezburgerStructs} from "./CheezburgerStructs.sol"; interface ICheezburgerFactory is CheezburgerStructs { function deployWithToken( TokenCustomization memory _customization, address _router, address _rightSide, uint256 _rightSideAmount, LiquiditySettings memory _liquidity, DynamicSettings memory _fee, DynamicSettings memory _wallet, ReferralSettings memory _referral ) external returns (address); function burgerRegistry( address token ) external view returns ( address, address, address, address, address, address, LiquiditySettings calldata, DynamicSettings calldata, DynamicSettings calldata, ReferralSettings calldata ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for converting numbers into strings and other string operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) library LibString { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The `length` of the output is too small to contain all the hex digits. error HexLengthInsufficient(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The constant returned when the `search` is not found in the string. uint256 internal constant NOT_FOUND = type(uint256).max; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* DECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the base 10 decimal representation of `value`. function toString(uint256 value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. str := add(mload(0x40), 0x80) // Update the free memory pointer to allocate. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str let w := not(0) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { str := add(str, w) // `sub(str, 1)`. // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } /// @dev Returns the base 10 decimal representation of `value`. function toString(int256 value) internal pure returns (string memory str) { if (value >= 0) { return toString(uint256(value)); } unchecked { str = toString(uint256(-value)); } /// @solidity memory-safe-assembly assembly { // We still have some spare memory space on the left, // as we have allocated 3 words (96 bytes) for up to 78 digits. let length := mload(str) // Load the string length. mstore(str, 0x2d) // Store the '-' character. str := sub(str, 1) // Move back the string pointer by a byte. mstore(str, add(length, 1)) // Update the string length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HEXADECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `length` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `length * 2 + 2` bytes. /// Reverts if `length` is too small for the output to contain all the digits. function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) { str = toHexStringNoPrefix(value, length); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `length` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `length * 2` bytes. /// Reverts if `length` is too small for the output to contain all the digits. function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length. // We add 0x20 to the total and round down to a multiple of 0x20. // (0x20 + 0x20 + 0x02 + 0x20) = 0x62. str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f))) // Allocate the memory. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let start := sub(str, add(length, length)) let w := not(1) // Tsk. let temp := value // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for {} 1 {} { str := add(str, w) // `sub(str, 2)`. mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(xor(str, start)) { break } } if temp { // Store the function selector of `HexLengthInsufficient()`. mstore(0x00, 0x2194895a) // Revert with (offset, size). revert(0x1c, 0x04) } // Compute the string's length. let strLength := sub(end, str) // Move the pointer and write the length. str := sub(str, 0x20) mstore(str, strLength) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2 + 2` bytes. function toHexString(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x". /// The output excludes leading "0" from the `toHexString` output. /// `0x00: "0x0", 0x01: "0x1", 0x12: "0x12", 0x123: "0x123"`. function toMinimalHexString(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present. let strLength := add(mload(str), 2) // Compute the length. mstore(add(str, o), 0x3078) // Write the "0x" prefix, accounting for leading zero. str := sub(add(str, o), 2) // Move the pointer, accounting for leading zero. mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output excludes leading "0" from the `toHexStringNoPrefix` output. /// `0x00: "0", 0x01: "1", 0x12: "12", 0x123: "123"`. function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present. let strLength := mload(str) // Get the length. str := add(str, o) // Move the pointer, accounting for leading zero. mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2` bytes. function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x40 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0. str := add(mload(0x40), 0x80) // Allocate the memory. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let w := not(1) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { str := add(str, w) // `sub(str, 2)`. mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(temp) { break } } // Compute the string's length. let strLength := sub(end, str) // Move the pointer and write the length. str := sub(str, 0x20) mstore(str, strLength) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte, /// and the alphabets are capitalized conditionally according to /// https://eips.ethereum.org/EIPS/eip-55 function toHexStringChecksummed(address value) internal pure returns (string memory str) { str = toHexString(value); /// @solidity memory-safe-assembly assembly { let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...` let o := add(str, 0x22) let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... ` let t := shl(240, 136) // `0b10001000 << 240` for { let i := 0 } 1 {} { mstore(add(i, i), mul(t, byte(i, hashed))) i := add(i, 1) if eq(i, 20) { break } } mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask))))) o := add(o, 0x20) mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask))))) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. function toHexString(address value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(address value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { str := mload(0x40) // Allocate the memory. // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x28 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80. mstore(0x40, add(str, 0x80)) // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) str := add(str, 2) mstore(str, 40) let o := add(str, 0x20) mstore(add(o, 40), 0) value := shl(96, value) // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let i := 0 } 1 {} { let p := add(o, add(i, i)) let temp := byte(i, value) mstore8(add(p, 1), mload(and(temp, 15))) mstore8(p, mload(shr(4, temp))) i := add(i, 1) if eq(i, 20) { break } } } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexString(bytes memory raw) internal pure returns (string memory str) { str = toHexStringNoPrefix(raw); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { let length := mload(raw) str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix. mstore(str, add(length, length)) // Store the length of the output. // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let o := add(str, 0x20) let end := add(raw, length) for {} iszero(eq(raw, end)) {} { raw := add(raw, 1) mstore8(add(o, 1), mload(and(mload(raw), 15))) mstore8(o, mload(and(shr(4, mload(raw)), 15))) o := add(o, 2) } mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate the memory. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RUNE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the number of UTF characters in the string. function runeCount(string memory s) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { if mload(s) { mstore(0x00, div(not(0), 255)) mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506) let o := add(s, 0x20) let end := add(o, mload(s)) for { result := 1 } 1 { result := add(result, 1) } { o := add(o, byte(0, mload(shr(250, mload(o))))) if iszero(lt(o, end)) { break } } } } } /// @dev Returns if this string is a 7-bit ASCII string. /// (i.e. all characters codes are in [0..127]) function is7BitASCII(string memory s) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let mask := shl(7, div(not(0), 255)) result := 1 let n := mload(s) if n { let o := add(s, 0x20) let end := add(o, n) let last := mload(end) mstore(end, 0) for {} 1 {} { if and(mask, mload(o)) { result := 0 break } o := add(o, 0x20) if iszero(lt(o, end)) { break } } mstore(end, last) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // For performance and bytecode compactness, all indices of the following operations // are byte (ASCII) offsets, not UTF character offsets. /// @dev Returns `subject` all occurrences of `search` replaced with `replacement`. function replace(string memory subject, string memory search, string memory replacement) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) let searchLength := mload(search) let replacementLength := mload(replacement) subject := add(subject, 0x20) search := add(search, 0x20) replacement := add(replacement, 0x20) result := add(mload(0x40), 0x20) let subjectEnd := add(subject, subjectLength) if iszero(gt(searchLength, subjectLength)) { let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1) let h := 0 if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) } let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(search) for {} 1 {} { let t := mload(subject) // Whether the first `searchLength % 32` bytes of // `subject` and `search` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(subject, searchLength), h)) { mstore(result, t) result := add(result, 1) subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } continue } } // Copy the `replacement` one word at a time. for { let o := 0 } 1 {} { mstore(add(result, o), mload(add(replacement, o))) o := add(o, 0x20) if iszero(lt(o, replacementLength)) { break } } result := add(result, replacementLength) subject := add(subject, searchLength) if searchLength { if iszero(lt(subject, subjectSearchEnd)) { break } continue } } mstore(result, t) result := add(result, 1) subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } } } let resultRemainder := result result := add(mload(0x40), 0x20) let k := add(sub(resultRemainder, result), sub(subjectEnd, subject)) // Copy the rest of the string one word at a time. for {} lt(subject, subjectEnd) {} { mstore(resultRemainder, mload(subject)) resultRemainder := add(resultRemainder, 0x20) subject := add(subject, 0x20) } result := sub(result, 0x20) let last := add(add(result, 0x20), k) // Zeroize the slot after the string. mstore(last, 0) mstore(0x40, add(last, 0x20)) // Allocate the memory. mstore(result, k) // Store the length. } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from left to right, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function indexOf(string memory subject, string memory search, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for { let subjectLength := mload(subject) } 1 {} { if iszero(mload(search)) { if iszero(gt(from, subjectLength)) { result := from break } result := subjectLength break } let searchLength := mload(search) let subjectStart := add(subject, 0x20) result := not(0) // Initialize to `NOT_FOUND`. subject := add(subjectStart, from) let end := add(sub(add(subjectStart, subjectLength), searchLength), 1) let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(add(search, 0x20)) if iszero(and(lt(subject, end), lt(from, subjectLength))) { break } if iszero(lt(searchLength, 0x20)) { for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} { if iszero(shr(m, xor(mload(subject), s))) { if eq(keccak256(subject, searchLength), h) { result := sub(subject, subjectStart) break } } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } for {} 1 {} { if iszero(shr(m, xor(mload(subject), s))) { result := sub(subject, subjectStart) break } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from left to right. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function indexOf(string memory subject, string memory search) internal pure returns (uint256 result) { result = indexOf(subject, search, 0); } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from right to left, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function lastIndexOf(string memory subject, string memory search, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for {} 1 {} { result := not(0) // Initialize to `NOT_FOUND`. let searchLength := mload(search) if gt(searchLength, mload(subject)) { break } let w := result let fromMax := sub(mload(subject), searchLength) if iszero(gt(fromMax, from)) { from := fromMax } let end := add(add(subject, 0x20), w) subject := add(add(subject, 0x20), from) if iszero(gt(subject, end)) { break } // As this function is not too often used, // we shall simply use keccak256 for smaller bytecode size. for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} { if eq(keccak256(subject, searchLength), h) { result := sub(subject, add(end, 1)) break } subject := add(subject, w) // `sub(subject, 1)`. if iszero(gt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from right to left. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function lastIndexOf(string memory subject, string memory search) internal pure returns (uint256 result) { result = lastIndexOf(subject, search, uint256(int256(-1))); } /// @dev Returns whether `subject` starts with `search`. function startsWith(string memory subject, string memory search) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let searchLength := mload(search) // Just using keccak256 directly is actually cheaper. // forgefmt: disable-next-item result := and( iszero(gt(searchLength, mload(subject))), eq( keccak256(add(subject, 0x20), searchLength), keccak256(add(search, 0x20), searchLength) ) ) } } /// @dev Returns whether `subject` ends with `search`. function endsWith(string memory subject, string memory search) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let searchLength := mload(search) let subjectLength := mload(subject) // Whether `search` is not longer than `subject`. let withinRange := iszero(gt(searchLength, subjectLength)) // Just using keccak256 directly is actually cheaper. // forgefmt: disable-next-item result := and( withinRange, eq( keccak256( // `subject + 0x20 + max(subjectLength - searchLength, 0)`. add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))), searchLength ), keccak256(add(search, 0x20), searchLength) ) ) } } /// @dev Returns `subject` repeated `times`. function repeat(string memory subject, uint256 times) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) if iszero(or(iszero(times), iszero(subjectLength))) { subject := add(subject, 0x20) result := mload(0x40) let output := add(result, 0x20) for {} 1 {} { // Copy the `subject` one word at a time. for { let o := 0 } 1 {} { mstore(add(output, o), mload(add(subject, o))) o := add(o, 0x20) if iszero(lt(o, subjectLength)) { break } } output := add(output, subjectLength) times := sub(times, 1) if iszero(times) { break } } mstore(output, 0) // Zeroize the slot after the string. let resultLength := sub(output, add(result, 0x20)) mstore(result, resultLength) // Store the length. // Allocate the memory. mstore(0x40, add(result, add(resultLength, 0x20))) } } } /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive). /// `start` and `end` are byte offsets. function slice(string memory subject, uint256 start, uint256 end) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) if iszero(gt(subjectLength, end)) { end := subjectLength } if iszero(gt(subjectLength, start)) { start := subjectLength } if lt(start, end) { result := mload(0x40) let resultLength := sub(end, start) mstore(result, resultLength) subject := add(subject, start) let w := not(0x1f) // Copy the `subject` one word at a time, backwards. for { let o := and(add(resultLength, 0x1f), w) } 1 {} { mstore(add(result, o), mload(add(subject, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } // Zeroize the slot after the string. mstore(add(add(result, 0x20), resultLength), 0) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(result, and(add(resultLength, 0x3f), w))) } } } /// @dev Returns a copy of `subject` sliced from `start` to the end of the string. /// `start` is a byte offset. function slice(string memory subject, uint256 start) internal pure returns (string memory result) { result = slice(subject, start, uint256(int256(-1))); } /// @dev Returns all the indices of `search` in `subject`. /// The indices are byte offsets. function indicesOf(string memory subject, string memory search) internal pure returns (uint256[] memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) let searchLength := mload(search) if iszero(gt(searchLength, subjectLength)) { subject := add(subject, 0x20) search := add(search, 0x20) result := add(mload(0x40), 0x20) let subjectStart := subject let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1) let h := 0 if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) } let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(search) for {} 1 {} { let t := mload(subject) // Whether the first `searchLength % 32` bytes of // `subject` and `search` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(subject, searchLength), h)) { subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } continue } } // Append to `result`. mstore(result, sub(subject, subjectStart)) result := add(result, 0x20) // Advance `subject` by `searchLength`. subject := add(subject, searchLength) if searchLength { if iszero(lt(subject, subjectSearchEnd)) { break } continue } } subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } } let resultEnd := result // Assign `result` to the free memory pointer. result := mload(0x40) // Store the length of `result`. mstore(result, shr(5, sub(resultEnd, add(result, 0x20)))) // Allocate memory for result. // We allocate one more word, so this array can be recycled for {split}. mstore(0x40, add(resultEnd, 0x20)) } } } /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string. function split(string memory subject, string memory delimiter) internal pure returns (string[] memory result) { uint256[] memory indices = indicesOf(subject, delimiter); /// @solidity memory-safe-assembly assembly { let w := not(0x1f) let indexPtr := add(indices, 0x20) let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1))) mstore(add(indicesEnd, w), mload(subject)) mstore(indices, add(mload(indices), 1)) let prevIndex := 0 for {} 1 {} { let index := mload(indexPtr) mstore(indexPtr, 0x60) if iszero(eq(index, prevIndex)) { let element := mload(0x40) let elementLength := sub(index, prevIndex) mstore(element, elementLength) // Copy the `subject` one word at a time, backwards. for { let o := and(add(elementLength, 0x1f), w) } 1 {} { mstore(add(element, o), mload(add(add(subject, prevIndex), o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } // Zeroize the slot after the string. mstore(add(add(element, 0x20), elementLength), 0) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(element, and(add(elementLength, 0x3f), w))) // Store the `element` into the array. mstore(indexPtr, element) } prevIndex := add(index, mload(delimiter)) indexPtr := add(indexPtr, 0x20) if iszero(lt(indexPtr, indicesEnd)) { break } } result := indices if iszero(mload(delimiter)) { result := add(indices, 0x20) mstore(result, sub(mload(indices), 2)) } } } /// @dev Returns a concatenated string of `a` and `b`. /// Cheaper than `string.concat()` and does not de-align the free memory pointer. function concat(string memory a, string memory b) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let w := not(0x1f) result := mload(0x40) let aLength := mload(a) // Copy `a` one word at a time, backwards. for { let o := and(add(aLength, 0x20), w) } 1 {} { mstore(add(result, o), mload(add(a, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let bLength := mload(b) let output := add(result, aLength) // Copy `b` one word at a time, backwards. for { let o := and(add(bLength, 0x20), w) } 1 {} { mstore(add(output, o), mload(add(b, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let totalLength := add(aLength, bLength) let last := add(add(result, 0x20), totalLength) // Zeroize the slot after the string. mstore(last, 0) // Stores the length. mstore(result, totalLength) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, and(add(last, 0x1f), w)) } } /// @dev Returns a copy of the string in either lowercase or UPPERCASE. /// WARNING! This function is only compatible with 7-bit ASCII strings. function toCase(string memory subject, bool toUpper) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let length := mload(subject) if length { result := add(mload(0x40), 0x20) subject := add(subject, 1) let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff) let w := not(0) for { let o := length } 1 {} { o := add(o, w) let b := and(0xff, mload(add(subject, o))) mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20))) if iszero(o) { break } } result := mload(0x40) mstore(result, length) // Store the length. let last := add(add(result, 0x20), length) mstore(last, 0) // Zeroize the slot after the string. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } } /// @dev Returns a string from a small bytes32 string. /// `smallString` must be null terminated, or behavior will be undefined. function fromSmallString(bytes32 smallString) internal pure returns (string memory result) { if (smallString == bytes32(0)) return result; /// @solidity memory-safe-assembly assembly { result := mload(0x40) let n := 0 for {} 1 {} { n := add(n, 1) if iszero(byte(n, smallString)) { break } // Scan for '\0'. } mstore(result, n) let o := add(result, 0x20) mstore(o, smallString) mstore(add(o, n), 0) mstore(0x40, add(result, 0x40)) } } /// @dev Returns a lowercased copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function lower(string memory subject) internal pure returns (string memory result) { result = toCase(subject, false); } /// @dev Returns an UPPERCASED copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function upper(string memory subject) internal pure returns (string memory result) { result = toCase(subject, true); } /// @dev Escapes the string to be used within HTML tags. function escapeHTML(string memory s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let end := add(s, mload(s)) result := add(mload(0x40), 0x20) // Store the bytes of the packed offsets and strides into the scratch space. // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6. mstore(0x1f, 0x900094) mstore(0x08, 0xc0000000a6ab) // Store ""&'<>" into the scratch space. mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b)) for {} iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) // Not in `["\"","'","&","<",">"]`. if iszero(and(shl(c, 1), 0x500000c400000000)) { mstore8(result, c) result := add(result, 1) continue } let t := shr(248, mload(c)) mstore(result, mload(and(t, 0x1f))) result := add(result, shr(5, t)) } let last := result mstore(last, 0) // Zeroize the slot after the string. result := mload(0x40) mstore(result, sub(last, add(result, 0x20))) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. /// If `addDoubleQuotes` is true, the result will be enclosed in double-quotes. function escapeJSON(string memory s, bool addDoubleQuotes) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let end := add(s, mload(s)) result := add(mload(0x40), 0x20) if addDoubleQuotes { mstore8(result, 34) result := add(1, result) } // Store "\\u0000" in scratch space. // Store "0123456789abcdef" in scratch space. // Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`. // into the scratch space. mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672) // Bitmask for detecting `["\"","\\"]`. let e := or(shl(0x22, 1), shl(0x5c, 1)) for {} iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) if iszero(lt(c, 0x20)) { if iszero(and(shl(c, 1), e)) { // Not in `["\"","\\"]`. mstore8(result, c) result := add(result, 1) continue } mstore8(result, 0x5c) // "\\". mstore8(add(result, 1), c) result := add(result, 2) continue } if iszero(and(shl(c, 1), 0x3700)) { // Not in `["\b","\t","\n","\f","\d"]`. mstore8(0x1d, mload(shr(4, c))) // Hex value. mstore8(0x1e, mload(and(c, 15))) // Hex value. mstore(result, mload(0x19)) // "\\u00XX". result := add(result, 6) continue } mstore8(result, 0x5c) // "\\". mstore8(add(result, 1), mload(add(c, 8))) result := add(result, 2) } if addDoubleQuotes { mstore8(result, 34) result := add(1, result) } let last := result mstore(last, 0) // Zeroize the slot after the string. result := mload(0x40) mstore(result, sub(last, add(result, 0x20))) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. function escapeJSON(string memory s) internal pure returns (string memory result) { result = escapeJSON(s, false); } /// @dev Returns whether `a` equals `b`. function eq(string memory a, string memory b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b))) } } /// @dev Returns whether `a` equals `b`. For small strings up to 32 bytes. /// `b` must be null terminated, or behavior will be undefined. function eqs(string memory a, bytes32 b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { // These should be evaluated on compile time, as far as possible. let x := and(b, add(not(b), 1)) let r := or(shl(8, iszero(b)), shl(7, iszero(iszero(shr(128, x))))) r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x)))))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) result := gt(eq(mload(a), sub(32, shr(3, r))), shr(r, xor(b, mload(add(a, 0x20))))) } } /// @dev Packs a single string with its length into a single word. /// Returns `bytes32(0)` if the length is zero or greater than 31. function packOne(string memory a) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { // We don't need to zero right pad the string, // since this is our own custom non-standard packing scheme. result := mul( // Load the length and the bytes. mload(add(a, 0x1f)), // `length != 0 && length < 32`. Abuses underflow. // Assumes that the length is valid and within the block gas limit. lt(sub(mload(a), 1), 0x1f) ) } } /// @dev Unpacks a string packed using {packOne}. /// Returns the empty string if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packOne}, the output behavior is undefined. function unpackOne(bytes32 packed) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. result := mload(0x40) // Allocate 2 words (1 for the length, 1 for the bytes). mstore(0x40, add(result, 0x40)) // Zeroize the length slot. mstore(result, 0) // Store the length and bytes. mstore(add(result, 0x1f), packed) // Right pad with zeroes. mstore(add(add(result, 0x20), mload(result)), 0) } } /// @dev Packs two strings with their lengths into a single word. /// Returns `bytes32(0)` if combined length is zero or greater than 30. function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let aLength := mload(a) // We don't need to zero right pad the strings, // since this is our own custom non-standard packing scheme. result := mul( // Load the length and the bytes of `a` and `b`. or( shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))), mload(sub(add(b, 0x1e), aLength)) ), // `totalLength != 0 && totalLength < 31`. Abuses underflow. // Assumes that the lengths are valid and within the block gas limit. lt(sub(add(aLength, mload(b)), 1), 0x1e) ) } } /// @dev Unpacks strings packed using {packTwo}. /// Returns the empty strings if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packTwo}, the output behavior is undefined. function unpackTwo(bytes32 packed) internal pure returns (string memory resultA, string memory resultB) { /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. resultA := mload(0x40) resultB := add(resultA, 0x40) // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words. mstore(0x40, add(resultB, 0x40)) // Zeroize the length slots. mstore(resultA, 0) mstore(resultB, 0) // Store the lengths and bytes. mstore(add(resultA, 0x1f), packed) mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA)))) // Right pad with zeroes. mstore(add(add(resultA, 0x20), mload(resultA)), 0) mstore(add(add(resultB, 0x20), mload(resultB)), 0) } } /// @dev Directly returns `a` without copying. function directReturn(string memory a) internal pure { assembly { // Assumes that the string does not start from the scratch space. let retStart := sub(a, 0x20) let retSize := add(mload(a), 0x40) // Right pad with zeroes. Just in case the string is produced // by a method that doesn't zero right pad. mstore(add(retStart, retSize), 0) // Store the return offset. mstore(retStart, 0x20) // End the transaction, returning the string. return(retStart, retSize) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// /// @dev Note: /// This implementation does NOT auto-initialize the owner to `msg.sender`. /// You MUST call the `_initializeOwner` in the constructor / initializer. /// /// While the ownable portion follows /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, /// the nomenclature for the 2-step ownership handover may be unique to this codebase. abstract contract Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The caller is not authorized to call the function. error Unauthorized(); /// @dev The `newOwner` cannot be the zero address. error NewOwnerIsZeroAddress(); /// @dev The `pendingOwner` does not have a valid handover request. error NoHandoverRequest(); /// @dev Cannot double-initialize. error AlreadyInitialized(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership is transferred from `oldOwner` to `newOwner`. /// This event is intentionally kept the same as OpenZeppelin's Ownable to be /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173), /// despite it not being as lightweight as a single argument event. event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// @dev An ownership handover to `pendingOwner` has been requested. event OwnershipHandoverRequested(address indexed pendingOwner); /// @dev The ownership handover to `pendingOwner` has been canceled. event OwnershipHandoverCanceled(address indexed pendingOwner); /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`. uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE = 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0; /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE = 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d; /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE = 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The owner slot is given by: /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`. /// It is intentionally chosen to be a high value /// to avoid collision with lower slots. /// The choice of manual storage layout is to enable compatibility /// with both regular and upgradeable contracts. bytes32 internal constant _OWNER_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927; /// The ownership handover slot of `newOwner` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED)) /// let handoverSlot := keccak256(0x00, 0x20) /// ``` /// It stores the expiry timestamp of the two-step ownership handover. uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override to return true to make `_initializeOwner` prevent double-initialization. function _guardInitializeOwner() internal pure virtual returns (bool guard) {} /// @dev Initializes the owner directly without authorization guard. /// This function must be called upon initialization, /// regardless of whether the contract is upgradeable or not. /// This is to enable generalization to both regular and upgradeable contracts, /// and to save gas in case the initial owner is not the caller. /// For performance reasons, this function will not check if there /// is an existing owner. function _initializeOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT if sload(ownerSlot) { mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`. revert(0x1c, 0x04) } // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } else { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(_OWNER_SLOT, newOwner) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } } /// @dev Sets the owner directly without authorization guard. function _setOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) } } else { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, newOwner) } } } /// @dev Throws if the sender is not the owner. function _checkOwner() internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner, revert. if iszero(eq(caller(), sload(_OWNER_SLOT))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Returns how long a two-step ownership handover is valid for in seconds. /// Override to return a different value if needed. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ownershipHandoverValidFor() internal view virtual returns (uint64) { return 48 * 3600; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { if iszero(shl(96, newOwner)) { mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`. revert(0x1c, 0x04) } } _setOwner(newOwner); } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public payable virtual onlyOwner { _setOwner(address(0)); } /// @dev Request a two-step ownership handover to the caller. /// The request will automatically expire in 48 hours (172800 seconds) by default. function requestOwnershipHandover() public payable virtual { unchecked { uint256 expires = block.timestamp + _ownershipHandoverValidFor(); /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to `expires`. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), expires) // Emit the {OwnershipHandoverRequested} event. log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller()) } } } /// @dev Cancels the two-step ownership handover to the caller, if any. function cancelOwnershipHandover() public payable virtual { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), 0) // Emit the {OwnershipHandoverCanceled} event. log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller()) } } /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`. /// Reverts if there is no existing ownership handover requested by `pendingOwner`. function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) let handoverSlot := keccak256(0x0c, 0x20) // If the handover does not exist, or has expired. if gt(timestamp(), sload(handoverSlot)) { mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`. revert(0x1c, 0x04) } // Set the handover slot to 0. sstore(handoverSlot, 0) } _setOwner(pendingOwner); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { result := sload(_OWNER_SLOT) } } /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`. function ownershipHandoverExpiresAt(address pendingOwner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the handover slot. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) // Load the handover slot. result := sload(keccak256(0x0c, 0x20)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {Ownable} from "./Ownable.sol"; /// @notice Simple single owner and multiroles authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173) /// for compatibility, the nomenclature for the 2-step ownership handover and roles /// may be unique to this codebase. abstract contract OwnableRoles is Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The `user`'s roles is updated to `roles`. /// Each bit of `roles` represents whether the role is set. event RolesUpdated(address indexed user, uint256 indexed roles); /// @dev `keccak256(bytes("RolesUpdated(address,uint256)"))`. uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE = 0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The role slot of `user` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED)) /// let roleSlot := keccak256(0x00, 0x20) /// ``` /// This automatically ignores the upper bits of the `user` in case /// they are not clean, as well as keep the `keccak256` under 32-bytes. /// /// Note: This is equivalent to `uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))`. uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Overwrite the roles directly without authorization guard. function _setRoles(address user, uint256 roles) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) // Store the new value. sstore(keccak256(0x0c, 0x20), roles) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles) } } /// @dev Updates the roles directly without authorization guard. /// If `on` is true, each set bit of `roles` will be turned on, /// otherwise, each set bit of `roles` will be turned off. function _updateRoles(address user, uint256 roles, bool on) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) let roleSlot := keccak256(0x0c, 0x20) // Load the current value. let current := sload(roleSlot) // Compute the updated roles if `on` is true. let updated := or(current, roles) // Compute the updated roles if `on` is false. // Use `and` to compute the intersection of `current` and `roles`, // `xor` it with `current` to flip the bits in the intersection. if iszero(on) { updated := xor(current, and(current, roles)) } // Then, store the new value. sstore(roleSlot, updated) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated) } } /// @dev Grants the roles directly without authorization guard. /// Each bit of `roles` represents the role to turn on. function _grantRoles(address user, uint256 roles) internal virtual { _updateRoles(user, roles, true); } /// @dev Removes the roles directly without authorization guard. /// Each bit of `roles` represents the role to turn off. function _removeRoles(address user, uint256 roles) internal virtual { _updateRoles(user, roles, false); } /// @dev Throws if the sender does not have any of the `roles`. function _checkRoles(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Throws if the sender is not the owner, /// and does not have any of the `roles`. /// Checks for ownership first, then lazily checks for roles. function _checkOwnerOrRoles(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner. // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`. if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } } /// @dev Throws if the sender does not have any of the `roles`, /// and is not the owner. /// Checks for roles first, then lazily checks for ownership. function _checkRolesOrOwner(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { // If the caller is not the stored owner. // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`. if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } } /// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`. /// This is meant for frontends like Etherscan, and is therefore not fully optimized. /// Not recommended to be called on-chain. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _rolesFromOrdinals(uint8[] memory ordinals) internal pure returns (uint256 roles) { /// @solidity memory-safe-assembly assembly { for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } { // We don't need to mask the values of `ordinals`, as Solidity // cleans dirty upper bits when storing variables into memory. roles := or(shl(mload(add(ordinals, i)), 1), roles) } } } /// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap. /// This is meant for frontends like Etherscan, and is therefore not fully optimized. /// Not recommended to be called on-chain. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ordinalsFromRoles(uint256 roles) internal pure returns (uint8[] memory ordinals) { /// @solidity memory-safe-assembly assembly { // Grab the pointer to the free memory. ordinals := mload(0x40) let ptr := add(ordinals, 0x20) let o := 0 // The absence of lookup tables, De Bruijn, etc., here is intentional for // smaller bytecode, as this function is not meant to be called on-chain. for { let t := roles } 1 {} { mstore(ptr, o) // `shr` 5 is equivalent to multiplying by 0x20. // Push back into the ordinals array if the bit is set. ptr := add(ptr, shl(5, and(t, 1))) o := add(o, 1) t := shr(o, roles) if iszero(t) { break } } // Store the length of `ordinals`. mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20)))) // Allocate the memory. mstore(0x40, ptr) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to grant `user` `roles`. /// If the `user` already has a role, then it will be an no-op for the role. function grantRoles(address user, uint256 roles) public payable virtual onlyOwner { _grantRoles(user, roles); } /// @dev Allows the owner to remove `user` `roles`. /// If the `user` does not have a role, then it will be an no-op for the role. function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner { _removeRoles(user, roles); } /// @dev Allow the caller to remove their own roles. /// If the caller does not have a role, then it will be an no-op for the role. function renounceRoles(uint256 roles) public payable virtual { _removeRoles(msg.sender, roles); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the roles of `user`. function rolesOf(address user) public view virtual returns (uint256 roles) { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) // Load the stored value. roles := sload(keccak256(0x0c, 0x20)) } } /// @dev Returns whether `user` has any of `roles`. function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) { return rolesOf(user) & roles != 0; } /// @dev Returns whether `user` has all of `roles`. function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) { return rolesOf(user) & roles == roles; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by an account with `roles`. modifier onlyRoles(uint256 roles) virtual { _checkRoles(roles); _; } /// @dev Marks a function as only callable by the owner or by an account /// with `roles`. Checks for ownership first, then lazily checks for roles. modifier onlyOwnerOrRoles(uint256 roles) virtual { _checkOwnerOrRoles(roles); _; } /// @dev Marks a function as only callable by an account with `roles` /// or the owner. Checks for roles first, then lazily checks for ownership. modifier onlyRolesOrOwner(uint256 roles) virtual { _checkRolesOrOwner(roles); _; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ROLE CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // IYKYK uint256 internal constant _ROLE_0 = 1 << 0; uint256 internal constant _ROLE_1 = 1 << 1; uint256 internal constant _ROLE_2 = 1 << 2; uint256 internal constant _ROLE_3 = 1 << 3; uint256 internal constant _ROLE_4 = 1 << 4; uint256 internal constant _ROLE_5 = 1 << 5; uint256 internal constant _ROLE_6 = 1 << 6; uint256 internal constant _ROLE_7 = 1 << 7; uint256 internal constant _ROLE_8 = 1 << 8; uint256 internal constant _ROLE_9 = 1 << 9; uint256 internal constant _ROLE_10 = 1 << 10; uint256 internal constant _ROLE_11 = 1 << 11; uint256 internal constant _ROLE_12 = 1 << 12; uint256 internal constant _ROLE_13 = 1 << 13; uint256 internal constant _ROLE_14 = 1 << 14; uint256 internal constant _ROLE_15 = 1 << 15; uint256 internal constant _ROLE_16 = 1 << 16; uint256 internal constant _ROLE_17 = 1 << 17; uint256 internal constant _ROLE_18 = 1 << 18; uint256 internal constant _ROLE_19 = 1 << 19; uint256 internal constant _ROLE_20 = 1 << 20; uint256 internal constant _ROLE_21 = 1 << 21; uint256 internal constant _ROLE_22 = 1 << 22; uint256 internal constant _ROLE_23 = 1 << 23; uint256 internal constant _ROLE_24 = 1 << 24; uint256 internal constant _ROLE_25 = 1 << 25; uint256 internal constant _ROLE_26 = 1 << 26; uint256 internal constant _ROLE_27 = 1 << 27; uint256 internal constant _ROLE_28 = 1 << 28; uint256 internal constant _ROLE_29 = 1 << 29; uint256 internal constant _ROLE_30 = 1 << 30; uint256 internal constant _ROLE_31 = 1 << 31; uint256 internal constant _ROLE_32 = 1 << 32; uint256 internal constant _ROLE_33 = 1 << 33; uint256 internal constant _ROLE_34 = 1 << 34; uint256 internal constant _ROLE_35 = 1 << 35; uint256 internal constant _ROLE_36 = 1 << 36; uint256 internal constant _ROLE_37 = 1 << 37; uint256 internal constant _ROLE_38 = 1 << 38; uint256 internal constant _ROLE_39 = 1 << 39; uint256 internal constant _ROLE_40 = 1 << 40; uint256 internal constant _ROLE_41 = 1 << 41; uint256 internal constant _ROLE_42 = 1 << 42; uint256 internal constant _ROLE_43 = 1 << 43; uint256 internal constant _ROLE_44 = 1 << 44; uint256 internal constant _ROLE_45 = 1 << 45; uint256 internal constant _ROLE_46 = 1 << 46; uint256 internal constant _ROLE_47 = 1 << 47; uint256 internal constant _ROLE_48 = 1 << 48; uint256 internal constant _ROLE_49 = 1 << 49; uint256 internal constant _ROLE_50 = 1 << 50; uint256 internal constant _ROLE_51 = 1 << 51; uint256 internal constant _ROLE_52 = 1 << 52; uint256 internal constant _ROLE_53 = 1 << 53; uint256 internal constant _ROLE_54 = 1 << 54; uint256 internal constant _ROLE_55 = 1 << 55; uint256 internal constant _ROLE_56 = 1 << 56; uint256 internal constant _ROLE_57 = 1 << 57; uint256 internal constant _ROLE_58 = 1 << 58; uint256 internal constant _ROLE_59 = 1 << 59; uint256 internal constant _ROLE_60 = 1 << 60; uint256 internal constant _ROLE_61 = 1 << 61; uint256 internal constant _ROLE_62 = 1 << 62; uint256 internal constant _ROLE_63 = 1 << 63; uint256 internal constant _ROLE_64 = 1 << 64; uint256 internal constant _ROLE_65 = 1 << 65; uint256 internal constant _ROLE_66 = 1 << 66; uint256 internal constant _ROLE_67 = 1 << 67; uint256 internal constant _ROLE_68 = 1 << 68; uint256 internal constant _ROLE_69 = 1 << 69; uint256 internal constant _ROLE_70 = 1 << 70; uint256 internal constant _ROLE_71 = 1 << 71; uint256 internal constant _ROLE_72 = 1 << 72; uint256 internal constant _ROLE_73 = 1 << 73; uint256 internal constant _ROLE_74 = 1 << 74; uint256 internal constant _ROLE_75 = 1 << 75; uint256 internal constant _ROLE_76 = 1 << 76; uint256 internal constant _ROLE_77 = 1 << 77; uint256 internal constant _ROLE_78 = 1 << 78; uint256 internal constant _ROLE_79 = 1 << 79; uint256 internal constant _ROLE_80 = 1 << 80; uint256 internal constant _ROLE_81 = 1 << 81; uint256 internal constant _ROLE_82 = 1 << 82; uint256 internal constant _ROLE_83 = 1 << 83; uint256 internal constant _ROLE_84 = 1 << 84; uint256 internal constant _ROLE_85 = 1 << 85; uint256 internal constant _ROLE_86 = 1 << 86; uint256 internal constant _ROLE_87 = 1 << 87; uint256 internal constant _ROLE_88 = 1 << 88; uint256 internal constant _ROLE_89 = 1 << 89; uint256 internal constant _ROLE_90 = 1 << 90; uint256 internal constant _ROLE_91 = 1 << 91; uint256 internal constant _ROLE_92 = 1 << 92; uint256 internal constant _ROLE_93 = 1 << 93; uint256 internal constant _ROLE_94 = 1 << 94; uint256 internal constant _ROLE_95 = 1 << 95; uint256 internal constant _ROLE_96 = 1 << 96; uint256 internal constant _ROLE_97 = 1 << 97; uint256 internal constant _ROLE_98 = 1 << 98; uint256 internal constant _ROLE_99 = 1 << 99; uint256 internal constant _ROLE_100 = 1 << 100; uint256 internal constant _ROLE_101 = 1 << 101; uint256 internal constant _ROLE_102 = 1 << 102; uint256 internal constant _ROLE_103 = 1 << 103; uint256 internal constant _ROLE_104 = 1 << 104; uint256 internal constant _ROLE_105 = 1 << 105; uint256 internal constant _ROLE_106 = 1 << 106; uint256 internal constant _ROLE_107 = 1 << 107; uint256 internal constant _ROLE_108 = 1 << 108; uint256 internal constant _ROLE_109 = 1 << 109; uint256 internal constant _ROLE_110 = 1 << 110; uint256 internal constant _ROLE_111 = 1 << 111; uint256 internal constant _ROLE_112 = 1 << 112; uint256 internal constant _ROLE_113 = 1 << 113; uint256 internal constant _ROLE_114 = 1 << 114; uint256 internal constant _ROLE_115 = 1 << 115; uint256 internal constant _ROLE_116 = 1 << 116; uint256 internal constant _ROLE_117 = 1 << 117; uint256 internal constant _ROLE_118 = 1 << 118; uint256 internal constant _ROLE_119 = 1 << 119; uint256 internal constant _ROLE_120 = 1 << 120; uint256 internal constant _ROLE_121 = 1 << 121; uint256 internal constant _ROLE_122 = 1 << 122; uint256 internal constant _ROLE_123 = 1 << 123; uint256 internal constant _ROLE_124 = 1 << 124; uint256 internal constant _ROLE_125 = 1 << 125; uint256 internal constant _ROLE_126 = 1 << 126; uint256 internal constant _ROLE_127 = 1 << 127; uint256 internal constant _ROLE_128 = 1 << 128; uint256 internal constant _ROLE_129 = 1 << 129; uint256 internal constant _ROLE_130 = 1 << 130; uint256 internal constant _ROLE_131 = 1 << 131; uint256 internal constant _ROLE_132 = 1 << 132; uint256 internal constant _ROLE_133 = 1 << 133; uint256 internal constant _ROLE_134 = 1 << 134; uint256 internal constant _ROLE_135 = 1 << 135; uint256 internal constant _ROLE_136 = 1 << 136; uint256 internal constant _ROLE_137 = 1 << 137; uint256 internal constant _ROLE_138 = 1 << 138; uint256 internal constant _ROLE_139 = 1 << 139; uint256 internal constant _ROLE_140 = 1 << 140; uint256 internal constant _ROLE_141 = 1 << 141; uint256 internal constant _ROLE_142 = 1 << 142; uint256 internal constant _ROLE_143 = 1 << 143; uint256 internal constant _ROLE_144 = 1 << 144; uint256 internal constant _ROLE_145 = 1 << 145; uint256 internal constant _ROLE_146 = 1 << 146; uint256 internal constant _ROLE_147 = 1 << 147; uint256 internal constant _ROLE_148 = 1 << 148; uint256 internal constant _ROLE_149 = 1 << 149; uint256 internal constant _ROLE_150 = 1 << 150; uint256 internal constant _ROLE_151 = 1 << 151; uint256 internal constant _ROLE_152 = 1 << 152; uint256 internal constant _ROLE_153 = 1 << 153; uint256 internal constant _ROLE_154 = 1 << 154; uint256 internal constant _ROLE_155 = 1 << 155; uint256 internal constant _ROLE_156 = 1 << 156; uint256 internal constant _ROLE_157 = 1 << 157; uint256 internal constant _ROLE_158 = 1 << 158; uint256 internal constant _ROLE_159 = 1 << 159; uint256 internal constant _ROLE_160 = 1 << 160; uint256 internal constant _ROLE_161 = 1 << 161; uint256 internal constant _ROLE_162 = 1 << 162; uint256 internal constant _ROLE_163 = 1 << 163; uint256 internal constant _ROLE_164 = 1 << 164; uint256 internal constant _ROLE_165 = 1 << 165; uint256 internal constant _ROLE_166 = 1 << 166; uint256 internal constant _ROLE_167 = 1 << 167; uint256 internal constant _ROLE_168 = 1 << 168; uint256 internal constant _ROLE_169 = 1 << 169; uint256 internal constant _ROLE_170 = 1 << 170; uint256 internal constant _ROLE_171 = 1 << 171; uint256 internal constant _ROLE_172 = 1 << 172; uint256 internal constant _ROLE_173 = 1 << 173; uint256 internal constant _ROLE_174 = 1 << 174; uint256 internal constant _ROLE_175 = 1 << 175; uint256 internal constant _ROLE_176 = 1 << 176; uint256 internal constant _ROLE_177 = 1 << 177; uint256 internal constant _ROLE_178 = 1 << 178; uint256 internal constant _ROLE_179 = 1 << 179; uint256 internal constant _ROLE_180 = 1 << 180; uint256 internal constant _ROLE_181 = 1 << 181; uint256 internal constant _ROLE_182 = 1 << 182; uint256 internal constant _ROLE_183 = 1 << 183; uint256 internal constant _ROLE_184 = 1 << 184; uint256 internal constant _ROLE_185 = 1 << 185; uint256 internal constant _ROLE_186 = 1 << 186; uint256 internal constant _ROLE_187 = 1 << 187; uint256 internal constant _ROLE_188 = 1 << 188; uint256 internal constant _ROLE_189 = 1 << 189; uint256 internal constant _ROLE_190 = 1 << 190; uint256 internal constant _ROLE_191 = 1 << 191; uint256 internal constant _ROLE_192 = 1 << 192; uint256 internal constant _ROLE_193 = 1 << 193; uint256 internal constant _ROLE_194 = 1 << 194; uint256 internal constant _ROLE_195 = 1 << 195; uint256 internal constant _ROLE_196 = 1 << 196; uint256 internal constant _ROLE_197 = 1 << 197; uint256 internal constant _ROLE_198 = 1 << 198; uint256 internal constant _ROLE_199 = 1 << 199; uint256 internal constant _ROLE_200 = 1 << 200; uint256 internal constant _ROLE_201 = 1 << 201; uint256 internal constant _ROLE_202 = 1 << 202; uint256 internal constant _ROLE_203 = 1 << 203; uint256 internal constant _ROLE_204 = 1 << 204; uint256 internal constant _ROLE_205 = 1 << 205; uint256 internal constant _ROLE_206 = 1 << 206; uint256 internal constant _ROLE_207 = 1 << 207; uint256 internal constant _ROLE_208 = 1 << 208; uint256 internal constant _ROLE_209 = 1 << 209; uint256 internal constant _ROLE_210 = 1 << 210; uint256 internal constant _ROLE_211 = 1 << 211; uint256 internal constant _ROLE_212 = 1 << 212; uint256 internal constant _ROLE_213 = 1 << 213; uint256 internal constant _ROLE_214 = 1 << 214; uint256 internal constant _ROLE_215 = 1 << 215; uint256 internal constant _ROLE_216 = 1 << 216; uint256 internal constant _ROLE_217 = 1 << 217; uint256 internal constant _ROLE_218 = 1 << 218; uint256 internal constant _ROLE_219 = 1 << 219; uint256 internal constant _ROLE_220 = 1 << 220; uint256 internal constant _ROLE_221 = 1 << 221; uint256 internal constant _ROLE_222 = 1 << 222; uint256 internal constant _ROLE_223 = 1 << 223; uint256 internal constant _ROLE_224 = 1 << 224; uint256 internal constant _ROLE_225 = 1 << 225; uint256 internal constant _ROLE_226 = 1 << 226; uint256 internal constant _ROLE_227 = 1 << 227; uint256 internal constant _ROLE_228 = 1 << 228; uint256 internal constant _ROLE_229 = 1 << 229; uint256 internal constant _ROLE_230 = 1 << 230; uint256 internal constant _ROLE_231 = 1 << 231; uint256 internal constant _ROLE_232 = 1 << 232; uint256 internal constant _ROLE_233 = 1 << 233; uint256 internal constant _ROLE_234 = 1 << 234; uint256 internal constant _ROLE_235 = 1 << 235; uint256 internal constant _ROLE_236 = 1 << 236; uint256 internal constant _ROLE_237 = 1 << 237; uint256 internal constant _ROLE_238 = 1 << 238; uint256 internal constant _ROLE_239 = 1 << 239; uint256 internal constant _ROLE_240 = 1 << 240; uint256 internal constant _ROLE_241 = 1 << 241; uint256 internal constant _ROLE_242 = 1 << 242; uint256 internal constant _ROLE_243 = 1 << 243; uint256 internal constant _ROLE_244 = 1 << 244; uint256 internal constant _ROLE_245 = 1 << 245; uint256 internal constant _ROLE_246 = 1 << 246; uint256 internal constant _ROLE_247 = 1 << 247; uint256 internal constant _ROLE_248 = 1 << 248; uint256 internal constant _ROLE_249 = 1 << 249; uint256 internal constant _ROLE_250 = 1 << 250; uint256 internal constant _ROLE_251 = 1 << 251; uint256 internal constant _ROLE_252 = 1 << 252; uint256 internal constant _ROLE_253 = 1 << 253; uint256 internal constant _ROLE_254 = 1 << 254; uint256 internal constant _ROLE_255 = 1 << 255; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.22; /// @notice Gas optimized reentrancy protection for smart contracts /// @author Cheezburger (https://cheezburger.lol) abstract contract ReentrancyGuard { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ error ReentrancyDetected(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ uint8 private locked = 1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ modifier nonReentrant() virtual { if (locked == 2) { revert ReentrancyDetected(); } locked = 2; _; locked = 1; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// /// @dev Note: /// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection. /// - For ERC20s, this implementation won't check that a token has code, /// responsibility is delegated to the caller. library SafeTransferLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ETH transfer has failed. error ETHTransferFailed(); /// @dev The ERC20 `transferFrom` has failed. error TransferFromFailed(); /// @dev The ERC20 `transfer` has failed. error TransferFailed(); /// @dev The ERC20 `approve` has failed. error ApproveFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes. uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300; /// @dev Suggested gas stipend for contract receiving ETH to perform a few /// storage reads and writes, but low enough to prevent griefing. uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants. // // The regular variants: // - Forwards all remaining gas to the target. // - Reverts if the target reverts. // - Reverts if the current contract has insufficient balance. // // The force variants: // - Forwards with an optional gas stipend // (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases). // - If the target reverts, or if the gas stipend is exhausted, // creates a temporary contract to force send the ETH via `SELFDESTRUCT`. // Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758. // - Reverts if the current contract has insufficient balance. // // The try variants: // - Forwards with a mandatory gas stipend. // - Instead of reverting, returns whether the transfer succeeded. /// @dev Sends `amount` (in wei) ETH to `to`. function safeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Sends all the ETH in the current contract to `to`. function safeTransferAllETH(address to) internal { /// @solidity memory-safe-assembly assembly { // Transfer all the ETH and check if it succeeded or not. if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`. function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { if lt(selfbalance(), amount) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`. function forceSafeTransferAllETH(address to, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`. function forceSafeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { if lt(selfbalance(), amount) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`. function forceSafeTransferAllETH(address to) internal { /// @solidity memory-safe-assembly assembly { // forgefmt: disable-next-item if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`. function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00) } } /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`. function trySafeTransferAllETH(address to, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferFrom(address token, address from, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, amount) // Store the `amount` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends all of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have their entire balance approved for /// the current contract to manage. function safeTransferAllFrom(address token, address from, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`. // Read the balance, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`. amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransfer(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sends all of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransferAll(address token, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, address()) // Store the address of the current contract. // Read the balance, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x14, to) // Store the `to` argument. amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// Reverts upon failure. function safeApprove(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// If the initial attempt to approve fails, attempts to reset the approved amount to zero, /// then retries the approval again (some tokens, e.g. USDT, requires this). /// Reverts upon failure. function safeApproveWithRetry(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, retrying upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x34, 0) // Store 0 for the `amount`. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval. mstore(0x34, amount) // Store back the original `amount`. // Retry the approval, reverting upon failure. if iszero( and( or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Returns the amount of ERC20 `token` owned by `account`. /// Returns zero if the `token` does not exist. function balanceOf(address token, address account) internal view returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x14, account) // Store the `account` argument. mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`. amount := mul( mload(0x20), and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20) ) ) } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"website","type":"string"},{"internalType":"string","name":"social","type":"string"},{"internalType":"uint256","name":"supply","type":"uint256"}],"internalType":"struct CheezburgerStructs.TokenCustomization","name":"_customization","type":"tuple"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_router","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AllowanceOverflow","type":"error"},{"inputs":[],"name":"AllowanceUnderflow","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"CannotReceiveEtherDirectly","type":"error"},{"inputs":[],"name":"CannotUseCHZBNamespace","type":"error"},{"inputs":[],"name":"EmptyAddressNotAllowed","type":"error"},{"inputs":[],"name":"EmptyNumericUserId","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"IncorrectPoolOpeningFee","type":"error"},{"inputs":[],"name":"InsufficientAllowance","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidPermit","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"PermitExpired","type":"error"},{"inputs":[],"name":"ReentrancyDetected","type":"error"},{"inputs":[],"name":"SocialNotOpened","type":"error"},{"inputs":[],"name":"SupplyAllocationExceeded","type":"error"},{"inputs":[],"name":"SupplyOverflow","type":"error"},{"inputs":[],"name":"TotalSupplyOverflow","type":"error"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"TransferToToken","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"uint256","name":"userId","type":"uint256"}],"name":"UserIdAlreadyExist","type":"error"},{"inputs":[],"name":"UserIdNotFound","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"GlobalSettingsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"creationAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentOutOfCirculationSupply","type":"uint256"}],"name":"LiquidityLessTokenDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"PairingAmountsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"RolesUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"SettingsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"userId","type":"uint256"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"creationAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentOutOfCirculationSupply","type":"uint256"}],"name":"SocialTokenDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pair","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SocialTokenFeeWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"result","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract ICheezburgerFactory","name":"factory","type":"address"},{"internalType":"address","name":"router","type":"address"}],"internalType":"struct CheezburgerDeployerKit.GlobalSettings","name":"_globalSettings","type":"tuple"}],"name":"changeGlobalSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_socialPairingAmount","type":"uint256"},{"internalType":"uint256","name":"_tokenPairingAmount","type":"uint256"}],"name":"changePairingAmounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"pairingAmount","type":"uint256"},{"internalType":"uint256","name":"leftSideSupply","type":"uint256"},{"internalType":"uint256","name":"openFeeWei","type":"uint256"},{"internalType":"uint8","name":"poolCreatorFeePercentage","type":"uint8"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"walletSettings","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"feeSettings","type":"tuple"}],"internalType":"struct CheezburgerDeployerKit.SocialSettings","name":"_socialSettings","type":"tuple"},{"components":[{"internalType":"uint256","name":"pairingAmount","type":"uint256"},{"internalType":"uint256","name":"openFeeWei","type":"uint256"}],"internalType":"struct CheezburgerDeployerKit.TokenSettings","name":"_tokenSettings","type":"tuple"}],"name":"changeSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"userId","type":"uint256"}],"name":"deploySocialTokenWithCHZB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"website","type":"string"},{"internalType":"string","name":"social","type":"string"},{"internalType":"uint256","name":"supply","type":"uint256"}],"internalType":"struct CheezburgerStructs.TokenCustomization","name":"_customization","type":"tuple"},{"components":[{"internalType":"uint8","name":"feeThresholdPercent","type":"uint8"},{"internalType":"address[]","name":"feeAddresses","type":"address[]"},{"internalType":"uint8[]","name":"feePercentages","type":"uint8[]"}],"internalType":"struct CheezburgerStructs.LiquiditySettings","name":"_liquidity","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"_fee","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"_wallet","type":"tuple"},{"components":[{"internalType":"address","name":"feeReceiver","type":"address"},{"internalType":"uint8","name":"feePercentage","type":"uint8"}],"internalType":"struct CheezburgerStructs.ReferralSettings","name":"_referral","type":"tuple"}],"name":"deployTokenWithCHZB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"globalSettings","outputs":[{"internalType":"contract ICheezburgerFactory","name":"factory","type":"address"},{"internalType":"address","name":"router","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"grantRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAllRoles","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAnyRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"outOfCirculationTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"renounceRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"revokeRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rolesOf","outputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"social","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"socialIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"socialSettings","outputs":[{"internalType":"uint256","name":"pairingAmount","type":"uint256"},{"internalType":"uint256","name":"leftSideSupply","type":"uint256"},{"internalType":"uint256","name":"openFeeWei","type":"uint256"},{"internalType":"uint8","name":"poolCreatorFeePercentage","type":"uint8"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"walletSettings","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"feeSettings","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"socialTokens","outputs":[{"internalType":"address","name":"factory","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"pair","type":"address"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address","name":"leftSide","type":"address"},{"internalType":"address","name":"rightSide","type":"address"},{"components":[{"internalType":"uint8","name":"feeThresholdPercent","type":"uint8"},{"internalType":"address[]","name":"feeAddresses","type":"address[]"},{"internalType":"uint8[]","name":"feePercentages","type":"uint8[]"}],"internalType":"struct CheezburgerStructs.LiquiditySettings","name":"liquidity","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"fee","type":"tuple"},{"components":[{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint16","name":"percentStart","type":"uint16"},{"internalType":"uint16","name":"percentEnd","type":"uint16"}],"internalType":"struct CheezburgerStructs.DynamicSettings","name":"wallet","type":"tuple"},{"components":[{"internalType":"address","name":"feeReceiver","type":"address"},{"internalType":"uint8","name":"feePercentage","type":"uint8"}],"internalType":"struct CheezburgerStructs.ReferralSettings","name":"referral","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenSettings","outputs":[{"internalType":"uint256","name":"pairingAmount","type":"uint256"},{"internalType":"uint256","name":"openFeeWei","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"website","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawCreationFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_userId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawFeesOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040525f805460ff191660011790553480156200001c575f80fd5b5060405162003ae538038062003ae58339810160408190526200003f91620005cc565b6001600160a01b03821615806200005d57506001600160a01b038116155b156200007c576040516387e5f21360e01b815260040160405180910390fd5b82516012906200008d908262000766565b506020830151601390620000a2908262000766565b506040830151600190620000b7908262000766565b506060830151600290620000cc908262000766565b50620000d833620001b8565b6200010233620000eb6012600a62000941565b8560800151620000fc919062000958565b620001f4565b6040805160c0810182525f808252620f424060208084019190915282840182905260046060808501919091528451808201865262127500815261012c81840152611324818701526080850152845190810185526201518081526101f48183015260c88186015260a0840152835180850190945281845283015262000186916200028b565b604080518082019091526001600160a01b03808416825282166020820152620001af906200034e565b50505062000972565b6001600160a01b0316638b78c6d819819055805f7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a35b50565b620002015f8383620003b6565b6805345cdf77eb68f44c5481810181811015620002255763e5cfe9575f526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52815f526020600c208181540181555080602052600c5160601c5f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3620002875f83836200040b565b5050565b6010620002988162000466565b60208381015160075560408085015160085560608501516009805460ff191660ff90921691909117905560808501518051600a5580830151600b80549284015161ffff92831663ffffffff19948516176201000091841682021790915560a08801518051600c5580860151600d805492870151918516929095169190911792160217905590830151600f55517f85a52584e2a604db198ab2f447cba2fc038a972048381c24b40219ef7a83df70905f90a1505050565b6200035862000499565b8051600480546001600160a01b039283166001600160a01b0319918216179091556020830151600580549190931691161790556040517fe8b17a7524058d1a342afefcf40dad4efc8d3d505c865b90ba810c43cff793e6905f90a150565b6001600160a01b03831615801590620003d757506001600160a01b03821630145b156200040657604051634ae889f760e01b81526001600160a01b03831660048201526024015b60405180910390fd5b505050565b6001600160a01b0382161580156200043357506387a211a2600c9081525f8052602090205415155b15620004065760405163281a1b1360e01b81526001600160a01b03808516600483015283166024820152604401620003fd565b638b78c6d819543314620001f157638b78c6d8600c52335f52806020600c205416620001f1576382b429005f526004601cfd5b638b78c6d819543314620004b4576382b429005f526004601cfd5b565b634e487b7160e01b5f52604160045260245ffd5b60405160a081016001600160401b0381118282101715620004ef57620004ef620004b6565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620005205762000520620004b6565b604052919050565b5f82601f83011262000538575f80fd5b81516001600160401b03811115620005545762000554620004b6565b60206200056a601f8301601f19168201620004f5565b82815285828487010111156200057e575f80fd5b5f5b838110156200059d57858101830151828201840152820162000580565b505f928101909101919091529392505050565b80516001600160a01b0381168114620005c7575f80fd5b919050565b5f805f60608486031215620005df575f80fd5b83516001600160401b0380821115620005f6575f80fd5b9085019060a082880312156200060a575f80fd5b62000614620004ca565b82518281111562000623575f80fd5b620006318982860162000528565b82525060208301518281111562000646575f80fd5b620006548982860162000528565b6020830152506040830151828111156200066c575f80fd5b6200067a8982860162000528565b60408301525060608301518281111562000692575f80fd5b620006a08982860162000528565b60608301525060808301516080820152809550505050620006c460208501620005b0565b9150620006d460408501620005b0565b90509250925092565b600181811c90821680620006f257607f821691505b6020821081036200071157634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156200040657805f5260205f20601f840160051c810160208510156200073e5750805b601f840160051c820191505b818110156200075f575f81556001016200074a565b5050505050565b81516001600160401b03811115620007825762000782620004b6565b6200079a81620007938454620006dd565b8462000717565b602080601f831160018114620007d0575f8415620007b85750858301515b5f19600386901b1c1916600185901b1785556200082a565b5f85815260208120601f198616915b828110156200080057888601518255948401946001909101908401620007df565b50858210156200081e57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52601160045260245ffd5b600181815b808511156200088657815f19048211156200086a576200086a62000832565b808516156200087857918102915b93841c93908002906200084b565b509250929050565b5f826200089e575060016200093b565b81620008ac57505f6200093b565b8160018114620008c55760028114620008d057620008f0565b60019150506200093b565b60ff841115620008e457620008e462000832565b50506001821b6200093b565b5060208310610133831016604e8410600b841016171562000915575081810a6200093b565b62000921838362000846565b805f190482111562000937576200093762000832565b0290505b92915050565b5f6200095160ff8416836200088e565b9392505050565b80820281158282048414176200093b576200093b62000832565b61316580620009805f395ff3fe6080604052600436106102c4575f3560e01c806370a0823111610170578063cfcd8b76116100d1578063de3c3e2c11610087578063f04e283e11610062578063f04e283e14610844578063f2fde38b14610857578063fee81cf41461086a575f80fd5b8063de3c3e2c146107e7578063e29c24fd14610812578063e2cc88a714610825575f80fd5b8063d505accf116100b7578063d505accf14610781578063dbcae73f146107a0578063dd62ed3e146107b3575f80fd5b8063cfcd8b761461072d578063d324657214610762575f80fd5b8063876ad4471161012657806395d89b411161010c57806395d89b41146106e6578063a9059cbb146106fa578063beb0a41614610719575f80fd5b8063876ad4471461068b5780638da5cb5b146106ba575f80fd5b80637233f2be116101565780637233f2be1461062757806379cc67901461063b5780637ecebe001461065a575f80fd5b806370a08231146105ee578063715018a61461061f575f80fd5b8063307770611161022557806342966c68116101db5780635224b55d116101b65780635224b55d146105b257806354d1f13d146105d15780636ca2826b146105d9575f80fd5b806342966c681461054b5780634a4ee7b11461056a578063514e62fc1461057d575f80fd5b806334d1c00a1161020b57806334d1c00a1461048b578063359ecf10146105185780633644e51514610537575f80fd5b8063307770611461045c578063313ce56714610470575f80fd5b80631cd64df41161027a57806323b872dd1161026057806323b872dd1461040457806325692962146104235780632de948071461042b575f80fd5b80631cd64df4146103895780631dcf615e146103be575f80fd5b806318160ddd116102aa57806318160ddd1461033f578063183a4f6e146103615780631c10893f14610376575f80fd5b806306fdde03146102e6578063095ea7b314610310575f80fd5b366102e25760405163668a64f760e11b815260040160405180910390fd5b5f80fd5b3480156102f1575f80fd5b506102fa61089b565b60405161030791906123b5565b60405180910390f35b34801561031b575f80fd5b5061032f61032a3660046123e2565b61092b565b6040519015158152602001610307565b34801561034a575f80fd5b5061035361097a565b604051908152602001610307565b61037461036f36600461240c565b610995565b005b6103746103843660046123e2565b6109a2565b348015610394575f80fd5b5061032f6103a33660046123e2565b638b78c6d8600c9081525f9290925260209091205481161490565b3480156103c9575f80fd5b506004546005546103e4916001600160a01b03908116911682565b604080516001600160a01b03938416815292909116602083015201610307565b34801561040f575f80fd5b5061032f61041e366004612423565b6109b8565b610374610a88565b348015610436575f80fd5b50610353610445366004612461565b638b78c6d8600c9081525f91909152602090205490565b348015610467575f80fd5b50610374610ad5565b34801561047b575f80fd5b5060405160128152602001610307565b348015610496575f80fd5b506006546007546008546009546040805160608082018352600a548252600b5461ffff808216602080860191909152620100009283900482168587015285519384018652600c548452600d54808316918501919091529190910416928101929092526105069594939260ff169186565b6040516103079695949392919061247c565b348015610523575f80fd5b506103536105323660046124e0565b610ae9565b348015610542575f80fd5b50610353610b07565b348015610556575f80fd5b5061037461056536600461240c565b610b83565b6103746105783660046123e2565b610b8d565b348015610588575f80fd5b5061032f6105973660046123e2565b638b78c6d8600c9081525f9290925260209091205416151590565b3480156105bd575f80fd5b506103746105cc366004612657565b610b9f565b610374610c60565b3480156105e4575f80fd5b5061035360035481565b3480156105f9575f80fd5b50610353610608366004612461565b6387a211a2600c9081525f91909152602090205490565b610374610c99565b348015610632575f80fd5b506102fa610cac565b348015610646575f80fd5b506103746106553660046123e2565b610cbb565b348015610665575f80fd5b50610353610674366004612461565b6338377508600c9081525f91909152602090205490565b348015610696575f80fd5b50600e54600f546106a5919082565b60408051928352602083019190915201610307565b3480156106c5575f80fd5b50638b78c6d819545b6040516001600160a01b039091168152602001610307565b3480156106f1575f80fd5b506102fa610cd0565b348015610705575f80fd5b5061032f6107143660046123e2565b610cdf565b348015610724575f80fd5b506102fa610d6c565b348015610738575f80fd5b5061074c61074736600461240c565b610d7b565b6040516103079a999897969594939291906127b5565b34801561076d575f80fd5b5061037461077c366004612881565b610f34565b34801561078c575f80fd5b5061037461079b3660046128a1565b610fb9565b6106ce6107ae36600461240c565b61114c565b3480156107be575f80fd5b506103536107cd36600461290d565b602052637f5e9f20600c9081525f91909152603490205490565b3480156107f2575f80fd5b50610353610801366004612461565b60116020525f908152604090205481565b6106ce610820366004612b5a565b611758565b348015610830575f80fd5b5061037461083f366004612c90565b6118b8565b610374610852366004612461565b61192b565b610374610865366004612461565b611965565b348015610875575f80fd5b50610353610884366004612461565b63389a75e1600c9081525f91909152602090205490565b6060601280546108aa90612ccf565b80601f01602080910402602001604051908101604052809291908181526020018280546108d690612ccf565b80156109215780601f106108f857610100808354040283529160200191610921565b820191905f5260205f20905b81548152906001019060200180831161090457829003601f168201915b5050505050905090565b5f82602052637f5e9f20600c52335f52816034600c2055815f52602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560205fa350600192915050565b5f60035461098f6805345cdf77eb68f44c5490565b03905090565b61099f338261198b565b50565b6109aa611996565b6109b482826119b0565b5050565b5f6109c48484846119bc565b8360601b33602052637f5e9f208117600c526034600c2080546001810115610a0157808511156109fb576313be252b5f526004601cfd5b84810382555b50506387a211a28117600c526020600c20805480851115610a295763f4d678b85f526004601cfd5b84810382555050835f526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350610a7e848484611a0a565b5060019392505050565b5f6202a30067ffffffffffffffff164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a250565b6004610ae081611a62565b61099f33611a86565b5f6002610af581611a62565b610aff8484611ab0565b949350505050565b5f80610b1161089b565b8051906020012090506040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81528160208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015260a081209250505090565b61099f3382611b3e565b610b95611996565b6109b4828261198b565b6010610baa81611bc4565b60208381015160075560408085015160085560608501516009805460ff191660ff90921691909117905560808501518051600a5580830151600b80549284015161ffff92831663ffffffff19948516176201000091841682021790915560a08801518051600c5580860151600d805492870151918516929095169190911792160217905590830151600f55517f85a52584e2a604db198ab2f447cba2fc038a972048381c24b40219ef7a83df70905f90a1505050565b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2565b610ca1611996565b610caa5f611bf5565b565b6060600280546108aa90612ccf565b610cc6823383611c32565b6109b48282611b3e565b6060601380546108aa90612ccf565b5f610ceb3384846119bc565b6387a211a2600c52335f526020600c20805480841115610d125763f4d678b85f526004601cfd5b83810382555050825f526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3610d63338484611a0a565b50600192915050565b6060600180546108aa90612ccf565b601060209081525f9182526040918290208054600182015460028301546003840154600485015460058601548851606081018a5260068801805460ff1682526007890180548c51818d0281018d01909d52808d526001600160a01b03998a169c988a169b978a169a968a16999586169895909416969294919385840193830182828015610e2f57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610e11575b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610ea257602002820191905f5260205f20905f905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411610e735790505b505050919092525050604080516060808201835260098601548252600a86015461ffff808216602080860191909152620100009283900482168587015285519384018652600b8901548452600c890154808316858301529290920416828501528351808501909452600d909601546001600160a01b0381168452600160a01b900460ff1695830195909552929391508a565b6008610f3f81611bc4565b5f6019610f4a61097a565b610f549190612d07565b905080841180610f6357508083115b15610f8157604051630b1af1c560e01b815260040160405180910390fd5b6006849055600e8390556040517f5e61ef6a89edc7c475a1c786c7687a2c66ab5a996d29f9601a78281bf9580a08905f90a150505050565b5f610fc261089b565b80519060200120905084421115610fe057631a15a3cc5f526004601cfd5b6040518860601b60601c98508760601b60601c975065383775081901600e52885f526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528360208401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528a60208401528960408401528860608401528060808401528760a084015260c08320604e526042602c205f528660ff16602052856040528460605260208060805f60015afa8b3d51146110e85763ddafbaef5f526004601cfd5b019055777f5e9f20000000000000000000000000000000000000000088176040526034602c2087905587897f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a360405250505f606052505050505050565b5f805460ff166002036111725760405163c5f2be5160e01b815260040160405180910390fd5b5f805460ff1916600217815582900361119e5760405163aef4e71760e01b815260040160405180910390fd5b5f828152601060205260409020600401546001600160a01b0316156111de576040516310ca6e0960e01b8152600481018390526024015b60405180910390fd5b6040805160028082526060820183525f926020830190803683370190505090505f815f8151811061121157611211612d26565b60200260200101906001600160a01b031690816001600160a01b031681525050308160018151811061124557611245612d26565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092525f918160200160208202803683370190505090506032815f8151811061129557611295612d26565b602002602001019060ff16908160ff16815250505f6112b385611c73565b90505f6115206040518060a00160405280611303856040518060400160405280600981526020017f2028536f6369616c290000000000000000000000000000000000000000000000815250611cb5565b81526020016113476040518060400160405280600781526020017f43485a422d582d0000000000000000000000000000000000000000000000000081525086611cb5565b81526020016001805461135990612ccf565b80601f016020809104026020016040519081016040528092919081815260200182805461138590612ccf565b80156113d05780601f106113a7576101008083540402835291602001916113d0565b820191905f5260205f20905b8154815290600101906020018083116113b357829003601f168201915b50505050508152602001600280546113e790612ccf565b80601f016020809104026020016040519081016040528092919081815260200182805461141390612ccf565b801561145e5780601f106114355761010080835404028352916020019161145e565b820191905f5260205f20905b81548152906001019060200180831161144157829003601f168201915b50505091835250506007546020918201526040805160608082018352600282528184018a905281830189905282518082018452600c548152600d5461ffff80821683880152620100009182900481168387015285519384018652600a548452600b54808216978501979097529504909416928101929092526009549092919060ff166114fc57604080518082019091525f8082526020820152611515565b6040805180820190915233815260095460ff1660208201525b600654600854611d0f565b5f878152601060209081526040918290208351815473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b03928316178355858401516001840180548316918416919091179055938501516002830180548616918316919091179055606085015160038301805486169183169190911790556080850151600483018054861691831691909117905560a085015160058301805490951691161790925560c0830151805160068401805460ff191660ff9092169190911781558183015180519596508695929391926116019260078701920190612256565b506040820151805161161d9160028401916020909101906122c6565b50505060e082015180516009830155602080820151600a8401805460409485015161ffff9081166201000090810263ffffffff1993841695831695909517949094179092556101008701518051600b88015580850151600c88018054928801518516909502919092169190921617179055610120909301518051600d90930180549185015160ff16600160a01b027fffffffffffffffffffffff0000000000000000000000000000000000000000009092166001600160a01b039485161791909117905560808401805183165f9081526011909452928190208990556006549251600354915192169189917fcc3e9264e04b0c3e95caab810e2b79dcf92ad5a919096173776c77ae4f32db119161173691815260200190565b60405180910390a46080015193505050505f805460ff19166001179055919050565b5f805460ff1660020361177e5760405163c5f2be5160e01b815260040160405180910390fd5b5f805460ff191660021790556020868101516040805180820190915260058082527f43485a422d000000000000000000000000000000000000000000000000000000918401919091529181018290209051909111157f779f6a5034e01e3f8c94a4dd8ce33ae89e62528ef26eb9bb20ca5c37a9596fd69091141680156118165750638b78c6d8600c908152335f526020908190205416155b156118345760405163361cb83960e11b815260040160405180910390fd5b5f61184d8787878787600e5f0154600e60010154611d0f565b9050600e5f015481608001516001600160a01b03167fffbb7fa028a13c99395f25007a703011e59272cbf40f7a02823f34629c27ef2760035460405161189591815260200190565b60405180910390a36080015190505f805460ff1916600117905595945050505050565b6118c0611996565b8051600480546001600160a01b0392831673ffffffffffffffffffffffffffffffffffffffff19918216179091556020830151600580549190931691161790556040517fe8b17a7524058d1a342afefcf40dad4efc8d3d505c865b90ba810c43cff793e6905f90a150565b611933611996565b63389a75e1600c52805f526020600c20805442111561195957636f5e88185f526004601cfd5b5f905561099f81611bf5565b61196d611996565b8060601b61198257637448fbae5f526004601cfd5b61099f81611bf5565b6109b482825f611f16565b638b78c6d819543314610caa576382b429005f526004601cfd5b6109b482826001611f16565b6001600160a01b038316158015906119dc57506001600160a01b03821630145b15611a0557604051634ae889f760e01b81526001600160a01b03831660048201526024016111d5565b505050565b6001600160a01b038216158015611a3157506387a211a2600c9081525f8052602090205415155b15611a055760405163281a1b1360e01b81526001600160a01b038085166004830152831660248201526044016111d5565b638b78c6d8600c52335f52806020600c20541661099f576382b429005f526004601cfd5b5f385f384785620186a0f161099f57805f526073600b5360ff6020536016600b47f061099f573838fd5b5f828152601060205260408120600201546001600160a01b031680611ae85760405163252fe3c560e01b815260040160405180910390fd5b5f611af38285611f6d565b905080846001600160a01b0316836001600160a01b03167f0d3436d46d19d0f7b8fe80eef1d937706e673070d9099df32fd119aa611736d260405160405180910390a4949350505050565b611b49825f836119bc565b6387a211a2600c52815f526020600c20805480831115611b705763f4d678b85f526004601cfd5b82900390556805345cdf77eb68f44c805482900390555f8181526001600160a01b0383167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602083a36109b4825f83611a0a565b638b78c6d81954331461099f57638b78c6d8600c52335f52806020600c20541661099f576382b429005f526004601cfd5b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a355565b81602052637f5e9f20600c52825f526034600c2080546001810115611c6c5780831115611c66576313be252b5f526004601cfd5b82810382555b5050505050565b60606080604051019050602081016040525f8152805f19835b928101926030600a8206018453600a900480611c8c575050819003601f19909101908152919050565b6040518251601f19906020810182165b8581015184820152820180611cc5575083518184018360208301165b8681015182820152840180611ce15750505f910183810160208101929092528352603f011660405292915050565b611daf60408051610140810182525f808252602080830182905282840182905260608084018390526080840183905260a084018390528451808201865283815280830182905280860182905260c08501528451808201865283815280830184905280860184905260e08501528451908101855282815280820183905280850183905261010084015283518085019094528184528301529061012082015290565b813414611dd857604051633c0ef5cb60e11b8152346004820152602481018390526044016111d5565b611de23084611fe5565b600454611dfa9030906001600160a01b031685612073565b5f60045f015f9054906101000a90046001600160a01b03166001600160a01b031663bec8acc88a60046001015f9054906101000a90046001600160a01b031630888d8d8d8d6040518963ffffffff1660e01b8152600401611e62989796959493929190612d3a565b6020604051808303815f875af1158015611e7e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ea29190612e8b565b6004549091505f90611ebd906001600160a01b0316836120bc565b9050611ecd81604001515f611f6d565b5084611ed761097a565b01611ee061097a565b1115611eff57604051637ebdee1b60e01b815260040160405180910390fd5b60038054860190559150505b979650505050505050565b638b78c6d8600c52825f526020600c20805483811783611f37575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe265f80a3505050505050565b5f6370a082315f5230602052602060346024601c865afa601f3d1116611f9a576390b8ec185f526004601cfd5b8160145260345190506fa9059cbb0000000000000000000000005f5260205f604460105f875af13d1560015f51141716611fdb576390b8ec185f526004601cfd5b5f60345292915050565b611ff05f83836119bc565b6805345cdf77eb68f44c54818101818110156120135763e5cfe9575f526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52815f526020600c208181540181555080602052600c5160601c5f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a36109b45f8383611a0a565b81601452806034526f095ea7b30000000000000000000000005f5260205f604460105f875af13d1560015f511417166120b357633e3f8f735f526004601cfd5b5f603452505050565b61215c60408051610140810182525f808252602080830182905282840182905260608084018390526080840183905260a084018390528451808201865283815280830182905280860182905260c08501528451808201865283815280830184905280860184905260e08501528451908101855282815280820183905280850183905261010084015283518085019094528184528301529061012082015290565b5f805f805f805f805f808c6001600160a01b03166301b7cc648d6040518263ffffffff1660e01b81526004016121a191906001600160a01b0391909116815260200190565b5f60405180830381865afa1580156121bb573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526121e29190810190613050565b60408051610140810182526001600160a01b039b8c168152998b1660208b0152978a169789019790975294881660608801529287166080870152951660a085015260c084019490945260e08301939093526101008201929092526101208101919091529d9c50505050505050505050505050565b828054828255905f5260205f209081019282156122b6579160200282015b828111156122b6578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190612274565b506122c292915061235e565b5090565b828054828255905f5260205f2090601f016020900481019282156122b6579160200282015f5b8382111561232957835183826101000a81548160ff021916908360ff16021790555092602001926001016020815f010492830192600103026122ec565b80156123555782816101000a81549060ff02191690556001016020815f01049283019260010302612329565b50506122c29291505b5b808211156122c2575f815560010161235f565b5f81518084525f5b818110156123965760208185018101518683018201520161237a565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f6123c76020830184612372565b9392505050565b6001600160a01b038116811461099f575f80fd5b5f80604083850312156123f3575f80fd5b82356123fe816123ce565b946020939093013593505050565b5f6020828403121561241c575f80fd5b5035919050565b5f805f60608486031215612435575f80fd5b8335612440816123ce565b92506020840135612450816123ce565b929592945050506040919091013590565b5f60208284031215612471575f80fd5b81356123c7816123ce565b8681526020808201879052604080830187905260ff86166060840152845160808401528482015161ffff90811660a085015285820151811660c0850152845160e0850152918401518216610100840152830151166101208201526101408101611f0b565b5f80604083850312156124f1575f80fd5b823591506020830135612503816123ce565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156125455761254561250e565b60405290565b6040805190810167ffffffffffffffff811182821017156125455761254561250e565b60405160a0810167ffffffffffffffff811182821017156125455761254561250e565b604051601f8201601f1916810167ffffffffffffffff811182821017156125ba576125ba61250e565b604052919050565b60ff8116811461099f575f80fd5b61ffff8116811461099f575f80fd5b5f606082840312156125ef575f80fd5b6125f7612522565b905081358152602082013561260b816125d0565b6020820152604082013561261e816125d0565b604082015292915050565b5f60408284031215612639575f80fd5b61264161254b565b9050813581526020820135602082015292915050565b5f8082840361018081121561266a575f80fd5b61014080821215612679575f80fd5b604051915060c0820182811067ffffffffffffffff8211171561269e5761269e61250e565b806040525084358252602085013560208301526040850135604083015260608501356126c9816125c2565b60608301526126db86608087016125df565b60808301526126ed8660e087016125df565b60a083015281935061270186828701612629565b925050509250929050565b5f6060830160ff80845116855260208085015160608288015283815180865260808901915083830195505f92505b808310156127635785516001600160a01b0316825294830194600192909201919083019061273a565b50604087810151898303918a01919091528051808352908401955090830191505f905b808210156127a857855185168352948301949183019160019190910190612786565b5090979650505050505050565b5f6101e06001600160a01b03808e168452808d166020850152808c166040850152808b166060850152808a16608085015280891660a0850152508060c08401526128018184018861270c565b865160e0850152602087015161ffff908116610100860152604088015116610120850152915061282e9050565b8351610140830152602084015161ffff90811661016084015260408501511661018083015282516001600160a01b03166101a0830152602083015160ff166101c08301529b9a5050505050505050505050565b5f8060408385031215612892575f80fd5b50508035926020909101359150565b5f805f805f805f60e0888a0312156128b7575f80fd5b87356128c2816123ce565b965060208801356128d2816123ce565b9550604088013594506060880135935060808801356128f0816125c2565b9699959850939692959460a0840135945060c09093013592915050565b5f806040838503121561291e575f80fd5b8235612929816123ce565b91506020830135612503816123ce565b5f82601f830112612948575f80fd5b813567ffffffffffffffff8111156129625761296261250e565b612975601f8201601f1916602001612591565b818152846020838601011115612989575f80fd5b816020850160208301375f918101602001919091529392505050565b5f67ffffffffffffffff8211156129be576129be61250e565b5060051b60200190565b5f82601f8301126129d7575f80fd5b813560206129ec6129e7836129a5565b612591565b8083825260208201915060208460051b870101935086841115612a0d575f80fd5b602086015b84811015612a32578035612a25816125c2565b8352918301918301612a12565b509695505050505050565b5f60608284031215612a4d575f80fd5b612a55612522565b90508135612a62816125c2565b815260208281013567ffffffffffffffff80821115612a7f575f80fd5b818501915085601f830112612a92575f80fd5b8135612aa06129e7826129a5565b81815260059190911b83018401908481019088831115612abe575f80fd5b938501935b82851015612ae5578435612ad6816123ce565b82529385019390850190612ac3565b80868801525050506040850135925080831115612b00575f80fd5b5050612b0e848285016129c8565b60408301525092915050565b5f60408284031215612b2a575f80fd5b612b3261254b565b90508135612b3f816123ce565b81526020820135612b4f816125c2565b602082015292915050565b5f805f805f6101408688031215612b6f575f80fd5b853567ffffffffffffffff80821115612b86575f80fd5b9087019060a0828a031215612b99575f80fd5b612ba161256e565b823582811115612baf575f80fd5b612bbb8b828601612939565b825250602083013582811115612bcf575f80fd5b612bdb8b828601612939565b602083015250604083013582811115612bf2575f80fd5b612bfe8b828601612939565b604083015250606083013582811115612c15575f80fd5b612c218b828601612939565b60608301525060808301356080820152809750506020880135915080821115612c48575f80fd5b50612c5588828901612a3d565b945050612c6587604088016125df565b9250612c748760a088016125df565b9150612c84876101008801612b1a565b90509295509295909350565b5f60408284031215612ca0575f80fd5b612ca861254b565b8235612cb3816123ce565b81526020830135612cc3816123ce565b60208201529392505050565b600181811c90821680612ce357607f821691505b602082108103612d0157634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82612d2157634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b5f6101a08083528a5160a082850152612d57610240850182612372565b91505060208b015161019f1980858403016101c0860152612d788383612372565b925060408d0151915080858403016101e0860152612d968383612372565b925060608d01519150808584030161020086015250612db58282612372565b91505060808b0151610220840152612dd8602084018b6001600160a01b03169052565b6001600160a01b03891660408401528760608401528281036080840152612dff818861270c565b865160a0850152602087015161ffff90811660c086015260408801511660e08501529150612e2a9050565b8351610100830152602084015161ffff90811661012084015260408501511661014083015282516001600160a01b0316610160830152602083015160ff166101808301529998505050505050505050565b8051612e86816123ce565b919050565b5f60208284031215612e9b575f80fd5b81516123c7816123ce565b5f82601f830112612eb5575f80fd5b81516020612ec56129e7836129a5565b8083825260208201915060208460051b870101935086841115612ee6575f80fd5b602086015b84811015612a32578051612efe816125c2565b8352918301918301612eeb565b5f60608284031215612f1b575f80fd5b612f23612522565b90508151612f30816125c2565b815260208281015167ffffffffffffffff80821115612f4d575f80fd5b818501915085601f830112612f60575f80fd5b8151612f6e6129e7826129a5565b81815260059190911b83018401908481019088831115612f8c575f80fd5b938501935b82851015612fb3578451612fa4816123ce565b82529385019390850190612f91565b80868801525050506040850151925080831115612fce575f80fd5b5050612b0e84828501612ea6565b5f60608284031215612fec575f80fd5b612ff4612522565b9050815181526020820151613008816125d0565b6020820152604082015161261e816125d0565b5f6040828403121561302b575f80fd5b61303361254b565b90508151613040816123ce565b81526020820151612b4f816125c2565b5f805f805f805f805f806101e08b8d03121561306a575f80fd5b8a51613075816123ce565b60208c0151909a50613086816123ce565b60408c0151909950613097816123ce565b60608c01519098506130a8816123ce565b60808c01519097506130b9816123ce565b95506130c760a08c01612e7b565b945060c08b015167ffffffffffffffff8111156130e2575f80fd5b6130ee8d828e01612f0b565b9450506130fe8c60e08d01612fdc565b925061310e8c6101408d01612fdc565b915061311e8c6101a08d0161301b565b90509295989b9194979a509295985056fea2646970667358221220794159239f1deb143ed3a080e0bb6e618d2d7f7775a71578db816f68d6c56c5164736f6c634300081600330000000000000000000000000000000000000000000000000000000000000060000000000000000000000000b51b7d01c94ceff686e6463ce1ea461c2bb8276b0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000003b2e0f44000000000000000000000000000000000000000000000000000000000000000b436865657a627572676572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000443485a4200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001768747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000000000000000000000000000000000000000000000000000000000000000001768747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000
Deployed Bytecode
0x6080604052600436106102c4575f3560e01c806370a0823111610170578063cfcd8b76116100d1578063de3c3e2c11610087578063f04e283e11610062578063f04e283e14610844578063f2fde38b14610857578063fee81cf41461086a575f80fd5b8063de3c3e2c146107e7578063e29c24fd14610812578063e2cc88a714610825575f80fd5b8063d505accf116100b7578063d505accf14610781578063dbcae73f146107a0578063dd62ed3e146107b3575f80fd5b8063cfcd8b761461072d578063d324657214610762575f80fd5b8063876ad4471161012657806395d89b411161010c57806395d89b41146106e6578063a9059cbb146106fa578063beb0a41614610719575f80fd5b8063876ad4471461068b5780638da5cb5b146106ba575f80fd5b80637233f2be116101565780637233f2be1461062757806379cc67901461063b5780637ecebe001461065a575f80fd5b806370a08231146105ee578063715018a61461061f575f80fd5b8063307770611161022557806342966c68116101db5780635224b55d116101b65780635224b55d146105b257806354d1f13d146105d15780636ca2826b146105d9575f80fd5b806342966c681461054b5780634a4ee7b11461056a578063514e62fc1461057d575f80fd5b806334d1c00a1161020b57806334d1c00a1461048b578063359ecf10146105185780633644e51514610537575f80fd5b8063307770611461045c578063313ce56714610470575f80fd5b80631cd64df41161027a57806323b872dd1161026057806323b872dd1461040457806325692962146104235780632de948071461042b575f80fd5b80631cd64df4146103895780631dcf615e146103be575f80fd5b806318160ddd116102aa57806318160ddd1461033f578063183a4f6e146103615780631c10893f14610376575f80fd5b806306fdde03146102e6578063095ea7b314610310575f80fd5b366102e25760405163668a64f760e11b815260040160405180910390fd5b5f80fd5b3480156102f1575f80fd5b506102fa61089b565b60405161030791906123b5565b60405180910390f35b34801561031b575f80fd5b5061032f61032a3660046123e2565b61092b565b6040519015158152602001610307565b34801561034a575f80fd5b5061035361097a565b604051908152602001610307565b61037461036f36600461240c565b610995565b005b6103746103843660046123e2565b6109a2565b348015610394575f80fd5b5061032f6103a33660046123e2565b638b78c6d8600c9081525f9290925260209091205481161490565b3480156103c9575f80fd5b506004546005546103e4916001600160a01b03908116911682565b604080516001600160a01b03938416815292909116602083015201610307565b34801561040f575f80fd5b5061032f61041e366004612423565b6109b8565b610374610a88565b348015610436575f80fd5b50610353610445366004612461565b638b78c6d8600c9081525f91909152602090205490565b348015610467575f80fd5b50610374610ad5565b34801561047b575f80fd5b5060405160128152602001610307565b348015610496575f80fd5b506006546007546008546009546040805160608082018352600a548252600b5461ffff808216602080860191909152620100009283900482168587015285519384018652600c548452600d54808316918501919091529190910416928101929092526105069594939260ff169186565b6040516103079695949392919061247c565b348015610523575f80fd5b506103536105323660046124e0565b610ae9565b348015610542575f80fd5b50610353610b07565b348015610556575f80fd5b5061037461056536600461240c565b610b83565b6103746105783660046123e2565b610b8d565b348015610588575f80fd5b5061032f6105973660046123e2565b638b78c6d8600c9081525f9290925260209091205416151590565b3480156105bd575f80fd5b506103746105cc366004612657565b610b9f565b610374610c60565b3480156105e4575f80fd5b5061035360035481565b3480156105f9575f80fd5b50610353610608366004612461565b6387a211a2600c9081525f91909152602090205490565b610374610c99565b348015610632575f80fd5b506102fa610cac565b348015610646575f80fd5b506103746106553660046123e2565b610cbb565b348015610665575f80fd5b50610353610674366004612461565b6338377508600c9081525f91909152602090205490565b348015610696575f80fd5b50600e54600f546106a5919082565b60408051928352602083019190915201610307565b3480156106c5575f80fd5b50638b78c6d819545b6040516001600160a01b039091168152602001610307565b3480156106f1575f80fd5b506102fa610cd0565b348015610705575f80fd5b5061032f6107143660046123e2565b610cdf565b348015610724575f80fd5b506102fa610d6c565b348015610738575f80fd5b5061074c61074736600461240c565b610d7b565b6040516103079a999897969594939291906127b5565b34801561076d575f80fd5b5061037461077c366004612881565b610f34565b34801561078c575f80fd5b5061037461079b3660046128a1565b610fb9565b6106ce6107ae36600461240c565b61114c565b3480156107be575f80fd5b506103536107cd36600461290d565b602052637f5e9f20600c9081525f91909152603490205490565b3480156107f2575f80fd5b50610353610801366004612461565b60116020525f908152604090205481565b6106ce610820366004612b5a565b611758565b348015610830575f80fd5b5061037461083f366004612c90565b6118b8565b610374610852366004612461565b61192b565b610374610865366004612461565b611965565b348015610875575f80fd5b50610353610884366004612461565b63389a75e1600c9081525f91909152602090205490565b6060601280546108aa90612ccf565b80601f01602080910402602001604051908101604052809291908181526020018280546108d690612ccf565b80156109215780601f106108f857610100808354040283529160200191610921565b820191905f5260205f20905b81548152906001019060200180831161090457829003601f168201915b5050505050905090565b5f82602052637f5e9f20600c52335f52816034600c2055815f52602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560205fa350600192915050565b5f60035461098f6805345cdf77eb68f44c5490565b03905090565b61099f338261198b565b50565b6109aa611996565b6109b482826119b0565b5050565b5f6109c48484846119bc565b8360601b33602052637f5e9f208117600c526034600c2080546001810115610a0157808511156109fb576313be252b5f526004601cfd5b84810382555b50506387a211a28117600c526020600c20805480851115610a295763f4d678b85f526004601cfd5b84810382555050835f526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350610a7e848484611a0a565b5060019392505050565b5f6202a30067ffffffffffffffff164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a250565b6004610ae081611a62565b61099f33611a86565b5f6002610af581611a62565b610aff8484611ab0565b949350505050565b5f80610b1161089b565b8051906020012090506040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81528160208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015260a081209250505090565b61099f3382611b3e565b610b95611996565b6109b4828261198b565b6010610baa81611bc4565b60208381015160075560408085015160085560608501516009805460ff191660ff90921691909117905560808501518051600a5580830151600b80549284015161ffff92831663ffffffff19948516176201000091841682021790915560a08801518051600c5580860151600d805492870151918516929095169190911792160217905590830151600f55517f85a52584e2a604db198ab2f447cba2fc038a972048381c24b40219ef7a83df70905f90a1505050565b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2565b610ca1611996565b610caa5f611bf5565b565b6060600280546108aa90612ccf565b610cc6823383611c32565b6109b48282611b3e565b6060601380546108aa90612ccf565b5f610ceb3384846119bc565b6387a211a2600c52335f526020600c20805480841115610d125763f4d678b85f526004601cfd5b83810382555050825f526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3610d63338484611a0a565b50600192915050565b6060600180546108aa90612ccf565b601060209081525f9182526040918290208054600182015460028301546003840154600485015460058601548851606081018a5260068801805460ff1682526007890180548c51818d0281018d01909d52808d526001600160a01b03998a169c988a169b978a169a968a16999586169895909416969294919385840193830182828015610e2f57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610e11575b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610ea257602002820191905f5260205f20905f905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411610e735790505b505050919092525050604080516060808201835260098601548252600a86015461ffff808216602080860191909152620100009283900482168587015285519384018652600b8901548452600c890154808316858301529290920416828501528351808501909452600d909601546001600160a01b0381168452600160a01b900460ff1695830195909552929391508a565b6008610f3f81611bc4565b5f6019610f4a61097a565b610f549190612d07565b905080841180610f6357508083115b15610f8157604051630b1af1c560e01b815260040160405180910390fd5b6006849055600e8390556040517f5e61ef6a89edc7c475a1c786c7687a2c66ab5a996d29f9601a78281bf9580a08905f90a150505050565b5f610fc261089b565b80519060200120905084421115610fe057631a15a3cc5f526004601cfd5b6040518860601b60601c98508760601b60601c975065383775081901600e52885f526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528360208401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528a60208401528960408401528860608401528060808401528760a084015260c08320604e526042602c205f528660ff16602052856040528460605260208060805f60015afa8b3d51146110e85763ddafbaef5f526004601cfd5b019055777f5e9f20000000000000000000000000000000000000000088176040526034602c2087905587897f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a360405250505f606052505050505050565b5f805460ff166002036111725760405163c5f2be5160e01b815260040160405180910390fd5b5f805460ff1916600217815582900361119e5760405163aef4e71760e01b815260040160405180910390fd5b5f828152601060205260409020600401546001600160a01b0316156111de576040516310ca6e0960e01b8152600481018390526024015b60405180910390fd5b6040805160028082526060820183525f926020830190803683370190505090505f815f8151811061121157611211612d26565b60200260200101906001600160a01b031690816001600160a01b031681525050308160018151811061124557611245612d26565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092525f918160200160208202803683370190505090506032815f8151811061129557611295612d26565b602002602001019060ff16908160ff16815250505f6112b385611c73565b90505f6115206040518060a00160405280611303856040518060400160405280600981526020017f2028536f6369616c290000000000000000000000000000000000000000000000815250611cb5565b81526020016113476040518060400160405280600781526020017f43485a422d582d0000000000000000000000000000000000000000000000000081525086611cb5565b81526020016001805461135990612ccf565b80601f016020809104026020016040519081016040528092919081815260200182805461138590612ccf565b80156113d05780601f106113a7576101008083540402835291602001916113d0565b820191905f5260205f20905b8154815290600101906020018083116113b357829003601f168201915b50505050508152602001600280546113e790612ccf565b80601f016020809104026020016040519081016040528092919081815260200182805461141390612ccf565b801561145e5780601f106114355761010080835404028352916020019161145e565b820191905f5260205f20905b81548152906001019060200180831161144157829003601f168201915b50505091835250506007546020918201526040805160608082018352600282528184018a905281830189905282518082018452600c548152600d5461ffff80821683880152620100009182900481168387015285519384018652600a548452600b54808216978501979097529504909416928101929092526009549092919060ff166114fc57604080518082019091525f8082526020820152611515565b6040805180820190915233815260095460ff1660208201525b600654600854611d0f565b5f878152601060209081526040918290208351815473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b03928316178355858401516001840180548316918416919091179055938501516002830180548616918316919091179055606085015160038301805486169183169190911790556080850151600483018054861691831691909117905560a085015160058301805490951691161790925560c0830151805160068401805460ff191660ff9092169190911781558183015180519596508695929391926116019260078701920190612256565b506040820151805161161d9160028401916020909101906122c6565b50505060e082015180516009830155602080820151600a8401805460409485015161ffff9081166201000090810263ffffffff1993841695831695909517949094179092556101008701518051600b88015580850151600c88018054928801518516909502919092169190921617179055610120909301518051600d90930180549185015160ff16600160a01b027fffffffffffffffffffffff0000000000000000000000000000000000000000009092166001600160a01b039485161791909117905560808401805183165f9081526011909452928190208990556006549251600354915192169189917fcc3e9264e04b0c3e95caab810e2b79dcf92ad5a919096173776c77ae4f32db119161173691815260200190565b60405180910390a46080015193505050505f805460ff19166001179055919050565b5f805460ff1660020361177e5760405163c5f2be5160e01b815260040160405180910390fd5b5f805460ff191660021790556020868101516040805180820190915260058082527f43485a422d000000000000000000000000000000000000000000000000000000918401919091529181018290209051909111157f779f6a5034e01e3f8c94a4dd8ce33ae89e62528ef26eb9bb20ca5c37a9596fd69091141680156118165750638b78c6d8600c908152335f526020908190205416155b156118345760405163361cb83960e11b815260040160405180910390fd5b5f61184d8787878787600e5f0154600e60010154611d0f565b9050600e5f015481608001516001600160a01b03167fffbb7fa028a13c99395f25007a703011e59272cbf40f7a02823f34629c27ef2760035460405161189591815260200190565b60405180910390a36080015190505f805460ff1916600117905595945050505050565b6118c0611996565b8051600480546001600160a01b0392831673ffffffffffffffffffffffffffffffffffffffff19918216179091556020830151600580549190931691161790556040517fe8b17a7524058d1a342afefcf40dad4efc8d3d505c865b90ba810c43cff793e6905f90a150565b611933611996565b63389a75e1600c52805f526020600c20805442111561195957636f5e88185f526004601cfd5b5f905561099f81611bf5565b61196d611996565b8060601b61198257637448fbae5f526004601cfd5b61099f81611bf5565b6109b482825f611f16565b638b78c6d819543314610caa576382b429005f526004601cfd5b6109b482826001611f16565b6001600160a01b038316158015906119dc57506001600160a01b03821630145b15611a0557604051634ae889f760e01b81526001600160a01b03831660048201526024016111d5565b505050565b6001600160a01b038216158015611a3157506387a211a2600c9081525f8052602090205415155b15611a055760405163281a1b1360e01b81526001600160a01b038085166004830152831660248201526044016111d5565b638b78c6d8600c52335f52806020600c20541661099f576382b429005f526004601cfd5b5f385f384785620186a0f161099f57805f526073600b5360ff6020536016600b47f061099f573838fd5b5f828152601060205260408120600201546001600160a01b031680611ae85760405163252fe3c560e01b815260040160405180910390fd5b5f611af38285611f6d565b905080846001600160a01b0316836001600160a01b03167f0d3436d46d19d0f7b8fe80eef1d937706e673070d9099df32fd119aa611736d260405160405180910390a4949350505050565b611b49825f836119bc565b6387a211a2600c52815f526020600c20805480831115611b705763f4d678b85f526004601cfd5b82900390556805345cdf77eb68f44c805482900390555f8181526001600160a01b0383167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602083a36109b4825f83611a0a565b638b78c6d81954331461099f57638b78c6d8600c52335f52806020600c20541661099f576382b429005f526004601cfd5b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a355565b81602052637f5e9f20600c52825f526034600c2080546001810115611c6c5780831115611c66576313be252b5f526004601cfd5b82810382555b5050505050565b60606080604051019050602081016040525f8152805f19835b928101926030600a8206018453600a900480611c8c575050819003601f19909101908152919050565b6040518251601f19906020810182165b8581015184820152820180611cc5575083518184018360208301165b8681015182820152840180611ce15750505f910183810160208101929092528352603f011660405292915050565b611daf60408051610140810182525f808252602080830182905282840182905260608084018390526080840183905260a084018390528451808201865283815280830182905280860182905260c08501528451808201865283815280830184905280860184905260e08501528451908101855282815280820183905280850183905261010084015283518085019094528184528301529061012082015290565b813414611dd857604051633c0ef5cb60e11b8152346004820152602481018390526044016111d5565b611de23084611fe5565b600454611dfa9030906001600160a01b031685612073565b5f60045f015f9054906101000a90046001600160a01b03166001600160a01b031663bec8acc88a60046001015f9054906101000a90046001600160a01b031630888d8d8d8d6040518963ffffffff1660e01b8152600401611e62989796959493929190612d3a565b6020604051808303815f875af1158015611e7e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ea29190612e8b565b6004549091505f90611ebd906001600160a01b0316836120bc565b9050611ecd81604001515f611f6d565b5084611ed761097a565b01611ee061097a565b1115611eff57604051637ebdee1b60e01b815260040160405180910390fd5b60038054860190559150505b979650505050505050565b638b78c6d8600c52825f526020600c20805483811783611f37575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe265f80a3505050505050565b5f6370a082315f5230602052602060346024601c865afa601f3d1116611f9a576390b8ec185f526004601cfd5b8160145260345190506fa9059cbb0000000000000000000000005f5260205f604460105f875af13d1560015f51141716611fdb576390b8ec185f526004601cfd5b5f60345292915050565b611ff05f83836119bc565b6805345cdf77eb68f44c54818101818110156120135763e5cfe9575f526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52815f526020600c208181540181555080602052600c5160601c5f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a36109b45f8383611a0a565b81601452806034526f095ea7b30000000000000000000000005f5260205f604460105f875af13d1560015f511417166120b357633e3f8f735f526004601cfd5b5f603452505050565b61215c60408051610140810182525f808252602080830182905282840182905260608084018390526080840183905260a084018390528451808201865283815280830182905280860182905260c08501528451808201865283815280830184905280860184905260e08501528451908101855282815280820183905280850183905261010084015283518085019094528184528301529061012082015290565b5f805f805f805f805f808c6001600160a01b03166301b7cc648d6040518263ffffffff1660e01b81526004016121a191906001600160a01b0391909116815260200190565b5f60405180830381865afa1580156121bb573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526121e29190810190613050565b60408051610140810182526001600160a01b039b8c168152998b1660208b0152978a169789019790975294881660608801529287166080870152951660a085015260c084019490945260e08301939093526101008201929092526101208101919091529d9c50505050505050505050505050565b828054828255905f5260205f209081019282156122b6579160200282015b828111156122b6578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190612274565b506122c292915061235e565b5090565b828054828255905f5260205f2090601f016020900481019282156122b6579160200282015f5b8382111561232957835183826101000a81548160ff021916908360ff16021790555092602001926001016020815f010492830192600103026122ec565b80156123555782816101000a81549060ff02191690556001016020815f01049283019260010302612329565b50506122c29291505b5b808211156122c2575f815560010161235f565b5f81518084525f5b818110156123965760208185018101518683018201520161237a565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f6123c76020830184612372565b9392505050565b6001600160a01b038116811461099f575f80fd5b5f80604083850312156123f3575f80fd5b82356123fe816123ce565b946020939093013593505050565b5f6020828403121561241c575f80fd5b5035919050565b5f805f60608486031215612435575f80fd5b8335612440816123ce565b92506020840135612450816123ce565b929592945050506040919091013590565b5f60208284031215612471575f80fd5b81356123c7816123ce565b8681526020808201879052604080830187905260ff86166060840152845160808401528482015161ffff90811660a085015285820151811660c0850152845160e0850152918401518216610100840152830151166101208201526101408101611f0b565b5f80604083850312156124f1575f80fd5b823591506020830135612503816123ce565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156125455761254561250e565b60405290565b6040805190810167ffffffffffffffff811182821017156125455761254561250e565b60405160a0810167ffffffffffffffff811182821017156125455761254561250e565b604051601f8201601f1916810167ffffffffffffffff811182821017156125ba576125ba61250e565b604052919050565b60ff8116811461099f575f80fd5b61ffff8116811461099f575f80fd5b5f606082840312156125ef575f80fd5b6125f7612522565b905081358152602082013561260b816125d0565b6020820152604082013561261e816125d0565b604082015292915050565b5f60408284031215612639575f80fd5b61264161254b565b9050813581526020820135602082015292915050565b5f8082840361018081121561266a575f80fd5b61014080821215612679575f80fd5b604051915060c0820182811067ffffffffffffffff8211171561269e5761269e61250e565b806040525084358252602085013560208301526040850135604083015260608501356126c9816125c2565b60608301526126db86608087016125df565b60808301526126ed8660e087016125df565b60a083015281935061270186828701612629565b925050509250929050565b5f6060830160ff80845116855260208085015160608288015283815180865260808901915083830195505f92505b808310156127635785516001600160a01b0316825294830194600192909201919083019061273a565b50604087810151898303918a01919091528051808352908401955090830191505f905b808210156127a857855185168352948301949183019160019190910190612786565b5090979650505050505050565b5f6101e06001600160a01b03808e168452808d166020850152808c166040850152808b166060850152808a16608085015280891660a0850152508060c08401526128018184018861270c565b865160e0850152602087015161ffff908116610100860152604088015116610120850152915061282e9050565b8351610140830152602084015161ffff90811661016084015260408501511661018083015282516001600160a01b03166101a0830152602083015160ff166101c08301529b9a5050505050505050505050565b5f8060408385031215612892575f80fd5b50508035926020909101359150565b5f805f805f805f60e0888a0312156128b7575f80fd5b87356128c2816123ce565b965060208801356128d2816123ce565b9550604088013594506060880135935060808801356128f0816125c2565b9699959850939692959460a0840135945060c09093013592915050565b5f806040838503121561291e575f80fd5b8235612929816123ce565b91506020830135612503816123ce565b5f82601f830112612948575f80fd5b813567ffffffffffffffff8111156129625761296261250e565b612975601f8201601f1916602001612591565b818152846020838601011115612989575f80fd5b816020850160208301375f918101602001919091529392505050565b5f67ffffffffffffffff8211156129be576129be61250e565b5060051b60200190565b5f82601f8301126129d7575f80fd5b813560206129ec6129e7836129a5565b612591565b8083825260208201915060208460051b870101935086841115612a0d575f80fd5b602086015b84811015612a32578035612a25816125c2565b8352918301918301612a12565b509695505050505050565b5f60608284031215612a4d575f80fd5b612a55612522565b90508135612a62816125c2565b815260208281013567ffffffffffffffff80821115612a7f575f80fd5b818501915085601f830112612a92575f80fd5b8135612aa06129e7826129a5565b81815260059190911b83018401908481019088831115612abe575f80fd5b938501935b82851015612ae5578435612ad6816123ce565b82529385019390850190612ac3565b80868801525050506040850135925080831115612b00575f80fd5b5050612b0e848285016129c8565b60408301525092915050565b5f60408284031215612b2a575f80fd5b612b3261254b565b90508135612b3f816123ce565b81526020820135612b4f816125c2565b602082015292915050565b5f805f805f6101408688031215612b6f575f80fd5b853567ffffffffffffffff80821115612b86575f80fd5b9087019060a0828a031215612b99575f80fd5b612ba161256e565b823582811115612baf575f80fd5b612bbb8b828601612939565b825250602083013582811115612bcf575f80fd5b612bdb8b828601612939565b602083015250604083013582811115612bf2575f80fd5b612bfe8b828601612939565b604083015250606083013582811115612c15575f80fd5b612c218b828601612939565b60608301525060808301356080820152809750506020880135915080821115612c48575f80fd5b50612c5588828901612a3d565b945050612c6587604088016125df565b9250612c748760a088016125df565b9150612c84876101008801612b1a565b90509295509295909350565b5f60408284031215612ca0575f80fd5b612ca861254b565b8235612cb3816123ce565b81526020830135612cc3816123ce565b60208201529392505050565b600181811c90821680612ce357607f821691505b602082108103612d0157634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82612d2157634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b5f6101a08083528a5160a082850152612d57610240850182612372565b91505060208b015161019f1980858403016101c0860152612d788383612372565b925060408d0151915080858403016101e0860152612d968383612372565b925060608d01519150808584030161020086015250612db58282612372565b91505060808b0151610220840152612dd8602084018b6001600160a01b03169052565b6001600160a01b03891660408401528760608401528281036080840152612dff818861270c565b865160a0850152602087015161ffff90811660c086015260408801511660e08501529150612e2a9050565b8351610100830152602084015161ffff90811661012084015260408501511661014083015282516001600160a01b0316610160830152602083015160ff166101808301529998505050505050505050565b8051612e86816123ce565b919050565b5f60208284031215612e9b575f80fd5b81516123c7816123ce565b5f82601f830112612eb5575f80fd5b81516020612ec56129e7836129a5565b8083825260208201915060208460051b870101935086841115612ee6575f80fd5b602086015b84811015612a32578051612efe816125c2565b8352918301918301612eeb565b5f60608284031215612f1b575f80fd5b612f23612522565b90508151612f30816125c2565b815260208281015167ffffffffffffffff80821115612f4d575f80fd5b818501915085601f830112612f60575f80fd5b8151612f6e6129e7826129a5565b81815260059190911b83018401908481019088831115612f8c575f80fd5b938501935b82851015612fb3578451612fa4816123ce565b82529385019390850190612f91565b80868801525050506040850151925080831115612fce575f80fd5b5050612b0e84828501612ea6565b5f60608284031215612fec575f80fd5b612ff4612522565b9050815181526020820151613008816125d0565b6020820152604082015161261e816125d0565b5f6040828403121561302b575f80fd5b61303361254b565b90508151613040816123ce565b81526020820151612b4f816125c2565b5f805f805f805f805f806101e08b8d03121561306a575f80fd5b8a51613075816123ce565b60208c0151909a50613086816123ce565b60408c0151909950613097816123ce565b60608c01519098506130a8816123ce565b60808c01519097506130b9816123ce565b95506130c760a08c01612e7b565b945060c08b015167ffffffffffffffff8111156130e2575f80fd5b6130ee8d828e01612f0b565b9450506130fe8c60e08d01612fdc565b925061310e8c6101408d01612fdc565b915061311e8c6101a08d0161301b565b90509295989b9194979a509295985056fea2646970667358221220794159239f1deb143ed3a080e0bb6e618d2d7f7775a71578db816f68d6c56c5164736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000b51b7d01c94ceff686e6463ce1ea461c2bb8276b0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000003b2e0f44000000000000000000000000000000000000000000000000000000000000000b436865657a627572676572000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000443485a4200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001768747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000000000000000000000000000000000000000000000000000000000000000001768747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000
-----Decoded View---------------
Arg [0] : _customization (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [1] : _factory (address): 0xb51B7D01c94CEFF686E6463CE1eA461C2bb8276B
Arg [2] : _router (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
-----Encoded View---------------
16 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 000000000000000000000000b51b7d01c94ceff686e6463ce1ea461c2bb8276b
Arg [2] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [7] : 000000000000000000000000000000000000000000000000000000003b2e0f44
Arg [8] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [9] : 436865657a627572676572000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [11] : 43485a4200000000000000000000000000000000000000000000000000000000
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000017
Arg [13] : 68747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000017
Arg [15] : 68747470733a2f2f636865657a6275726765722e6c6f6c000000000000000000
Deployed Bytecode Sourcemap
2366:8525:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5818:28;;-1:-1:-1;;;5818:28:0;;;;;;;;;;;2366:8525;;;;6142:98;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7435:573:5;;;;;;;;;;-1:-1:-1;7435:573:5;;;;;:::i;:::-;;:::i;:::-;;;1311:14:13;;1304:22;1286:41;;1274:2;1259:18;7435:573:5;1146:187:13;6739:164:0;;;;;;;;;;;;;:::i;:::-;;;1484:25:13;;;1472:2;1457:18;6739:164:0;1338:177:13;10127:109:10;;;;;;:::i;:::-;;:::i;:::-;;9588:123;;;;;;:::i;:::-;;:::i;11178:139::-;;;;;;;;;;-1:-1:-1;11178:139:10;;;;;:::i;:::-;10769:15;10763:4;10756:29;;;11257:4;10798:18;;;;10898:4;10882:21;;;10876:28;11280:21;;:30;;11178:139;4182:36:1;;;;;;;;;;-1:-1:-1;4182:36:1;;;;;;-1:-1:-1;;;;;4182:36:1;;;;;;;;;;;-1:-1:-1;;;;;2118:15:13;;;2100:34;;2170:15;;;;2165:2;2150:18;;2143:43;2012:18;4182:36:1;1837:355:13;9969:2191:5;;;;;;;;;;-1:-1:-1;9969:2191:5;;;;;:::i;:::-;;:::i;9021:617:9:-;;;:::i;10567:353:10:-;;;;;;;;;;-1:-1:-1;10567:353:10;;;;;:::i;:::-;10769:15;10763:4;10756:29;;;10627:13;10798:18;;;;10898:4;10882:21;;10876:28;;10567:353;7935:176:0;;;;;;;;;;;;;:::i;5860:82:5:-;;;;;;;;;;-1:-1:-1;5860:82:5;;5933:2;3052:36:13;;3040:2;3025:18;5860:82:5;2910:184:13;4224:36:1;;;;;;;;;;-1:-1:-1;4224:36:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;7661:197:0:-;;;;;;;;;;-1:-1:-1;7661:197:0;;;;;:::i;:::-;;:::i;16620:693:5:-;;;;;;;;;;;;;:::i;7244:81:0:-;;;;;;;;;;-1:-1:-1;7244:81:0;;;;;:::i;:::-;;:::i;9856:125:10:-;;;;;;:::i;:::-;;:::i;10982:134::-;;;;;;;;;;-1:-1:-1;10982:134:10;;;;;:::i;:::-;10769:15;10763:4;10756:29;;;11060:4;10798:18;;;;10898:4;10882:21;;;10876:28;11083:21;:26;;;10982:134;8454:698:0;;;;;;;;;;-1:-1:-1;8454:698:0;;;;;:::i;:::-;;:::i;9720:456:9:-;;;:::i;4081:37:1:-;;;;;;;;;;;;;;;;6548:286:5;;;;;;;;;;-1:-1:-1;6548:286:5;;;;;:::i;:::-;6716:18;6710:4;6703:32;;;6611:14;6748:19;;;;6812:4;6796:21;;6790:28;;6548:286;8762:100:9;;;:::i;6447:85:0:-;;;;;;;;;;;;;:::i;7421:153::-;;;;;;;;;;-1:-1:-1;7421:153:0;;;;;:::i;:::-;;:::i;12800:340:5:-;;;;;;;;;;-1:-1:-1;12800:340:5;;;;;:::i;:::-;13023:17;13017:4;13010:31;;;12860:14;13054:19;;;;13118:4;13102:21;;13096:28;;12800:340;4266:34:1;;;;;;;;;;-1:-1:-1;4266:34:1;;;;;;;;;;;;;8161:25:13;;;8217:2;8202:18;;8195:34;;;;8134:18;4266:34:1;7987:248:13;11408:182:9;;;;;;;;;;-1:-1:-1;;;11556:18:9;11408:182;;;-1:-1:-1;;;;;8404:55:13;;;8386:74;;8374:2;8359:18;11408:182:9;8240:226:13;6246:102:0;;;;;;;;;;;;;:::i;8195:1406:5:-;;;;;;;;;;-1:-1:-1;8195:1406:5;;;;;:::i;:::-;;:::i;6354:87:0:-;;;;;;;;;;;;;:::i;4307:45:1:-;;;;;;;;;;-1:-1:-1;4307:45:1;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;:::i;9276:613:0:-;;;;;;;;;;-1:-1:-1;9276:613:0;;;;;:::i;:::-;;:::i;13324:3215:5:-;;;;;;;;;;-1:-1:-1;13324:3215:5;;;;;:::i;:::-;;:::i;4622:2198:1:-;;;;;;:::i;:::-;;:::i;6929:375:5:-;;;;;;;;;;-1:-1:-1;6929:375:5;;;;;:::i;:::-;7144:4;7137:21;7184:20;7178:4;7171:34;;;7041:14;7218:19;;;;7282:4;7266:21;;7260:28;;6929:375;4358:44:1;;;;;;;;;;-1:-1:-1;4358:44:1;;;;;:::i;:::-;;;;;;;;;;;;;;6902:953;;;;;;:::i;:::-;;:::i;8180:187:0:-;;;;;;;;;;-1:-1:-1;8180:187:0;;;;;:::i;:::-;;:::i;10363:708:9:-;;;;;;:::i;:::-;;:::i;8348:349::-;;;;;;:::i;:::-;;:::i;11693:435::-;;;;;;;;;;-1:-1:-1;11693:435:9;;;;;:::i;:::-;11963:19;11957:4;11950:33;;;11812:14;11996:26;;;;12106:4;12090:21;;12084:28;;11693:435;6142:98:0;6196:13;6228:5;6221:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6142:98;:::o;7435:573:5:-;7509:4;7668:7;7662:4;7655:21;7702:20;7696:4;7689:34;7749:8;7743:4;7736:22;7801:6;7794:4;7788;7778:21;7771:37;7876:6;7870:4;7863:20;7964:4;7958:11;7954:2;7950:20;7940:8;7913:25;7907:4;7901;7896:75;-1:-1:-1;7997:4:5;7435:573;;;;:::o;6739:164:0:-;6792:7;6864:22;;6842:19;6447:18:5;6441:25;;6287:195;6842:19:0;:44;6835:51;;6739:164;:::o;10127:109:10:-;10198:31;10211:10;10223:5;10198:12;:31::i;:::-;10127:109;:::o;9588:123::-;12517:13:9;:11;:13::i;:::-;9680:24:10::1;9692:4;9698:5;9680:11;:24::i;:::-;9588:123:::0;;:::o;9969:2191:5:-;10057:4;10073:38;10094:4;10100:2;10104:6;10073:20;:38::i;:::-;10208:4;10204:2;10200:13;10301:8;10295:4;10288:22;10346:20;10339:5;10336:31;10330:4;10323:45;10418:4;10412;10402:21;10460:13;10454:20;10572:1;10560:10;10556:18;10553:418;;;10688:10;10680:6;10677:22;10674:159;;;10735:10;10729:4;10722:24;10810:4;10804;10797:18;10674:159;10949:6;10937:10;10933:23;10918:13;10911:46;10553:418;;;11067:18;11060:5;11057:29;11051:4;11044:43;11139:4;11133;11123:21;11182:15;11176:22;11272:11;11264:6;11261:23;11258:146;;;11316:10;11310:4;11303:24;11385:4;11379;11372:18;11258:146;11513:6;11500:11;11496:24;11479:15;11472:49;;;11596:2;11590:4;11583:16;11649:4;11643;11633:21;11899:6;11883:13;11877:20;11873:33;11858:13;11851:56;;11975:6;11969:4;11962:20;12069:4;12063:11;12059:2;12055:20;12047:5;12043:2;12039:14;12012:25;12006:4;12000;11995:81;;12095:37;12115:4;12121:2;12125:6;12095:19;:37::i;:::-;-1:-1:-1;12149:4:5;9969:2191;;;;;:::o;9021:617:9:-;9114:15;7972:9;9132:46;;:15;:46;9114:64;;9346:19;9340:4;9333:33;9396:8;9390:4;9383:22;9452:7;9445:4;9439;9429:21;9422:38;9599:8;9552:45;9549:1;9546;9541:67;9248:374;9021:617::o;7935:176:0:-;12731:6:10;11733:18;11745:5;11733:11;:18::i;:::-;8053:51:0::1;8093:10;8053:39;:51::i;7661:197::-:0;7796:7;12683:6:10;11733:18;11745:5;11733:11;:18::i;:::-;7822:29:0::1;7838:7;7847:3;7822:15;:29::i;:::-;7815:36:::0;7661:197;-1:-1:-1;;;;7661:197:0:o;16620:693:5:-;16677:14;;16900:6;:4;:6::i;:::-;16884:24;;;;;;16873:35;;16999:4;16993:11;17060:16;17057:1;17050:27;17111:8;17104:4;17101:1;17097:12;17090:30;17154:13;17147:4;17144:1;17140:12;17133:35;17202:9;17195:4;17192:1;17188:12;17181:31;17246:9;17239:4;17236:1;17232:12;17225:31;17292:4;17289:1;17279:18;17269:28;;;16970:337;16620:693;:::o;7244:81:0:-;7293:25;7299:10;7311:6;7293:5;:25::i;9856:125:10:-;12517:13:9;:11;:13::i;:::-;9949:25:10::1;9962:4;9968:5;9949:12;:25::i;8454:698:0:-:0;12827:6:10;11991:25;12010:5;11991:18;:25::i;:::-;8714:30:0::1;::::0;;::::1;::::0;8682:29;:62;8782:26:::1;::::0;;::::1;::::0;8754:25;:54;8860:53:::1;::::0;::::1;::::0;8818:39;:95;;-1:-1:-1;;8818:95:0::1;;::::0;;::::1;::::0;;;::::1;::::0;;8955:30:::1;::::0;::::1;::::0;8923:62;;:29;:62;;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;::::1;-1:-1:-1::0;;8923:62:0;;;;;;;::::1;::::0;::::1;;::::0;;;9024:27:::1;::::0;::::1;::::0;8995:56;;:26;:56;;;::::1;::::0;;;;;;::::1;::::0;;;::::1;::::0;;;;;;;;;::::1;;;::::0;;9088:25;;::::1;::::0;9061:24;:52;9128:17;::::1;::::0;-1:-1:-1;;9128:17:0::1;8454:698:::0;;;:::o;9720:456:9:-;9922:19;9916:4;9909:33;9968:8;9962:4;9955:22;10020:1;10013:4;10007;9997:21;9990:32;10151:8;10105:44;10102:1;10099;10094:66;9720:456::o;8762:100::-;12517:13;:11;:13::i;:::-;8834:21:::1;8852:1;8834:9;:21::i;:::-;8762:100::o:0;6447:85:0:-;6486:13;6518:7;6511:14;;;;;:::i;7421:153::-;7491:44;7507:7;7516:10;7528:6;7491:15;:44::i;:::-;7545:22;7551:7;7560:6;7545:5;:22::i;6246:102::-;6302:13;6334:7;6327:14;;;;;:::i;8195:1406:5:-;8265:4;8281:44;8302:10;8314:2;8318:6;8281:20;:44::i;:::-;8474:18;8468:4;8461:32;8519:8;8513:4;8506:22;8580:4;8574;8564:21;8623:15;8617:22;8713:11;8705:6;8702:23;8699:146;;;8757:10;8751:4;8744:24;8826:4;8820;8813:18;8699:146;8954:6;8941:11;8937:24;8920:15;8913:49;;;9037:2;9031:4;9024:16;9090:4;9084;9074:21;9340:6;9324:13;9318:20;9314:33;9299:13;9292:56;;9416:6;9410:4;9403:20;9504:4;9498:11;9494:2;9490:20;9480:8;9453:25;9447:4;9441;9436:75;9530:43;9550:10;9562:2;9566:6;9530:19;:43::i;:::-;-1:-1:-1;9590:4:5;8195:1406;;;;:::o;6354:87:0:-;6394:13;6426:8;6419:15;;;;;:::i;4307:45:1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4307:45:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4307:45:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;4307:45:1;;;;-1:-1:-1;;4307:45:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4307:45:1;;;;-1:-1:-1;;;4307:45:1;;;;;;;;;;;;;;-1:-1:-1;4307:45:1;:::o;9276:613:0:-;12779:6:10;11991:25;12010:5;11991:18;:25::i;:::-;9449:28:0::1;9496:2;9480:13;:11;:13::i;:::-;:18;;;;:::i;:::-;9449:49;;9578:20;9555;:43;:101;;;;9636:20;9614:19;:42;9555:101;9538:187;;;9688:26;;-1:-1:-1::0;;;9688:26:0::1;;;;;;;;;;;9538:187;9734:14;:51:::0;;;9795:13:::1;:49:::0;;;9859:23:::1;::::0;::::1;::::0;9734:28:::1;::::0;9859:23:::1;9439:450;9276:613:::0;;;:::o;13324:3215:5:-;13523:16;13720:6;:4;:6::i;:::-;13704:24;;;;;;13693:35;;13896:8;13883:11;13880:25;13877:142;;;13937:10;13931:4;13924:24;14000:4;13994;13987:18;13877:142;14047:4;14041:11;14163:5;14159:2;14155:14;14151:2;14147:23;14138:32;;14210:7;14206:2;14202:16;14198:2;14194:25;14183:36;;14303:39;14297:4;14290:53;14369:5;14363:4;14356:19;14421:4;14415;14405:21;14463:9;14457:16;14541;14538:1;14531:27;14592:8;14585:4;14582:1;14578:12;14571:30;14635:13;14628:4;14625:1;14621:12;14614:35;14683:9;14676:4;14673:1;14669:12;14662:31;14727:9;14720:4;14717:1;14713:12;14706:31;14776:4;14773:1;14763:18;14757:4;14750:32;14845:16;14842:1;14835:27;14896:5;14889:4;14886:1;14882:12;14875:27;14936:7;14929:4;14926:1;14922:12;14915:29;14978:5;14971:4;14968:1;14964:12;14957:27;15018:10;15011:4;15008:1;15004:12;14997:32;15063:8;15056:4;15053:1;15049:12;15042:30;15111:4;15108:1;15098:18;15092:4;15085:32;15206:4;15200;15190:21;15184:4;15177:35;15248:1;15242:4;15238:12;15232:4;15225:26;15277:1;15271:4;15264:15;15305:1;15299:4;15292:15;15365:4;15359;15353;15350:1;15347;15340:5;15329:41;15786:5;15767:16;15761:23;15758:34;15748:159;;15825:10;15819:4;15812:24;15888:4;15882;15875:18;15748:159;15992:18;15974:37;;16190:30;16187:43;;16181:4;16174:57;16267:4;16261;16251:21;16244:36;;;16222:7;16387:5;16360:25;-1:-1:-1;16347:4:5;16340:12;;16335:67;16422:4;16415:15;-1:-1:-1;;16492:1:5;16486:4;16479:15;-1:-1:-1;;;;;;13324:3215:5:o;4622:2198:1:-;4726:7;1182:6:11;;;;1192:1;1182:11;1178:69;;1216:20;;-1:-1:-1;;;1216:20:11;;;;;;;;;;;1178:69;1256:6;:10;;-1:-1:-1;;1256:10:11;1265:1;1256:10;;;4783:11:1;;;4779:69:::1;;4817:20;;-1:-1:-1::0;;;4817:20:1::1;;;;;;;;;;;4779:69;4950:1;4909:20:::0;;;:12:::1;:20;::::0;;;;:29:::1;;::::0;-1:-1:-1;;;;;4909:29:1::1;:43:::0;4905:107:::1;;4975:26;::::0;-1:-1:-1;;;4975:26:1;;::::1;::::0;::::1;1484:25:13::0;;;1457:18;;4975:26:1::1;;;;;;;;4905:107;5145:16;::::0;;5159:1:::1;5145:16:::0;;;;;::::1;::::0;;5113:29:::1;::::0;5145:16:::1;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;-1:-1:-1;5145:16:1::1;5113:48;;5197:1;5171:12;5184:1;5171:15;;;;;;;;:::i;:::-;;;;;;:28;-1:-1:-1::0;;;;;5171:28:1::1;;;-1:-1:-1::0;;;;;5171:28:1::1;;;::::0;::::1;5235:4;5209:12;5222:1;5209:15;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;5209:31:1;;;::::1;:15;::::0;;::::1;::::0;;;;;;;:31;5311:14:::1;::::0;;5323:1:::1;5311:14:::0;;;;;::::1;::::0;;;5279:29:::1;::::0;5311:14:::1;;;;;;;;;;;::::0;-1:-1:-1;5311:14:1::1;5279:46;;5355:2;5335:14;5350:1;5335:17;;;;;;;;:::i;:::-;;;;;;:22;;;;;;;;;::::0;::::1;5431:26;5460:17;:6;:15;:17::i;:::-;5431:46;;5488:18;5509:986;5538:291;;;;;;;;5581:43;5598:12;5581:43;;;;;;;;;;;;;;;;::::0;:16:::1;:43::i;:::-;5538:291;;;;5650:41;;;;;;;;;;;;;;;;;::::0;5678:12:::1;5650:16;:41::i;:::-;5538:291;;;;5718:8;5538:291;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5752:7;5538:291;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;5538:291:1;;;-1:-1:-1;;5785:29:1;;5538:291:::1;::::0;;::::1;::::0;5843:165:::1;::::0;;::::1;::::0;;::::1;::::0;;5900:1:::1;5843:165:::0;;;;::::1;::::0;;;;;;;;;5509:986;;;;::::1;::::0;;6022:26;5509:986;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;;;;::::1;::::0;;6062:29;5509:986;;;;;;;::::1;::::0;;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;;;;;;6105:39;;5843:165;;5509:986;;5843:165:::1;6105:39;:299;;6343:61;::::0;;;;::::1;::::0;;;-1:-1:-1;6343:61:1;;;::::1;::::0;::::1;::::0;6105:299:::1;;;6167:157;::::0;;;;::::1;::::0;;;6219:10:::1;6167:157:::0;;6266:39;;::::1;;6167:157;::::0;::::1;::::0;6105:299:::1;6418:14;:28:::0;6460:25;;5509:15:::1;:986::i;:::-;6529:20;::::0;;;:12:::1;:20;::::0;;;;;;;;:28;;;;-1:-1:-1;;6529:28:1;;::::1;-1:-1:-1::0;;;;;6529:28:1;;::::1;;::::0;;;;::::1;::::0;-1:-1:-1;6529:28:1;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;::::1;;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;-1:-1:-1;;6529:28:1::1;;::::0;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;;;;;-1:-1:-1;6529:28:1;;;;;;::::1;::::0;;;;;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;6529:28:1::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;;;6529:28:1::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;-1:-1:-1::0;;6529:28:1;;;;;::::1;::::0;;;;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;::::1;::::0;::::1;;-1:-1:-1::0;;;6529:28:1::1;::::0;;;;-1:-1:-1;;;;;6529:28:1;;::::1;::::0;;;;::::1;::::0;;6577:14:::1;::::0;::::1;::::0;;6567:25;::::1;6529:28;6567:25:::0;;;:9:::1;:25:::0;;;;;;;:34;;;6698:14:::1;:28:::0;6670:14;;6740:22:::1;::::0;6617:155;;;::::1;::::0;6595:6;;6617:155:::1;::::0;::::1;::::0;1484:25:13;;1472:2;1457:18;;1338:177;6617:155:1::1;;;;;;;;6798:14;;::::0;;-1:-1:-1;;;;1287:6:11;:10;;-1:-1:-1;;1287:10:11;1296:1;1287:10;;;4622:2198:1;;-1:-1:-1;4622:2198:1:o;6902:953::-;7191:7;1182:6:11;;;;1192:1;1182:11;1178:69;;1216:20;;-1:-1:-1;;;1216:20:11;;;;;;;;;;;1178:69;1256:6;:10;;-1:-1:-1;;1256:10:11;1265:1;1256:10;;;7248:21:1::1;::::0;;::::1;::::0;7227:52:::1;::::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;27298:18:8;;;27288:43;;;27230:14;;-1:-1:-1;;;27206:40:8;27353:42;27264:149;;;27185:242;7227:107:1::1;;;;-1:-1:-1::0;10769:15:10;10763:4;10756:29;;;7307:10:1::1;11060:4:10::0;10798:18;12875:6:::1;10882:21:::0;;;;10876:28;11083:21;:26;7227:107:1::1;7210:191;;;7366:24;;-1:-1:-1::0;;;7366:24:1::1;;;;;;;;;;;7210:191;7411:18;7432:218;7461:14;7489:10;7513:4;7531:7;7552:9;7575:13;:27;;;7616:13;:24;;;7432:15;:218::i;:::-;7411:239;;7734:13;:27;;;7706:5;:14;;;-1:-1:-1::0;;;;;7666:141:1::1;;7775:22;;7666:141;;;;1484:25:13::0;;1472:2;1457:18;;1338:177;7666:141:1::1;;;;;;;;7833:14;;::::0;;-1:-1:-1;1287:6:11;:10;;-1:-1:-1;;1287:10:11;1296:1;1287:10;;;6902:953:1;;-1:-1:-1;;;;;6902:953:1:o;8180:187:0:-;12517:13:9;:11;:13::i;:::-;8290:32:0;;:14:::1;:32:::0;;-1:-1:-1;;;;;8290:32:0;;::::1;-1:-1:-1::0;;8290:32:0;;::::1;;::::0;;;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;::::1;;::::0;;8337:23:::1;::::0;::::1;::::0;8290:32:::1;::::0;8337:23:::1;8180:187:::0;:::o;10363:708:9:-;12517:13;:11;:13::i;:::-;10597:19:::1;10591:4;10584:33;10643:12;10637:4;10630:26;10705:4;10699;10689:21;10811:12;10805:19;10792:11;10789:36;10786:157;;;10857:10;10851:4;10844:24;10924:4;10918;10911:18;10786:157;11020:1;10999:23:::0;;11041::::1;11051:12:::0;11041:9:::1;:23::i;8348:349::-:0;12517:13;:11;:13::i;:::-;8520:8:::1;8516:2;8512:17;8502:150;;8562:10;8556:4;8549:24;8633:4;8627;8620:18;8502:150;8671:19;8681:8;8671:9;:19::i;4304:117:10:-:0;4382:32;4395:4;4401:5;4408;4382:12;:32::i;7292:355:9:-;-1:-1:-1;;7498:18:9;7488:8;7485:32;7475:156;;7550:10;7544:4;7537:24;7612:4;7606;7599:18;4053:115:10;4130:31;4143:4;4149:5;4156:4;4130:12;:31::i;10178:352:0:-;-1:-1:-1;;;;;10430:18:0;;;;;;:41;;-1:-1:-1;;;;;;10452:19:0;;10466:4;10452:19;10430:41;10426:98;;;10494:19;;-1:-1:-1;;;10494:19:0;;-1:-1:-1;;;;;8404:55:13;;10494:19:0;;;8386:74:13;8359:18;;10494:19:0;8240:226:13;10426:98:0;10178:352;;;:::o;10536:353::-;-1:-1:-1;;;;;10773:16:0;;;:45;;;;-1:-1:-1;6716:18:5;6710:4;6703:32;;;10817:1:0;6748:19:5;;6812:4;6796:21;;6790:28;10793:25:0;;10773:45;10769:114;;;10841:31;;-1:-1:-1;;;10841:31:0;;-1:-1:-1;;;;;2118:15:13;;;10841:31:0;;;2100:34:13;2170:15;;2150:18;;;2143:43;2012:18;;10841:31:0;1837:355:13;4495:554:10;4680:15;4674:4;4667:29;4722:8;4716:4;4709:22;4913:5;4905:4;4899;4889:21;4883:28;4879:40;4869:164;;4952:10;4946:4;4939:24;5014:4;5008;5001:18;6322:606:12;6581:4;6569:10;6563:4;6551:10;6536:13;6532:2;6510:20;6505:81;6495:417;;6619:2;6613:4;6606:16;6692:4;6686;6678:19;6748:4;6742;6734:19;6834:4;6828;6813:13;6806:33;6796:79;;6862:10;6850;6843:30;9963:402:1;10058:7;10100:21;;;:12;:21;;;;;:26;;;-1:-1:-1;;;;;10100:26:1;;10137:72;;10182:16;;-1:-1:-1;;;10182:16:1;;;;;;;;;;;10137:72;10218:14;10235:42;10267:4;10273:3;10235:31;:42::i;:::-;10218:59;;10328:6;10323:3;-1:-1:-1;;;;;10292:43:1;10317:4;-1:-1:-1;;;;;10292:43:1;;;;;;;;;;;10352:6;9963:402;-1:-1:-1;;;;9963:402:1:o;19295:1119:5:-;19367:46;19388:4;19402:1;19406:6;19367:20;:46::i;:::-;19562:18;19556:4;19549:32;19607:4;19601;19594:18;19664:4;19658;19648:21;19707:15;19701:22;19797:11;19789:6;19786:23;19783:146;;;19841:10;19835:4;19828:24;19910:4;19904;19897:18;19783:146;20021:24;;;19997:49;;20156:18;20150:25;;20146:38;;;20119:66;;-1:-1:-1;20240:20:5;;;-1:-1:-1;;;;;20317:22:5;;20290:25;20284:4;-1:-1:-1;20273:70:5;20362:45;20382:4;20396:1;20400:6;20362:19;:45::i;5219:802:10:-;-1:-1:-1;;5507:27:10;5497:8;5494:41;5484:521;;5610:15;5604:4;5597:29;5656:8;5650:4;5643:22;5859:5;5851:4;5845;5835:21;5829:28;5825:40;5815:176;;5902:10;5896:4;5889:24;5968:4;5962;5955:18;6145:1089:9;-1:-1:-1;;7093:16:9;;-1:-1:-1;;;;;6941:26:9;;;;;;7053:38;7050:1;;7042:78;7177:27;6145:1089::o;22532:947:5:-;22773:7;22767:4;22760:21;22807:20;22801:4;22794:34;22854:5;22848:4;22841:19;22910:4;22904;22894:21;22952:13;22946:20;23064:1;23052:10;23048:18;23045:418;;;23180:10;23172:6;23169:22;23166:159;;;23227:10;23221:4;23214:24;23302:4;23296;23289:18;23166:159;23441:6;23429:10;23425:23;23410:13;23403:46;23045:418;;;22532:947;;;:::o;1551:1641:8:-;1607:17;2052:4;2045;2039:11;2035:22;2028:29;;2151:4;2146:3;2142:14;2136:4;2129:28;2232:1;2227:3;2220:14;2333:3;2363:1;2359:6;2572:5;2554:402;2610:11;;;;2791:2;2805;2795:13;;2787:22;2610:11;2774:36;2897:2;2887:13;;2917:25;2554:402;2917:25;-1:-1:-1;;2984:13:8;;;-1:-1:-1;;3097:14:8;;;3157:19;;;3097:14;1551:1641;-1:-1:-1;1551:1641:8:o;36617:1365::-;36863:4;36857:11;36896:8;;-1:-1:-1;;36825:9:8;37004:4;36991:18;;36987:26;;36972:210;37068:9;;;37062:16;37046:14;;;37039:40;37101:9;;37146:22;36972:210;37146:22;36976:39;37216:1;37210:8;37257:7;37249:6;37245:20;37372:1;37365:4;37356:7;37352:18;37348:26;37333:210;37429:9;;;37423:16;37407:14;;;37400:40;37462:9;;37507:22;37333:210;37507:22;-1:-1:-1;;37732:1:8;37575:21;;37621:35;;;37637:4;37621:35;;37719:15;;;;37781:27;;37946:15;;37942:23;37936:4;37929:37;37629:6;36617:1365;-1:-1:-1;;36617:1365:8:o;8144:1732:1:-;8468:12;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8468:12:1;8539:11;8526:9;:24;8522:109;;8573:47;;-1:-1:-1;;;8573:47:1;;8597:9;8573:47;;;8161:25:13;8202:18;;;8195:34;;;8134:18;;8573:47:1;7987:248:13;8522:109:1;8809:36;8823:4;8830:14;8809:5;:36::i;:::-;8987:14;:22;8911:137;;8960:4;;-1:-1:-1;;;;;8987:22:1;9024:14;8911:27;:137::i;:::-;9087:20;9110:14;:22;;;;;;;;;;-1:-1:-1;;;;;9110:22:1;-1:-1:-1;;;;;9110:38:1;;9162:14;9190;:21;;;;;;;;;;-1:-1:-1;;;;;9190:21:1;9233:4;9252:14;9280:10;9304:4;9322:7;9343:9;9110:252;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9429:14;:22;9087:275;;-1:-1:-1;9399:18:1;;9420:46;;-1:-1:-1;;;;;9429:22:1;9087:275;9420:8;:46::i;:::-;9399:67;;9503:64;9543:5;:10;;;9564:1;9503:31;:64::i;:::-;;9687:14;9671:13;:11;:13::i;:::-;:30;9655:13;:11;:13::i;:::-;:46;9651:108;;;9728:16;;-1:-1:-1;;;9728:16:1;;;;;;;;;;;9651:108;9797:22;;;:39;;9772:64;;9864:5;-1:-1:-1;;8144:1732:1;;;;;;;;;;:::o;2952:967:10:-;3118:15;3112:4;3105:29;3160:4;3154;3147:18;3210:4;3204;3194:21;3288:8;3282:15;3395:5;3386:7;3383:18;3639:2;3629:62;;-1:-1:-1;3669:19:10;;;3656:33;;3629:62;3763:7;3753:8;3746:25;3895:7;3887:4;3881:11;3877:2;3873:20;3841:30;3838:1;3835;3830:73;;;;2952:967;;;:::o;12425:1612:12:-;12495:14;12600:10;12594:4;12587:24;12693:9;12687:4;12680:23;13053:4;13047;13041;13035;13028:5;13021;13010:48;12952:4;12934:16;12931:26;12846:230;12819:386;;13122:10;13116:4;13109:24;13186:4;13180;13173:18;12819:386;13231:2;13225:4;13218:16;13291:4;13285:11;13275:21;;13383:34;13377:4;13370:48;13772:4;13766;13760;13754;13751:1;13744:5;13737;13732:45;13666:16;13659:24;13655:1;13648:4;13642:11;13639:18;13636:48;13551:244;13524:400;;13841:10;13835:4;13828:24;13905:4;13899;13892:18;13524:400;13950:1;13944:4;13937:15;12425:1612;;;;:::o;17717:1172:5:-;17787:44;17816:1;17820:2;17824:6;17787:20;:44::i;:::-;17938:18;17932:25;18017:6;17998:17;17994:30;18114:17;18096:16;18093:39;18090:162;;;18164:10;18158:4;18151:24;18233:4;18227;18220:18;18090:162;18339:16;18319:18;18312:44;;;18442:18;18436:4;18429:32;18487:2;18481:4;18474:16;18540:4;18534;18524:21;18656:6;18640:13;18634:20;18630:33;18615:13;18608:56;;18732:6;18726:4;18719:20;18813:4;18807:11;18803:2;18799:20;18796:1;18769:25;18763:4;18757;18752:68;18839:43;18867:1;18871:2;18875:6;18839:19;:43::i;14171:936:12:-;14333:2;14327:4;14320:16;14390:6;14384:4;14377:20;14455:34;14449:4;14442:48;14843:4;14837;14831;14825;14822:1;14815:5;14808;14803:45;14737:16;14730:24;14726:1;14719:4;14713:11;14710:18;14707:48;14622:244;14595:399;;14912:10;14906:4;14899:24;14975:4;14969;14962:18;14595:399;15020:1;15014:4;15007:15;14171:936;;;:::o;1391:993:2:-;1506:12;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1506:12:2;1544:23;1581:22;1617:20;1651:16;1681:17;1712:18;1744:35;1793:27;1834:30;1878:33;1924:8;-1:-1:-1;;;;;1924:23:2;;1948:12;1924:37;;;;;;;;;;;;;;-1:-1:-1;;;;;8404:55:13;;;;8386:74;;8374:2;8359:18;;8240:226;1924:37:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1924:37:2;;;;;;;;;;;;:::i;:::-;1991:386;;;;;;;;-1:-1:-1;;;;;1991:386:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1391:993;-1:-1:-1;;;;;;;;;;;;;1391:993:2:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:423:13;56:3;94:5;88:12;121:6;116:3;109:19;146:1;156:162;170:6;167:1;164:13;156:162;;;232:4;288:13;;;284:22;;278:29;260:11;;;256:20;;249:59;185:12;156:162;;;160:3;363:1;356:4;347:6;342:3;338:16;334:27;327:38;426:4;419:2;415:7;410:2;402:6;398:15;394:29;389:3;385:39;381:50;374:57;;;14:423;;;;:::o;442:220::-;591:2;580:9;573:21;554:4;611:45;652:2;641:9;637:18;629:6;611:45;:::i;:::-;603:53;442:220;-1:-1:-1;;;442:220:13:o;667:154::-;-1:-1:-1;;;;;746:5:13;742:54;735:5;732:65;722:93;;811:1;808;801:12;826:315;894:6;902;955:2;943:9;934:7;930:23;926:32;923:52;;;971:1;968;961:12;923:52;1010:9;997:23;1029:31;1054:5;1029:31;:::i;:::-;1079:5;1131:2;1116:18;;;;1103:32;;-1:-1:-1;;;826:315:13:o;1520:180::-;1579:6;1632:2;1620:9;1611:7;1607:23;1603:32;1600:52;;;1648:1;1645;1638:12;1600:52;-1:-1:-1;1671:23:13;;1520:180;-1:-1:-1;1520:180:13:o;2197:456::-;2274:6;2282;2290;2343:2;2331:9;2322:7;2318:23;2314:32;2311:52;;;2359:1;2356;2349:12;2311:52;2398:9;2385:23;2417:31;2442:5;2417:31;:::i;:::-;2467:5;-1:-1:-1;2524:2:13;2509:18;;2496:32;2537:33;2496:32;2537:33;:::i;:::-;2197:456;;2589:7;;-1:-1:-1;;;2643:2:13;2628:18;;;;2615:32;;2197:456::o;2658:247::-;2717:6;2770:2;2758:9;2749:7;2745:23;2741:32;2738:52;;;2786:1;2783;2776:12;2738:52;2825:9;2812:23;2844:31;2869:5;2844:31;:::i;3400:728::-;3815:25;;;3871:2;3856:18;;;3849:34;;;3914:2;3899:18;;;3892:34;;;3974:4;3962:17;;3957:2;3942:18;;3935:45;3180:12;;4046:3;4031:19;;3168:25;3228:16;;;3222:23;3264:6;3302:21;;;3286:14;;;3279:45;3366:16;;;3360:23;3356:32;;3340:14;;;3333:56;3180:12;;4117:3;4102:19;;3168:25;3228:16;;;3222:23;3302:21;;3286:14;;;3279:45;3366:16;;3360:23;3356:32;3340:14;;;3333:56;3802:3;3787:19;;4060:62;3099:296;4133:315;4201:6;4209;4262:2;4250:9;4241:7;4237:23;4233:32;4230:52;;;4278:1;4275;4268:12;4230:52;4314:9;4301:23;4291:33;;4374:2;4363:9;4359:18;4346:32;4387:31;4412:5;4387:31;:::i;:::-;4437:5;4427:15;;;4133:315;;;;;:::o;4635:127::-;4696:10;4691:3;4687:20;4684:1;4677:31;4727:4;4724:1;4717:15;4751:4;4748:1;4741:15;4767:253;4839:2;4833:9;4881:4;4869:17;;4916:18;4901:34;;4937:22;;;4898:62;4895:88;;;4963:18;;:::i;:::-;4999:2;4992:22;4767:253;:::o;5025:257::-;5097:4;5091:11;;;5129:17;;5176:18;5161:34;;5197:22;;;5158:62;5155:88;;;5223:18;;:::i;5287:253::-;5359:2;5353:9;5401:4;5389:17;;5436:18;5421:34;;5457:22;;;5418:62;5415:88;;;5483:18;;:::i;5545:275::-;5616:2;5610:9;5681:2;5662:13;;-1:-1:-1;;5658:27:13;5646:40;;5716:18;5701:34;;5737:22;;;5698:62;5695:88;;;5763:18;;:::i;:::-;5799:2;5792:22;5545:275;;-1:-1:-1;5545:275:13:o;5825:114::-;5909:4;5902:5;5898:16;5891:5;5888:27;5878:55;;5929:1;5926;5919:12;5944:117;6029:6;6022:5;6018:18;6011:5;6008:29;5998:57;;6051:1;6048;6041:12;6066:499;6128:5;6176:4;6164:9;6159:3;6155:19;6151:30;6148:50;;;6194:1;6191;6184:12;6148:50;6216:22;;:::i;:::-;6207:31;;6274:9;6261:23;6254:5;6247:38;6337:2;6326:9;6322:18;6309:32;6350;6374:7;6350:32;:::i;:::-;6409:2;6398:14;;6391:31;6474:2;6459:18;;6446:32;6487;6446;6487;:::i;:::-;6546:2;6535:14;;6528:31;6539:5;6066:499;-1:-1:-1;;6066:499:13:o;6570:288::-;6630:5;6678:4;6666:9;6661:3;6657:19;6653:30;6650:50;;;6696:1;6693;6686:12;6650:50;6718:22;;:::i;:::-;6709:31;;6776:9;6763:23;6756:5;6749:38;6847:2;6836:9;6832:18;6819:32;6814:2;6807:5;6803:14;6796:56;6570:288;;;;:::o;6863:1119::-;6992:6;7000;7044:9;7035:7;7031:23;7074:3;7070:2;7066:12;7063:32;;;7091:1;7088;7081:12;7063:32;7114:6;7140:2;7136;7132:11;7129:31;;;7156:1;7153;7146:12;7129:31;7189:2;7183:9;7169:23;;7231:4;7223:6;7219:17;7302:6;7290:10;7287:22;7266:18;7254:10;7251:34;7248:62;7245:88;;;7313:18;;:::i;:::-;7353:10;7349:2;7342:22;;7401:9;7388:23;7380:6;7373:39;7473:2;7462:9;7458:18;7445:32;7440:2;7432:6;7428:15;7421:57;7539:2;7528:9;7524:18;7511:32;7506:2;7498:6;7494:15;7487:57;7594:2;7583:9;7579:18;7566:32;7607:29;7630:5;7607:29;:::i;:::-;7664:2;7652:15;;7645:30;7709:63;7764:7;7758:3;7743:19;;7709:63;:::i;:::-;7703:3;7695:6;7691:16;7684:89;7808:63;7863:7;7857:3;7846:9;7842:19;7808:63;:::i;:::-;7801:4;7793:6;7789:17;7782:90;7891:6;7881:16;;7916:60;7968:7;7963:2;7952:9;7948:18;7916:60;:::i;:::-;7906:70;;;;6863:1119;;;;;:::o;8471:1246::-;8531:3;8570:4;8565:3;8561:14;8594:4;8637;8629:5;8623:12;8619:23;8614:3;8607:36;8662:4;8712:2;8705:5;8701:14;8695:21;8746:4;8741:2;8736:3;8732:12;8725:26;8773:4;8806:12;8800:19;8841:6;8835:4;8828:20;8875:3;8870;8866:13;8857:22;;8920:2;8906:12;8902:21;8888:35;;8941:1;8932:10;;8951:224;8965:6;8962:1;8959:13;8951:224;;;9032:13;;-1:-1:-1;;;;;9028:62:13;9014:77;;9150:15;;;;8987:1;8980:9;;;;;9113:14;;;;8951:224;;;-1:-1:-1;9223:4:13;9212:16;;;9206:23;9261:15;;;9245:14;;;9238:39;;;;9329:21;;9359:23;;;9439;;;;-1:-1:-1;9400:14:13;;;;-1:-1:-1;;;9492:198:13;9508:8;9503:3;9500:17;9492:198;;;9581:15;;9577:24;;9563:39;;9663:17;;;;9624:14;;;;9536:1;9527:11;;;;;9492:198;;;-1:-1:-1;9706:5:13;;8471:1246;-1:-1:-1;;;;;;;8471:1246:13:o;9944:1352::-;10558:4;10587:3;-1:-1:-1;;;;;10690:2:13;10682:6;10678:15;10667:9;10660:34;10742:2;10734:6;10730:15;10725:2;10714:9;10710:18;10703:43;10794:2;10786:6;10782:15;10777:2;10766:9;10762:18;10755:43;10846:2;10838:6;10834:15;10829:2;10818:9;10814:18;10807:43;10899:2;10891:6;10887:15;10881:3;10870:9;10866:19;10859:44;10952:2;10944:6;10940:15;10934:3;10923:9;10919:19;10912:44;;10993:2;10987:3;10976:9;10972:19;10965:31;11013:63;11072:2;11061:9;11057:18;11049:6;11013:63;:::i;:::-;3180:12;;11142:3;11127:19;;3168:25;3239:4;3228:16;;3222:23;3264:6;3302:21;;;3286:14;;;3279:45;3377:4;3366:16;;3360:23;3356:32;3340:14;;;3333:56;11005:71;-1:-1:-1;11085:62:13;;-1:-1:-1;3099:296:13;11085:62;3180:12;;11213:3;11198:19;;3168:25;3239:4;3228:16;;3222:23;3264:6;3302:21;;;3286:14;;;3279:45;3377:4;3366:16;;3360:23;3356:32;3340:14;;;3333:56;9808:12;;-1:-1:-1;;;;;9804:61:13;11285:3;11270:19;;9792:74;9919:4;9908:16;;9902:23;9927:4;9898:34;9882:14;;;9875:58;9944:1352;;;;;;;;;;;;;:::o;11301:248::-;11369:6;11377;11430:2;11418:9;11409:7;11405:23;11401:32;11398:52;;;11446:1;11443;11436:12;11398:52;-1:-1:-1;;11469:23:13;;;11539:2;11524:18;;;11511:32;;-1:-1:-1;11301:248:13:o;11554:801::-;11665:6;11673;11681;11689;11697;11705;11713;11766:3;11754:9;11745:7;11741:23;11737:33;11734:53;;;11783:1;11780;11773:12;11734:53;11822:9;11809:23;11841:31;11866:5;11841:31;:::i;:::-;11891:5;-1:-1:-1;11948:2:13;11933:18;;11920:32;11961:33;11920:32;11961:33;:::i;:::-;12013:7;-1:-1:-1;12067:2:13;12052:18;;12039:32;;-1:-1:-1;12118:2:13;12103:18;;12090:32;;-1:-1:-1;12174:3:13;12159:19;;12146:33;12188:31;12146:33;12188:31;:::i;:::-;11554:801;;;;-1:-1:-1;11554:801:13;;;;12238:7;12292:3;12277:19;;12264:33;;-1:-1:-1;12344:3:13;12329:19;;;12316:33;;11554:801;-1:-1:-1;;11554:801:13:o;12360:388::-;12428:6;12436;12489:2;12477:9;12468:7;12464:23;12460:32;12457:52;;;12505:1;12502;12495:12;12457:52;12544:9;12531:23;12563:31;12588:5;12563:31;:::i;:::-;12613:5;-1:-1:-1;12670:2:13;12655:18;;12642:32;12683:33;12642:32;12683:33;:::i;12753:531::-;12796:5;12849:3;12842:4;12834:6;12830:17;12826:27;12816:55;;12867:1;12864;12857:12;12816:55;12903:6;12890:20;12929:18;12925:2;12922:26;12919:52;;;12951:18;;:::i;:::-;12995:55;13038:2;13019:13;;-1:-1:-1;;13015:27:13;13044:4;13011:38;12995:55;:::i;:::-;13075:2;13066:7;13059:19;13121:3;13114:4;13109:2;13101:6;13097:15;13093:26;13090:35;13087:55;;;13138:1;13135;13128:12;13087:55;13203:2;13196:4;13188:6;13184:17;13177:4;13168:7;13164:18;13151:55;13251:1;13226:16;;;13244:4;13222:27;13215:38;;;;13230:7;12753:531;-1:-1:-1;;;12753:531:13:o;13289:183::-;13349:4;13382:18;13374:6;13371:30;13368:56;;;13404:18;;:::i;:::-;-1:-1:-1;13449:1:13;13445:14;13461:4;13441:25;;13289:183::o;13477:739::-;13529:5;13582:3;13575:4;13567:6;13563:17;13559:27;13549:55;;13600:1;13597;13590:12;13549:55;13636:6;13623:20;13662:4;13686:60;13702:43;13742:2;13702:43;:::i;:::-;13686:60;:::i;:::-;13768:3;13792:2;13787:3;13780:15;13820:4;13815:3;13811:14;13804:21;;13877:4;13871:2;13868:1;13864:10;13856:6;13852:23;13848:34;13834:48;;13905:3;13897:6;13894:15;13891:35;;;13922:1;13919;13912:12;13891:35;13958:4;13950:6;13946:17;13972:215;13988:6;13983:3;13980:15;13972:215;;;14068:3;14055:17;14085:29;14108:5;14085:29;:::i;:::-;14127:18;;14165:12;;;;14005;;13972:215;;;-1:-1:-1;14205:5:13;13477:739;-1:-1:-1;;;;;;13477:739:13:o;14221:1335::-;14285:5;14333:4;14321:9;14316:3;14312:19;14308:30;14305:50;;;14351:1;14348;14341:12;14305:50;14373:22;;:::i;:::-;14364:31;;14432:9;14419:23;14451:31;14474:7;14451:31;:::i;:::-;14491:22;;14532:2;14570:18;;;14557:32;14608:18;14638:14;;;14635:34;;;14665:1;14662;14655:12;14635:34;14703:6;14692:9;14688:22;14678:32;;14748:3;14741:4;14737:2;14733:13;14729:23;14719:51;;14766:1;14763;14756:12;14719:51;14802:2;14789:16;14825:60;14841:43;14881:2;14841:43;:::i;14825:60::-;14919:15;;;15001:1;14997:10;;;;14989:19;;14985:28;;;14950:12;;;;15025:15;;;15022:35;;;15053:1;15050;15043:12;15022:35;15077:11;;;;15097:223;15113:6;15108:3;15105:15;15097:223;;;15195:3;15182:17;15212:33;15237:7;15212:33;:::i;:::-;15258:20;;15130:12;;;;15298;;;;15097:223;;;15352:5;15347:2;15340:5;15336:14;15329:29;;;;15411:2;15400:9;15396:18;15383:32;15367:48;;15440:2;15430:8;15427:16;15424:36;;;15456:1;15453;15446:12;15424:36;;;15492:57;15545:3;15534:8;15523:9;15519:24;15492:57;:::i;:::-;15487:2;15480:5;15476:14;15469:81;;14221:1335;;;;:::o;15561:435::-;15624:5;15672:4;15660:9;15655:3;15651:19;15647:30;15644:50;;;15690:1;15687;15680:12;15644:50;15712:22;;:::i;:::-;15703:31;;15771:9;15758:23;15790:33;15815:7;15790:33;:::i;:::-;15832:22;;15906:2;15891:18;;15878:32;15919:31;15878:32;15919:31;:::i;:::-;15977:2;15966:14;;15959:31;15970:5;15561:435;-1:-1:-1;;15561:435:13:o;16001:1841::-;16267:6;16275;16283;16291;16299;16352:3;16340:9;16331:7;16327:23;16323:33;16320:53;;;16369:1;16366;16359:12;16320:53;16409:9;16396:23;16438:18;16479:2;16471:6;16468:14;16465:34;;;16495:1;16492;16485:12;16465:34;16518:22;;;;16574:4;16556:16;;;16552:27;16549:47;;;16592:1;16589;16582:12;16549:47;16618:22;;:::i;:::-;16678:2;16665:16;16706:2;16696:8;16693:16;16690:36;;;16722:1;16719;16712:12;16690:36;16749:45;16786:7;16775:8;16771:2;16767:17;16749:45;:::i;:::-;16742:5;16735:60;;16841:2;16837;16833:11;16820:25;16870:2;16860:8;16857:16;16854:36;;;16886:1;16883;16876:12;16854:36;16922:45;16959:7;16948:8;16944:2;16940:17;16922:45;:::i;:::-;16917:2;16910:5;16906:14;16899:69;;17014:2;17010;17006:11;16993:25;17043:2;17033:8;17030:16;17027:36;;;17059:1;17056;17049:12;17027:36;17095:45;17132:7;17121:8;17117:2;17113:17;17095:45;:::i;:::-;17090:2;17083:5;17079:14;17072:69;;17187:2;17183;17179:11;17166:25;17216:2;17206:8;17203:16;17200:36;;;17232:1;17229;17222:12;17200:36;17268:45;17305:7;17294:8;17290:2;17286:17;17268:45;:::i;:::-;17263:2;17256:5;17252:14;17245:69;;17368:3;17364:2;17360:12;17347:26;17341:3;17334:5;17330:15;17323:51;17393:5;17383:15;;;17451:2;17440:9;17436:18;17423:32;17407:48;;17480:2;17470:8;17467:16;17464:36;;;17496:1;17493;17486:12;17464:36;;17519:70;17581:7;17570:8;17559:9;17555:24;17519:70;:::i;:::-;17509:80;;;17608:62;17662:7;17657:2;17646:9;17642:18;17608:62;:::i;:::-;17598:72;;17689:64;17745:7;17738:4;17727:9;17723:20;17689:64;:::i;:::-;17679:74;;17772:64;17828:7;17822:3;17811:9;17807:19;17772:64;:::i;:::-;17762:74;;16001:1841;;;;;;;;:::o;17847:495::-;17937:6;17990:2;17978:9;17969:7;17965:23;17961:32;17958:52;;;18006:1;18003;17996:12;17958:52;18032:22;;:::i;:::-;18091:9;18078:23;18110:33;18135:7;18110:33;:::i;:::-;18152:22;;18226:2;18211:18;;18198:32;18239:33;18198:32;18239:33;:::i;:::-;18299:2;18288:14;;18281:31;18292:5;17847:495;-1:-1:-1;;;17847:495:13:o;18347:380::-;18426:1;18422:12;;;;18469;;;18490:61;;18544:4;18536:6;18532:17;18522:27;;18490:61;18597:2;18589:6;18586:14;18566:18;18563:38;18560:161;;18643:10;18638:3;18634:20;18631:1;18624:31;18678:4;18675:1;18668:15;18706:4;18703:1;18696:15;18560:161;;18347:380;;;:::o;18732:217::-;18772:1;18798;18788:132;;18842:10;18837:3;18833:20;18830:1;18823:31;18877:4;18874:1;18867:15;18905:4;18902:1;18895:15;18788:132;-1:-1:-1;18934:9:13;;18732:217::o;18954:127::-;19015:10;19010:3;19006:20;19003:1;18996:31;19046:4;19043:1;19036:15;19070:4;19067:1;19060:15;19418:2012;20048:4;20077:3;20107:2;20096:9;20089:21;20145:6;20139:13;20188:4;20183:2;20172:9;20168:18;20161:32;20216:52;20263:3;20252:9;20248:19;20234:12;20216:52;:::i;:::-;20202:66;;;20317:4;20309:6;20305:17;20299:24;20346:3;20342:8;20415:2;20403:9;20395:6;20391:22;20387:31;20381:3;20370:9;20366:19;20359:60;20442:41;20476:6;20460:14;20442:41;:::i;:::-;20428:55;;20532:4;20524:6;20520:17;20514:24;20492:46;;20603:2;20591:9;20583:6;20579:22;20575:31;20569:3;20558:9;20554:19;20547:60;20630:41;20664:6;20648:14;20630:41;:::i;:::-;20616:55;;20720:4;20712:6;20708:17;20702:24;20680:46;;20791:2;20779:9;20771:6;20767:22;20763:31;20757:3;20746:9;20742:19;20735:60;;20818:41;20852:6;20836:14;20818:41;:::i;:::-;20804:55;;;20914:4;20906:6;20902:17;20896:24;20890:3;20879:9;20875:19;20868:53;20930:48;20972:4;20961:9;20957:20;20949:6;-1:-1:-1;;;;;1771:54:13;1759:67;;1705:127;20930:48;-1:-1:-1;;;;;1771:54:13;;21029:4;21014:20;;1759:67;21073:6;21066:4;21055:9;21051:20;21044:36;21130:9;21122:6;21118:22;21111:4;21100:9;21096:20;21089:52;21158:51;21202:6;21194;21158:51;:::i;:::-;3180:12;;21275:4;21260:20;;3168:25;3239:4;3228:16;;3222:23;3264:6;3302:21;;;3286:14;;;3279:45;3377:4;3366:16;;3360:23;3356:32;3340:14;;;3333:56;21150:59;-1:-1:-1;21218:63:13;;-1:-1:-1;3099:296:13;21218:63;3180:12;;21347:3;21332:19;;3168:25;3239:4;3228:16;;3222:23;3264:6;3302:21;;;3286:14;;;3279:45;3377:4;3366:16;;3360:23;3356:32;3340:14;;;3333:56;9808:12;;-1:-1:-1;;;;;9804:61:13;21419:3;21404:19;;9792:74;9919:4;9908:16;;9902:23;9927:4;9898:34;9882:14;;;9875:58;19418:2012;;;;;;;;;;;:::o;21435:138::-;21514:13;;21536:31;21514:13;21536:31;:::i;:::-;21435:138;;;:::o;21578:251::-;21648:6;21701:2;21689:9;21680:7;21676:23;21672:32;21669:52;;;21717:1;21714;21707:12;21669:52;21749:9;21743:16;21768:31;21793:5;21768:31;:::i;21834:736::-;21897:5;21950:3;21943:4;21935:6;21931:17;21927:27;21917:55;;21968:1;21965;21958:12;21917:55;21997:6;21991:13;22023:4;22047:60;22063:43;22103:2;22063:43;:::i;22047:60::-;22129:3;22153:2;22148:3;22141:15;22181:4;22176:3;22172:14;22165:21;;22238:4;22232:2;22229:1;22225:10;22217:6;22213:23;22209:34;22195:48;;22266:3;22258:6;22255:15;22252:35;;;22283:1;22280;22273:12;22252:35;22319:4;22311:6;22307:17;22333:208;22349:6;22344:3;22341:15;22333:208;;;22422:3;22416:10;22439:29;22462:5;22439:29;:::i;:::-;22481:18;;22519:12;;;;22366;;22333:208;;22575:1322;22650:5;22698:4;22686:9;22681:3;22677:19;22673:30;22670:50;;;22716:1;22713;22706:12;22670:50;22738:22;;:::i;:::-;22729:31;;22790:9;22784:16;22809:31;22832:7;22809:31;:::i;:::-;22849:22;;22890:2;22921:18;;;22915:25;22959:18;22989:14;;;22986:34;;;23016:1;23013;23006:12;22986:34;23054:6;23043:9;23039:22;23029:32;;23099:3;23092:4;23088:2;23084:13;23080:23;23070:51;;23117:1;23114;23107:12;23070:51;23146:2;23140:9;23169:60;23185:43;23225:2;23185:43;:::i;23169:60::-;23263:15;;;23345:1;23341:10;;;;23333:19;;23329:28;;;23294:12;;;;23369:15;;;23366:35;;;23397:1;23394;23387:12;23366:35;23421:11;;;;23441:216;23457:6;23452:3;23449:15;23441:216;;;23532:3;23526:10;23549:33;23574:7;23549:33;:::i;:::-;23595:20;;23474:12;;;;23635;;;;23441:216;;;23689:5;23684:2;23677:5;23673:14;23666:29;;;;23741:2;23730:9;23726:18;23720:25;23704:41;;23770:2;23760:8;23757:16;23754:36;;;23786:1;23783;23776:12;23754:36;;;23822:68;23886:3;23875:8;23864:9;23860:24;23822:68;:::i;23902:489::-;23975:5;24023:4;24011:9;24006:3;24002:19;23998:30;23995:50;;;24041:1;24038;24031:12;23995:50;24063:22;;:::i;:::-;24054:31;;24114:9;24108:16;24101:5;24094:31;24170:2;24159:9;24155:18;24149:25;24183:32;24207:7;24183:32;:::i;:::-;24242:2;24231:14;;24224:31;24300:2;24285:18;;24279:25;24313:32;24279:25;24313:32;:::i;24396:432::-;24470:5;24518:4;24506:9;24501:3;24497:19;24493:30;24490:50;;;24536:1;24533;24526:12;24490:50;24558:22;;:::i;:::-;24549:31;;24610:9;24604:16;24629:33;24654:7;24629:33;:::i;:::-;24671:22;;24738:2;24723:18;;24717:25;24751:31;24717:25;24751:31;:::i;24833:1564::-;25119:6;25127;25135;25143;25151;25159;25167;25175;25183;25191;25244:3;25232:9;25223:7;25219:23;25215:33;25212:53;;;25261:1;25258;25251:12;25212:53;25293:9;25287:16;25312:31;25337:5;25312:31;:::i;:::-;25412:2;25397:18;;25391:25;25362:5;;-1:-1:-1;25425:33:13;25391:25;25425:33;:::i;:::-;25529:2;25514:18;;25508:25;25477:7;;-1:-1:-1;25542:33:13;25508:25;25542:33;:::i;:::-;25646:2;25631:18;;25625:25;25594:7;;-1:-1:-1;25659:33:13;25625:25;25659:33;:::i;:::-;25763:3;25748:19;;25742:26;25711:7;;-1:-1:-1;25777:33:13;25742:26;25777:33;:::i;:::-;25829:7;-1:-1:-1;25855:50:13;25900:3;25885:19;;25855:50;:::i;:::-;25845:60;;25949:3;25938:9;25934:19;25928:26;25977:18;25969:6;25966:30;25963:50;;;26009:1;26006;25999:12;25963:50;26032:79;26103:7;26094:6;26083:9;26079:22;26032:79;:::i;:::-;26022:89;;;26130:74;26196:7;26190:3;26179:9;26175:19;26130:74;:::i;:::-;26120:84;;26223:74;26289:7;26283:3;26272:9;26268:19;26223:74;:::i;:::-;26213:84;;26316:75;26383:7;26377:3;26366:9;26362:19;26316:75;:::i;:::-;26306:85;;24833:1564;;;;;;;;;;;;;:::o
Swarm Source
ipfs://794159239f1deb143ed3a080e0bb6e618d2d7f7775a71578db816f68d6c56c51
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.