Overview
S Balance
0 S
S Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 6 from a total of 6 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Deploy Collectio... | 3285118 | 25 days ago | IN | 0 S | 0.04483648 | ||||
Deploy Collectio... | 3187110 | 25 days ago | IN | 0 S | 0.04483661 | ||||
Deploy Collectio... | 3186998 | 25 days ago | IN | 0 S | 0.04483668 | ||||
Deploy Collectio... | 3186644 | 25 days ago | IN | 0 S | 0.0443525 | ||||
Deploy Collectio... | 1370064 | 43 days ago | IN | 0 S | 0.00896729 | ||||
Deploy Collectio... | 919010 | 46 days ago | IN | 0 S | 0.00902064 |
Loading...
Loading
Contract Name:
CollectionContract
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@openzeppelin/contracts/token/ERC721/IERC721.sol'; import '@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol'; import '@openzeppelin/contracts/access/Ownable.sol'; import './StructLibrary.sol'; import './InterfaceLibrary.sol'; contract CollectionContract is Ownable { address public factory; mapping (address => Socials) socials; event DeployCollection(address indexed deployer); event SetCollectionInfo(address indexed account); constructor( address _factory ) { factory = _factory; } function allowedCollections() public view returns (uint256[] memory col) { uint256 counter = 0; int256[] memory c = new int256[](IFactory(factory).totalDeployed()); for (uint256 i = 0; i < IFactory(factory).totalDeployed(); i++) { ( , , , bool temp) = IFactory(factory).deployInfo(i); if (temp) { counter++; c[i] = int256(i); } } uint256[] memory allowed = new uint256[](counter); for (uint256 i = 0; i < allowed.length; i++) { for (uint256 j = 0; j < IFactory(factory).totalDeployed(); j++) { if (i == 0 && c[j] >= 0) { allowed[i] = j; c[j] = -1; break; } else if (c[j] >= 1) { allowed[i] = j; c[j] = -1; break; } } } return allowed; } function deployCollection(DeploymentParams memory dp, Socials memory _socials) public { IFactory(factory).deployGumBall(dp.name, dp.symbol, dp.uris, dp.supplyBASE, dp.supplyGBT, dp.base, dp.artist, dp.delay, dp.fees); (address gbt, , , ) = IFactory(factory).deployInfo(IFactory(factory).totalDeployed() - 1); _setCollectionInfo(_socials, gbt); emit DeployCollection(msg.sender); } function _setCollectionInfo(Socials memory _socials, address gbtAddress) internal { socials[gbtAddress] = _socials; } function setCollectionInfo(Socials memory _socials, address gbtAddress) public { require(msg.sender == IGBT(gbtAddress).artist() || msg.sender == owner(), "!Authorized"); socials[gbtAddress] = _socials; emit SetCollectionInfo(msg.sender); } function collectionPage(address[] memory gbts) public view returns (CollectionPage[] memory _cp) { CollectionPage[] memory cp = new CollectionPage[](gbts.length); for (uint256 i = 0; i < gbts.length; i++) { (uint256 index, address gbt, address nft, address xgbt, bool allowed) = findCollectionByAddress(gbts[i]); Socials memory col = socials[gbts[i]]; cp[i].base.token = IGBT(gbt).BASE_TOKEN(); cp[i].base.symbol = ERC20(cp[i].base.token).symbol(); cp[i].base.decimals = ERC20(cp[i].base.token).decimals(); cp[i].base.currentPrice = IGBT(gbt).currentPrice(); cp[i].collection.artist = IGBT(gbt).artist(); cp[i].collection.banner = col.banner; cp[i].collection.logo = col.logo; cp[i].collection.name = ERC20(gbt).name(); cp[i].collection.symbol = ERC20(gbt).symbol(); cp[i].collection.totalSupply = IERC20(gbt).totalSupply(); cp[i].collection.releaseDate = col.releaseDate; //Only Arbitrum. Catch if fee doesnt exist try IGBT(gbt).fee() returns (uint256 gbtFee) { cp[i].collection.fee = [gbtFee, IGNFT(nft).bFee()]; }catch{ cp[i].collection.fee = [25, IGNFT(nft).bFee()]; } cp[i].collection.tokenImg = col.tokenImg; cp[i].collection.fileExtension = col.fileExtension; cp[i].collection.baseImgURI = col.baseImgURI; cp[i].collection.socials = col.socials; cp[i].collection.mintableNFTs = (IGBT(gbt).initial_totalSupply() / 1e18) - (ERC721Enumerable(nft).totalSupply()); cp[i].collection._type = col._type; cp[i].apr = getApr(gbt); } return cp; } function individualCollection(address gbts) public view returns (CollectionPage memory _cp) { CollectionPage memory cp; (uint256 index, address gbt, address nft, address xgbt, bool allowed) = findCollectionByAddress(gbts); Socials memory col = socials[gbt]; cp.base.token = IGBT(gbt).BASE_TOKEN(); cp.base.symbol = ERC20(cp.base.token).symbol(); cp.base.decimals = ERC20(cp.base.token).decimals(); cp.base.currentPrice = IGBT(gbt).currentPrice(); cp.collection.artist = IGBT(gbt).artist(); cp.collection.banner = col.banner; cp.collection.logo = col.logo; cp.collection.name = ERC20(gbt).name(); cp.collection.symbol = ERC20(gbt).symbol(); cp.collection.totalSupply = IERC20(gbt).totalSupply(); cp.collection.releaseDate = col.releaseDate; //Only Arbitrum. Catch if fee doesnt exist try IGBT(gbt).fee() returns (uint256 gbtFee) { cp.collection.fee = [gbtFee, IGNFT(nft).bFee()]; }catch{ cp.collection.fee = [25, IGNFT(nft).bFee()]; } cp.collection.tokenImg = col.tokenImg; cp.collection.fileExtension = col.fileExtension; cp.collection.baseImgURI = col.baseImgURI; cp.collection.socials = col.socials; cp.collection.mintableNFTs = (IGBT(gbt).initial_totalSupply() / 1e18) - (ERC721Enumerable(nft).totalSupply()); cp.collection._type = col._type; cp.collection.tokenDeployed = gbt; cp.apr = getApr(gbt); return cp; } function getRewardTokens(address xgbt) internal view returns (address[] memory tokens) { uint256 counter = 0; for (uint256 i = 0; i < 50; i++) { try IXGBT(xgbt).rewardTokens(i) returns (address token) { counter++; } catch { break; } } address[] memory temp = new address[](counter); for (uint256 i = 0; i < counter; i++) { temp[i] = IXGBT(xgbt).rewardTokens(i); } return temp; } function user_Data(address[] memory gbts, address user) public view returns (UserData[] memory userData) { UserData[] memory ud = new UserData[](gbts.length); for (uint256 i = 0; i < ud.length; i++) { (uint256 index, address gbt, address nft, address xgbt, ) = findCollectionByAddress(gbts[i]); ud[i].currentPrice = IGBT(gbt).currentPrice(); if (user != address(0x0000000000000000000000000000000000000000)) { (uint256 num, uint256[] memory arr) = IXGBT(xgbt).balanceOfNFT(user); uint256 userBal = IERC721(nft).balanceOf(user); if (num != 0) { ud[i].stakedNFTs = arr; } ud[i].stakedGBTs = IXGBT(xgbt).balanceToken(user); if (userBal != 0) { uint256[] memory tokenIds = new uint256[](userBal); for (uint256 j = 0; j < userBal; j++) { tokenIds[j] = IGNFT(nft).tokenOfOwnerByIndex(user, j); } ud[i].unstakedNFTs = tokenIds; } ud[i].availableUnstake = ((arr.length * 1e18) + ud[i].stakedGBTs) - IGBT(gbt).mustStayGBT(user); ud[i].debt = IGBT(gbt).debt(user); ud[i].balanceOfBase = IERC20(IGBT(gbt).BASE_TOKEN()).balanceOf(user); if (ud[i].debt != 0) { ud[i].ltv = 100 * IGBT(gbt).debt(user) * _gbtPerEth(gbt) / (IXGBT(xgbt).balanceOf(user)); } else { ud[i].ltv = 0; } ud[i].borrowAmountAvailable = IGBT(gbt).borrowCredit(user); ud[i].unstakedGBTs = IERC20(gbt).balanceOf(user); address[] memory tokens = getRewardTokens(xgbt); //address[] memory tokens = IXGBT(xgbt)._rewardTokens(); Token[] memory rTokens = new Token[](tokens.length); for (uint256 i = 0; i < tokens.length; i++) { rTokens[i].addr = tokens[i]; rTokens[i].symbol = ERC20(tokens[i]).symbol(); rTokens[i].amount = IXGBT(xgbt).earned(user, tokens[i]); rTokens[i].decimals = ERC20(tokens[i]).decimals(); } ud[i].rewards.rewardTokens = rTokens; } else { uint256[] memory s = new uint256[](0); uint256[] memory u = new uint256[](0); ud[i].stakedNFTs = s; ud[i].unstakedNFTs = u; ud[i].balanceOfBase = 0; ud[i].debt = 0; ud[i].ltv = 0; ud[i].borrowAmountAvailable = 0; ud[i].stakedGBTs = 0; ud[i].unstakedGBTs = 0; ud[i].availableUnstake = 0; } ud[i].mintableNFTs = (IGBT(gbt).initial_totalSupply() / 1e18) - (ERC721Enumerable(nft).totalSupply()); ud[i]._type = socials[gbts[i]]._type; ud[i].apr = getApr(gbt); } return ud; } function _user_Data(address gbts, address user) internal view returns (UserData memory userData) { address[] memory temp = new address[](1); temp[0] = gbts; return user_Data(temp, user)[0]; } function getApr(address gbt) public view returns (uint256 apr) { (uint256 index, address gbt, address nft, address xgbt, ) = findCollectionByAddress(gbt); uint256 currentPrice = IGBT(gbt).currentPrice(); uint256 ethRewardForDuration = IXGBT(xgbt).getRewardForDuration(IGBT(gbt).BASE_TOKEN()); uint256 gbtRewardForDuration = IXGBT(xgbt).getRewardForDuration(gbt); uint256 totalSupply = IXGBT(xgbt).totalSupply(); uint256 weekly = (uint256(100) * uint256(365) / uint256(7)); if (ethRewardForDuration == 0 || gbtRewardForDuration == 0) { return 0; } else { uint256 apr = (weekly * ((ethRewardForDuration * 1e18 / currentPrice) + gbtRewardForDuration) * 1e18 / totalSupply); return apr; } } function _gbtPerEth(address collection) public view returns (uint256) { uint256 GBTperETH = IGBT(collection).reserveGBT() * 1e18 / (IGBT(collection).reserveVirtualBASE() + IGBT(collection).reserveRealBASE()); return GBTperETH; } function findCollectionByAddress(address gbt) public view returns (uint256 index, address token, address nft, address gumbar, bool allowed) { uint256 len = IFactory(factory).totalDeployed(); for (uint256 i = 0; i < len; i++) { (address _token, address _nft, address _xgbt, bool _allowed) = IFactory(factory).deployInfo(i); if (_token == gbt || _nft == gbt) { return (i, _token, _nft, _xgbt, _allowed); } } } function userDashboard(address user) public view returns (CollectionPage[] memory, UserData[] memory) { //uint256[] memory allCols = allowedCollections(); uint256 len = IFactory(factory).totalDeployed(); uint256[] memory depositedCollections = new uint256[](len); uint256 counter = 0; for (uint256 i = 0; i < len; i++) { (address gbt, address gnft, address xgbt, ) = IFactory(factory).deployInfo(i); if (user == IGBT(gbt).artist()) { depositedCollections[counter] = i; counter++; } else { (uint256 allBal, ) = IXGBT(xgbt).balanceOfNFT(user); allBal += IERC721(gnft).balanceOf(user) + IXGBT(xgbt).balanceOf(user); if (allBal + IERC20(gbt).balanceOf(user) > 0) { depositedCollections[counter] = i; counter++; } } } CollectionPage[] memory colInfo = new CollectionPage[](counter); UserData[] memory ud = new UserData[](counter); for (uint256 i = 0; i < counter; i++) { (address gbt, address gnft, address xgbt, ) = IFactory(factory).deployInfo(depositedCollections[i]); colInfo[i] = individualCollection(gbt); ud[i] = _user_Data(gbt, user); } return (colInfo, ud); } function TLL(address[] memory gbts) public view returns (BaseLocked[] memory) { BaseLocked[] memory bl = new BaseLocked[](gbts.length); for (uint256 i = 0; i < bl.length; i++) { bl[i].token = IGBT(gbts[i]).BASE_TOKEN(); bl[i].symbol = ERC20(bl[i].token).symbol(); bl[i].decimals = ERC20(bl[i].token).decimals(); bl[i].lockedAmount = IERC20(bl[i].token).balanceOf(gbts[i]); } return bl; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ 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. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256, /* firstTokenId */ uint256 batchSize ) internal virtual { if (batchSize > 1) { if (from != address(0)) { _balances[from] -= batchSize; } if (to != address(0)) { _balances[to] += batchSize; } } } /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "./IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev See {ERC721-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual override { super._beforeTokenTransfer(from, to, firstTokenId, batchSize); if (batchSize > 1) { // Will only trigger during construction. Batch transferring (minting) is not available afterwards. revert("ERC721Enumerable: consecutive transfers not supported"); } uint256 tokenId = firstTokenId; if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@openzeppelin/contracts/token/ERC721/IERC721.sol'; interface IFactory { function totalDeployed() external view returns (uint256 length); function deployInfo(uint256 id) external view returns (address token, address nft, address gumbar, bool _allowed); function deployGumBall( string calldata _name, string calldata _symbol, string[] calldata _URIs, uint256 _supplyBASE, uint256 _supplyGBT, address _base, address _artist, uint256 _delay, uint256[] memory _fees ) external; } interface IGBT { function fee() external view returns (uint256); function artist() external view returns (address); function currentPrice() external view returns (uint256); function buy(uint256 _amountBASE, uint256 _minGBT, uint256 expireTimestamp) external; function buy(uint256 _amountBASE, uint256 _minGBT, uint256 expireTimestamp, address affiliate) external; function sell(uint256 _amountGBT, uint256 _minETH, uint256 expireTimestamp) external; function BASE_TOKEN() external view returns (address); function name() external view returns (string memory); function symbol() external view returns (string memory); function XGBT() external view returns (address); function initial_totalSupply() external view returns (uint256); function reserveGBT() external view returns (uint256); function borrowCredit(address user) external view returns (uint256); function debt(address user) external view returns (uint256); function reserveVirtualBASE() external view returns (uint256); function reserveRealBASE() external view returns (uint256); function floorPrice() external view returns (uint256); function mustStayGBT(address user) external view returns (uint256); function balanceOf(address user) external view returns (uint256); } interface IGNFT { function approve(address to, uint256 tokenId) external; function swapForExact(uint256[] memory id) external; function swap(uint256 _amount) external; function redeem(uint256[] memory _id) external; function gumballs() external view returns (uint256[] memory arr); function totalSupply() external view returns (uint256); function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); function bFee() external view returns (uint256); } interface IXGBT { function GBTperXGBT() external view returns (uint256); function gumballsDeposited(address user) external view returns (uint256, uint256[] memory); function balanceOfNFT(address user) external view returns (uint256, uint256[] memory); function getRewardForDuration(address _rewardsToken) external view returns (uint256); function balanceOf(address account) external view returns (uint256); function balanceToken(address account) external view returns (uint256); function totalSupply() external view returns (uint256); function earned(address account, address _rewardsToken) external view returns (uint256); function rewardTokens(uint256 index) external view returns (address); function stakingToken() external view returns (IERC20); function stakingNFT() external view returns (IERC721); function getReward(address account) external; } interface ICollection { function findCollectionByAddress(address gbt) external view returns (uint256 index, address token, address nft, address gumbar, bool allowed); function allowedCollections() external view returns (uint256[] memory col); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; struct CollectionInfo { string banner; string logo; string name; string symbol; string tokenImg; string fileExtension; string baseImgURI; string[] socials; uint256 totalSupply; uint256[2] fee; address artist; uint256 mintableNFTs; string _type; address tokenDeployed; uint256 apr; uint256 releaseDate; } struct Socials { string banner; string logo; string name; string symbol; string tokenImg; string fileExtension; uint256 releaseDate; string baseImgURI; string[] socials; address artist; string _type; } struct DeploymentParams { string name; string symbol; string[] uris; uint256 supplyBASE; uint256 supplyGBT; address base; address artist; uint256 delay; uint256[] fees; } struct UserData { uint256 currentPrice; uint256[] stakedNFTs; uint256[] unstakedNFTs; uint256 balanceOfBase; uint256 stakedGBTs; uint256 unstakedGBTs; uint256 debt; uint256 ltv; uint256 borrowAmountAvailable; uint256 mintableNFTs; string _type; uint256 apr; uint256 availableUnstake; Rewards rewards; } struct ZapInParams { address gbtForCollection; uint256 amountBaseIn; uint256 amountNftOut; address affiliate; bool swapForExact; uint256[] ids; } struct ZapOutParams { address gbtForCollection; uint256 amountNftIn; uint256 amountBaseOut; uint256[] ids; } struct ZapParams { address gbtForCollection; address tokenIn; address tokenOut; uint256 amountIn; uint256 amountOut; address affiliate; bool swapForExact; uint256[] ids; } struct CollectionPage { CollectionInfo collection; BaseTokenInfo base; uint256 apr; } struct IndividualCollection { CollectionInfo collection; BaseTokenInfo base; uint256 totalSupply; } struct BaseTokenInfo { address token; string symbol; uint256 decimals; uint256 currentPrice; } struct Rewards { Token[] rewardTokens; } struct Token { address addr; string symbol; uint256 amount; uint256 decimals; } struct BaseLocked { address token; string symbol; uint256 decimals; uint256 lockedAmount; }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"deployer","type":"address"}],"name":"DeployCollection","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"SetCollectionInfo","type":"event"},{"inputs":[{"internalType":"address[]","name":"gbts","type":"address[]"}],"name":"TLL","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"decimals","type":"uint256"},{"internalType":"uint256","name":"lockedAmount","type":"uint256"}],"internalType":"struct BaseLocked[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"_gbtPerEth","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowedCollections","outputs":[{"internalType":"uint256[]","name":"col","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"gbts","type":"address[]"}],"name":"collectionPage","outputs":[{"components":[{"components":[{"internalType":"string","name":"banner","type":"string"},{"internalType":"string","name":"logo","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"tokenImg","type":"string"},{"internalType":"string","name":"fileExtension","type":"string"},{"internalType":"string","name":"baseImgURI","type":"string"},{"internalType":"string[]","name":"socials","type":"string[]"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256[2]","name":"fee","type":"uint256[2]"},{"internalType":"address","name":"artist","type":"address"},{"internalType":"uint256","name":"mintableNFTs","type":"uint256"},{"internalType":"string","name":"_type","type":"string"},{"internalType":"address","name":"tokenDeployed","type":"address"},{"internalType":"uint256","name":"apr","type":"uint256"},{"internalType":"uint256","name":"releaseDate","type":"uint256"}],"internalType":"struct CollectionInfo","name":"collection","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"decimals","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"}],"internalType":"struct BaseTokenInfo","name":"base","type":"tuple"},{"internalType":"uint256","name":"apr","type":"uint256"}],"internalType":"struct CollectionPage[]","name":"_cp","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string[]","name":"uris","type":"string[]"},{"internalType":"uint256","name":"supplyBASE","type":"uint256"},{"internalType":"uint256","name":"supplyGBT","type":"uint256"},{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"artist","type":"address"},{"internalType":"uint256","name":"delay","type":"uint256"},{"internalType":"uint256[]","name":"fees","type":"uint256[]"}],"internalType":"struct DeploymentParams","name":"dp","type":"tuple"},{"components":[{"internalType":"string","name":"banner","type":"string"},{"internalType":"string","name":"logo","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"tokenImg","type":"string"},{"internalType":"string","name":"fileExtension","type":"string"},{"internalType":"uint256","name":"releaseDate","type":"uint256"},{"internalType":"string","name":"baseImgURI","type":"string"},{"internalType":"string[]","name":"socials","type":"string[]"},{"internalType":"address","name":"artist","type":"address"},{"internalType":"string","name":"_type","type":"string"}],"internalType":"struct Socials","name":"_socials","type":"tuple"}],"name":"deployCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gbt","type":"address"}],"name":"findCollectionByAddress","outputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"nft","type":"address"},{"internalType":"address","name":"gumbar","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gbt","type":"address"}],"name":"getApr","outputs":[{"internalType":"uint256","name":"apr","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gbts","type":"address"}],"name":"individualCollection","outputs":[{"components":[{"components":[{"internalType":"string","name":"banner","type":"string"},{"internalType":"string","name":"logo","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"tokenImg","type":"string"},{"internalType":"string","name":"fileExtension","type":"string"},{"internalType":"string","name":"baseImgURI","type":"string"},{"internalType":"string[]","name":"socials","type":"string[]"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256[2]","name":"fee","type":"uint256[2]"},{"internalType":"address","name":"artist","type":"address"},{"internalType":"uint256","name":"mintableNFTs","type":"uint256"},{"internalType":"string","name":"_type","type":"string"},{"internalType":"address","name":"tokenDeployed","type":"address"},{"internalType":"uint256","name":"apr","type":"uint256"},{"internalType":"uint256","name":"releaseDate","type":"uint256"}],"internalType":"struct CollectionInfo","name":"collection","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"decimals","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"}],"internalType":"struct BaseTokenInfo","name":"base","type":"tuple"},{"internalType":"uint256","name":"apr","type":"uint256"}],"internalType":"struct CollectionPage","name":"_cp","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"banner","type":"string"},{"internalType":"string","name":"logo","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"tokenImg","type":"string"},{"internalType":"string","name":"fileExtension","type":"string"},{"internalType":"uint256","name":"releaseDate","type":"uint256"},{"internalType":"string","name":"baseImgURI","type":"string"},{"internalType":"string[]","name":"socials","type":"string[]"},{"internalType":"address","name":"artist","type":"address"},{"internalType":"string","name":"_type","type":"string"}],"internalType":"struct Socials","name":"_socials","type":"tuple"},{"internalType":"address","name":"gbtAddress","type":"address"}],"name":"setCollectionInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"userDashboard","outputs":[{"components":[{"components":[{"internalType":"string","name":"banner","type":"string"},{"internalType":"string","name":"logo","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"tokenImg","type":"string"},{"internalType":"string","name":"fileExtension","type":"string"},{"internalType":"string","name":"baseImgURI","type":"string"},{"internalType":"string[]","name":"socials","type":"string[]"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256[2]","name":"fee","type":"uint256[2]"},{"internalType":"address","name":"artist","type":"address"},{"internalType":"uint256","name":"mintableNFTs","type":"uint256"},{"internalType":"string","name":"_type","type":"string"},{"internalType":"address","name":"tokenDeployed","type":"address"},{"internalType":"uint256","name":"apr","type":"uint256"},{"internalType":"uint256","name":"releaseDate","type":"uint256"}],"internalType":"struct CollectionInfo","name":"collection","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"decimals","type":"uint256"},{"internalType":"uint256","name":"currentPrice","type":"uint256"}],"internalType":"struct BaseTokenInfo","name":"base","type":"tuple"},{"internalType":"uint256","name":"apr","type":"uint256"}],"internalType":"struct CollectionPage[]","name":"","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256[]","name":"stakedNFTs","type":"uint256[]"},{"internalType":"uint256[]","name":"unstakedNFTs","type":"uint256[]"},{"internalType":"uint256","name":"balanceOfBase","type":"uint256"},{"internalType":"uint256","name":"stakedGBTs","type":"uint256"},{"internalType":"uint256","name":"unstakedGBTs","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"uint256","name":"borrowAmountAvailable","type":"uint256"},{"internalType":"uint256","name":"mintableNFTs","type":"uint256"},{"internalType":"string","name":"_type","type":"string"},{"internalType":"uint256","name":"apr","type":"uint256"},{"internalType":"uint256","name":"availableUnstake","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"decimals","type":"uint256"}],"internalType":"struct Token[]","name":"rewardTokens","type":"tuple[]"}],"internalType":"struct Rewards","name":"rewards","type":"tuple"}],"internalType":"struct UserData[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"gbts","type":"address[]"},{"internalType":"address","name":"user","type":"address"}],"name":"user_Data","outputs":[{"components":[{"internalType":"uint256","name":"currentPrice","type":"uint256"},{"internalType":"uint256[]","name":"stakedNFTs","type":"uint256[]"},{"internalType":"uint256[]","name":"unstakedNFTs","type":"uint256[]"},{"internalType":"uint256","name":"balanceOfBase","type":"uint256"},{"internalType":"uint256","name":"stakedGBTs","type":"uint256"},{"internalType":"uint256","name":"unstakedGBTs","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"uint256","name":"borrowAmountAvailable","type":"uint256"},{"internalType":"uint256","name":"mintableNFTs","type":"uint256"},{"internalType":"string","name":"_type","type":"string"},{"internalType":"uint256","name":"apr","type":"uint256"},{"internalType":"uint256","name":"availableUnstake","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"decimals","type":"uint256"}],"internalType":"struct Token[]","name":"rewardTokens","type":"tuple[]"}],"internalType":"struct Rewards","name":"rewards","type":"tuple"}],"internalType":"struct UserData[]","name":"userData","type":"tuple[]"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608034620000ad57601f6200583c38819003918201601f19168301916001600160401b03831184841017620000b257808492602094604052833981010312620000ad57516001600160a01b039081811690819003620000ad5760005460018060a01b0319903382821617600055604051933391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a360015416176001556157739081620000c98239f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c80630a1c372314612dcf5780630cf2dc8214612d9657806329811ee514612d725780633697bc3814612d1957806340c703c814612ced578063604676ee14611e955780636f770f83146119b3578063715018a6146119595780638da5cb5b14611932578063bb33085714611609578063c45a0155146115e0578063d790f6bd14610d57578063e171223014610d07578063e53a840e1461018a5763f2fde38b146100c257600080fd5b34610187576020366003190112610187576100db613126565b6100e3613851565b6001600160a01b0390811690811561013357600054826001600160601b0360a01b821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b80fd5b5034610187576040366003190112610187576004356001600160401b038111610d03576101bb9036906004016136af565b6001600160a01b036101cb61313c565b166040516321de0b0960e11b8152602081600481855afa908115610cf8578491610cba575b506001600160a01b031633148015610ca7575b15610c745782526002602052604082209080519283516001600160401b038111610c60576102318454613998565b601f8111610c30575b50602094601f8211600114610bcd579482939495829392610bc2575b50508160011b916000199060031b1c19161783555b6001830160208301518051906001600160401b0382116107d55781906102918454613998565b601f8111610b92575b50602090601f8311600114610b2e578592610b23575b50508160011b916000199060031b1c19161790555b6002830160408301518051906001600160401b0382116107d55781906102eb8454613998565b601f8111610af3575b50602090601f8311600114610a8f578592610a84575b50508160011b916000199060031b1c19161790555b6003830160608301518051906001600160401b0382116107d55781906103458454613998565b601f8111610a54575b50602090601f83116001146109f05785926109e5575b50508160011b916000199060031b1c19161790555b6004830160808301518051906001600160401b0382116107d557819061039f8454613998565b601f81116109b5575b50602090601f8311600114610951578592610946575b50508160011b916000199060031b1c19161790555b60a08201519283516001600160401b038111610625576103f66005830154613998565b601f8111610913575b506020601f82116001146108a7578394958293949261089c575b50508160011b916000199060031b1c19161760058201555b60c083015160068201556007810160e08401518051906001600160401b0382116108885781906104618454613998565b601f8111610858575b50602090601f83116001146107f45786926107e9575b50508160011b916000199060031b1c19161790555b610100830151805190600160401b82116107d557600883015482600885015580831061075c575b506020016008830184526020842084915b838310610639578686610140600a886009810160018060a01b03610120870151166001600160601b0360a01b825416179055019201519182516001600160401b0381116106255761051e8254613998565b601f81116105ea575b506020601f82116001146105885783948293949261057d575b50508160011b916000199060031b1c19161790555b337f32ce3a76fe66acae4a4f238322564eec8bd40d3e765393d1e84ad518db1c38da8280a280f35b015190508480610540565b8284526020842090601f198316855b8181106105d2575095836001959697106105b9575b505050811b019055610555565b015160001960f88460031b161c191690558480806105ac565b9192602060018192868b015181550194019201610597565b6106159083855260208520601f840160051c8101916020851061061b575b601f0160051c01906139d2565b84610527565b9091508190610608565b634e487b7160e01b83526041600452602483fd5b80518051906001600160401b038211610748576106568454613998565b601f8111610718575b50602090601f83116001146106ab5792826001949360209386958c926106a0575b5050600019600383901b1c191690841b1785555b019201920191906104cd565b015190503880610680565b908489526020892091895b601f1985168110610700575083602093600196938796938794601f198116106106e7575b505050811b018555610694565b015160001960f88460031b161c191690553880806106da565b919260206001819286850151815501940192016106b6565b61074290858a5260208a20601f850160051c8101916020861061061b57601f0160051c01906139d2565b3861065f565b634e487b7160e01b88526041600452602488fd5b60088401855260208520908382015b818301811061077b5750506104bc565b8061078860019254613998565b80610795575b500161076b565b601f811183146107ab5750600081555b3861078e565b818952602089206107c691601f0160051c81019084016139d2565b876020812060008355556107a5565b634e487b7160e01b84526041600452602484fd5b015190503880610480565b848752602087209250601f198416875b8181106108405750908460019594939210610827575b505050811b019055610495565b015160001960f88460031b161c1916905538808061081a565b92936020600181928786015181550195019301610804565b6108829085885260208820601f850160051c8101916020861061061b57601f0160051c01906139d2565b3861046a565b634e487b7160e01b85526041600452602485fd5b015190503880610419565b6005830184526020842090845b601f19841681106108fb575060019394959683601f198116106108e2575b505050811b016005820155610431565b015160001960f88460031b161c191690553880806108d2565b9091602060018192858b0151815501930191016108b4565b6109409060058401855260208520601f840160051c8101916020851061061b57601f0160051c01906139d2565b386103ff565b0151905038806103be565b848652602086209250601f198416865b81811061099d5750908460019594939210610984575b505050811b0190556103d3565b015160001960f88460031b161c19169055388080610977565b92936020600181928786015181550195019301610961565b6109df9085875260208720601f850160051c8101916020861061061b57601f0160051c01906139d2565b386103a8565b015190503880610364565b848652602086209250601f198416865b818110610a3c5750908460019594939210610a23575b505050811b019055610379565b015160001960f88460031b161c19169055388080610a16565b92936020600181928786015181550195019301610a00565b610a7e9085875260208720601f850160051c8101916020861061061b57601f0160051c01906139d2565b3861034e565b01519050388061030a565b848652602086209250601f198416865b818110610adb5750908460019594939210610ac2575b505050811b01905561031f565b015160001960f88460031b161c19169055388080610ab5565b92936020600181928786015181550195019301610a9f565b610b1d9085875260208720601f850160051c8101916020861061061b57601f0160051c01906139d2565b386102f4565b0151905038806102b0565b848652602086209250601f198416865b818110610b7a5750908460019594939210610b61575b505050811b0190556102c5565b015160001960f88460031b161c19169055388080610b54565b92936020600181928786015181550195019301610b3e565b610bbc9085875260208720601f850160051c8101916020861061061b57601f0160051c01906139d2565b3861029a565b015190503880610256565b601f198216958584526020842091845b888110610c1857508360019596979810610bff575b505050811b01835561026b565b015160001960f88460031b161c19169055388080610bf2565b91926020600181928685015181550194019201610bdd565b610c5a9085845260208420601f840160051c8101916020851061061b57601f0160051c01906139d2565b3861023a565b634e487b7160e01b82526041600452602482fd5b60405162461bcd60e51b815260206004820152600b60248201526a08505d5d1a1bdc9a5e995960aa1b6044820152606490fd5b5082546001600160a01b03163314610203565b90506020813d602011610cf0575b81610cd5602093836130ee565b81010312610cec57610ce6906138ce565b386101f0565b8380fd5b3d9150610cc8565b6040513d86823e3d90fd5b5080fd5b50346101875760203660031901126101875760a0610d2b610d26613126565b6155fe565b92604051948552600180871b039283809216602087015216604085015216606083015215156080820152f35b5034610187576020366003190112610187576004356001600160401b038111610d0357610d88903690600401613166565b610d928151613adf565b825b82518110156115c657610db96001600160a01b03610db28386613945565b51166155fe565b50909392506001600160a01b039050610dd28387613945565b511686526002928360205260408720610e1460405195610df187613086565b610dfa83613b2f565b8752610e0860018401613b2f565b60208801528201613b2f565b6040860152610e2560038201613b2f565b6060860152610e3660048201613b2f565b6080860152610e4760058201613b2f565b60a0860152600681015460c0860152610e6260078201613b2f565b60e08601526008810154610e758161310f565b90610e8360405192836130ee565b80825260208201600884018b5260208b20908b905b8382106115a9575050505061010086015260098101546001600160a01b0316610120860152610ec990600a01613b2f565b61014085015260405163084198f960e21b81526020816004816001600160a01b0387165afa90811561130d57889161156f575b506020610f098588613945565b5101516001600160a01b03918216905260049088906020610f2a878a613945565b5101515116604051928380926395d89b4160e01b82525afa90811561130d578891611555575b50602080610f5e8689613945565b5101510152600460206001600160a01b0381610f7a878a613945565b51015151166040519283809263313ce56760e01b82525afa801561130d5760ff918991611526575b501660406020610fb28689613945565b5101510152604051634e8da32560e11b81526020816004816001600160a01b0387165afa90811561130d5788916114f4575b5060606020610ff38689613945565b51015101526040516321de0b0960e11b81526020816004816001600160a01b0387165afa90811561130d5788916114b6575b506101406110338588613945565b51516001600160a01b03909216910152835161104f8487613945565b515152602084015160206110638588613945565b515101526040516306fdde0360e01b815287816004816001600160a01b0387165afa90811561130d57889161149c575b5060406110a08588613945565b515101526040516395d89b4160e01b815287816004816001600160a01b0387165afa90811561130d57889161147a575b5060606110dd8588613945565b515101526040516318160ddd60e01b81526020816004816001600160a01b0387165afa90811561130d578891611448575b5061010061111c8588613945565b5151015260c08401516101e06111328588613945565b5151015260405163ddca3f4360e01b81526020816004816001600160a01b0387165afa889181611414575b5061138a575060405161116f816130b8565b601981526040516392ec16ed60e01b81526020816004816001600160a01b0387165afa90811561137f57899161134d575b5060208201526101206111b38588613945565b515101525b608084015160806111c98588613945565b5151015260a084015160a06111de8588613945565b5151015260e084015160c06111f38588613945565b5151015261010084015160e06112098588613945565b51510152604051635dda172d60e11b8152906020826004816001600160a01b0387165afa91821561130d578892611318575b506040516318160ddd60e01b81529190602090839060049082906001600160a01b03165afa91821561130d5788926112d0575b506112cb9461128e6112b79493670de0b6b3a7640000610140940461398b565b61016061129b878a613945565b5151015201516101806112ae8588613945565b515101526151e3565b60406112c38386613945565b5101526138a9565b610d94565b9291506020833d602011611305575b816112ec602093836130ee565b8101031261130057915190916112cb61126e565b600080fd5b3d91506112df565b6040513d8a823e3d90fd5b91506020823d602011611345575b81611333602093836130ee565b8101031261130057905190602061123b565b3d9150611326565b90506020813d602011611377575b81611368602093836130ee565b810103126113005751386111a0565b3d915061135b565b6040513d8b823e3d90fd5b60405190611397826130b8565b81526040516392ec16ed60e01b81526020816004816001600160a01b0387165afa90811561137f5789916113e2575b5060208201526101206113d98588613945565b515101526111b8565b90506020813d60201161140c575b816113fd602093836130ee565b810103126113005751386113c6565b3d91506113f0565b9091506020813d602011611440575b81611430602093836130ee565b810103126113005751903861115d565b3d9150611423565b90506020813d602011611472575b81611463602093836130ee565b8101031261130057513861110e565b3d9150611456565b61149691503d808a833e61148e81836130ee565b810190613bd5565b386110d0565b6114b091503d808a833e61148e81836130ee565b38611093565b90506020813d6020116114ec575b816114d1602093836130ee565b810103126114e8576114e2906138ce565b38611025565b8780fd5b3d91506114c4565b90506020813d60201161151e575b8161150f602093836130ee565b81010312611300575138610fe4565b3d9150611502565b611548915060203d60201161154e575b61154081836130ee565b810190613c36565b38610fa2565b503d611536565b61156991503d808a833e61148e81836130ee565b38610f50565b90506020813d6020116115a1575b8161158a602093836130ee565b810103126114e85761159b906138ce565b38610efc565b3d915061157d565b6001602081926115b886613b2f565b815201930191019091610e98565b604051602080825281906115dc908201856137fc565b0390f35b50346101875780600319360112610187576001546040516001600160a01b039091168152602090f35b50346101875780600319360112610187576001805460405162cfb14b60e41b8082526001600160a01b039092169360209391908085836004818a5afa9283156119275782936118f8575b509083916116608461310f565b9361166e60405195866130ee565b80855261167d601f199161310f565b01368886013781835b6117eb575b5061169590613959565b9681925b6116b1575b604051878152806115dc818a018b61342c565b87518310156117e6578492828115855b6116d7575b50506116d1906138a9565b92611699565b9091929394506040518881528981600481885afa9081156117db5790889187916117aa575b508310156117a15750808061178d575b1561173b575081816116d192611725899796958d613945565b526117336000199188613945565b5290386116c6565b9392909894959791968861174f8b89613945565b51121561177557611765899a99969798996138a9565b90979596999485999293996116c1565b96889695996116d1929399955080611725838d613945565b50846117998388613945565b51121561170c565b949392916116c6565b8092508b8092503d83116117d4575b6117c381836130ee565b8101031261130057879051386116fc565b503d6117b9565b6040513d88823e3d90fd5b61169e565b9091925060405186815287816004818c5afa908115610cf85790869185916118c7575b508210156118bf575060405163d4305c8d60e01b81526004810182905260809081816024818d5afa9182156118b45790879392918692611883575b5050611862575b611859906138a9565b81939291611686565b9161186f611859916138a9565b928061187b8188613945565b529050611850565b6118a29250803d106118ad575b61189a81836130ee565b8101906138e2565b925050503880611849565b503d611890565b6040513d87823e3d90fd5b92919061168b565b809250898092503d83116118f1575b6118e081836130ee565b81010312611300578590513861180e565b503d6118d6565b9092508581813d8311611920575b61191081836130ee565b8101031261130057519138611653565b503d611906565b6040513d84823e3d90fd5b5034610187578060031936011261018757546040516001600160a01b039091168152602090f35b5034610187578060031936011261018757611972613851565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b5034610187576020366003190112610187576119cd613126565b60015460405162cfb14b60e41b81526001600160a01b039091169190602081600481865afa908115610cf8578491611e63575b50611a0a81613959565b91849185905b808210611b56575050611a2282613adf565b93611a2c83614452565b93865b848110611a6057611a52876115dc886040519384936040855260408501906137fc565b908382036020850152613460565b611a6a8183613945565b51906040519163d4305c8d60e01b835260048301526080918281602481885afa928a8415611b4a57611b2594611b0993611b04938a9392611b2a575b50508b611abc86611ab684613c6f565b92613945565b52611ac7858d613945565b50611ad06143a5565b5060405190611ade826130b8565b6001825260203681840137611af282613922565b6001600160a01b039091169052614530565b613922565b51611b148289613945565b52611b1f8188613945565b506138a9565b611a2f565b611b409250803d106118ad5761189a81836130ee565b5050503880611aa6565b604051903d90823e3d90fd5b909260405163d4305c8d60e01b81528460048201526080816024818a5afa801561130d57889089928a91611e3d575b506040516321de0b0960e11b81526020816004816001600160a01b0387165afa908115611d91578b91611dff575b506001600160a01b03878116911603611bed57505050611be18185611bdb611be79489613945565b526138a9565b936138a9565b90611a10565b604051637ad8807560e11b81526001600160a01b0387811660048301529497949093908b908590602490829086165afa938415611d91578b94611dd1575b506040516370a0823160e01b81526001600160a01b03888116600483015290929160209184916024918391165afa918215611d91578b92611d9c575b506040516370a0823160e01b81526001600160a01b03888116600483015290929160209184916024918391165afa918215611d91578b92611d5c575b50602493611cb6602093611cbc93614523565b90614523565b6040516370a0823160e01b81526001600160a01b038881166004830152909491938592918391165afa90811561137f578991611d26575b611cfd9250614523565b611d0b575b611be7906138a9565b92611d1e8185611bdb611be79489613945565b939050611d02565b90506020823d602011611d54575b81611d41602093836130ee565b8101031261130057611cfd915190611cf3565b3d9150611d34565b91506020823d602011611d89575b81611d77602093836130ee565b81010312611300579051906024611ca3565b3d9150611d6a565b6040513d8d823e3d90fd5b91506020823d602011611dc9575b81611db7602093836130ee565b81010312611300579051906020611c67565b3d9150611daa565b602492919450611df56020918d3d8091833e611ded81836130ee565b8101906144a2565b5094919250611c2b565b90506020813d602011611e35575b81611e1a602093836130ee565b81010312611e3157611e2b906138ce565b38611bb3565b8a80fd5b3d9150611e0d565b915050611e59915060803d6080116118ad5761189a81836130ee565b5091909138611b85565b90506020813d602011611e8d575b81611e7e602093836130ee565b81010312611300575138611a00565b3d9150611e71565b503461018757604036600319011261018757600435906001600160401b038211610187576101206003198336030112610187576040519161012083018381106001600160401b038211176106255760405280600401356001600160401b038111612ce957611f0990600436918401016135e8565b835260248101356001600160401b038111612ce957611f2e90600436918401016135e8565b602084015260448101356001600160401b038111612ce957611f56906004369184010161362f565b60408401526064810135606084015260848101356080840152611f7b60a48201613152565b60a0840152611f8c60c48201613152565b60c084015260e481013560e08401526101048101356001600160401b038111612ce957366023828401011215612ce9576004818301013590611fcd8261310f565b92611fdb60405194856130ee565b82845260208401913660248560051b838501010111612ce5579190602483820101925b60248560051b82840101018410612cd0578787876101008301526024356001600160401b038111610d03576120379036906004016136af565b9060018060a01b03600154168351936020810151946040820151916060810151608082015160018060a01b0360a0840151169060018060a01b0360c0850151169261010060e086015195015195883b15612ccc57926101209895928a9895926120d18e6120bf60049b986040519e8f9d8e6385e95b2d60e01b815201526101248d01906131ef565b8b81036003190160248d0152906131ef565b6003198a82030160448b0152875180825260208201916020808360051b8301019a01928d915b838310612c8d5750505050506064890152608488015260a487015260c486015260e4850152600319848303016101048501528391859183916121389161342c565b03925af1801561192757612c76575b509060018060a01b036001541660405162cfb14b60e41b8152602081600481855afa908115610cf8578491612c44575b506000198101908111612c305760809060246040518094819363d4305c8d60e01b835260048301525afa908115612c25578391612c04575b506001600160a01b0316825260026020526040822081518051909391906001600160401b038111610625576121e48254613998565b601f8111612bd4575b506020601f8211600114612b6e5783949582939492612b63575b50508160011b916000199060031b1c19161781555b60208301519283516001600160401b0381116107d55761223f6001840154613998565b601f8111612b30575b506020601f8211600114612ac45784958293949592612ab9575b50508160011b916000199060031b1c19161760018301555b60408101519283516001600160401b038111610c605761229d6002850154613998565b601f8111612a86575b506020601f8211600114612a1a5782939495829392612a0f575b50508160011b916000199060031b1c19161760028401555b60608201519283516001600160401b038111610625576122fb6003830154613998565b601f81116129dc575b506020601f82116001146129705783949582939492612965575b50508160011b916000199060031b1c19161760038201555b60808301519283516001600160401b0381116107d5576123596004840154613998565b601f8111612932575b506020601f82116001146128c657849582939495926128bb575b50508160011b916000199060031b1c19161760048301555b60a08101519283516001600160401b038111610c60576123b76005850154613998565b601f8111612888575b506020601f821160011461281c5782939495829392612811575b50508160011b916000199060031b1c19161760058401555b60c0820151600684015560e08201519283516001600160401b0381116106255761241f6007830154613998565b601f81116127de575b506020601f82116001146127725783949582939492612767575b50508160011b916000199060031b1c19161760078201555b610100830151805190600160401b82116107d55760088301548260088501558083106126ee575b506020016008830184526020842084915b8383106125df578686610140600a886009810160018060a01b03610120870151166001600160601b0360a01b825416179055019201519182516001600160401b038111610625576124e38254613998565b601f81116125af575b506020601f821160011461254d57839482939492612542575b50508160011b916000199060031b1c19161790555b337f4ae5170293a98522588167162defa1d76e4ebef99d3be3dfbe091280e478ec1d8280a280f35b015190508480612505565b8284526020842090601f198316855b8181106125975750958360019596971061257e575b505050811b01905561251a565b015160001960f88460031b161c19169055848080612571565b9192602060018192868b01518155019401920161255c565b6125d99083855260208520601f840160051c8101916020851061061b57601f0160051c01906139d2565b846124ec565b80518051906001600160401b038211610748576125fc8454613998565b601f81116126be575b50602090601f83116001146126515792826001949360209386958c92612646575b5050600019600383901b1c191690841b1785555b01920192019190612492565b015190508c80612626565b908489526020892091895b601f19851681106126a6575083602093600196938796938794601f1981161061268d575b505050811b01855561263a565b015160001960f88460031b161c191690558c8080612680565b9192602060018192868501518155019401920161265c565b6126e890858a5260208a20601f850160051c8101916020861061061b57601f0160051c01906139d2565b89612605565b60088401855260208520908382015b818301811061270d575050612481565b8061271a60019254613998565b80612727575b50016126fd565b601f8111831461273d5750600081555b89612720565b8189526020892061275891601f0160051c81019084016139d2565b87602081206000835555612737565b015190508580612442565b6007830184526020842090845b601f19841681106127c6575060019394959683601f198116106127ad575b505050811b01600782015561245a565b015160001960f88460031b161c1916905585808061279d565b9091602060018192858b01518155019301910161277f565b61280b9060078401855260208520601f840160051c8101916020851061061b57601f0160051c01906139d2565b85612428565b0151905085806123da565b6005850183526020832090835b601f1984168110612870575060019394959683601f19811610612857575b505050811b0160058401556123f2565b015160001960f88460031b161c19169055858080612847565b9091602060018192858b015181550193019101612829565b6128b59060058601845260208420601f840160051c8101916020851061061b57601f0160051c01906139d2565b856123c0565b01519050858061237c565b6004840185526020852090855b601f198416811061291a575060019394959683601f19811610612901575b505050811b016004830155612394565b015160001960f88460031b161c191690558580806128f1565b9091602060018192858b0151815501930191016128d3565b61295f9060048501865260208620601f840160051c8101916020851061061b57601f0160051c01906139d2565b85612362565b01519050858061231e565b6003830184526020842090845b601f19841681106129c4575060019394959683601f198116106129ab575b505050811b016003820155612336565b015160001960f88460031b161c1916905585808061299b565b9091602060018192858b01518155019301910161297d565b612a099060038401855260208520601f840160051c8101916020851061061b57601f0160051c01906139d2565b85612304565b0151905085806122c0565b6002850183526020832090835b601f1984168110612a6e575060019394959683601f19811610612a55575b505050811b0160028401556122d8565b015160001960f88460031b161c19169055858080612a45565b9091602060018192858b015181550193019101612a27565b612ab39060028601845260208420601f840160051c8101916020851061061b57601f0160051c01906139d2565b856122a6565b015190508580612262565b6001840185526020852090855b601f1984168110612b18575060019394959683601f19811610612aff575b505050811b01600183015561227a565b015160001960f88460031b161c19169055858080612aef565b9091602060018192858b015181550193019101612ad1565b612b5d9060018501865260208620601f840160051c8101916020851061061b57601f0160051c01906139d2565b85612248565b015190508580612207565b8284526020842090845b601f1984168110612bbc575060019394959683601f19811610612ba3575b505050811b01815561221c565b015160001960f88460031b161c19169055858080612b96565b9091602060018192858b015181550193019101612b78565b612bfe9083855260208520601f840160051c8101916020851061061b57601f0160051c01906139d2565b856121ed565b612c1c915060803d81116118ad5761189a81836130ee565b505050836121af565b6040513d85823e3d90fd5b634e487b7160e01b84526011600452602484fd5b90506020813d602011612c6e575b81612c5f602093836130ee565b81010312611300575184612177565b3d9150612c52565b6001600160401b038111610c605760405282612147565b929597999b9d50929b5092949698602080612cb46001938f601f19878303018852516131ef565b9d01930193018d9b999795938f9d9b999795926120f7565b8980fd5b60208060249486358152019401939250611ffe565b8580fd5b8280fd5b5034610187576020366003190112610187576020612d11612d0c613126565b6154a9565b604051908152f35b503461018757604036600319011261018757600435906001600160401b038211610187576115dc612d5e612d503660048601613166565b612d5861313c565b90614530565b604051918291602083526020830190613460565b5034610187576020366003190112610187576020612d11612d91613126565b6151e3565b5034610187576020366003190112610187576115dc612dbb612db6613126565b613c6f565b604051918291602083526020830190613250565b50346101875760209081600319360112610187576004356001600160401b038111610d0357612e02903690600401613166565b805190612e0e8261310f565b91612e1c60405193846130ee565b808352612e2b601f199161310f565b0184845b82811061307057505050825b8251811015613011576001600160a01b039060048683612e5b8487613945565b51166040519283809263084198f960e21b82525afa9081156117db578691612fdc575b5082612e8a8387613945565b519116905260048583612e9d8488613945565b515116604051928380926395d89b4160e01b82525afa9081156117db578691612fc2575b5086612ecd8387613945565b51015260048683612ede8488613945565b5151166040519283809263313ce56760e01b82525afa9081156117db579060ff918791612fa5575b50166040612f148387613945565b5101528582612f238387613945565b51511692612f318386613945565b51166024604051809581936370a0823160e01b835260048301525afa80156118b4578590612f70575b612f6b925060606112c38387613945565b612e3b565b50908581813d8311612f9e575b612f8781836130ee565b81010312612f9a5790612f6b9151612f5a565b8480fd5b503d612f7d565b612fbc9150883d8a1161154e5761154081836130ee565b38612f06565b612fd691503d8088833e61148e81836130ee565b38612ec1565b90508681813d831161300a575b612ff381836130ee565b81010312612ce557613004906138ce565b38612e7e565b503d612fe9565b84848460405191838301848452825180915260408401948060408360051b870101940192955b8287106130445785850386f35b909192938280613060600193603f198a82030186528851613214565b9601920196019592919092613037565b6130786139e9565b828287010152018590612e2f565b61016081019081106001600160401b038211176130a257604052565b634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b038211176130a257604052565b602081019081106001600160401b038211176130a257604052565b90601f801991011681019081106001600160401b038211176130a257604052565b6001600160401b0381116130a25760051b60200190565b600435906001600160a01b038216820361130057565b602435906001600160a01b038216820361130057565b35906001600160a01b038216820361130057565b81601f820112156113005780359161317d8361310f565b9261318b60405194856130ee565b808452602092838086019260051b820101928311611300578301905b8282106131b5575050505090565b8380916131c184613152565b8152019101906131a7565b60005b8381106131df5750506000910152565b81810151838201526020016131cf565b90602091613208815180928185528580860191016131cc565b601f01601f1916010190565b9060018060a01b03825116815260608061323d60208501516080602086015260808501906131ef565b9360408101516040850152015191015290565b90815160608252805190613272610220928360608601526102808501906131ef565b6020916132d56132c16132ad6132998685015195605f1996878b83030160808c01526131ef565b6040850151868a83030160a08b01526131ef565b6060840151858983030160c08a01526131ef565b6080830151848883030160e08901526131ef565b936132f160a083015195610100968589830301888a01526131ef565b9061330d60c08401519261012093868a830301858b01526131ef565b9560e08401519061014097868a820301898b015282518082528882019189808360051b8301019501926000915b8b848410613401575050505050508401519261016093848a01528401519461018095868a016000905b600282106133ec57505050926133e395926133b560409996938a99968c61020060018060a01b03809b89015116966101c09788840152880151986101e0998a84015288015192828503019101526131ef565b956101a084015116908a01528101516102408901520151610260870152808701519086830390870152613214565b93015191015290565b89806001928551815201930191019091613363565b8061341d6001939495969799601f198682030187528a516131ef565b9801930193019193929061333a565b90815180825260208080930193019160005b82811061344c575050505090565b83518552938101939281019260010161343e565b9080825190818152602080910192600593828085871b84010196019460009081935b86851061349457505050505050505090565b909192939480969798601f19838203018652895190815181526134c4838301516101c0808685015283019061342c565b6135396134dd604092838601518582038587015261342c565b606080860151908501526080808601519085015260a0808601519085015260c0808601519085015260e08086015190850152610100808601519085015261012080860151908501526101408086015190858303908601526131ef565b91610160808501519082015261018080850151908201526101a080940151938184039101528382019251928483528351809152848284019282891b850101940192885b82811061359f57505050505090806001929a019501950193969594929190613482565b919395806135bb6001939597603f198782030189528951613214565b970195019101918b959493919261357c565b6001600160401b0381116130a257601f01601f191660200190565b81601f82011215611300578035906135ff826135cd565b9261360d60405194856130ee565b8284526020838301011161130057816000926020809301838601378301015290565b9080601f83011215611300578135906136478261310f565b9261365560405194856130ee565b828452602092838086019160051b8301019280841161130057848301915b8483106136835750505050505090565b82356001600160401b0381116113005786916136a4848480948901016135e8565b815201920191613673565b91909161016090818185031261130057604051918201906001600160401b0391838110838211176130a2576040528294813583811161130057816136f49184016135e8565b84526020820135838111611300578161370e9184016135e8565b60208501526040820135838111611300578161372b9184016135e8565b6040850152606082013583811161130057816137489184016135e8565b6060850152608082013583811161130057816137659184016135e8565b608085015260a082013583811161130057816137829184016135e8565b60a085015260c082013560c085015260e082013583811161130057816137a99184016135e8565b60e08501526101008083013584811161130057826137c891850161362f565b908501526101206137da818401613152565b908501526101409283830135908111611300576137f792016135e8565b910152565b90815180825260208092019182818360051b82019501936000915b8483106138275750505050505090565b909192939495848061384183856001950387528a51613250565b9801930193019194939290613817565b6000546001600160a01b0316330361386557565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b60001981146138b85760010190565b634e487b7160e01b600052601160045260246000fd5b51906001600160a01b038216820361130057565b9190826080910312611300576138f7826138ce565b91613904602082016138ce565b916060613913604084016138ce565b92015180151581036113005790565b80511561392f5760200190565b634e487b7160e01b600052603260045260246000fd5b805182101561392f5760209160051b010190565b906139638261310f565b61397060405191826130ee565b8281528092613981601f199161310f565b0190602036910137565b919082039182116138b857565b90600182811c921680156139c8575b60208310146139b257565b634e487b7160e01b600052602260045260246000fd5b91607f16916139a7565b8181106139dd575050565b600081556001016139d2565b60405190608082018281106001600160401b038211176130a25760405260006060838281528160208201528260408201520152565b604051906060808301926001600160401b0390808510828611176130a2578094610260820192818410908411176130a25760409283528381528360808301528360a08301528360c08301528360e0830152836101008301528361012083015283610140830152600093846101608401528351613a99816130b8565b84368237610180840152846101a0840152846101c08401526101e08301528361020083015283610220830152836102408301528152613ad66139e9565b60208201520152565b90613ae98261310f565b613af660405191826130ee565b8281528092613b07601f199161310f565b019060005b828110613b1857505050565b602090613b23613a1e565b82828501015201613b0c565b9060405191826000825492613b4384613998565b908184526001948581169081600014613bb25750600114613b6f575b5050613b6d925003836130ee565b565b9093915060005260209081600020936000915b818310613b9a575050613b6d93508201013880613b5f565b85548884018501529485019487945091830191613b82565b915050613b6d94506020925060ff191682840152151560051b8201013880613b5f565b602081830312611300578051906001600160401b038211611300570181601f82011215611300578051613c07816135cd565b92613c1560405194856130ee565b8184526020828401011161130057613c3391602080850191016131cc565b90565b90816020910312611300575160ff811681036113005790565b8115613c59570490565b634e487b7160e01b600052601260045260246000fd5b613c77613a1e565b50613c89613c83613a1e565b916155fe565b5050915060018060a01b0381166000526002602052604060002060405190613cb082613086565b613cb981613b2f565b8252613cc760018201613b2f565b6020830152613cd860028201613b2f565b6040830152613ce960038201613b2f565b6060830152613cfa60048201613b2f565b6080830152613d0b60058201613b2f565b60a0830152600681015460c0830152613d2660078201613b2f565b60e08301526008810154613d398161310f565b90613d4760405192836130ee565b808252602082016008840160005260206000206000915b838310614388575050505061010083015260098101546001600160a01b0316610120830152613d8f90600a01613b2f565b61014082015260405163084198f960e21b81526020816004816001600160a01b0387165afa9081156141185760009161434e575b506020850180516001600160a01b03928316905251516040516395d89b4160e01b81529160009183916004918391165afa90811561411857600091614333575b506020858101805182019290925290515160405163313ce56760e01b81529190829060049082906001600160a01b03165afa80156141185760ff91600091614314575b5016604060208601510152604051634e8da32560e11b815260208160048160018060a01b0387165afa908115614118576000916142e2575b50602085810151606001919091526040516321de0b0960e11b815290816004816001600160a01b0387165afa908115614118576000916142a8575b5084516001600160a01b039182166101409091015281518551526020808301518651909101526040516306fdde0360e01b8152906000908290600490829087165afa9081156141185760009161428d575b508451604090810191909152516395d89b4160e01b81526000816004816001600160a01b0387165afa90811561411857600091614272575b508451606001526040516318160ddd60e01b81526020816004816001600160a01b0387165afa90811561411857600091614240575b508451610100015260c081015184516101e0015260405163ddca3f4360e01b81526020816004816001600160a01b0387165afa6000918161420c575b5061418b5750604051613fc5816130b8565b601981526040516392ec16ed60e01b81526020816004816001600160a01b0389165afa90811561411857600091614159575b506020820152610120855101525b608081015160808551015260a081015160a08551015260e081015160c08551015261010081015160e08551015260405192635dda172d60e11b845260208460048160018060a01b0387165afa93841561411857600094614124575b506040516318160ddd60e01b81529390602090859060049082906001600160a01b03165afa938415614118576000946140e0575b50906140b06140d894670de0b6b3a7640000610140940461398b565b8551610160015201518351610180015282516001600160a01b0382166101a0909101526151e3565b604082015290565b9350906020843d602011614110575b816140fc602093836130ee565b8101031261130057925192906140b0614094565b3d91506140ef565b6040513d6000823e3d90fd5b93506020843d602011614151575b8161413f602093836130ee565b81010312611300579251926020614060565b3d9150614132565b90506020813d602011614183575b81614174602093836130ee565b81010312611300575138613ff7565b3d9150614167565b60405190614198826130b8565b81526040516392ec16ed60e01b81526020816004816001600160a01b0389165afa908115614118576000916141da575b50602082015261012085510152614005565b90506020813d602011614204575b816141f5602093836130ee565b810103126113005751386141c8565b3d91506141e8565b9091506020813d602011614238575b81614228602093836130ee565b8101031261130057519038613fb3565b3d915061421b565b90506020813d60201161426a575b8161425b602093836130ee565b81010312611300575138613f77565b3d915061424e565b61428791503d806000833e61148e81836130ee565b38613f42565b6142a291503d806000833e61148e81836130ee565b38613f0a565b90506020813d6020116142da575b816142c3602093836130ee565b81010312611300576142d4906138ce565b38613eb9565b3d91506142b6565b90506020813d60201161430c575b816142fd602093836130ee565b81010312611300575138613e7e565b3d91506142f0565b61432d915060203d60201161154e5761154081836130ee565b38613e46565b61434891503d806000833e61148e81836130ee565b38613e03565b90506020813d602011614380575b81614369602093836130ee565b810103126113005761437a906138ce565b38613dc3565b3d915061435c565b60016020819261439785613b2f565b815201920192019190613d5e565b604051906001600160401b036101c08301818111848210176130a2576040528260009182825260606020830152606060408301528260608301528260808301528260a08301528260c08301528260e08301528261010083015282610120830152606061014083015282610160830152826101808301526040519260208401918483109083111761443e5750604052606082526101a00152565b634e487b7160e01b81526041600452602490fd5b9061445c8261310f565b61446960405191826130ee565b828152809261447a601f199161310f565b019060005b82811061448b57505050565b6020906144966143a5565b8282850101520161447f565b91906040838203126113005782519260209081810151906001600160401b03821161130057019180601f840112156113005782516144df8161310f565b936144ed60405195866130ee565b818552838086019260051b820101928311611300578301905b828210614514575050505090565b81518152908301908301614506565b919082018092116138b857565b9161453b8351614452565b916000905b83518210156151dc5761455e6001600160a01b03610db28488613945565b50604051634e8da32560e11b815291979095929350906020816004816001600160a01b0388165afa908115614118576000916151aa575b506145a08383613945565b51526001600160a01b038416156150e657604051637ad8807560e11b81526001600160a01b038581166004830152600090829060249082908a165afa9081156141185760009081926150ca575b506040516370a0823160e01b81526001600160a01b038781166004830152909190602090839060249082908e165afa91821561411857600092615096575b50615081575b60405163022cc80960e11b81526001600160a01b038781166004830152602090829060249082908c165afa9081156141185760009161504f575b5060806146788686613945565b51015280614f98575b5051670de0b6b3a76400009080828102048214811517156138b8576146b69160806146ac8686613945565b5101519102614523565b60405163ce98fd6760e01b81526001600160a01b0386811660048301526020908290602490829089165afa90811561411857600091614f64575b506146fa9161398b565b6101806147078484613945565b5101526040516326db15bb60e21b81526001600160a01b0385811660048301526020908290602490829088165afa90811561411857600091614f32575b5060c06147518484613945565b51015260405163084198f960e21b81526020816004816001600160a01b0388165afa90811561411857600091614ef3575b506040516370a0823160e01b81526001600160a01b038681166004830152909160209183916024918391165afa90811561411857600091614ec1575b5060606147cb8484613945565b51015260c06147da8383613945565b51015115614eab576040516326db15bb60e21b81526001600160a01b0385811660048301526020908290602490829088165afa90811561411857600091614e79575b5060648181029080820483036138b857614835866154a9565b91808284860202048314901517156138b8576040516370a0823160e01b81526001600160a01b038881166004830152909290602090849060249082908d165afa92831561411857600093614e41575b50614890930202613c4f565b60e061489c8484613945565b5101525b604051630eebdf4f60e01b81526001600160a01b0385811660048301526020908290602490829088165afa90811561411857600091614e0f575b506101006148e88484613945565b5101526040516370a0823160e01b81526001600160a01b0385811660048301526020908290602490829088165afa90811561411857600091614ddd575b5060a06149328484613945565b510152600097885b60328110614d56575b5061494d89613959565b9860005b818110614cb25750508851966149668861310f565b97614974604051998a6130ee565b808952614983601f199161310f565b0160005b818110614c9b57505060005b8a51811015614b2e576001600160a01b036149ae828d613945565b51166149ba828b613945565b5152600460006001600160a01b036149d2848f613945565b5116604051928380926395d89b4160e01b82525afa90811561411857600091614b15575b506020614a03838c613945565b5101526001600160a01b03614a18828d613945565b5160405163211dc32d60e01b81526001600160a01b038a8116600483015292909116602482015290602090829060449082908d165afa90811561411857600091614ae2575b50906004916040614a6e838d613945565b51015260206001600160a01b03614a85838f613945565b51166040519384809263313ce56760e01b82525afa91821561411857614abe9260ff91600091614ac3575b501660606112c3838d613945565b614993565b614adc915060203d60201161154e5761154081836130ee565b38614ab0565b906020823d602011614b0d575b81614afc602093836130ee565b810103126101875750516004614a5d565b3d9150614aef565b614b28913d8091833e61148e81836130ee565b386149f6565b509792949550959097506101a0614b45858a613945565b510151525b604051635dda172d60e11b81526020816004816001600160a01b0387165afa90811561411857600091614c68575b506040516318160ddd60e01b815291602090839060049082906001600160a01b03165afa91821561411857600092614c32575b5091614bc8614c1b92670de0b6b3a7640000614c2896950461398b565b610120614bd5858b613945565b5101526001600160a01b03614bea8488613945565b51166000526002602052600a604060002001614c14610140614c0c868c613945565b510191613b2f565b90526151e3565b6101606112c38389613945565b9093929193614540565b90916020823d602011614c60575b81614c4d602093836130ee565b8101031261018757505190614bc8614bab565b3d9150614c40565b906020823d602011614c93575b81614c82602093836130ee565b810103126101875750516020614b78565b3d9150614c75565b602090614ca66139e9565b82828d01015201614987565b604051637bb7bed160e01b815260048101829052906020826024816001600160a01b038d165afa8015614118578c92600091614d0e575b50614cf782614d0994613945565b6001600160a01b0390911690526138a9565b614951565b9192506020823d602011614d4e575b81614d2a602093836130ee565b810103126101875750908b614cf782614d45614d09956138ce565b92945050614ce9565b3d9150614d1d565b604051637bb7bed160e01b8152600481018290526020816024816001600160a01b038c165afa9081614da4575b50156000036149435798614d99614d9f916138a9565b996138a9565b61493a565b6020813d602011614dd5575b81614dbd602093836130ee565b8101031261130057614dce906138ce565b5038614d83565b3d9150614db0565b906020823d602011614e07575b81614df7602093836130ee565b8101031261018757505138614925565b3d9150614dea565b906020823d602011614e39575b81614e29602093836130ee565b81010312610187575051386148da565b3d9150614e1c565b9091926020823d602011614e71575b81614e5d602093836130ee565b810103126101875750519190614890614884565b3d9150614e50565b906020823d602011614ea3575b81614e93602093836130ee565b810103126101875750513861481c565b3d9150614e86565b600060e0614eb98484613945565b5101526148a0565b906020823d602011614eeb575b81614edb602093836130ee565b81010312610187575051386147be565b3d9150614ece565b906020823d602011614f2a575b81614f0d602093836130ee565b8101031261018757506020614f236024926138ce565b9150614782565b3d9150614f00565b906020823d602011614f5c575b81614f4c602093836130ee565b8101031261018757505138614744565b3d9150614f3f565b906020823d602011614f90575b81614f7e602093836130ee565b810103126101875750516146fa6146f0565b3d9150614f71565b614fa181613959565b9060005b818110614fc35750506040614fba8585613945565b51015238614681565b604460208c60405192838092632f745c5960e01b82528d60018060a01b0316600483015286602483015260018060a01b03165afa9081156141185760009161501b575b509061501691611bdb8286613945565b614fa5565b906020823d602011615047575b81615035602093836130ee565b81010312610187575051615016615006565b3d9150615028565b906020823d602011615079575b81615069602093836130ee565b810103126101875750513861466b565b3d915061505c565b81602061508e8686613945565b510152614631565b90916020823d6020116150c2575b816150b1602093836130ee565b81010312610187575051903861462b565b3d91506150a4565b906150df92503d8091833e611ded81836130ee565b90386145ed565b969495909293506040516150f9816130d3565b600081526040519061510a826130d3565b60008252602061511a868b613945565b5101526040615129858a613945565b5101526000606061513a858a613945565b510152600060c061514b858a613945565b510152600060e061515c858a613945565b510152600061010061516e858a613945565b5101526000608061517f858a613945565b510152600060a0615190858a613945565b51015260006101806151a2858a613945565b510152614b4a565b906020823d6020116151d4575b816151c4602093836130ee565b8101031261018757505138614595565b3d91506151b7565b5050915090565b6151ec906155fe565b5060408051634e8da32560e11b8152600496955090936001600160a01b03935083169160209081838981875afa9283156153fb57908591600094615477575b501685519363084198f960e21b855282858a81845afa94851561543557600095615440575b508651632f34440560e21b80825295909616898701528286602481855afa95861561543557600096615406575b508651948552888501528184602481845afa9384156153fb57908892916000956153c5575b5081908751938480926318160ddd60e01b82525afa9586156153bb575060009561538a575b5050821592838015615382575b156152e457506000955050505050565b670de0b6b3a7640000938482029182048514171561536d5761530f929161530a91613c4f565b614523565b61145e9080820291820481036153585769011aa6c91f0b46b800000291818304149015171561534357613c33929350613c4f565b601184634e487b7160e01b6000525260246000fd5b601186634e487b7160e01b6000525260246000fd5b601187634e487b7160e01b6000525260246000fd5b5082156152d4565b8181969293963d83116153b4575b6153a281836130ee565b810103126101875750519238806152c7565b503d615398565b513d6000823e3d90fd5b9180935082819692963d83116153f4575b6153e081836130ee565b8101031261018757505192879190816152a2565b503d6153d6565b86513d6000823e3d90fd5b90958382813d831161542e575b61541d81836130ee565b81010312610187575051943861527d565b503d615413565b87513d6000823e3d90fd5b90948382813d8311615470575b61545781836130ee565b810103126101875750615469906138ce565b9338615250565b503d61544d565b9150928282813d83116154a2575b61548f81836130ee565b810103126101875750849051923861522b565b503d615485565b60408051635626268760e01b8152916001600160a01b031660208084600481855afa9384156155f3576000946155c4575b50670de0b6b3a7640000938481029481860414901517156138b8578251630a4d82ff60e01b8152918183600481845afa9283156155b95760009361558a575b509080600492855193848092638d4a998960e01b82525afa9384156153bb5750600093615557575b5050613c33929161555191614523565b90613c4f565b8181949293943d8311615583575b61556f81836130ee565b810103126101875750519080613c33615541565b503d615565565b90928282813d83116155b2575b6155a181836130ee565b810103126101875750519181615519565b503d615597565b84513d6000823e3d90fd5b90938482813d83116155ec575b6155db81836130ee565b8101031261018757505192386154da565b503d6155d1565b83513d6000823e3d90fd5b6001546040805162cfb14b60e41b81526000948594859485948594926004928692916001600160a01b039182166020878781845afa968715615733578597615700575b50845b878110615655575050505050505050565b845163d4305c8d60e01b81528781018290526080908181602481875afa9182156156f657889289928a928b926156d4575b505087871680898616149081156156c8575b506156af57505050506156aa906138a9565b615644565b9d509d509d509d50979850505050505050509493929190565b90508884161438615698565b92509250506156ef9250803d106118ad5761189a81836130ee565b3880615686565b87513d8a823e3d90fd5b9096506020813d821161572b575b8161571b602093836130ee565b81010312612f9a57519538615641565b3d915061570e565b84513d87823e3d90fdfea2646970667358221220d4a66bb4597b4e4060a1c5714781d14048a7aff80e13f4361f6d0a99437086aa64736f6c6343000811003300000000000000000000000043fde9cb7d2bd5f91e920ea6f4206fe3015194b2
Deployed Bytecode
0x6080604052600436101561001257600080fd5b6000803560e01c80630a1c372314612dcf5780630cf2dc8214612d9657806329811ee514612d725780633697bc3814612d1957806340c703c814612ced578063604676ee14611e955780636f770f83146119b3578063715018a6146119595780638da5cb5b14611932578063bb33085714611609578063c45a0155146115e0578063d790f6bd14610d57578063e171223014610d07578063e53a840e1461018a5763f2fde38b146100c257600080fd5b34610187576020366003190112610187576100db613126565b6100e3613851565b6001600160a01b0390811690811561013357600054826001600160601b0360a01b821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a380f35b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b80fd5b5034610187576040366003190112610187576004356001600160401b038111610d03576101bb9036906004016136af565b6001600160a01b036101cb61313c565b166040516321de0b0960e11b8152602081600481855afa908115610cf8578491610cba575b506001600160a01b031633148015610ca7575b15610c745782526002602052604082209080519283516001600160401b038111610c60576102318454613998565b601f8111610c30575b50602094601f8211600114610bcd579482939495829392610bc2575b50508160011b916000199060031b1c19161783555b6001830160208301518051906001600160401b0382116107d55781906102918454613998565b601f8111610b92575b50602090601f8311600114610b2e578592610b23575b50508160011b916000199060031b1c19161790555b6002830160408301518051906001600160401b0382116107d55781906102eb8454613998565b601f8111610af3575b50602090601f8311600114610a8f578592610a84575b50508160011b916000199060031b1c19161790555b6003830160608301518051906001600160401b0382116107d55781906103458454613998565b601f8111610a54575b50602090601f83116001146109f05785926109e5575b50508160011b916000199060031b1c19161790555b6004830160808301518051906001600160401b0382116107d557819061039f8454613998565b601f81116109b5575b50602090601f8311600114610951578592610946575b50508160011b916000199060031b1c19161790555b60a08201519283516001600160401b038111610625576103f66005830154613998565b601f8111610913575b506020601f82116001146108a7578394958293949261089c575b50508160011b916000199060031b1c19161760058201555b60c083015160068201556007810160e08401518051906001600160401b0382116108885781906104618454613998565b601f8111610858575b50602090601f83116001146107f45786926107e9575b50508160011b916000199060031b1c19161790555b610100830151805190600160401b82116107d557600883015482600885015580831061075c575b506020016008830184526020842084915b838310610639578686610140600a886009810160018060a01b03610120870151166001600160601b0360a01b825416179055019201519182516001600160401b0381116106255761051e8254613998565b601f81116105ea575b506020601f82116001146105885783948293949261057d575b50508160011b916000199060031b1c19161790555b337f32ce3a76fe66acae4a4f238322564eec8bd40d3e765393d1e84ad518db1c38da8280a280f35b015190508480610540565b8284526020842090601f198316855b8181106105d2575095836001959697106105b9575b505050811b019055610555565b015160001960f88460031b161c191690558480806105ac565b9192602060018192868b015181550194019201610597565b6106159083855260208520601f840160051c8101916020851061061b575b601f0160051c01906139d2565b84610527565b9091508190610608565b634e487b7160e01b83526041600452602483fd5b80518051906001600160401b038211610748576106568454613998565b601f8111610718575b50602090601f83116001146106ab5792826001949360209386958c926106a0575b5050600019600383901b1c191690841b1785555b019201920191906104cd565b015190503880610680565b908489526020892091895b601f1985168110610700575083602093600196938796938794601f198116106106e7575b505050811b018555610694565b015160001960f88460031b161c191690553880806106da565b919260206001819286850151815501940192016106b6565b61074290858a5260208a20601f850160051c8101916020861061061b57601f0160051c01906139d2565b3861065f565b634e487b7160e01b88526041600452602488fd5b60088401855260208520908382015b818301811061077b5750506104bc565b8061078860019254613998565b80610795575b500161076b565b601f811183146107ab5750600081555b3861078e565b818952602089206107c691601f0160051c81019084016139d2565b876020812060008355556107a5565b634e487b7160e01b84526041600452602484fd5b015190503880610480565b848752602087209250601f198416875b8181106108405750908460019594939210610827575b505050811b019055610495565b015160001960f88460031b161c1916905538808061081a565b92936020600181928786015181550195019301610804565b6108829085885260208820601f850160051c8101916020861061061b57601f0160051c01906139d2565b3861046a565b634e487b7160e01b85526041600452602485fd5b015190503880610419565b6005830184526020842090845b601f19841681106108fb575060019394959683601f198116106108e2575b505050811b016005820155610431565b015160001960f88460031b161c191690553880806108d2565b9091602060018192858b0151815501930191016108b4565b6109409060058401855260208520601f840160051c8101916020851061061b57601f0160051c01906139d2565b386103ff565b0151905038806103be565b848652602086209250601f198416865b81811061099d5750908460019594939210610984575b505050811b0190556103d3565b015160001960f88460031b161c19169055388080610977565b92936020600181928786015181550195019301610961565b6109df9085875260208720601f850160051c8101916020861061061b57601f0160051c01906139d2565b386103a8565b015190503880610364565b848652602086209250601f198416865b818110610a3c5750908460019594939210610a23575b505050811b019055610379565b015160001960f88460031b161c19169055388080610a16565b92936020600181928786015181550195019301610a00565b610a7e9085875260208720601f850160051c8101916020861061061b57601f0160051c01906139d2565b3861034e565b01519050388061030a565b848652602086209250601f198416865b818110610adb5750908460019594939210610ac2575b505050811b01905561031f565b015160001960f88460031b161c19169055388080610ab5565b92936020600181928786015181550195019301610a9f565b610b1d9085875260208720601f850160051c8101916020861061061b57601f0160051c01906139d2565b386102f4565b0151905038806102b0565b848652602086209250601f198416865b818110610b7a5750908460019594939210610b61575b505050811b0190556102c5565b015160001960f88460031b161c19169055388080610b54565b92936020600181928786015181550195019301610b3e565b610bbc9085875260208720601f850160051c8101916020861061061b57601f0160051c01906139d2565b3861029a565b015190503880610256565b601f198216958584526020842091845b888110610c1857508360019596979810610bff575b505050811b01835561026b565b015160001960f88460031b161c19169055388080610bf2565b91926020600181928685015181550194019201610bdd565b610c5a9085845260208420601f840160051c8101916020851061061b57601f0160051c01906139d2565b3861023a565b634e487b7160e01b82526041600452602482fd5b60405162461bcd60e51b815260206004820152600b60248201526a08505d5d1a1bdc9a5e995960aa1b6044820152606490fd5b5082546001600160a01b03163314610203565b90506020813d602011610cf0575b81610cd5602093836130ee565b81010312610cec57610ce6906138ce565b386101f0565b8380fd5b3d9150610cc8565b6040513d86823e3d90fd5b5080fd5b50346101875760203660031901126101875760a0610d2b610d26613126565b6155fe565b92604051948552600180871b039283809216602087015216604085015216606083015215156080820152f35b5034610187576020366003190112610187576004356001600160401b038111610d0357610d88903690600401613166565b610d928151613adf565b825b82518110156115c657610db96001600160a01b03610db28386613945565b51166155fe565b50909392506001600160a01b039050610dd28387613945565b511686526002928360205260408720610e1460405195610df187613086565b610dfa83613b2f565b8752610e0860018401613b2f565b60208801528201613b2f565b6040860152610e2560038201613b2f565b6060860152610e3660048201613b2f565b6080860152610e4760058201613b2f565b60a0860152600681015460c0860152610e6260078201613b2f565b60e08601526008810154610e758161310f565b90610e8360405192836130ee565b80825260208201600884018b5260208b20908b905b8382106115a9575050505061010086015260098101546001600160a01b0316610120860152610ec990600a01613b2f565b61014085015260405163084198f960e21b81526020816004816001600160a01b0387165afa90811561130d57889161156f575b506020610f098588613945565b5101516001600160a01b03918216905260049088906020610f2a878a613945565b5101515116604051928380926395d89b4160e01b82525afa90811561130d578891611555575b50602080610f5e8689613945565b5101510152600460206001600160a01b0381610f7a878a613945565b51015151166040519283809263313ce56760e01b82525afa801561130d5760ff918991611526575b501660406020610fb28689613945565b5101510152604051634e8da32560e11b81526020816004816001600160a01b0387165afa90811561130d5788916114f4575b5060606020610ff38689613945565b51015101526040516321de0b0960e11b81526020816004816001600160a01b0387165afa90811561130d5788916114b6575b506101406110338588613945565b51516001600160a01b03909216910152835161104f8487613945565b515152602084015160206110638588613945565b515101526040516306fdde0360e01b815287816004816001600160a01b0387165afa90811561130d57889161149c575b5060406110a08588613945565b515101526040516395d89b4160e01b815287816004816001600160a01b0387165afa90811561130d57889161147a575b5060606110dd8588613945565b515101526040516318160ddd60e01b81526020816004816001600160a01b0387165afa90811561130d578891611448575b5061010061111c8588613945565b5151015260c08401516101e06111328588613945565b5151015260405163ddca3f4360e01b81526020816004816001600160a01b0387165afa889181611414575b5061138a575060405161116f816130b8565b601981526040516392ec16ed60e01b81526020816004816001600160a01b0387165afa90811561137f57899161134d575b5060208201526101206111b38588613945565b515101525b608084015160806111c98588613945565b5151015260a084015160a06111de8588613945565b5151015260e084015160c06111f38588613945565b5151015261010084015160e06112098588613945565b51510152604051635dda172d60e11b8152906020826004816001600160a01b0387165afa91821561130d578892611318575b506040516318160ddd60e01b81529190602090839060049082906001600160a01b03165afa91821561130d5788926112d0575b506112cb9461128e6112b79493670de0b6b3a7640000610140940461398b565b61016061129b878a613945565b5151015201516101806112ae8588613945565b515101526151e3565b60406112c38386613945565b5101526138a9565b610d94565b9291506020833d602011611305575b816112ec602093836130ee565b8101031261130057915190916112cb61126e565b600080fd5b3d91506112df565b6040513d8a823e3d90fd5b91506020823d602011611345575b81611333602093836130ee565b8101031261130057905190602061123b565b3d9150611326565b90506020813d602011611377575b81611368602093836130ee565b810103126113005751386111a0565b3d915061135b565b6040513d8b823e3d90fd5b60405190611397826130b8565b81526040516392ec16ed60e01b81526020816004816001600160a01b0387165afa90811561137f5789916113e2575b5060208201526101206113d98588613945565b515101526111b8565b90506020813d60201161140c575b816113fd602093836130ee565b810103126113005751386113c6565b3d91506113f0565b9091506020813d602011611440575b81611430602093836130ee565b810103126113005751903861115d565b3d9150611423565b90506020813d602011611472575b81611463602093836130ee565b8101031261130057513861110e565b3d9150611456565b61149691503d808a833e61148e81836130ee565b810190613bd5565b386110d0565b6114b091503d808a833e61148e81836130ee565b38611093565b90506020813d6020116114ec575b816114d1602093836130ee565b810103126114e8576114e2906138ce565b38611025565b8780fd5b3d91506114c4565b90506020813d60201161151e575b8161150f602093836130ee565b81010312611300575138610fe4565b3d9150611502565b611548915060203d60201161154e575b61154081836130ee565b810190613c36565b38610fa2565b503d611536565b61156991503d808a833e61148e81836130ee565b38610f50565b90506020813d6020116115a1575b8161158a602093836130ee565b810103126114e85761159b906138ce565b38610efc565b3d915061157d565b6001602081926115b886613b2f565b815201930191019091610e98565b604051602080825281906115dc908201856137fc565b0390f35b50346101875780600319360112610187576001546040516001600160a01b039091168152602090f35b50346101875780600319360112610187576001805460405162cfb14b60e41b8082526001600160a01b039092169360209391908085836004818a5afa9283156119275782936118f8575b509083916116608461310f565b9361166e60405195866130ee565b80855261167d601f199161310f565b01368886013781835b6117eb575b5061169590613959565b9681925b6116b1575b604051878152806115dc818a018b61342c565b87518310156117e6578492828115855b6116d7575b50506116d1906138a9565b92611699565b9091929394506040518881528981600481885afa9081156117db5790889187916117aa575b508310156117a15750808061178d575b1561173b575081816116d192611725899796958d613945565b526117336000199188613945565b5290386116c6565b9392909894959791968861174f8b89613945565b51121561177557611765899a99969798996138a9565b90979596999485999293996116c1565b96889695996116d1929399955080611725838d613945565b50846117998388613945565b51121561170c565b949392916116c6565b8092508b8092503d83116117d4575b6117c381836130ee565b8101031261130057879051386116fc565b503d6117b9565b6040513d88823e3d90fd5b61169e565b9091925060405186815287816004818c5afa908115610cf85790869185916118c7575b508210156118bf575060405163d4305c8d60e01b81526004810182905260809081816024818d5afa9182156118b45790879392918692611883575b5050611862575b611859906138a9565b81939291611686565b9161186f611859916138a9565b928061187b8188613945565b529050611850565b6118a29250803d106118ad575b61189a81836130ee565b8101906138e2565b925050503880611849565b503d611890565b6040513d87823e3d90fd5b92919061168b565b809250898092503d83116118f1575b6118e081836130ee565b81010312611300578590513861180e565b503d6118d6565b9092508581813d8311611920575b61191081836130ee565b8101031261130057519138611653565b503d611906565b6040513d84823e3d90fd5b5034610187578060031936011261018757546040516001600160a01b039091168152602090f35b5034610187578060031936011261018757611972613851565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b5034610187576020366003190112610187576119cd613126565b60015460405162cfb14b60e41b81526001600160a01b039091169190602081600481865afa908115610cf8578491611e63575b50611a0a81613959565b91849185905b808210611b56575050611a2282613adf565b93611a2c83614452565b93865b848110611a6057611a52876115dc886040519384936040855260408501906137fc565b908382036020850152613460565b611a6a8183613945565b51906040519163d4305c8d60e01b835260048301526080918281602481885afa928a8415611b4a57611b2594611b0993611b04938a9392611b2a575b50508b611abc86611ab684613c6f565b92613945565b52611ac7858d613945565b50611ad06143a5565b5060405190611ade826130b8565b6001825260203681840137611af282613922565b6001600160a01b039091169052614530565b613922565b51611b148289613945565b52611b1f8188613945565b506138a9565b611a2f565b611b409250803d106118ad5761189a81836130ee565b5050503880611aa6565b604051903d90823e3d90fd5b909260405163d4305c8d60e01b81528460048201526080816024818a5afa801561130d57889089928a91611e3d575b506040516321de0b0960e11b81526020816004816001600160a01b0387165afa908115611d91578b91611dff575b506001600160a01b03878116911603611bed57505050611be18185611bdb611be79489613945565b526138a9565b936138a9565b90611a10565b604051637ad8807560e11b81526001600160a01b0387811660048301529497949093908b908590602490829086165afa938415611d91578b94611dd1575b506040516370a0823160e01b81526001600160a01b03888116600483015290929160209184916024918391165afa918215611d91578b92611d9c575b506040516370a0823160e01b81526001600160a01b03888116600483015290929160209184916024918391165afa918215611d91578b92611d5c575b50602493611cb6602093611cbc93614523565b90614523565b6040516370a0823160e01b81526001600160a01b038881166004830152909491938592918391165afa90811561137f578991611d26575b611cfd9250614523565b611d0b575b611be7906138a9565b92611d1e8185611bdb611be79489613945565b939050611d02565b90506020823d602011611d54575b81611d41602093836130ee565b8101031261130057611cfd915190611cf3565b3d9150611d34565b91506020823d602011611d89575b81611d77602093836130ee565b81010312611300579051906024611ca3565b3d9150611d6a565b6040513d8d823e3d90fd5b91506020823d602011611dc9575b81611db7602093836130ee565b81010312611300579051906020611c67565b3d9150611daa565b602492919450611df56020918d3d8091833e611ded81836130ee565b8101906144a2565b5094919250611c2b565b90506020813d602011611e35575b81611e1a602093836130ee565b81010312611e3157611e2b906138ce565b38611bb3565b8a80fd5b3d9150611e0d565b915050611e59915060803d6080116118ad5761189a81836130ee565b5091909138611b85565b90506020813d602011611e8d575b81611e7e602093836130ee565b81010312611300575138611a00565b3d9150611e71565b503461018757604036600319011261018757600435906001600160401b038211610187576101206003198336030112610187576040519161012083018381106001600160401b038211176106255760405280600401356001600160401b038111612ce957611f0990600436918401016135e8565b835260248101356001600160401b038111612ce957611f2e90600436918401016135e8565b602084015260448101356001600160401b038111612ce957611f56906004369184010161362f565b60408401526064810135606084015260848101356080840152611f7b60a48201613152565b60a0840152611f8c60c48201613152565b60c084015260e481013560e08401526101048101356001600160401b038111612ce957366023828401011215612ce9576004818301013590611fcd8261310f565b92611fdb60405194856130ee565b82845260208401913660248560051b838501010111612ce5579190602483820101925b60248560051b82840101018410612cd0578787876101008301526024356001600160401b038111610d03576120379036906004016136af565b9060018060a01b03600154168351936020810151946040820151916060810151608082015160018060a01b0360a0840151169060018060a01b0360c0850151169261010060e086015195015195883b15612ccc57926101209895928a9895926120d18e6120bf60049b986040519e8f9d8e6385e95b2d60e01b815201526101248d01906131ef565b8b81036003190160248d0152906131ef565b6003198a82030160448b0152875180825260208201916020808360051b8301019a01928d915b838310612c8d5750505050506064890152608488015260a487015260c486015260e4850152600319848303016101048501528391859183916121389161342c565b03925af1801561192757612c76575b509060018060a01b036001541660405162cfb14b60e41b8152602081600481855afa908115610cf8578491612c44575b506000198101908111612c305760809060246040518094819363d4305c8d60e01b835260048301525afa908115612c25578391612c04575b506001600160a01b0316825260026020526040822081518051909391906001600160401b038111610625576121e48254613998565b601f8111612bd4575b506020601f8211600114612b6e5783949582939492612b63575b50508160011b916000199060031b1c19161781555b60208301519283516001600160401b0381116107d55761223f6001840154613998565b601f8111612b30575b506020601f8211600114612ac45784958293949592612ab9575b50508160011b916000199060031b1c19161760018301555b60408101519283516001600160401b038111610c605761229d6002850154613998565b601f8111612a86575b506020601f8211600114612a1a5782939495829392612a0f575b50508160011b916000199060031b1c19161760028401555b60608201519283516001600160401b038111610625576122fb6003830154613998565b601f81116129dc575b506020601f82116001146129705783949582939492612965575b50508160011b916000199060031b1c19161760038201555b60808301519283516001600160401b0381116107d5576123596004840154613998565b601f8111612932575b506020601f82116001146128c657849582939495926128bb575b50508160011b916000199060031b1c19161760048301555b60a08101519283516001600160401b038111610c60576123b76005850154613998565b601f8111612888575b506020601f821160011461281c5782939495829392612811575b50508160011b916000199060031b1c19161760058401555b60c0820151600684015560e08201519283516001600160401b0381116106255761241f6007830154613998565b601f81116127de575b506020601f82116001146127725783949582939492612767575b50508160011b916000199060031b1c19161760078201555b610100830151805190600160401b82116107d55760088301548260088501558083106126ee575b506020016008830184526020842084915b8383106125df578686610140600a886009810160018060a01b03610120870151166001600160601b0360a01b825416179055019201519182516001600160401b038111610625576124e38254613998565b601f81116125af575b506020601f821160011461254d57839482939492612542575b50508160011b916000199060031b1c19161790555b337f4ae5170293a98522588167162defa1d76e4ebef99d3be3dfbe091280e478ec1d8280a280f35b015190508480612505565b8284526020842090601f198316855b8181106125975750958360019596971061257e575b505050811b01905561251a565b015160001960f88460031b161c19169055848080612571565b9192602060018192868b01518155019401920161255c565b6125d99083855260208520601f840160051c8101916020851061061b57601f0160051c01906139d2565b846124ec565b80518051906001600160401b038211610748576125fc8454613998565b601f81116126be575b50602090601f83116001146126515792826001949360209386958c92612646575b5050600019600383901b1c191690841b1785555b01920192019190612492565b015190508c80612626565b908489526020892091895b601f19851681106126a6575083602093600196938796938794601f1981161061268d575b505050811b01855561263a565b015160001960f88460031b161c191690558c8080612680565b9192602060018192868501518155019401920161265c565b6126e890858a5260208a20601f850160051c8101916020861061061b57601f0160051c01906139d2565b89612605565b60088401855260208520908382015b818301811061270d575050612481565b8061271a60019254613998565b80612727575b50016126fd565b601f8111831461273d5750600081555b89612720565b8189526020892061275891601f0160051c81019084016139d2565b87602081206000835555612737565b015190508580612442565b6007830184526020842090845b601f19841681106127c6575060019394959683601f198116106127ad575b505050811b01600782015561245a565b015160001960f88460031b161c1916905585808061279d565b9091602060018192858b01518155019301910161277f565b61280b9060078401855260208520601f840160051c8101916020851061061b57601f0160051c01906139d2565b85612428565b0151905085806123da565b6005850183526020832090835b601f1984168110612870575060019394959683601f19811610612857575b505050811b0160058401556123f2565b015160001960f88460031b161c19169055858080612847565b9091602060018192858b015181550193019101612829565b6128b59060058601845260208420601f840160051c8101916020851061061b57601f0160051c01906139d2565b856123c0565b01519050858061237c565b6004840185526020852090855b601f198416811061291a575060019394959683601f19811610612901575b505050811b016004830155612394565b015160001960f88460031b161c191690558580806128f1565b9091602060018192858b0151815501930191016128d3565b61295f9060048501865260208620601f840160051c8101916020851061061b57601f0160051c01906139d2565b85612362565b01519050858061231e565b6003830184526020842090845b601f19841681106129c4575060019394959683601f198116106129ab575b505050811b016003820155612336565b015160001960f88460031b161c1916905585808061299b565b9091602060018192858b01518155019301910161297d565b612a099060038401855260208520601f840160051c8101916020851061061b57601f0160051c01906139d2565b85612304565b0151905085806122c0565b6002850183526020832090835b601f1984168110612a6e575060019394959683601f19811610612a55575b505050811b0160028401556122d8565b015160001960f88460031b161c19169055858080612a45565b9091602060018192858b015181550193019101612a27565b612ab39060028601845260208420601f840160051c8101916020851061061b57601f0160051c01906139d2565b856122a6565b015190508580612262565b6001840185526020852090855b601f1984168110612b18575060019394959683601f19811610612aff575b505050811b01600183015561227a565b015160001960f88460031b161c19169055858080612aef565b9091602060018192858b015181550193019101612ad1565b612b5d9060018501865260208620601f840160051c8101916020851061061b57601f0160051c01906139d2565b85612248565b015190508580612207565b8284526020842090845b601f1984168110612bbc575060019394959683601f19811610612ba3575b505050811b01815561221c565b015160001960f88460031b161c19169055858080612b96565b9091602060018192858b015181550193019101612b78565b612bfe9083855260208520601f840160051c8101916020851061061b57601f0160051c01906139d2565b856121ed565b612c1c915060803d81116118ad5761189a81836130ee565b505050836121af565b6040513d85823e3d90fd5b634e487b7160e01b84526011600452602484fd5b90506020813d602011612c6e575b81612c5f602093836130ee565b81010312611300575184612177565b3d9150612c52565b6001600160401b038111610c605760405282612147565b929597999b9d50929b5092949698602080612cb46001938f601f19878303018852516131ef565b9d01930193018d9b999795938f9d9b999795926120f7565b8980fd5b60208060249486358152019401939250611ffe565b8580fd5b8280fd5b5034610187576020366003190112610187576020612d11612d0c613126565b6154a9565b604051908152f35b503461018757604036600319011261018757600435906001600160401b038211610187576115dc612d5e612d503660048601613166565b612d5861313c565b90614530565b604051918291602083526020830190613460565b5034610187576020366003190112610187576020612d11612d91613126565b6151e3565b5034610187576020366003190112610187576115dc612dbb612db6613126565b613c6f565b604051918291602083526020830190613250565b50346101875760209081600319360112610187576004356001600160401b038111610d0357612e02903690600401613166565b805190612e0e8261310f565b91612e1c60405193846130ee565b808352612e2b601f199161310f565b0184845b82811061307057505050825b8251811015613011576001600160a01b039060048683612e5b8487613945565b51166040519283809263084198f960e21b82525afa9081156117db578691612fdc575b5082612e8a8387613945565b519116905260048583612e9d8488613945565b515116604051928380926395d89b4160e01b82525afa9081156117db578691612fc2575b5086612ecd8387613945565b51015260048683612ede8488613945565b5151166040519283809263313ce56760e01b82525afa9081156117db579060ff918791612fa5575b50166040612f148387613945565b5101528582612f238387613945565b51511692612f318386613945565b51166024604051809581936370a0823160e01b835260048301525afa80156118b4578590612f70575b612f6b925060606112c38387613945565b612e3b565b50908581813d8311612f9e575b612f8781836130ee565b81010312612f9a5790612f6b9151612f5a565b8480fd5b503d612f7d565b612fbc9150883d8a1161154e5761154081836130ee565b38612f06565b612fd691503d8088833e61148e81836130ee565b38612ec1565b90508681813d831161300a575b612ff381836130ee565b81010312612ce557613004906138ce565b38612e7e565b503d612fe9565b84848460405191838301848452825180915260408401948060408360051b870101940192955b8287106130445785850386f35b909192938280613060600193603f198a82030186528851613214565b9601920196019592919092613037565b6130786139e9565b828287010152018590612e2f565b61016081019081106001600160401b038211176130a257604052565b634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b038211176130a257604052565b602081019081106001600160401b038211176130a257604052565b90601f801991011681019081106001600160401b038211176130a257604052565b6001600160401b0381116130a25760051b60200190565b600435906001600160a01b038216820361130057565b602435906001600160a01b038216820361130057565b35906001600160a01b038216820361130057565b81601f820112156113005780359161317d8361310f565b9261318b60405194856130ee565b808452602092838086019260051b820101928311611300578301905b8282106131b5575050505090565b8380916131c184613152565b8152019101906131a7565b60005b8381106131df5750506000910152565b81810151838201526020016131cf565b90602091613208815180928185528580860191016131cc565b601f01601f1916010190565b9060018060a01b03825116815260608061323d60208501516080602086015260808501906131ef565b9360408101516040850152015191015290565b90815160608252805190613272610220928360608601526102808501906131ef565b6020916132d56132c16132ad6132998685015195605f1996878b83030160808c01526131ef565b6040850151868a83030160a08b01526131ef565b6060840151858983030160c08a01526131ef565b6080830151848883030160e08901526131ef565b936132f160a083015195610100968589830301888a01526131ef565b9061330d60c08401519261012093868a830301858b01526131ef565b9560e08401519061014097868a820301898b015282518082528882019189808360051b8301019501926000915b8b848410613401575050505050508401519261016093848a01528401519461018095868a016000905b600282106133ec57505050926133e395926133b560409996938a99968c61020060018060a01b03809b89015116966101c09788840152880151986101e0998a84015288015192828503019101526131ef565b956101a084015116908a01528101516102408901520151610260870152808701519086830390870152613214565b93015191015290565b89806001928551815201930191019091613363565b8061341d6001939495969799601f198682030187528a516131ef565b9801930193019193929061333a565b90815180825260208080930193019160005b82811061344c575050505090565b83518552938101939281019260010161343e565b9080825190818152602080910192600593828085871b84010196019460009081935b86851061349457505050505050505090565b909192939480969798601f19838203018652895190815181526134c4838301516101c0808685015283019061342c565b6135396134dd604092838601518582038587015261342c565b606080860151908501526080808601519085015260a0808601519085015260c0808601519085015260e08086015190850152610100808601519085015261012080860151908501526101408086015190858303908601526131ef565b91610160808501519082015261018080850151908201526101a080940151938184039101528382019251928483528351809152848284019282891b850101940192885b82811061359f57505050505090806001929a019501950193969594929190613482565b919395806135bb6001939597603f198782030189528951613214565b970195019101918b959493919261357c565b6001600160401b0381116130a257601f01601f191660200190565b81601f82011215611300578035906135ff826135cd565b9261360d60405194856130ee565b8284526020838301011161130057816000926020809301838601378301015290565b9080601f83011215611300578135906136478261310f565b9261365560405194856130ee565b828452602092838086019160051b8301019280841161130057848301915b8483106136835750505050505090565b82356001600160401b0381116113005786916136a4848480948901016135e8565b815201920191613673565b91909161016090818185031261130057604051918201906001600160401b0391838110838211176130a2576040528294813583811161130057816136f49184016135e8565b84526020820135838111611300578161370e9184016135e8565b60208501526040820135838111611300578161372b9184016135e8565b6040850152606082013583811161130057816137489184016135e8565b6060850152608082013583811161130057816137659184016135e8565b608085015260a082013583811161130057816137829184016135e8565b60a085015260c082013560c085015260e082013583811161130057816137a99184016135e8565b60e08501526101008083013584811161130057826137c891850161362f565b908501526101206137da818401613152565b908501526101409283830135908111611300576137f792016135e8565b910152565b90815180825260208092019182818360051b82019501936000915b8483106138275750505050505090565b909192939495848061384183856001950387528a51613250565b9801930193019194939290613817565b6000546001600160a01b0316330361386557565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b60001981146138b85760010190565b634e487b7160e01b600052601160045260246000fd5b51906001600160a01b038216820361130057565b9190826080910312611300576138f7826138ce565b91613904602082016138ce565b916060613913604084016138ce565b92015180151581036113005790565b80511561392f5760200190565b634e487b7160e01b600052603260045260246000fd5b805182101561392f5760209160051b010190565b906139638261310f565b61397060405191826130ee565b8281528092613981601f199161310f565b0190602036910137565b919082039182116138b857565b90600182811c921680156139c8575b60208310146139b257565b634e487b7160e01b600052602260045260246000fd5b91607f16916139a7565b8181106139dd575050565b600081556001016139d2565b60405190608082018281106001600160401b038211176130a25760405260006060838281528160208201528260408201520152565b604051906060808301926001600160401b0390808510828611176130a2578094610260820192818410908411176130a25760409283528381528360808301528360a08301528360c08301528360e0830152836101008301528361012083015283610140830152600093846101608401528351613a99816130b8565b84368237610180840152846101a0840152846101c08401526101e08301528361020083015283610220830152836102408301528152613ad66139e9565b60208201520152565b90613ae98261310f565b613af660405191826130ee565b8281528092613b07601f199161310f565b019060005b828110613b1857505050565b602090613b23613a1e565b82828501015201613b0c565b9060405191826000825492613b4384613998565b908184526001948581169081600014613bb25750600114613b6f575b5050613b6d925003836130ee565b565b9093915060005260209081600020936000915b818310613b9a575050613b6d93508201013880613b5f565b85548884018501529485019487945091830191613b82565b915050613b6d94506020925060ff191682840152151560051b8201013880613b5f565b602081830312611300578051906001600160401b038211611300570181601f82011215611300578051613c07816135cd565b92613c1560405194856130ee565b8184526020828401011161130057613c3391602080850191016131cc565b90565b90816020910312611300575160ff811681036113005790565b8115613c59570490565b634e487b7160e01b600052601260045260246000fd5b613c77613a1e565b50613c89613c83613a1e565b916155fe565b5050915060018060a01b0381166000526002602052604060002060405190613cb082613086565b613cb981613b2f565b8252613cc760018201613b2f565b6020830152613cd860028201613b2f565b6040830152613ce960038201613b2f565b6060830152613cfa60048201613b2f565b6080830152613d0b60058201613b2f565b60a0830152600681015460c0830152613d2660078201613b2f565b60e08301526008810154613d398161310f565b90613d4760405192836130ee565b808252602082016008840160005260206000206000915b838310614388575050505061010083015260098101546001600160a01b0316610120830152613d8f90600a01613b2f565b61014082015260405163084198f960e21b81526020816004816001600160a01b0387165afa9081156141185760009161434e575b506020850180516001600160a01b03928316905251516040516395d89b4160e01b81529160009183916004918391165afa90811561411857600091614333575b506020858101805182019290925290515160405163313ce56760e01b81529190829060049082906001600160a01b03165afa80156141185760ff91600091614314575b5016604060208601510152604051634e8da32560e11b815260208160048160018060a01b0387165afa908115614118576000916142e2575b50602085810151606001919091526040516321de0b0960e11b815290816004816001600160a01b0387165afa908115614118576000916142a8575b5084516001600160a01b039182166101409091015281518551526020808301518651909101526040516306fdde0360e01b8152906000908290600490829087165afa9081156141185760009161428d575b508451604090810191909152516395d89b4160e01b81526000816004816001600160a01b0387165afa90811561411857600091614272575b508451606001526040516318160ddd60e01b81526020816004816001600160a01b0387165afa90811561411857600091614240575b508451610100015260c081015184516101e0015260405163ddca3f4360e01b81526020816004816001600160a01b0387165afa6000918161420c575b5061418b5750604051613fc5816130b8565b601981526040516392ec16ed60e01b81526020816004816001600160a01b0389165afa90811561411857600091614159575b506020820152610120855101525b608081015160808551015260a081015160a08551015260e081015160c08551015261010081015160e08551015260405192635dda172d60e11b845260208460048160018060a01b0387165afa93841561411857600094614124575b506040516318160ddd60e01b81529390602090859060049082906001600160a01b03165afa938415614118576000946140e0575b50906140b06140d894670de0b6b3a7640000610140940461398b565b8551610160015201518351610180015282516001600160a01b0382166101a0909101526151e3565b604082015290565b9350906020843d602011614110575b816140fc602093836130ee565b8101031261130057925192906140b0614094565b3d91506140ef565b6040513d6000823e3d90fd5b93506020843d602011614151575b8161413f602093836130ee565b81010312611300579251926020614060565b3d9150614132565b90506020813d602011614183575b81614174602093836130ee565b81010312611300575138613ff7565b3d9150614167565b60405190614198826130b8565b81526040516392ec16ed60e01b81526020816004816001600160a01b0389165afa908115614118576000916141da575b50602082015261012085510152614005565b90506020813d602011614204575b816141f5602093836130ee565b810103126113005751386141c8565b3d91506141e8565b9091506020813d602011614238575b81614228602093836130ee565b8101031261130057519038613fb3565b3d915061421b565b90506020813d60201161426a575b8161425b602093836130ee565b81010312611300575138613f77565b3d915061424e565b61428791503d806000833e61148e81836130ee565b38613f42565b6142a291503d806000833e61148e81836130ee565b38613f0a565b90506020813d6020116142da575b816142c3602093836130ee565b81010312611300576142d4906138ce565b38613eb9565b3d91506142b6565b90506020813d60201161430c575b816142fd602093836130ee565b81010312611300575138613e7e565b3d91506142f0565b61432d915060203d60201161154e5761154081836130ee565b38613e46565b61434891503d806000833e61148e81836130ee565b38613e03565b90506020813d602011614380575b81614369602093836130ee565b810103126113005761437a906138ce565b38613dc3565b3d915061435c565b60016020819261439785613b2f565b815201920192019190613d5e565b604051906001600160401b036101c08301818111848210176130a2576040528260009182825260606020830152606060408301528260608301528260808301528260a08301528260c08301528260e08301528261010083015282610120830152606061014083015282610160830152826101808301526040519260208401918483109083111761443e5750604052606082526101a00152565b634e487b7160e01b81526041600452602490fd5b9061445c8261310f565b61446960405191826130ee565b828152809261447a601f199161310f565b019060005b82811061448b57505050565b6020906144966143a5565b8282850101520161447f565b91906040838203126113005782519260209081810151906001600160401b03821161130057019180601f840112156113005782516144df8161310f565b936144ed60405195866130ee565b818552838086019260051b820101928311611300578301905b828210614514575050505090565b81518152908301908301614506565b919082018092116138b857565b9161453b8351614452565b916000905b83518210156151dc5761455e6001600160a01b03610db28488613945565b50604051634e8da32560e11b815291979095929350906020816004816001600160a01b0388165afa908115614118576000916151aa575b506145a08383613945565b51526001600160a01b038416156150e657604051637ad8807560e11b81526001600160a01b038581166004830152600090829060249082908a165afa9081156141185760009081926150ca575b506040516370a0823160e01b81526001600160a01b038781166004830152909190602090839060249082908e165afa91821561411857600092615096575b50615081575b60405163022cc80960e11b81526001600160a01b038781166004830152602090829060249082908c165afa9081156141185760009161504f575b5060806146788686613945565b51015280614f98575b5051670de0b6b3a76400009080828102048214811517156138b8576146b69160806146ac8686613945565b5101519102614523565b60405163ce98fd6760e01b81526001600160a01b0386811660048301526020908290602490829089165afa90811561411857600091614f64575b506146fa9161398b565b6101806147078484613945565b5101526040516326db15bb60e21b81526001600160a01b0385811660048301526020908290602490829088165afa90811561411857600091614f32575b5060c06147518484613945565b51015260405163084198f960e21b81526020816004816001600160a01b0388165afa90811561411857600091614ef3575b506040516370a0823160e01b81526001600160a01b038681166004830152909160209183916024918391165afa90811561411857600091614ec1575b5060606147cb8484613945565b51015260c06147da8383613945565b51015115614eab576040516326db15bb60e21b81526001600160a01b0385811660048301526020908290602490829088165afa90811561411857600091614e79575b5060648181029080820483036138b857614835866154a9565b91808284860202048314901517156138b8576040516370a0823160e01b81526001600160a01b038881166004830152909290602090849060249082908d165afa92831561411857600093614e41575b50614890930202613c4f565b60e061489c8484613945565b5101525b604051630eebdf4f60e01b81526001600160a01b0385811660048301526020908290602490829088165afa90811561411857600091614e0f575b506101006148e88484613945565b5101526040516370a0823160e01b81526001600160a01b0385811660048301526020908290602490829088165afa90811561411857600091614ddd575b5060a06149328484613945565b510152600097885b60328110614d56575b5061494d89613959565b9860005b818110614cb25750508851966149668861310f565b97614974604051998a6130ee565b808952614983601f199161310f565b0160005b818110614c9b57505060005b8a51811015614b2e576001600160a01b036149ae828d613945565b51166149ba828b613945565b5152600460006001600160a01b036149d2848f613945565b5116604051928380926395d89b4160e01b82525afa90811561411857600091614b15575b506020614a03838c613945565b5101526001600160a01b03614a18828d613945565b5160405163211dc32d60e01b81526001600160a01b038a8116600483015292909116602482015290602090829060449082908d165afa90811561411857600091614ae2575b50906004916040614a6e838d613945565b51015260206001600160a01b03614a85838f613945565b51166040519384809263313ce56760e01b82525afa91821561411857614abe9260ff91600091614ac3575b501660606112c3838d613945565b614993565b614adc915060203d60201161154e5761154081836130ee565b38614ab0565b906020823d602011614b0d575b81614afc602093836130ee565b810103126101875750516004614a5d565b3d9150614aef565b614b28913d8091833e61148e81836130ee565b386149f6565b509792949550959097506101a0614b45858a613945565b510151525b604051635dda172d60e11b81526020816004816001600160a01b0387165afa90811561411857600091614c68575b506040516318160ddd60e01b815291602090839060049082906001600160a01b03165afa91821561411857600092614c32575b5091614bc8614c1b92670de0b6b3a7640000614c2896950461398b565b610120614bd5858b613945565b5101526001600160a01b03614bea8488613945565b51166000526002602052600a604060002001614c14610140614c0c868c613945565b510191613b2f565b90526151e3565b6101606112c38389613945565b9093929193614540565b90916020823d602011614c60575b81614c4d602093836130ee565b8101031261018757505190614bc8614bab565b3d9150614c40565b906020823d602011614c93575b81614c82602093836130ee565b810103126101875750516020614b78565b3d9150614c75565b602090614ca66139e9565b82828d01015201614987565b604051637bb7bed160e01b815260048101829052906020826024816001600160a01b038d165afa8015614118578c92600091614d0e575b50614cf782614d0994613945565b6001600160a01b0390911690526138a9565b614951565b9192506020823d602011614d4e575b81614d2a602093836130ee565b810103126101875750908b614cf782614d45614d09956138ce565b92945050614ce9565b3d9150614d1d565b604051637bb7bed160e01b8152600481018290526020816024816001600160a01b038c165afa9081614da4575b50156000036149435798614d99614d9f916138a9565b996138a9565b61493a565b6020813d602011614dd5575b81614dbd602093836130ee565b8101031261130057614dce906138ce565b5038614d83565b3d9150614db0565b906020823d602011614e07575b81614df7602093836130ee565b8101031261018757505138614925565b3d9150614dea565b906020823d602011614e39575b81614e29602093836130ee565b81010312610187575051386148da565b3d9150614e1c565b9091926020823d602011614e71575b81614e5d602093836130ee565b810103126101875750519190614890614884565b3d9150614e50565b906020823d602011614ea3575b81614e93602093836130ee565b810103126101875750513861481c565b3d9150614e86565b600060e0614eb98484613945565b5101526148a0565b906020823d602011614eeb575b81614edb602093836130ee565b81010312610187575051386147be565b3d9150614ece565b906020823d602011614f2a575b81614f0d602093836130ee565b8101031261018757506020614f236024926138ce565b9150614782565b3d9150614f00565b906020823d602011614f5c575b81614f4c602093836130ee565b8101031261018757505138614744565b3d9150614f3f565b906020823d602011614f90575b81614f7e602093836130ee565b810103126101875750516146fa6146f0565b3d9150614f71565b614fa181613959565b9060005b818110614fc35750506040614fba8585613945565b51015238614681565b604460208c60405192838092632f745c5960e01b82528d60018060a01b0316600483015286602483015260018060a01b03165afa9081156141185760009161501b575b509061501691611bdb8286613945565b614fa5565b906020823d602011615047575b81615035602093836130ee565b81010312610187575051615016615006565b3d9150615028565b906020823d602011615079575b81615069602093836130ee565b810103126101875750513861466b565b3d915061505c565b81602061508e8686613945565b510152614631565b90916020823d6020116150c2575b816150b1602093836130ee565b81010312610187575051903861462b565b3d91506150a4565b906150df92503d8091833e611ded81836130ee565b90386145ed565b969495909293506040516150f9816130d3565b600081526040519061510a826130d3565b60008252602061511a868b613945565b5101526040615129858a613945565b5101526000606061513a858a613945565b510152600060c061514b858a613945565b510152600060e061515c858a613945565b510152600061010061516e858a613945565b5101526000608061517f858a613945565b510152600060a0615190858a613945565b51015260006101806151a2858a613945565b510152614b4a565b906020823d6020116151d4575b816151c4602093836130ee565b8101031261018757505138614595565b3d91506151b7565b5050915090565b6151ec906155fe565b5060408051634e8da32560e11b8152600496955090936001600160a01b03935083169160209081838981875afa9283156153fb57908591600094615477575b501685519363084198f960e21b855282858a81845afa94851561543557600095615440575b508651632f34440560e21b80825295909616898701528286602481855afa95861561543557600096615406575b508651948552888501528184602481845afa9384156153fb57908892916000956153c5575b5081908751938480926318160ddd60e01b82525afa9586156153bb575060009561538a575b5050821592838015615382575b156152e457506000955050505050565b670de0b6b3a7640000938482029182048514171561536d5761530f929161530a91613c4f565b614523565b61145e9080820291820481036153585769011aa6c91f0b46b800000291818304149015171561534357613c33929350613c4f565b601184634e487b7160e01b6000525260246000fd5b601186634e487b7160e01b6000525260246000fd5b601187634e487b7160e01b6000525260246000fd5b5082156152d4565b8181969293963d83116153b4575b6153a281836130ee565b810103126101875750519238806152c7565b503d615398565b513d6000823e3d90fd5b9180935082819692963d83116153f4575b6153e081836130ee565b8101031261018757505192879190816152a2565b503d6153d6565b86513d6000823e3d90fd5b90958382813d831161542e575b61541d81836130ee565b81010312610187575051943861527d565b503d615413565b87513d6000823e3d90fd5b90948382813d8311615470575b61545781836130ee565b810103126101875750615469906138ce565b9338615250565b503d61544d565b9150928282813d83116154a2575b61548f81836130ee565b810103126101875750849051923861522b565b503d615485565b60408051635626268760e01b8152916001600160a01b031660208084600481855afa9384156155f3576000946155c4575b50670de0b6b3a7640000938481029481860414901517156138b8578251630a4d82ff60e01b8152918183600481845afa9283156155b95760009361558a575b509080600492855193848092638d4a998960e01b82525afa9384156153bb5750600093615557575b5050613c33929161555191614523565b90613c4f565b8181949293943d8311615583575b61556f81836130ee565b810103126101875750519080613c33615541565b503d615565565b90928282813d83116155b2575b6155a181836130ee565b810103126101875750519181615519565b503d615597565b84513d6000823e3d90fd5b90938482813d83116155ec575b6155db81836130ee565b8101031261018757505192386154da565b503d6155d1565b83513d6000823e3d90fd5b6001546040805162cfb14b60e41b81526000948594859485948594926004928692916001600160a01b039182166020878781845afa968715615733578597615700575b50845b878110615655575050505050505050565b845163d4305c8d60e01b81528781018290526080908181602481875afa9182156156f657889289928a928b926156d4575b505087871680898616149081156156c8575b506156af57505050506156aa906138a9565b615644565b9d509d509d509d50979850505050505050509493929190565b90508884161438615698565b92509250506156ef9250803d106118ad5761189a81836130ee565b3880615686565b87513d8a823e3d90fd5b9096506020813d821161572b575b8161571b602093836130ee565b81010312612f9a57519538615641565b3d915061570e565b84513d87823e3d90fdfea2646970667358221220d4a66bb4597b4e4060a1c5714781d14048a7aff80e13f4361f6d0a99437086aa64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000043fde9cb7d2bd5f91e920ea6f4206fe3015194b2
-----Decoded View---------------
Arg [0] : _factory (address): 0x43FDE9Cb7D2BD5F91e920Ea6f4206Fe3015194B2
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000043fde9cb7d2bd5f91e920ea6f4206fe3015194b2
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.