Contract Overview
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Contract Name:
ERC721CollectionV2
Compiler Version
v0.7.6+commit.7338295f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; import "../interfaces/ICollectionManager.sol"; import "../commons/OwnableInitializable.sol"; import "../commons/NativeMetaTransaction.sol"; import "../libs/String.sol"; contract Rarities is OwnableInitializable, NativeMetaTransaction { using String for string; struct Rarity { string name; uint256 maxSupply; uint256 price; } Rarity[] public rarities; /// @dev indexes will start in 1 mapping(bytes32 => uint256) rarityIndex; event AddRarity(Rarity _rarity); event UpdatePrice(string _name, uint256 _price); /** * @notice Create the contract * @param _owner - owner of the contract */ constructor(address _owner, Rarity[] memory _rarities) { // EIP712 init _initializeEIP712('Decentraland Rarities', '1'); // Ownable init _initOwnable(); transferOwnership(_owner); for (uint256 i = 0 ; i < _rarities.length; i++) { _addRarity(_rarities[i]); } } function updatePrices(string[] calldata _names, uint256[] calldata _prices) external onlyOwner { require(_names.length == _prices.length, "Rarities#updatePrices: LENGTH_MISMATCH"); for (uint256 i = 0; i < _names.length; i++) { string memory name = _names[i]; uint256 price = _prices[i]; bytes32 rarityKey = keccak256(bytes(name.toLowerCase())); uint256 index = rarityIndex[rarityKey]; require(rarityIndex[rarityKey] > 0, "Rarities#updatePrices: INVALID_RARITY"); rarities[index - 1].price = price; emit UpdatePrice(name, price); } } function addRarities(Rarity[] memory _rarities) external onlyOwner { for (uint256 i = 0; i < _rarities.length; i++) { _addRarity(_rarities[i]); } } function _addRarity(Rarity memory _rarity) internal { uint256 rarityLength = bytes(_rarity.name).length; require(rarityLength > 0 && rarityLength <= 32, "Rarities#_addRarity: INVALID_LENGTH"); bytes32 rarityKey = keccak256(bytes(_rarity.name.toLowerCase())); require(rarityIndex[rarityKey] == 0, "Rarities#_addRarity: RARITY_ALREADY_ADDED"); rarities.push(_rarity); rarityIndex[rarityKey] = rarities.length; emit AddRarity(_rarity); } /** * @notice Returns the amount of item in the collection * @return Amount of items in the collection */ function raritiesCount() external view returns (uint256) { return rarities.length; } /** * @notice Returns a rarity * @dev will revert if the rarity is out of bounds * @return rarity for the given index */ function getRarityByName(string memory _rarity) public view returns (Rarity memory) { bytes32 rarityKey = keccak256(bytes(_rarity.toLowerCase())); uint256 index = rarityIndex[rarityKey]; require(rarityIndex[rarityKey] > 0, "Rarities#getRarityByName: INVALID_RARITY"); return rarities[index - 1]; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; interface ICollectionManager { function manageCollection(address _forwarder, address _collection, bytes calldata _data) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; import "./ContextMixin.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 OwnableInitializable is ContextMixin { address internal _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function _initOwnable () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { 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 { emit OwnershipTransferred(_owner, address(0)); _owner = 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"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; import { EIP712Base } from "./EIP712Base.sol"; contract NativeMetaTransaction is EIP712Base { using SafeMath for uint256; bytes32 private constant META_TRANSACTION_TYPEHASH = keccak256( bytes( "MetaTransaction(uint256 nonce,address from,bytes functionSignature)" ) ); event MetaTransactionExecuted( address userAddress, address relayerAddress, bytes functionSignature ); mapping(address => uint256) nonces; struct MetaTransaction { uint256 nonce; address from; bytes functionSignature; } function executeMetaTransaction( address userAddress, bytes memory functionSignature, bytes32 sigR, bytes32 sigS, uint8 sigV ) external payable returns (bytes memory) { MetaTransaction memory metaTx = MetaTransaction({ nonce: nonces[userAddress], from: userAddress, functionSignature: functionSignature }); require( verify(userAddress, metaTx, sigR, sigS, sigV), "NMT#executeMetaTransaction: SIGNER_AND_SIGNATURE_DO_NOT_MATCH" ); // increase nonce for user (to avoid re-use) nonces[userAddress] = nonces[userAddress].add(1); emit MetaTransactionExecuted( userAddress, msg.sender, functionSignature ); // Append userAddress and relayer address at the end to extract it from calling context (bool success, bytes memory returnData) = address(this).call{value: msg.value}( abi.encodePacked(functionSignature, userAddress) ); require(success, "NMT#executeMetaTransaction: CALL_FAILED"); return returnData; } function hashMetaTransaction(MetaTransaction memory metaTx) internal pure returns (bytes32) { return keccak256( abi.encode( META_TRANSACTION_TYPEHASH, metaTx.nonce, metaTx.from, keccak256(metaTx.functionSignature) ) ); } function getNonce(address user) external view returns (uint256 nonce) { nonce = nonces[user]; } function verify( address signer, MetaTransaction memory metaTx, bytes32 sigR, bytes32 sigS, uint8 sigV ) internal view returns (bool) { require(signer != address(0), "NMT#verify: INVALID_SIGNER"); return signer == ecrecover( toTypedMessageHash(hashMetaTransaction(metaTx)), sigV, sigR, sigS ); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12; library String { /** * @dev Convert bytes32 to string. * @param _x - to be converted to string. * @return string */ function bytes32ToString(bytes32 _x) internal pure returns (string memory) { bytes memory bytesString = new bytes(32); uint charCount = 0; for (uint j = 0; j < 32; j++) { bytes1 currentChar = bytes1(bytes32(uint(_x) * 2 ** (8 * j))); if (currentChar != 0) { bytesString[charCount] = currentChar; charCount++; } } bytes memory bytesStringTrimmed = new bytes(charCount); for (uint j = 0; j < charCount; j++) { bytesStringTrimmed[j] = bytesString[j]; } return string(bytesStringTrimmed); } /** * @dev Convert uint to string. * @param _i - uint256 to be converted to string. * @return _uintAsString uint in string */ function uintToString(uint _i) internal pure returns (string memory _uintAsString) { uint i = _i; if (i == 0) { return "0"; } uint j = i; uint len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint k = len - 1; while (i != 0) { bstr[k--] = bytes1(uint8(48 + i % 10)); i /= 10; } return string(bstr); } /** * @dev Convert an address to string. * @param _x - address to be converted to string. * @return string representation of the address */ function addressToString(address _x) internal pure returns (string memory) { bytes memory s = new bytes(40); for (uint i = 0; i < 20; i++) { bytes1 b = bytes1(uint8(uint160(_x) / (2**(8*(19 - i))))); bytes1 hi = bytes1(uint8(b) / 16); bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); s[2*i] = char(hi); s[2*i+1] = char(lo); } return string(s); } function char(bytes1 b) internal pure returns (bytes1 c) { if (uint8(b) < 10) return bytes1(uint8(b) + 0x30); else return bytes1(uint8(b) + 0x57); } /** * @dev Lowercase a string. * @param _str - to be converted to string. * @return string */ function toLowerCase(string memory _str) internal pure returns (string memory) { bytes memory bStr = bytes(_str); bytes memory bLower = new bytes(bStr.length); for (uint i = 0; i < bStr.length; i++) { // Uppercase character... if ((bStr[i] >= 0x41) && (bStr[i] <= 0x5A)) { // So we add 0x20 to make it lowercase bLower[i] = bytes1(uint8(bStr[i]) + 0x20); } else { bLower[i] = bStr[i]; } } return string(bLower); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; abstract contract ContextMixin { function _msgSender() internal view virtual returns (address payable sender) { if (msg.sender == address(this)) { bytes memory array = msg.data; uint256 index = msg.data.length; assembly { // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those. sender := and( mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff ) } } else { sender = msg.sender; } return sender; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; contract EIP712Base { struct EIP712Domain { string name; string version; address verifyingContract; bytes32 salt; } bytes32 internal constant EIP712_DOMAIN_TYPEHASH = keccak256( bytes( "EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)" ) ); bytes32 public domainSeparator; // supposed to be called once while initializing. // one of the contractsa that inherits this contract follows proxy pattern // so it is not possible to do this in a constructor function _initializeEIP712( string memory name, string memory version ) internal { domainSeparator = keccak256( abi.encode( EIP712_DOMAIN_TYPEHASH, keccak256(bytes(name)), keccak256(bytes(version)), address(this), bytes32(getChainId()) ) ); } function getChainId() public pure returns (uint256) { uint256 id; assembly { id := chainid() } return id; } /** * Accept message hash and returns hash message in EIP712 compatible form * So that it can be used to recover signer from signature signed using EIP712 formatted data * https://eips.ethereum.org/EIPS/eip-712 * "\\x19" makes the encoding deterministic * "\\x01" is the version byte to make it compatible to EIP-191 */ function toTypedMessageHash(bytes32 messageHash) internal view returns (bytes32) { return keccak256( abi.encodePacked("\x19\x01", domainSeparator, messageHash) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/math/SafeMath.sol"; import "../../interfaces/IERC20.sol"; import "../../interfaces/IERC721CollectionV2.sol"; import "../../commons/OwnableInitializable.sol"; import "../../commons/NativeMetaTransaction.sol"; contract CollectionStore is OwnableInitializable, NativeMetaTransaction { using SafeMath for uint256; struct ItemToBuy { IERC721CollectionV2 collection; uint256[] ids; uint256[] prices; address[] beneficiaries; } uint256 constant public BASE_FEE = 1000000; IERC20 public acceptedToken; uint256 public fee; address public feeOwner; event Bought(ItemToBuy[] _itemsToBuy); event SetFee(uint256 _oldFee, uint256 _newFee); event SetFeeOwner(address indexed _oldFeeOwner, address indexed _newFeeOwner); /** * @notice Constructor of the contract. * @param _acceptedToken - Address of the ERC20 token accepted * @param _feeOwner - address where fees will be transferred * @param _fee - fee to charge for each sale */ constructor(address _owner, IERC20 _acceptedToken, address _feeOwner, uint256 _fee) { // EIP712 init _initializeEIP712('Decentraland Collection Store', '1'); // Ownable init _initOwnable(); acceptedToken = _acceptedToken; feeOwner = _feeOwner; setFee(_fee); transferOwnership(_owner); } /** * @notice Buy collection's items. * @dev There is a maximum amount of NFTs that can be issued per call by the block's limit. * @param _itemsToBuy - items to buy */ function buy(ItemToBuy[] memory _itemsToBuy) external { uint256 totalFee = 0; address sender = _msgSender(); for (uint256 i = 0; i < _itemsToBuy.length; i++) { ItemToBuy memory itemToBuy = _itemsToBuy[i]; IERC721CollectionV2 collection = itemToBuy.collection; uint256 amountOfItems = itemToBuy.ids.length; require(amountOfItems == itemToBuy.prices.length, "CollectionStore#buy: LENGTH_MISMATCH"); for (uint256 j = 0; j < amountOfItems; j++) { uint256 itemId = itemToBuy.ids[j]; uint256 price = itemToBuy.prices[j]; (uint256 itemPrice, address itemBeneficiary) = getItemBuyData(collection, itemId); require(price == itemPrice, "CollectionStore#buy: ITEM_PRICE_MISMATCH"); if (itemPrice > 0) { // Calculate sale share uint256 saleShareAmount = itemPrice.mul(fee).div(BASE_FEE); totalFee = totalFee.add(saleShareAmount); // Transfer sale amount to the item beneficiary require( acceptedToken.transferFrom(sender, itemBeneficiary, itemPrice.sub(saleShareAmount)), "CollectionStore#buy: TRANSFER_PRICE_FAILED" ); } } // Mint Token collection.issueTokens(itemToBuy.beneficiaries, itemToBuy.ids); } if (totalFee > 0) { // Transfer share amount for fees owner require( acceptedToken.transferFrom(sender, feeOwner, totalFee), "CollectionStore#buy: TRANSFER_FEES_FAILED" ); } emit Bought(_itemsToBuy); } /** * @notice Get item's price and beneficiary * @param _collection - collection address * @param _itemId - item id * @return uint256 of the item's price * @return address of the item's beneficiary */ function getItemBuyData(IERC721CollectionV2 _collection, uint256 _itemId) public view returns (uint256, address) { (,,,uint256 price, address beneficiary,,) = _collection.items(_itemId); return (price, beneficiary); } // Owner functions /** * @notice Sets the fee of the contract that's charged to the seller on each sale * @param _newFee - Fee from 0 to 999,999 */ function setFee(uint256 _newFee) public onlyOwner { require(_newFee < BASE_FEE, "CollectionStore#setFee: FEE_SHOULD_BE_LOWER_THAN_BASE_FEE"); require(_newFee != fee, "CollectionStore#setFee: SAME_FEE"); emit SetFee(fee, _newFee); fee = _newFee; } /** * @notice Set a new fee owner. * @param _newFeeOwner - Address of the new fee owner */ function setFeeOwner(address _newFeeOwner) external onlyOwner { require(_newFeeOwner != address(0), "CollectionStore#setFeeOwner: INVALID_ADDRESS"); require(_newFeeOwner != feeOwner, "CollectionStore#setFeeOwner: SAME_FEE_OWNER"); emit SetFeeOwner(feeOwner, _newFeeOwner); feeOwner = _newFeeOwner; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12; interface IERC20 { function balanceOf(address from) external view returns (uint256); function transferFrom(address from, address to, uint tokens) external returns (bool); function transfer(address to, uint tokens) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function burn(uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; interface IERC721CollectionV2 { function COLLECTION_HASH() external view returns (bytes32); struct ItemParam { string rarity; uint256 price; address beneficiary; string metadata; } function issueTokens(address[] calldata _beneficiaries, uint256[] calldata _itemIds) external; function setApproved(bool _value) external; /// @dev For some reason using the Struct Item as an output parameter fails, but works as an input parameter function initialize( string memory _name, string memory _symbol, string memory _baseURI, address _creator, bool _shouldComplete, bool _isApproved, address _rarities, ItemParam[] memory _items ) external; function items(uint256 _itemId) external view returns (string memory, uint256, uint256, uint256, address, string memory, string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; import "../markets/v2/CollectionStore.sol"; interface EventsInterface { event Issue(address indexed _beneficiary, uint256 indexed _tokenId, uint256 indexed _itemId, uint256 _issuedId, address _caller); event Transfer(address indexed _from, address indexed _to, uint256 _value); } contract DummyCollectionStore is EventsInterface, CollectionStore { constructor ( address _owner, IERC20 _acceptedToken, address _feeOwner, uint256 _fee ) CollectionStore(_owner, _acceptedToken, _feeOwner, _fee) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; import "../interfaces/ICollectionManager.sol"; import "../commons/OwnableInitializable.sol"; import "../commons/NativeMetaTransaction.sol"; contract Committee is OwnableInitializable, NativeMetaTransaction { mapping(address => bool) public members; event MemberSet(address indexed _member, bool _value); /** * @notice Create the contract * @param _owner - owner of the contract * @param _members - members to be added at contract creation */ constructor(address _owner, address[] memory _members) { // EIP712 init _initializeEIP712('Decentraland Collection Committee', '1'); // Ownable init _initOwnable(); transferOwnership(_owner); for (uint256 i = 0; i < _members.length; i++) { _setMember(_members[i], true); } } /** * @notice Set members * @param _members - members to be added * @param _values - whether the members should be added or removed */ function setMembers(address[] calldata _members, bool[] calldata _values) external onlyOwner { require(_members.length == _values.length, "Committee#setMembers: LENGTH_MISMATCH"); for (uint256 i = 0; i < _members.length; i++) { _setMember(_members[i], _values[i]); } } /** * @notice Set members * @param _member - member to be added * @param _value - whether the member should be added or removed */ function _setMember(address _member, bool _value) internal { members[_member] = _value; emit MemberSet(_member, _value); } /** * @notice Manage collection * @param _collectionManager - collection manager * @param _forwarder - forwarder contract owner of the collection * @param _collection - collection to be managed * @param _data - call data to be used */ function manageCollection(ICollectionManager _collectionManager, address _forwarder, address _collection, bytes memory _data) external { require(members[_msgSender()], "Committee#manageCollection: UNAUTHORIZED_SENDER"); _collectionManager.manageCollection(_forwarder, _collection, _data); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/math/SafeMath.sol"; import "../interfaces/IForwarder.sol"; import "../interfaces/IERC20.sol"; import "../interfaces/IERC721CollectionV2.sol"; import "../interfaces/IERC721CollectionFactoryV2.sol"; import "../interfaces/IRarities.sol"; import "../commons/OwnableInitializable.sol"; import "../commons/NativeMetaTransaction.sol"; contract CollectionManager is OwnableInitializable, NativeMetaTransaction { using SafeMath for uint256; IERC20 public acceptedToken; IRarities public rarities; address public committee; address public feesCollector; uint256 public pricePerItem; mapping(bytes4 => bool) public allowedCommitteeMethods; event AcceptedTokenSet(IERC20 indexed _oldAcceptedToken, IERC20 indexed _newAcceptedToken); event CommitteeSet(address indexed _oldCommittee, address indexed _newCommittee); event CommitteeMethodSet(bytes4 indexed _method, bool _isAllowed); event FeesCollectorSet(address indexed _oldFeesCollector, address indexed _newFeesCollector); event RaritiesSet(IRarities indexed _oldRarities, IRarities indexed _newRarities); /** * @notice Create the contract * @param _owner - owner of the contract * @param _acceptedToken - accepted ERC20 token for collection deployment * @param _committee - committee contract * @param _feesCollector - fees collector * @param _rarities - rarities contract * @param _committeeMethods - method selectors * @param _committeeValues - whether the method is allowed or not */ constructor( address _owner, IERC20 _acceptedToken, address _committee, address _feesCollector, IRarities _rarities, bytes4[] memory _committeeMethods, bool[] memory _committeeValues ) { // EIP712 init _initializeEIP712('Decentraland Collection Manager', '1'); // Ownable init _initOwnable(); setAcceptedToken(_acceptedToken); // Committee setCommittee(_committee); setCommitteeMethods(_committeeMethods, _committeeValues); setFeesCollector(_feesCollector); setRarities(_rarities); transferOwnership(_owner); } /** * @notice Set the accepted token * @param _newAcceptedToken - accepted ERC20 token for collection deployment */ function setAcceptedToken(IERC20 _newAcceptedToken) onlyOwner public { require(address(_newAcceptedToken) != address(0), "CollectionManager#setAcceptedToken: INVALID_ACCEPTED_TOKEN"); emit AcceptedTokenSet(acceptedToken, _newAcceptedToken); acceptedToken = _newAcceptedToken; } /** * @notice Set the committee * @param _newCommittee - committee contract */ function setCommittee(address _newCommittee) onlyOwner public { require(_newCommittee != address(0), "CollectionManager#setCommittee: INVALID_COMMITTEE"); emit CommitteeSet(committee, _newCommittee); committee = _newCommittee; } /** * @notice Set methods to be allowed by the committee * @param _methods - method selectors * @param _values - whether the method is allowed or not */ function setCommitteeMethods(bytes4[] memory _methods, bool[] memory _values) onlyOwner public { uint256 length = _methods.length; require(length > 0 && length == _values.length, "CollectionManager#setCommitteeMethods: EMPTY_METHODS"); for (uint256 i = 0; i < length; i++) { bytes4 method = _methods[i]; bool value = _values[i]; allowedCommitteeMethods[method] = value; emit CommitteeMethodSet(method, value); } } /** * @notice Set the fees collector * @param _newFeesCollector - fees collector */ function setFeesCollector(address _newFeesCollector) onlyOwner public { require(_newFeesCollector != address(0), "CollectionManager#setFeesCollector: INVALID_FEES_COLLECTOR"); emit FeesCollectorSet(feesCollector, _newFeesCollector); feesCollector = _newFeesCollector; } /** * @notice Set the rarities * @param _newRarities - price per item */ function setRarities(IRarities _newRarities) onlyOwner public { require(address(_newRarities) != address(0), "CollectionManager#setRarities: INVALID_RARITIES"); emit RaritiesSet(rarities, _newRarities); rarities = _newRarities; } /** * @notice Create a collection * @param _forwarder - forwarder contract owner of the collection factory * @param _factory - collection factory * @param _salt - arbitrary 32 bytes hexa * @param _name - name of the contract * @param _symbol - symbol of the contract * @param _baseURI - base URI for token URIs * @param _creator - creator address * @param _items - items to be added */ function createCollection( IForwarder _forwarder, IERC721CollectionFactoryV2 _factory, bytes32 _salt, string memory _name, string memory _symbol, string memory _baseURI, address _creator, IERC721CollectionV2.ItemParam[] memory _items ) external { require(address(_forwarder) != address(this), "CollectionManager#createCollection: FORWARDER_CANT_BE_THIS"); uint256 amount = 0; for (uint256 i = 0; i < _items.length; i++) { IERC721CollectionV2.ItemParam memory item = _items[i]; IRarities.Rarity memory rarity = rarities.getRarityByName(item.rarity); amount = amount.add(rarity.price); } // Transfer fees to collector if (amount > 0) { require( acceptedToken.transferFrom(_msgSender(), feesCollector, amount), "CollectionManager#createCollection: TRANSFER_FEES_FAILED" ); } bytes memory data = abi.encodeWithSelector( IERC721CollectionV2.initialize.selector, _name, _symbol, _baseURI, _creator, true, // Collection should be completed false, // Collection should start disapproved rarities, _items ); (bool success,) = _forwarder.forwardCall(address(_factory), abi.encodeWithSelector(_factory.createCollection.selector, _salt, data)); require( success, "CollectionManager#createCollection: FORWARD_FAILED" ); } /** * @notice Manage a collection * @param _forwarder - forwarder contract owner of the collection factory * @param _collection - collection to be managed * @param _data - call data to be used */ function manageCollection(IForwarder _forwarder, IERC721CollectionV2 _collection, bytes calldata _data) external { require(address(_forwarder) != address(this), "CollectionManager#manageCollection: FORWARDER_CANT_BE_THIS"); require( _msgSender() == committee, "CollectionManager#manageCollection: UNAUTHORIZED_SENDER" ); (bytes4 method) = abi.decode(_data, (bytes4)); require(allowedCommitteeMethods[method], "CollectionManager#manageCollection: COMMITTEE_METHOD_NOT_ALLOWED"); bool success; bytes memory res; (success, res) = address(_collection).staticcall(abi.encodeWithSelector(_collection.COLLECTION_HASH.selector)); require( success && abi.decode(res, (bytes32)) == keccak256("Decentraland Collection"), "CollectionManager#manageCollection: INVALID_COLLECTION" ); (success,) = _forwarder.forwardCall(address(_collection), _data); require( success, "CollectionManager#manageCollection: FORWARD_FAILED" ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; interface IForwarder { function forwardCall(address _address, bytes calldata _data) external returns (bool, bytes memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; interface IERC721CollectionFactoryV2 { function createCollection(bytes32 _salt, bytes memory _data) external returns (address addr); function transferOwnership(address newOwner) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; interface IRarities { struct Rarity { string name; uint256 maxSupply; uint256 price; } function getRarityByName(string calldata rarity) external view returns (Rarity memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/math/SafeMath.sol"; import "../../interfaces/IRarities.sol"; import "../../commons//OwnableInitializable.sol"; import "../../commons//NativeMetaTransaction.sol"; import "../../tokens/ERC721Initializable.sol"; import "../../libs/String.sol"; abstract contract ERC721BaseCollectionV2 is OwnableInitializable, ERC721Initializable, NativeMetaTransaction { using String for bytes32; using String for uint256; using String for address; using SafeMath for uint256; bytes32 constant public COLLECTION_HASH = keccak256("Decentraland Collection"); uint8 constant public ITEM_ID_BITS = 40; uint8 constant public ISSUED_ID_BITS = 216; uint40 constant public MAX_ITEM_ID = type(uint40).max; uint216 constant public MAX_ISSUED_ID = type(uint216).max; bytes32 constant internal EMPTY_CONTENT = bytes32(0); struct ItemParam { string rarity; uint256 price; address beneficiary; string metadata; } struct Item { string rarity; uint256 maxSupply; // max supply uint256 totalSupply; // current supply uint256 price; address beneficiary; string metadata; string contentHash; // used for safe purposes } IRarities public rarities; // Roles address public creator; mapping(address => bool) public globalMinters; mapping(address => bool) public globalManagers; mapping(uint256 => mapping (address => uint256)) public itemMinters; mapping(uint256 => mapping (address => bool)) public itemManagers; Item[] public items; // Status uint256 public createdAt; bool public isInitialized; bool public isCompleted; bool public isEditable; bool public isApproved; event BaseURI(string _oldBaseURI, string _newBaseURI); event SetGlobalMinter(address indexed _minter, bool _value); event SetGlobalManager(address indexed _manager, bool _value); event SetItemMinter(uint256 indexed _itemId, address indexed _minter, uint256 _value); event SetItemManager(uint256 indexed _itemId, address indexed _manager, bool _value); event AddItem(uint256 indexed _itemId, Item _item); event RescueItem(uint256 indexed _itemId, string _contentHash, string _metadata); event Issue(address indexed _beneficiary, uint256 indexed _tokenId, uint256 indexed _itemId, uint256 _issuedId, address _caller); event UpdateItemData(uint256 indexed _itemId, uint256 _price, address _beneficiary, string _metadata); event CreatorshipTransferred(address indexed _previousCreator, address indexed _newCreator); event SetApproved(bool _previousValue, bool _newValue); event SetEditable(bool _previousValue, bool _newValue); event Complete(); /* * Init functions */ /** * @notice Init the contract */ function initImplementation() public { require(!isInitialized, "initialize: ALREADY_INITIALIZED"); isInitialized = true; } /** * @notice Create the contract * @param _name - name of the contract * @param _symbol - symbol of the contract * @param _baseURI - base URI for token URIs * @param _creator - creator address * @param _shouldComplete - Whether the collection should be completed by the end of this call * @param _isApproved - Whether the collection should be approved by the end of this call * @param _rarities - rarities address * @param _items - items to be added */ function initialize( string memory _name, string memory _symbol, string memory _baseURI, address _creator, bool _shouldComplete, bool _isApproved, IRarities _rarities, ItemParam[] memory _items ) external virtual { initImplementation(); require(_creator != address(0), "initialize: INVALID_CREATOR"); require(address(_rarities) != address(0), "initialize: INVALID_RARITIES"); // Ownable init _initOwnable(); // EIP712 init _initializeEIP712('Decentraland Collection', '2'); // ERC721 init _initERC721(_name, _symbol); // Base URI init setBaseURI(_baseURI); // Creator init creator = _creator; // Rarities init rarities = _rarities; // Items init _addItems(_items); if (_shouldComplete) { _completeCollection(); } isApproved = _isApproved; isEditable = true; createdAt = block.timestamp; } /* * Roles checkers */ function _isCreator() internal view returns (bool) { return creator == _msgSender(); } function _isManager(uint256 _itemId) internal view returns (bool) { address sender = _msgSender(); return globalManagers[sender] || itemManagers[_itemId][sender]; } modifier onlyCreator() { require( _isCreator(), "onlyCreator: CALLER_IS_NOT_CREATOR" ); _; } /* * Role functions */ /** * @notice Set allowed account to manage items. * @param _minters - minter addresses * @param _values - values array */ function setMinters(address[] calldata _minters, bool[] calldata _values) external onlyCreator { require( _minters.length == _values.length, "setMinters: LENGTH_MISMATCH" ); for (uint256 i = 0; i < _minters.length; i++) { address minter = _minters[i]; bool value = _values[i]; require(minter != address(0), "setMinters: INVALID_MINTER_ADDRESS"); require(globalMinters[minter] != value, "setMinters: VALUE_IS_THE_SAME"); globalMinters[minter] = value; emit SetGlobalMinter(minter, value); } } /** * @notice Set allowed account to mint items. * @param _itemIds - item ids * @param _minters - minter addresses * @param _values - values array */ function setItemsMinters( uint256[] calldata _itemIds, address[] calldata _minters, uint256[] calldata _values ) external onlyCreator { require( _itemIds.length == _minters.length && _minters.length == _values.length, "setItemsMinters: LENGTH_MISMATCH" ); for (uint256 i = 0; i < _minters.length; i++) { address minter = _minters[i]; uint256 itemId = _itemIds[i]; uint256 value = _values[i]; require(minter != address(0), "setItemsMinters: INVALID_MINTER_ADDRESS"); require(itemId < items.length, "setItemsMinters: ITEM_DOES_NOT_EXIST"); require(itemMinters[itemId][minter] != value, "setItemsMinters: VALUE_IS_THE_SAME"); itemMinters[itemId][minter] = value; emit SetItemMinter(itemId, minter, value); } } /** * @notice Set allowed account to manage items. * @param _managers - Address allowed to manage items * @param _values - Whether is allowed or not */ function setManagers(address[] calldata _managers, bool[] calldata _values) external onlyCreator { require( _managers.length == _values.length, "setManagers: LENGTH_MISMATCH" ); for (uint256 i = 0; i < _managers.length; i++) { address manager = _managers[i]; bool value = _values[i]; require(manager != address(0), "setManagers: INVALID_MANAGER_ADDRESS"); require(globalManagers[manager] != value, "setManagers: VALUE_IS_THE_SAME"); globalManagers[manager] = value; emit SetGlobalManager(manager, value); } } /** * @notice Set allowed account to manage items. * @param _itemIds - item ids to set managers * @param _managers - Addresses allowed to manage items * @param _values - Whether is allowed or not */ function setItemsManagers( uint256[] calldata _itemIds, address[] calldata _managers, bool[] calldata _values ) external onlyCreator { require( _itemIds.length == _managers.length && _managers.length == _values.length, "setItemsManagers: LENGTH_MISMATCH" ); for (uint256 i = 0; i < _managers.length; i++) { address manager = _managers[i]; uint256 itemId = _itemIds[i]; bool value = _values[i]; require(manager != address(0), "setItemsManagers: INVALID_MANAGER_ADDRESS"); require(itemId < items.length, "setItemsManagers: ITEM_DOES_NOT_EXIST"); require(itemManagers[itemId][manager] != value, "setItemsManagers: VALUE_IS_THE_SAME"); itemManagers[itemId][manager] = value; emit SetItemManager(itemId, manager, value); } } /** * @notice Transfers ownership of the contract to a new account (`newOwner`). * @dev Forced owner to check against msg.sender always */ function transferCreatorship(address _newCreator) external virtual { address sender = _msgSender(); require(sender == owner() || sender == creator, "transferCreatorship: CALLER_IS_NOT_OWNER_OR_CREATOR"); require(_newCreator != address(0), "transferCreatorship: INVALID_CREATOR_ADDRESS"); emit CreatorshipTransferred(creator, _newCreator); creator = _newCreator; } /* * Items functions */ /** * @notice Add items to the collection. * @param _items - items to add */ function addItems(ItemParam[] memory _items) external virtual onlyOwner { require(!isCompleted, "_addItem: COLLECTION_COMPLETED"); _addItems(_items); } /** * @notice Edit items * @param _itemIds - items ids to edit * @param _prices - new prices * @param _beneficiaries - new beneficiaries */ function editItemsData( uint256[] calldata _itemIds, uint256[] calldata _prices, address[] calldata _beneficiaries, string[] calldata _metadatas ) external virtual { // Check lengths require( _itemIds.length == _prices.length && _prices.length == _beneficiaries.length && _beneficiaries.length == _metadatas.length, "editItemsData: LENGTH_MISMATCH" ); require( isEditable, "editItemsData: COLLECTION_NOT_EDITABLE" ); // Check item id for (uint256 i = 0; i < _itemIds.length; i++) { uint256 itemId = _itemIds[i]; uint256 price = _prices[i]; address beneficiary = _beneficiaries[i]; string memory metadata = _metadatas[i]; require(_isCreator() || _isManager(itemId), "editItemsData: CALLER_IS_NOT_CREATOR_OR_MANAGER"); require(itemId < items.length, "editItemsData: ITEM_DOES_NOT_EXIST"); require( price > 0 && beneficiary != address(0) || price == 0 && beneficiary == address(0), "editItemsData: INVALID_PRICE_AND_BENEFICIARY" ); require(bytes(metadata).length > 0, "editItemsData: EMPTY_METADATA"); Item storage item = items[itemId]; require( !isApproved || keccak256(abi.encode(item.metadata)) == keccak256(abi.encode(metadata)), "editItemsData: CAN_NOT_EDIT_METADATA" ); item.price = price; item.beneficiary = beneficiary; item.metadata = metadata; emit UpdateItemData(itemId, price, beneficiary, metadata); } } /** * @notice Add new items to the collection. * @dev The item should follow: * rarity: should be one of the RARITY enum * totalSupply: starts in 0 * metadata: shouldn't be empty * price & beneficiary: is the price is > 0, a beneficiary should be passed. If not, price and * beneficiary should be empty. * contentHash: starts empty * @param _items - items to add */ function _addItems(ItemParam[] memory _items) internal { require(_items.length > 0, "_addItems: EMPTY_ITEMS"); IRarities.Rarity memory rarity; bytes32 lastRarityKey; for (uint256 i = 0; i < _items.length; i++) { ItemParam memory _item = _items[i]; bytes32 rarityKey = keccak256(bytes(_item.rarity)); if (lastRarityKey != rarityKey) { rarity = rarities.getRarityByName(_item.rarity); lastRarityKey = rarityKey; require( rarity.maxSupply > 0 && rarity.maxSupply <= MAX_ISSUED_ID, "_addItem: INVALID_RARITY" ); } require(bytes(_item.metadata).length > 0, "_addItem: EMPTY_METADATA"); require( _item.price > 0 && _item.beneficiary != address(0) || _item.price == 0 && _item.beneficiary == address(0), "_addItem: INVALID_PRICE_AND_BENEFICIARY" ); uint256 newItemId = items.length; require(newItemId < MAX_ITEM_ID, "_addItem: MAX_ITEM_ID_REACHED"); Item memory item = Item({ rarity: rarity.name, maxSupply: rarity.maxSupply, totalSupply: 0, price: _item.price, beneficiary: _item.beneficiary, metadata: _item.metadata, contentHash: '' }); items.push(item); emit AddItem(newItemId, item); } } /** * @notice Issue tokens by item ids. * @dev Will throw if the items have reached its maximum or is invalid * @param _beneficiaries - owner of the tokens * @param _itemIds - item ids */ function issueTokens(address[] calldata _beneficiaries, uint256[] calldata _itemIds) external virtual { require(isMintingAllowed(), "issueTokens: MINT_NOT_ALLOWED"); require(_beneficiaries.length == _itemIds.length, "issueTokens: LENGTH_MISMATCH"); address sender = _msgSender(); for (uint256 i = 0; i < _itemIds.length; i++) { _issueToken(_beneficiaries[i], _itemIds[i], sender); } } /** * @notice Issue a new token of the specified item. * @dev Will throw if the item has reached its maximum or is invalid * @param _beneficiary - owner of the token * @param _itemId - item id * @param _sender - transaction sender */ function _issueToken(address _beneficiary, uint256 _itemId, address _sender) internal virtual { if (!(_isCreator() || globalMinters[_sender])) { uint256 allowance = itemMinters[_itemId][_sender]; require(allowance > 0, "_issueToken: CALLER_CAN_NOT_MINT"); if (allowance != type(uint256).max) { itemMinters[_itemId][_sender]--; } } // Check item id require(_itemId < items.length, "_issueToken: ITEM_DOES_NOT_EXIST"); Item storage item = items[_itemId]; uint256 currentIssuance = item.totalSupply.add(1); // Check issuance require(currentIssuance <= item.maxSupply, "_issueToken: ITEM_EXHAUSTED"); // Encode token id uint256 tokenId = encodeTokenId(_itemId, currentIssuance); // Increase issuance item.totalSupply = currentIssuance; // Mint token to beneficiary super._mint(_beneficiary, tokenId); // Log emit Issue(_beneficiary, tokenId, _itemId, currentIssuance, _sender); } /** * @notice Rescue an item by providing new metadata and/or content hash * @dev Only the owner can rescue an item. This function should be used * to resolve a dispute or fix a broken metadata or hashContent item * @param _itemIds - Item ids to be fixed * @param _contentHashes - New items content hash * @param _metadatas - New items metadata */ function rescueItems( uint256[] calldata _itemIds, string[] calldata _contentHashes, string[] calldata _metadatas ) external onlyOwner { // Check lengths require( _itemIds.length == _contentHashes.length && _contentHashes.length == _metadatas.length, "rescueItems: LENGTH_MISMATCH" ); for (uint256 i = 0; i < _itemIds.length; i++) { uint256 itemId = _itemIds[i]; require(itemId < items.length, "rescueItems: ITEM_DOES_NOT_EXIST"); Item storage item = items[itemId]; string memory contentHash = _contentHashes[i]; string memory metadata = _metadatas[i]; item.contentHash = contentHash; if (bytes(metadata).length > 0) { item.metadata = metadata; } emit RescueItem(itemId, contentHash, item.metadata); } } /** * @notice Returns the amount of item in the collection * @return Amount of items in the collection */ function itemsCount() external view returns (uint256) { return items.length; } /* * Status functions */ /** * @notice Get whether minting is allowed * @return boolean whether minting is allowed or not */ function isMintingAllowed() public view returns (bool) { return isCompleted && isApproved; } /** * @notice Complete the collection. * @dev Disable forever the possibility of adding new items in the collection. * The issuance is still allowed. */ function completeCollection() external onlyCreator { require(!isCompleted, "completeCollection: COLLECTION_ALREADY_COMPLETED"); _completeCollection(); } /** * @notice Complete the collection. * @dev Internal. Disable forever the possibility of adding new items in the collection. * The issuance is still allowed. */ function _completeCollection() internal { isCompleted = true; emit Complete(); } /** * @notice Approve a collection */ function setApproved(bool _value) external virtual onlyOwner { require(isApproved != _value, "setApproved: VALUE_IS_THE_SAME"); emit SetApproved(isApproved, _value); isApproved = _value; } /** * @notice Set whether the collection can be editable or not. * @dev This property is used off-chain to check whether the items of the collection * can be updated or not * @param _value - Value to set */ function setEditable(bool _value) external onlyOwner { require(isEditable != _value, "setEditable: VALUE_IS_THE_SAME"); emit SetEditable(isEditable, _value); isEditable = _value; } /* * URI functions */ /** * @notice Set Base URI * @param _baseURI - base URI for token URIs */ function setBaseURI(string memory _baseURI) public onlyOwner { emit BaseURI(baseURI(), _baseURI); _setBaseURI(_baseURI); } /** * @notice Returns an URI for a given token ID. * Throws if the token ID does not exist. May return an empty string. * @param _tokenId - uint256 ID of the token queried * @return token URI */ function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) { require(_exists(_tokenId), "tokenURI: INVALID_TOKEN_ID"); (uint256 itemId, uint256 issuedId) = decodeTokenId(_tokenId); uint256 id; assembly { id := chainid() } return string( abi.encodePacked( baseURI(), id.uintToString(), "/", "0x", address(this).addressToString(), "/", itemId.uintToString(), "/", issuedId.uintToString() ) ); } /* * Batch Transfer functions */ /** * @notice Transfers the ownership of given tokens ID to another address. * Usage of this method is discouraged, use {safeBatchTransferFrom} whenever possible. * Requires the msg.sender to be the owner, approved, or operator. * @param _from current owner of the token * @param _to address to receive the ownership of the given token ID * @param _tokenIds uint256 ID of the token to be transferred */ function batchTransferFrom(address _from, address _to, uint256[] calldata _tokenIds) external { for (uint256 i = 0; i < _tokenIds.length; i++) { transferFrom(_from, _to, _tokenIds[i]); } } /** * @notice Safely transfers the ownership of given token IDs to another address * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received}, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the msg.sender to be the owner, approved, or operator * @param _from - current owner of the token * @param _to - address to receive the ownership of the given token ID * @param _tokenIds - uint256 ID of the tokens to be transferred * @param _data bytes data to send along with a safe transfer check */ function safeBatchTransferFrom(address _from, address _to, uint256[] memory _tokenIds, bytes memory _data) external { for (uint256 i = 0; i < _tokenIds.length; i++) { safeTransferFrom(_from, _to, _tokenIds[i], _data); } } /* * Token Utils functions */ /** * @notice Encode token id * @dev itemId (`itemIdBits` bits) + issuedId (`issuedIdBits` bits) * @param _itemId - item id * @param _issuedId - issued id * @return id uint256 of the encoded id */ function encodeTokenId(uint256 _itemId, uint256 _issuedId) public pure returns (uint256 id) { require(_itemId <= MAX_ITEM_ID, "encodeTokenId: INVALID_ITEM_ID"); require(_issuedId <= MAX_ISSUED_ID, "encodeTokenId: INVALID_ISSUED_ID"); // solium-disable-next-line security/no-inline-assembly assembly { id := or(shl(ISSUED_ID_BITS, _itemId), _issuedId) } } /** * @notice Decode token id * @dev itemId (`itemIdBits` bits) + issuedId (`issuedIdBits` bits) * @param _id - token id * @return itemId uint256 of the item id * @return issuedId uint256 of the issued id */ function decodeTokenId(uint256 _id) public pure returns (uint256 itemId, uint256 issuedId) { uint256 mask = MAX_ISSUED_ID; // solium-disable-next-line security/no-inline-assembly assembly { itemId := shr(ISSUED_ID_BITS, _id) issuedId := and(mask, _id) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "@openzeppelin/contracts/introspection/ERC165.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/EnumerableSet.sol"; import "@openzeppelin/contracts/utils/EnumerableMap.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "../commons/ContextMixin.sol"; /** * @title ERC721 Non-Fungible Token Standard basic implementation * This is the same contract at `openzeppelin/contracts 3.1.0` but `tokenURI` was changed to virtual override * @dev see https://eips.ethereum.org/EIPS/eip-721 */ abstract contract ERC721Initializable is ContextMixin, ERC165, IERC721, IERC721Metadata, IERC721Enumerable { using SafeMath for uint256; using Address for address; using EnumerableSet for EnumerableSet.UintSet; using EnumerableMap for EnumerableMap.UintToAddressMap; using Strings for uint256; // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; // Mapping from holder address to their (enumerable) set of owned tokens mapping (address => EnumerableSet.UintSet) private _holderTokens; // Enumerable mapping from token ids to their owners EnumerableMap.UintToAddressMap private _tokenOwners; // 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; // Token name string private _name; // Token symbol string private _symbol; // Optional mapping for token URIs mapping(uint256 => string) private _tokenURIs; // Base URI string private _baseURI; /* * bytes4(keccak256('balanceOf(address)')) == 0x70a08231 * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde * * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ * 0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd */ bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; /* * bytes4(keccak256('name()')) == 0x06fdde03 * bytes4(keccak256('symbol()')) == 0x95d89b41 * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd * * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f */ bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; /* * bytes4(keccak256('totalSupply()')) == 0x18160ddd * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 * * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 */ bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; constructor() {} /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ function _initERC721(string memory __name, string memory __symbol) internal { _name = __name; _symbol = __symbol; // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_INTERFACE_ID_ERC721); _registerInterface(_INTERFACE_ID_ERC721_METADATA); _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view override returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); return _holderTokens[owner].length(); } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view override returns (address) { return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token"); } /** * @dev See {IERC721Metadata-name}. */ function name() public view override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); string memory _tokenURI = _tokenURIs[tokenId]; // If there is no base URI, return the token URI. if (bytes(_baseURI).length == 0) { return _tokenURI; } // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked). if (bytes(_tokenURI).length > 0) { return string(abi.encodePacked(_baseURI, _tokenURI)); } // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI. return string(abi.encodePacked(_baseURI, tokenId.toString())); } /** * @dev Returns the base URI set via {_setBaseURI}. This will be * automatically added as a prefix in {tokenURI} to each token's URI, or * to the token ID if no specific URI is set for that token ID. */ function baseURI() public view returns (string memory) { return _baseURI; } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) { return _holderTokens[owner].at(index); } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view override returns (uint256) { // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds return _tokenOwners.length(); } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view override returns (uint256) { (uint256 tokenId, ) = _tokenOwners.at(index); return tokenId; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view override returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { require(operator != _msgSender(), "ERC721: approve to caller"); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view 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: transfer caller is not owner nor 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: transfer caller is not owner nor 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 mecanisms 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 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 returns (bool) { return _tokenOwners.contains(tokenId); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: d* * - `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); _holderTokens[to].add(tokenId); _tokenOwners.set(tokenId, to); emit Transfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); // Clear metadata (if any) if (bytes(_tokenURIs[tokenId]).length != 0) { delete _tokenURIs[tokenId]; } _holderTokens[owner].remove(tokenId); _tokenOwners.remove(tokenId); emit Transfer(owner, address(0), tokenId); } /** * @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(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _holderTokens[from].remove(tokenId); _holderTokens[to].add(tokenId); _tokenOwners.set(tokenId, to); emit Transfer(from, to, tokenId); } /** * @dev Sets `_tokenURI` as the tokenURI of `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual { require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token"); _tokenURIs[tokenId] = _tokenURI; } /** * @dev Internal function to set the base URI for all token IDs. It is * automatically added as a prefix to the value returned in {tokenURI}, * or to the token ID if {tokenURI} is empty. */ function _setBaseURI(string memory baseURI_) internal virtual { _baseURI = baseURI_; } /** * @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()) { return true; } bytes memory returndata = to.functionCall(abi.encodeWithSelector( IERC721Receiver(to).onERC721Received.selector, _msgSender(), from, tokenId, _data ), "ERC721: transfer to non ERC721Receiver implementer"); bytes4 retval = abi.decode(returndata, (bytes4)); return (retval == _ERC721_RECEIVED); } function _approve(address to, uint256 tokenId) private { _tokenApprovals[tokenId] = to; emit Approval(ownerOf(tokenId), to, tokenId); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; import "../../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`, 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 be 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: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * 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 Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @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 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); /** * @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; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <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 pragma solidity >=0.6.2 <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 tokenId); /** * @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 pragma solidity >=0.6.0 <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 `IERC721.onERC721Received.selector`. */ function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts may inherit from this and call {_registerInterface} to declare * their support of an interface. */ abstract contract ERC165 is IERC165 { /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Mapping of interface ids to whether or not it's supported. */ mapping(bytes4 => bool) private _supportedInterfaces; constructor () internal { // Derived contracts need only register support for their own interfaces, // we register support for ERC165 itself here _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev See {IERC165-supportsInterface}. * * Time complexity O(1), guaranteed to always use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev Registers the contract as an implementer of the interface defined by * `interfaceId`. Support of the actual ERC165 interface is automatic and * registering its interface id is not required. * * See {IERC165-supportsInterface}. * * Requirements: * * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). */ function _registerInterface(bytes4 interfaceId) internal virtual { require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); _supportedInterfaces[interfaceId] = true; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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 functionCall(target, data, "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"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(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) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(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) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { require(set._values.length > index, "EnumerableSet: index out of bounds"); return set._values[index]; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Library for managing an enumerable variant of Solidity's * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] * type. * * Maps have the following properties: * * - Entries are added, removed, and checked for existence in constant time * (O(1)). * - Entries are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableMap for EnumerableMap.UintToAddressMap; * * // Declare a set state variable * EnumerableMap.UintToAddressMap private myMap; * } * ``` * * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are * supported. */ library EnumerableMap { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Map type with // bytes32 keys and values. // The Map implementation uses private functions, and user-facing // implementations (such as Uint256ToAddressMap) are just wrappers around // the underlying Map. // This means that we can only create new EnumerableMaps for types that fit // in bytes32. struct MapEntry { bytes32 _key; bytes32 _value; } struct Map { // Storage of map keys and values MapEntry[] _entries; // Position of the entry defined by a key in the `entries` array, plus 1 // because index 0 means a key is not in the map. mapping (bytes32 => uint256) _indexes; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) { // We read and store the key's index to prevent multiple reads from the same storage slot uint256 keyIndex = map._indexes[key]; if (keyIndex == 0) { // Equivalent to !contains(map, key) map._entries.push(MapEntry({ _key: key, _value: value })); // The entry is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value map._indexes[key] = map._entries.length; return true; } else { map._entries[keyIndex - 1]._value = value; return false; } } /** * @dev Removes a key-value pair from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function _remove(Map storage map, bytes32 key) private returns (bool) { // We read and store the key's index to prevent multiple reads from the same storage slot uint256 keyIndex = map._indexes[key]; if (keyIndex != 0) { // Equivalent to contains(map, key) // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one // in the array, and then remove the last entry (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = keyIndex - 1; uint256 lastIndex = map._entries.length - 1; // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. MapEntry storage lastEntry = map._entries[lastIndex]; // Move the last entry to the index where the entry to delete is map._entries[toDeleteIndex] = lastEntry; // Update the index for the moved entry map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved entry was stored map._entries.pop(); // Delete the index for the deleted slot delete map._indexes[key]; return true; } else { return false; } } /** * @dev Returns true if the key is in the map. O(1). */ function _contains(Map storage map, bytes32 key) private view returns (bool) { return map._indexes[key] != 0; } /** * @dev Returns the number of key-value pairs in the map. O(1). */ function _length(Map storage map) private view returns (uint256) { return map._entries.length; } /** * @dev Returns the key-value pair stored at position `index` in the map. O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) { require(map._entries.length > index, "EnumerableMap: index out of bounds"); MapEntry storage entry = map._entries[index]; return (entry._key, entry._value); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) { uint256 keyIndex = map._indexes[key]; if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key) return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function _get(Map storage map, bytes32 key) private view returns (bytes32) { uint256 keyIndex = map._indexes[key]; require(keyIndex != 0, "EnumerableMap: nonexistent key"); // Equivalent to contains(map, key) return map._entries[keyIndex - 1]._value; // All indexes are 1-based } /** * @dev Same as {_get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {_tryGet}. */ function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) { uint256 keyIndex = map._indexes[key]; require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key) return map._entries[keyIndex - 1]._value; // All indexes are 1-based } // UintToAddressMap struct UintToAddressMap { Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { return _remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { return _contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToAddressMap storage map) internal view returns (uint256) { return _length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { (bytes32 key, bytes32 value) = _at(map._inner, index); return (uint256(key), address(uint160(uint256(value)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. * * _Available since v3.4._ */ function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key)); return (success, address(uint160(uint256(value)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { return address(uint160(uint256(_get(map._inner, bytes32(key))))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) { return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage)))); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev String operations. */ library Strings { /** * @dev Converts a `uint256` to its ASCII `string` representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); uint256 index = digits - 1; temp = value; while (temp != 0) { buffer[index--] = bytes1(uint8(48 + temp % 10)); temp /= 10; } return string(buffer); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <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 pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; import "./ERC721BaseCollectionV2.sol"; contract ERC721CollectionV2 is ERC721BaseCollectionV2 { constructor() {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; import "@openzeppelin/contracts/utils/Address.sol"; contract MinimalProxyFactory { using Address for address; address public implementation; bytes public code; bytes32 public codeHash; event ProxyCreated(address indexed _address, bytes32 _salt); event ImplementationSet(address indexed _implementation, bytes32 _codeHash, bytes _code); /** * @notice Create the contract * @param _implementation - contract implementation */ constructor(address _implementation) { _setImplementation(_implementation); } /** * @notice Create a contract * @param _salt - arbitrary 32 bytes hexa * @param _data - call data used to call the contract already created if passed * @return addr - address of the contract created */ function _createProxy(bytes32 _salt, bytes memory _data) internal virtual returns (address addr) { bytes memory slotcode = code; bytes32 salt = keccak256(abi.encodePacked(_salt, msg.sender, _data)); // solium-disable-next-line security/no-inline-assembly assembly { addr := create2(0, add(slotcode, 0x20), mload(slotcode), salt) } require(addr != address(0), "MinimalProxyFactory#createProxy: CREATION_FAILED"); emit ProxyCreated(addr, _salt); if (_data.length > 0) { (bool success,) = addr.call(_data); require(success, "MinimalProxyFactory#createProxy: CALL_FAILED"); } } /** * @notice Get a deterministics contract address * @param _salt - arbitrary 32 bytes hexa * @param _address - supposed sender of the transaction * @return address of the deterministic contract */ function getAddress(bytes32 _salt, address _address, bytes calldata _data) external view returns (address) { return address( uint256( keccak256( abi.encodePacked( byte(0xff), address(this), keccak256(abi.encodePacked(_salt, _address, _data)), codeHash ) ) ) ); } /** * @notice Set the contract implementation * @param _implementation - contract implementation */ function _setImplementation(address _implementation) internal { require( _implementation != address(0) && _implementation.isContract(), "MinimalProxyFactoryV2#_setImplementation: INVALID_IMPLEMENTATION" ); // Adapted from https://github.com/optionality/clone-factory/blob/32782f82dfc5a00d103a7e61a17a5dedbd1e8e9d/contracts/CloneFactory.sol code = abi.encodePacked( hex"3d602d80600a3d3981f3363d3d373d3d3d363d73", _implementation, hex"5af43d82803e903d91602b57fd5bf3" ); codeHash = keccak256(code); implementation = _implementation; emit ImplementationSet(implementation, codeHash, code); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; import "@openzeppelin/contracts/access/Ownable.sol"; import "../../commons/MinimalProxyFactory.sol"; contract ERC721CollectionFactoryV2 is Ownable, MinimalProxyFactory { address[] public collections; mapping(address => bool) public isCollectionFromFactory; /** * @notice Create the contract * @param _owner - contract owner * @param _implementation - contract implementation */ constructor(address _owner, address _implementation) MinimalProxyFactory(_implementation) { transferOwnership(_owner); } /** * @notice Create a collection * @param _salt - arbitrary 32 bytes hexa * @param _data - call data used to call the contract already created if passed * @return addr - address of the contract created */ function createCollection(bytes32 _salt, bytes memory _data) external onlyOwner returns (address addr) { // Deploy a new collection addr = _createProxy(_salt, _data); // Transfer ownership to the owner after deployment Ownable(addr).transferOwnership(owner()); // Set variables for handle data faster // This use storage and therefore make deployments expensive. collections.push(addr); isCollectionFromFactory[addr] = true; } /** * @notice Get the amount of collections deployed * @return amount of collections deployed */ function collectionsSize() external view returns (uint256) { return collections.length; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <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 () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { 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 { emit OwnershipTransferred(_owner, address(0)); _owner = 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"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <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 GSN 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 payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @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, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.7.6; import "@openzeppelin/contracts/access/Ownable.sol"; contract Forwarder is Ownable { address public caller; event CallerSet(address indexed _oldCaller, address indexed _newCaller); /** * @notice Create the contract * @param _owner - contract owner * @param _caller - target address to call */ constructor(address _owner, address _caller) { setCaller(_caller); transferOwnership(_owner); } /** * @notice Set the caller allowed to forward calls * @param _newCaller - target address to call */ function setCaller(address _newCaller) public onlyOwner { emit CallerSet(caller, _newCaller); caller = _newCaller; } /** * @notice Forward a call * @param _target - target address to call * @param _data - call data to be used * @return whether the call was a success or not * @return response in bytes if any */ function forwardCall(address _target, bytes calldata _data) external payable returns (bool, bytes memory) { require( msg.sender == caller || msg.sender == owner(), "Owner#forwardCall: UNAUTHORIZED_SENDER" ); return _target.call{value: msg.value}(_data); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../utils/Context.sol";
{ "optimizer": { "enabled": true, "runs": 1 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_itemId","type":"uint256"},{"components":[{"internalType":"string","name":"rarity","type":"string"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"string","name":"metadata","type":"string"},{"internalType":"string","name":"contentHash","type":"string"}],"indexed":false,"internalType":"struct ERC721BaseCollectionV2.Item","name":"_item","type":"tuple"}],"name":"AddItem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_oldBaseURI","type":"string"},{"indexed":false,"internalType":"string","name":"_newBaseURI","type":"string"}],"name":"BaseURI","type":"event"},{"anonymous":false,"inputs":[],"name":"Complete","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_previousCreator","type":"address"},{"indexed":true,"internalType":"address","name":"_newCreator","type":"address"}],"name":"CreatorshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_beneficiary","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_itemId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_issuedId","type":"uint256"},{"indexed":false,"internalType":"address","name":"_caller","type":"address"}],"name":"Issue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","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":"uint256","name":"_itemId","type":"uint256"},{"indexed":false,"internalType":"string","name":"_contentHash","type":"string"},{"indexed":false,"internalType":"string","name":"_metadata","type":"string"}],"name":"RescueItem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_previousValue","type":"bool"},{"indexed":false,"internalType":"bool","name":"_newValue","type":"bool"}],"name":"SetApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_previousValue","type":"bool"},{"indexed":false,"internalType":"bool","name":"_newValue","type":"bool"}],"name":"SetEditable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_manager","type":"address"},{"indexed":false,"internalType":"bool","name":"_value","type":"bool"}],"name":"SetGlobalManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_minter","type":"address"},{"indexed":false,"internalType":"bool","name":"_value","type":"bool"}],"name":"SetGlobalMinter","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_itemId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_manager","type":"address"},{"indexed":false,"internalType":"bool","name":"_value","type":"bool"}],"name":"SetItemManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_itemId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"SetItemMinter","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_itemId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_price","type":"uint256"},{"indexed":false,"internalType":"address","name":"_beneficiary","type":"address"},{"indexed":false,"internalType":"string","name":"_metadata","type":"string"}],"name":"UpdateItemData","type":"event"},{"inputs":[],"name":"COLLECTION_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ISSUED_ID_BITS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ITEM_ID_BITS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ISSUED_ID","outputs":[{"internalType":"uint216","name":"","type":"uint216"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ITEM_ID","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"rarity","type":"string"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"string","name":"metadata","type":"string"}],"internalType":"struct ERC721BaseCollectionV2.ItemParam[]","name":"_items","type":"tuple[]"}],"name":"addItems","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"batchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"completeCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"createdAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"creator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"decodeTokenId","outputs":[{"internalType":"uint256","name":"itemId","type":"uint256"},{"internalType":"uint256","name":"issuedId","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_itemIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_prices","type":"uint256[]"},{"internalType":"address[]","name":"_beneficiaries","type":"address[]"},{"internalType":"string[]","name":"_metadatas","type":"string[]"}],"name":"editItemsData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_itemId","type":"uint256"},{"internalType":"uint256","name":"_issuedId","type":"uint256"}],"name":"encodeTokenId","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"globalManagers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"globalMinters","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_baseURI","type":"string"},{"internalType":"address","name":"_creator","type":"address"},{"internalType":"bool","name":"_shouldComplete","type":"bool"},{"internalType":"bool","name":"_isApproved","type":"bool"},{"internalType":"contract IRarities","name":"_rarities","type":"address"},{"components":[{"internalType":"string","name":"rarity","type":"string"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"string","name":"metadata","type":"string"}],"internalType":"struct ERC721BaseCollectionV2.ItemParam[]","name":"_items","type":"tuple[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isCompleted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isEditable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMintingAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_beneficiaries","type":"address[]"},{"internalType":"uint256[]","name":"_itemIds","type":"uint256[]"}],"name":"issueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"itemManagers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"itemMinters","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"items","outputs":[{"internalType":"string","name":"rarity","type":"string"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"string","name":"metadata","type":"string"},{"internalType":"string","name":"contentHash","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"itemsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rarities","outputs":[{"internalType":"contract IRarities","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_itemIds","type":"uint256[]"},{"internalType":"string[]","name":"_contentHashes","type":"string[]"},{"internalType":"string[]","name":"_metadatas","type":"string[]"}],"name":"rescueItems","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_value","type":"bool"}],"name":"setApproved","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_value","type":"bool"}],"name":"setEditable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_itemIds","type":"uint256[]"},{"internalType":"address[]","name":"_managers","type":"address[]"},{"internalType":"bool[]","name":"_values","type":"bool[]"}],"name":"setItemsManagers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_itemIds","type":"uint256[]"},{"internalType":"address[]","name":"_minters","type":"address[]"},{"internalType":"uint256[]","name":"_values","type":"uint256[]"}],"name":"setItemsMinters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_managers","type":"address[]"},{"internalType":"bool[]","name":"_values","type":"bool[]"}],"name":"setManagers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_minters","type":"address[]"},{"internalType":"bool[]","name":"_values","type":"bool[]"}],"name":"setMinters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newCreator","type":"address"}],"name":"transferCreatorship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50620000246301ffc9a760e01b6200002a565b620000b2565b6001600160e01b031980821614156200008a576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152600160208190526040909120805460ff19169091179055565b615de880620000c26000396000f3fe6080604052600436106102bd5760003560e01c806301ffc9a7146102c257806302d05d3f146102f857806306fdde031461031a578063081812fc1461033c578063095ea7b31461035c5780630c53c51c1461037e5780630ebde06e1461039157806318160ddd146103b1578063239a603b146103d357806323b872dd146103f357806328cfbd461461041357806328f371aa146104335780632b481883146104485780632cb0d48a1461045d5780632d0335ab1461047d5780632f745c591461049d57806330127574146104bd5780633408e470146104d2578063392e53cd146104e75780633992cd0d146104fc5780633bdcc923146105115780633c9636551461053157806341bceced14610551578063425f60ed1461057157806342842e0e1461059157806346d5a568146105b157806348622018146105d15780634f6ccce7146105f357806355f804b3146106135780635ec7c537146106335780636352211e146106555780636c0360eb146106755780636d2e4b1b1461068a5780636d67b1ab146106aa57806370a08231146106ca578063715018a6146106ea5780637682dfca146106ff5780637c8f76a11461071f5780637e12acce1461073f5780637efd9112146107545780638da5cb5b14610782578063950fa9041461079757806395d89b41146107ac578063a22cb465146107c1578063b4c2025e146107e1578063b4da4e3714610801578063b88d4fde14610816578063be4763b314610836578063bfb231d214610856578063c87b56dd14610889578063cf09e0d0146108a9578063d14fee77146108be578063e2c03ace146108de578063e6170a53146108f3578063e985e9c514610913578063ebd46d6414610933578063f2fde38b14610953578063f3993d1114610973578063f59d9e3f14610993578063f698da25146109a8578063f6f07b63146109bd578063fa391c64146109df575b600080fd5b3480156102ce57600080fd5b506102e26102dd36600461488e565b6109f4565b6040516102ef9190614c4d565b60405180910390f35b34801561030457600080fd5b5061030d610a17565b6040516102ef9190614c39565b34801561032657600080fd5b5061032f610a26565b6040516102ef9190614c73565b34801561034857600080fd5b5061030d610357366004614a95565b610abd565b34801561036857600080fd5b5061037c6103773660046145f2565b610b1f565b005b61032f61038c366004614578565b610bf5565b34801561039d57600080fd5b5061037c6103ac3660046147b6565b610ee2565b3480156103bd57600080fd5b506103c66111fa565b6040516102ef9190614c6a565b3480156103df57600080fd5b5061037c6103ee3660046146ab565b61120b565b3480156103ff57600080fd5b5061037c61040e3660046144a7565b6113d2565b34801561041f57600080fd5b5061037c61042e3660046143ca565b611429565b34801561043f57600080fd5b506102e2611463565b34801561045457600080fd5b506102e2611473565b34801561046957600080fd5b5061037c610478366004614874565b611499565b34801561048957600080fd5b506103c6610498366004614314565b611585565b3480156104a957600080fd5b506103c66104b83660046145f2565b6115a0565b3480156104c957600080fd5b5061037c6115cb565b3480156104de57600080fd5b506103c66115fd565b3480156104f357600080fd5b506102e2611601565b34801561050857600080fd5b5061030d61160a565b34801561051d57600080fd5b5061037c61052c36600461461d565b611619565b34801561053d57600080fd5b5061037c61054c366004614740565b61177c565b34801561055d57600080fd5b5061037c61056c36600461461d565b611992565b34801561057d57600080fd5b5061037c61058c366004614679565b611af5565b34801561059d57600080fd5b5061037c6105ac3660046144a7565b611b81565b3480156105bd57600080fd5b5061037c6105cc366004614874565b611b9c565b3480156105dd57600080fd5b506105e6611c8b565b6040516102ef919061592c565b3480156105ff57600080fd5b506103c661060e366004614a95565b611c94565b34801561061f57600080fd5b5061037c61062e3660046148b6565b611caa565b34801561063f57600080fd5b50610648611d4b565b6040516102ef919061593e565b34801561066157600080fd5b5061030d610670366004614a95565b611d50565b34801561068157600080fd5b5061032f611d78565b34801561069657600080fd5b5061037c6106a5366004614314565b611dd9565b3480156106b657600080fd5b506103c66106c5366004614aad565b611eb8565b3480156106d657600080fd5b506103c66106e5366004614314565b611ed5565b3480156106f657600080fd5b5061037c611f3d565b34801561070b57600080fd5b506102e261071a366004614314565b611fcd565b34801561072b57600080fd5b5061037c61073a36600461461d565b611fe2565b34801561074b57600080fd5b506103c6612089565b34801561076057600080fd5b5061077461076f366004614a95565b6120ad565b6040516102ef92919061591e565b34801561078e57600080fd5b5061030d6120c1565b3480156107a357600080fd5b506106486120d0565b3480156107b857600080fd5b5061032f6120d5565b3480156107cd57600080fd5b5061037c6107dc366004614544565b612136565b3480156107ed57600080fd5b506102e26107fc366004614314565b612237565b34801561080d57600080fd5b506102e261224c565b34801561082257600080fd5b5061037c6108313660046144e7565b61225b565b34801561084257600080fd5b506102e2610851366004614aad565b6122b9565b34801561086257600080fd5b50610876610871366004614a95565b6122d9565b6040516102ef9796959493929190614cd9565b34801561089557600080fd5b5061032f6108a4366004614a95565b6124d1565b3480156108b557600080fd5b506103c6612563565b3480156108ca57600080fd5b5061037c6108d93660046148e8565b612569565b3480156108ea57600080fd5b506103c66126a5565b3480156108ff57600080fd5b5061037c61090e366004614740565b6126ab565b34801561091f57600080fd5b506102e261092e366004614330565b61284d565b34801561093f57600080fd5b506103c661094e366004614ad1565b61287b565b34801561095f57600080fd5b5061037c61096e366004614314565b6128d4565b34801561097f57600080fd5b5061037c61098e366004614368565b6129ba565b34801561099f57600080fd5b5061037c6129ea565b3480156109b457600080fd5b506103c6612a40565b3480156109c957600080fd5b506109d2612a46565b6040516102ef91906158c9565b3480156109eb57600080fd5b506102e2612a51565b6001600160e01b0319811660009081526001602052604090205460ff165b919050565b600e546001600160a01b031681565b60078054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ab25780601f10610a8757610100808354040283529160200191610ab2565b820191906000526020600020905b815481529060010190602001808311610a9557829003601f168201915b505050505090505b90565b6000610ac882612a5f565b610b035760405162461bcd60e51b815260040180806020018281038252602c815260200180615cac602c913960400191505060405180910390fd5b506000908152600560205260409020546001600160a01b031690565b6000610b2a82611d50565b9050806001600160a01b0316836001600160a01b03161415610b7d5760405162461bcd60e51b8152600401808060200182810382526021815260200180615d616021913960400191505060405180910390fd5b806001600160a01b0316610b8f612a6c565b6001600160a01b03161480610bab5750610bab8161092e612a6c565b610be65760405162461bcd60e51b8152600401808060200182810382526038815260200180615bd86038913960400191505060405180910390fd5b610bf08383612ac8565b505050565b60408051606081810183526001600160a01b0388166000818152600c602090815290859020548452830152918101869052610c338782878787612b36565b610c6e5760405162461bcd60e51b815260040180806020018281038252603d815260200180615b9b603d913960400191505060405180910390fd5b6001600160a01b0387166000908152600c6020526040902054610c92906001612c23565b600c6000896001600160a01b03166001600160a01b03168152602001908152602001600020819055507f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b87338860405180846001600160a01b03168152602001836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610d3a578181015183820152602001610d22565b50505050905090810190601f168015610d675780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a1600080306001600160a01b031634898b6040516020018083805190602001908083835b60208310610db85780518252601f199092019160209182019101610d99565b6001836020036101000a038019825116818451168082178552505050505050905001826001600160a01b031660601b8152601401925050506040516020818303038152906040526040518082805190602001908083835b60208310610e2e5780518252601f199092019160209182019101610e0f565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114610e90576040519150601f19603f3d011682016040523d82523d6000602084013e610e95565b606091505b509150915081610ed65760405162461bcd60e51b8152600401808060200182810382526027815260200180615c856027913960400191505060405180910390fd5b98975050505050505050565b8685148015610ef057508483145b8015610efb57508281145b610f205760405162461bcd60e51b8152600401610f1790614d57565b60405180910390fd5b60155462010000900460ff16610f485760405162461bcd60e51b8152600401610f179061557a565b60005b878110156111ef576000898983818110610f6157fe5b9050602002013590506000888884818110610f7857fe5b9050602002013590506000878785818110610f8f57fe5b9050602002016020810190610fa49190614314565b90506000868686818110610fb457fe5b9050602002810190610fc6919061594c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293506110079250612c7b915050565b80611016575061101684612c9b565b6110325760405162461bcd60e51b8152600401610f17906155c0565b60135484106110535760405162461bcd60e51b8152600401610f17906154ec565b60008311801561106b57506001600160a01b03821615155b8061108657508215801561108657506001600160a01b038216155b6110a25760405162461bcd60e51b8152600401610f1790614dc4565b60008151116110c35760405162461bcd60e51b8152600401610f1790615453565b6000601385815481106110d257fe5b90600052602060002090600702019050601560039054906101000a900460ff16158061114c57508160405160200161110a9190614c73565b60405160208183030381529060405280519060200120816005016040516020016111349190614d44565b60405160208183030381529060405280519060200120145b6111685760405162461bcd60e51b8152600401610f17906156d4565b600381018490556004810180546001600160a01b0319166001600160a01b03851617905581516111a190600583019060208501906140b7565b50847fc3835f7dd5063bbc8fdc7077944498159008d73d30bf55fe6513e683c8c382098585856040516111d6939291906158f4565b60405180910390a2505060019093019250610f4b915050565b505050505050505050565b60006112066003612cf9565b905090565b611213612c7b565b61122f5760405162461bcd60e51b8152600401610f1790615373565b848314801561123d57508281145b6112595760405162461bcd60e51b8152600401610f17906152c7565b60005b838110156113c957600085858381811061127257fe5b90506020020160208101906112879190614314565b9050600088888481811061129757fe5b90506020020135905060008585858181106112ae57fe5b90506020020160208101906112c39190614874565b90506001600160a01b0383166112eb5760405162461bcd60e51b8152600401610f1790615654565b601354821061130c5760405162461bcd60e51b8152600401610f179061560f565b60008281526012602090815260408083206001600160a01b038716845290915290205460ff16151581151514156113555760405162461bcd60e51b8152600401610f17906157fd565b60008281526012602090815260408083206001600160a01b038716808552925291829020805460ff1916841515179055905183907f1271b13cf757efd2a177fe5f26c2111b69ce904f1d0e3372832dc4e4773298cc906113b6908590614c4d565b60405180910390a350505060010161125c565b50505050505050565b6113e36113dd612a6c565b82612d04565b61141e5760405162461bcd60e51b8152600401808060200182810382526031815260200180615d826031913960400191505060405180910390fd5b610bf0838383612da8565b60005b825181101561145c57611454858585848151811061144657fe5b60200260200101518561225b565b60010161142c565b5050505050565b6015546301000000900460ff1681565b601554600090610100900460ff1680156112065750506015546301000000900460ff1690565b6114a1612a6c565b6000546001600160a01b039081169116146114f1576040805162461bcd60e51b81526020600482018190526024820152600080516020615cd8833981519152604482015290519081900360640190fd5b60155460ff6201000090910416151581151514156115215760405162461bcd60e51b8152600401610f1790614e10565b7fc8ca126810b77bfdcb10ae82ef3bc72619d404f9e3c4bf2057f03f057dcf230a601560029054906101000a900460ff1682604051611561929190614c58565b60405180910390a160158054911515620100000262ff000019909216919091179055565b6001600160a01b03166000908152600c602052604090205490565b6001600160a01b03821660009081526002602052604081206115c29083612ee2565b90505b92915050565b60155460ff16156115ee5760405162461bcd60e51b8152600401610f17906150ed565b6015805460ff19166001179055565b4690565b60155460ff1681565b600d546001600160a01b031681565b611621612c7b565b61163d5760405162461bcd60e51b8152600401610f1790615373565b82811461165c5760405162461bcd60e51b8152600401610f17906153b5565b60005b8381101561145c57600085858381811061167557fe5b905060200201602081019061168a9190614314565b9050600084848481811061169a57fe5b90506020020160208101906116af9190614874565b90506001600160a01b0382166116d75760405162461bcd60e51b8152600401610f1790614ecf565b6001600160a01b03821660009081526010602052604090205460ff16151581151514156117165760405162461bcd60e51b8152600401610f1790615214565b6001600160a01b03821660008181526010602052604090819020805460ff1916841515179055517f68bb2af98a57ecc88afb707f2d75e1e253c3e30191071548355731e21322a4329061176a908490614c4d565b60405180910390a2505060010161165f565b611784612a6c565b6000546001600160a01b039081169116146117d4576040805162461bcd60e51b81526020600482018190526024820152600080516020615cd8833981519152604482015290519081900360640190fd5b84831480156117e257508281145b6117fe5760405162461bcd60e51b8152600401610f1790614d8e565b60005b858110156113c957600087878381811061181757fe5b90506020020135905060138054905081106118445760405162461bcd60e51b8152600401610f17906151df565b60006013828154811061185357fe5b90600052602060002090600702019050600087878581811061187157fe5b9050602002810190611883919061594c565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394508992508891508790508181106118c857fe5b90506020028101906118da919061594c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250508451929350611926926006870192506020860191506140b7565b5080511561194557805161194390600585019060208401906140b7565b505b837f87a972ab2db2d47a0bbefe72cefc4fe5a38b1b9d2bc4b9f366b59fdb6dbd9581838560050160405161197a929190614cb4565b60405180910390a25050600190920191506118019050565b61199a612c7b565b6119b65760405162461bcd60e51b8152600401610f1790615373565b8281146119d55760405162461bcd60e51b8152600401610f179061524b565b60005b8381101561145c5760008585838181106119ee57fe5b9050602002016020810190611a039190614314565b90506000848484818110611a1357fe5b9050602002016020810190611a289190614874565b90506001600160a01b038216611a505760405162461bcd60e51b8152600401610f1790614fb6565b6001600160a01b0382166000908152600f602052604090205460ff1615158115151415611a8f5760405162461bcd60e51b8152600401610f179061574f565b6001600160a01b0382166000818152600f602052604090819020805460ff1916841515179055517f27defe4b442489e757345f4f743096c5db8d2399e1474bb9653118cdf531386990611ae3908490614c4d565b60405180910390a250506001016119d8565b611afd612a6c565b6000546001600160a01b03908116911614611b4d576040805162461bcd60e51b81526020600482018190526024820152600080516020615cd8833981519152604482015290519081900360640190fd5b601554610100900460ff1615611b755760405162461bcd60e51b8152600401610f1790615124565b611b7e81612eee565b50565b610bf08383836040518060200160405280600081525061225b565b611ba4612a6c565b6000546001600160a01b03908116911614611bf4576040805162461bcd60e51b81526020600482018190526024820152600080516020615cd8833981519152604482015290519081900360640190fd5b60155460ff63010000009091041615158115151415611c255760405162461bcd60e51b8152600401610f1790614f7f565b7f9ea3c7bd2b8ff87a3768286a529f5932ca385584c8ddf42eea8eade2ac1fb121601560039054906101000a900460ff1682604051611c65929190614c58565b60405180910390a16015805491151563010000000263ff00000019909216919091179055565b64ffffffffff81565b600080611ca260038461322a565b509392505050565b611cb2612a6c565b6000546001600160a01b03908116911614611d02576040805162461bcd60e51b81526020600482018190526024820152600080516020615cd8833981519152604482015290519081900360640190fd5b7fb8fdf10126d507f6daf46465ec25a2bbc08449cf6c944c98219264161391040a611d2b611d78565b82604051611d3a929190614c86565b60405180910390a1611b7e81613248565b602881565b60006115c582604051806060016040528060298152602001615c3a602991396003919061325f565b600a8054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ab25780601f10610a8757610100808354040283529160200191610ab2565b6000611de3612a6c565b9050611ded6120c1565b6001600160a01b0316816001600160a01b03161480611e195750600e546001600160a01b038281169116145b611e355760405162461bcd60e51b8152600401610f1790614e7c565b6001600160a01b038216611e5b5760405162461bcd60e51b8152600401610f179061552e565b600e546040516001600160a01b038085169216907ff25c6226b06a6bf4b2c2391bb66962bb4290c323cf8b5814efb185aba3f42d5f90600090a350600e80546001600160a01b0319166001600160a01b0392909216919091179055565b601160209081526000928352604080842090915290825290205481565b60006001600160a01b038216611f1c5760405162461bcd60e51b815260040180806020018281038252602a815260200180615c10602a913960400191505060405180910390fd5b6001600160a01b03821660009081526002602052604090206115c590612cf9565b611f45612a6c565b6000546001600160a01b03908116911614611f95576040805162461bcd60e51b81526020600482018190526024820152600080516020615cd8833981519152604482015290519081900360640190fd5b600080546040516001600160a01b0390911690600080516020615cf8833981519152908390a3600080546001600160a01b0319169055565b60106020526000908152604090205460ff1681565b611fea611473565b6120065760405162461bcd60e51b8152600401610f1790614f13565b8281146120255760405162461bcd60e51b8152600401610f179061533d565b600061202f612a6c565b905060005b828110156120815761207986868381811061204b57fe5b90506020020160208101906120609190614314565b85858481811061206c57fe5b905060200201358461326c565b600101612034565b505050505050565b7f085858259777fa9b13d1b7719cc0a9d4d012e29b100679e2974863bab94a0c1a81565b60d881901c916001600160d81b0390911690565b6000546001600160a01b031690565b60d881565b60088054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ab25780601f10610a8757610100808354040283529160200191610ab2565b61213e612a6c565b6001600160a01b0316826001600160a01b031614156121a0576040805162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b604482015290519081900360640190fd5b80600660006121ad612a6c565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff1916921515929092179091556121f1612a6c565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b600f6020526000908152604090205460ff1681565b60155462010000900460ff1681565b61226c612266612a6c565b83612d04565b6122a75760405162461bcd60e51b8152600401808060200182810382526031815260200180615d826031913960400191505060405180910390fd5b6122b3848484846133fd565b50505050565b601260209081526000928352604080842090915290825290205460ff1681565b601381815481106122e957600080fd5b60009182526020918290206007919091020180546040805160026001841615610100026000190190931692909204601f8101859004850283018501909152808252919350918391908301828280156123825780601f1061235757610100808354040283529160200191612382565b820191906000526020600020905b81548152906001019060200180831161236557829003601f168201915b5050506001808501546002808701546003880154600489015460058a018054604080516020601f6000199b851615610100029b909b01909316979097049889018290048202870182019052878652999a95999398509196506001600160a01b03169490918301828280156124375780601f1061240c57610100808354040283529160200191612437565b820191906000526020600020905b81548152906001019060200180831161241a57829003601f168201915b5050505060068301805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529495949350908301828280156124c75780601f1061249c576101008083540402835291602001916124c7565b820191906000526020600020905b8154815290600101906020018083116124aa57829003601f168201915b5050505050905087565b60606124dc82612a5f565b6124f85760405162461bcd60e51b8152600401610f17906151ab565b600080612504846120ad565b909250905046612512611d78565b61251b8261344f565b61252430613529565b61252d8661344f565b6125368661344f565b60405160200161254a959493929190614ba1565b6040516020818303038152906040529350505050919050565b60145481565b6125716115cb565b6001600160a01b0385166125975760405162461bcd60e51b8152600401610f1790614f4a565b6001600160a01b0382166125bd5760405162461bcd60e51b8152600401610f179061541d565b6125c561361e565b612617604051806040016040528060178152602001762232b1b2b73a3930b630b7321021b7b63632b1ba34b7b760491b815250604051806040016040528060018152602001601960f91b815250613662565b61262188886136f3565b61262a86611caa565b600e80546001600160a01b038088166001600160a01b031992831617909255600d80549285169290911691909117905561266381612eee565b83156126715761267161374b565b50506015805462ff00001992151563010000000263ff00000019909116179190911662010000179055505042601455505050565b60135490565b6126b3612c7b565b6126cf5760405162461bcd60e51b8152600401610f1790615373565b84831480156126dd57508281145b6126f95760405162461bcd60e51b8152600401610f1790615308565b60005b838110156113c957600085858381811061271257fe5b90506020020160208101906127279190614314565b9050600088888481811061273757fe5b905060200201359050600085858581811061274e57fe5b60200291909101359150506001600160a01b03831661277f5760405162461bcd60e51b8152600401610f1790614ff8565b60135482106127a05760405162461bcd60e51b8152600401610f1790615074565b60008281526011602090815260408083206001600160a01b03871684529091529020548114156127e25760405162461bcd60e51b8152600401610f1790615786565b60008281526011602090815260408083206001600160a01b038716808552925291829020839055905183907f45a634291439a8ec187e2b70279696615889c34c17c3a1208a7f85544e13b5659061283a908590614c6a565b60405180910390a35050506001016126fc565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b600064ffffffffff8311156128a25760405162461bcd60e51b8152600401610f1790615718565b6001600160d81b038211156128c95760405162461bcd60e51b8152600401610f1790614e47565b5060d89190911b1790565b6128dc612a6c565b6000546001600160a01b0390811691161461292c576040805162461bcd60e51b81526020600482018190526024820152600080516020615cd8833981519152604482015290519081900360640190fd5b6001600160a01b0381166129715760405162461bcd60e51b8152600401808060200182810382526026815260200180615ad66026913960400191505060405180910390fd5b600080546040516001600160a01b0380851693921691600080516020615cf883398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60005b8181101561145c576129e285858585858181106129d657fe5b905060200201356113d2565b6001016129bd565b6129f2612c7b565b612a0e5760405162461bcd60e51b8152600401610f1790615373565b601554610100900460ff1615612a365760405162461bcd60e51b8152600401610f179061515b565b612a3e61374b565b565b600b5481565b6001600160d81b0381565b601554610100900460ff1681565b60006115c5600383613785565b600033301415612ac357600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b03169150610aba9050565b503390565b600081815260056020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612afd82611d50565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006001600160a01b038616612b90576040805162461bcd60e51b815260206004820152601a6024820152792726aa11bb32b934b33c9d1024a72b20a624a22fa9a4a3a722a960311b604482015290519081900360640190fd5b6001612ba3612b9e87613791565b613814565b83868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612bfa573d6000803e3d6000fd5b505050602060405103516001600160a01b0316866001600160a01b031614905095945050505050565b6000828201838110156115c2576040805162461bcd60e51b815260206004820152601b60248201527a536166654d6174683a206164646974696f6e206f766572666c6f7760281b604482015290519081900360640190fd5b6000612c85612a6c565b600e546001600160a01b03908116911614905090565b600080612ca6612a6c565b6001600160a01b03811660009081526010602052604090205490915060ff1680612cf2575060008381526012602090815260408083206001600160a01b038516845290915290205460ff165b9392505050565b60006115c582613852565b6000612d0f82612a5f565b612d4a5760405162461bcd60e51b815260040180806020018281038252602c815260200180615b6f602c913960400191505060405180910390fd5b6000612d5583611d50565b9050806001600160a01b0316846001600160a01b03161480612d905750836001600160a01b0316612d8584610abd565b6001600160a01b0316145b80612da05750612da0818561284d565b949350505050565b826001600160a01b0316612dbb82611d50565b6001600160a01b031614612e005760405162461bcd60e51b8152600401808060200182810382526029815260200180615d186029913960400191505060405180910390fd5b6001600160a01b038216612e455760405162461bcd60e51b8152600401808060200182810382526024815260200180615b4b6024913960400191505060405180910390fd5b612e50838383610bf0565b612e5b600082612ac8565b6001600160a01b0383166000908152600260205260409020612e7d9082613856565b506001600160a01b0382166000908152600260205260409020612ea09082613862565b50612ead6003828461386e565b5080826001600160a01b0316846001600160a01b0316600080516020615d4183398151915260405160405180910390a4505050565b60006115c28383613884565b6000815111612f0f5760405162461bcd60e51b8152600401610f179061548a565b612f17614143565b6000805b83518110156122b3576000848281518110612f3257fe5b602002602001015190506000816000015180519060200120905080841461301757600d54825160405163b526233360e01b81526001600160a01b039092169163b526233391612f8391600401614c73565b60006040518083038186803b158015612f9b57600080fd5b505afa158015612faf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612fd791908101906149d2565b945080935060008560200151118015612ffb575060208501516001600160d81b0310155b6130175760405162461bcd60e51b8152600401610f17906153eb565b60008260600151511161303c5760405162461bcd60e51b8152600401610f17906154ba565b6000826020015111801561305c575060408201516001600160a01b031615155b8061307f5750602082015115801561307f575060408201516001600160a01b0316155b61309b5760405162461bcd60e51b8152600401610f1790615280565b60135464ffffffffff81106130c25760405162461bcd60e51b8152600401610f179061569d565b6040805160e0810182528751815260208089015181830152600082840181905286820151606080850191909152878501516001600160a01b0316608085015287015160a0840152835180830190945280845260c0830193909352601380546001810182559352815180519293849360079091027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09001926131669284929101906140b7565b506020828101516001830155604083015160028301556060830151600383015560808301516004830180546001600160a01b0319166001600160a01b0390921691909117905560a083015180516131c392600585019201906140b7565b5060c082015180516131df9160068401916020909101906140b7565b505050817f1464db75caec2c4f1b56b5246ef01a229ff5edc3b0fcf9b2953fec53b3987d8f826040516132129190615840565b60405180910390a2505060019092019150612f1b9050565b600080808061323986866138e8565b909450925050505b9250929050565b805161325b90600a9060208401906140b7565b5050565b6000612da0848484613963565b613274612c7b565b8061329757506001600160a01b0381166000908152600f602052604090205460ff165b6133115760008281526011602090815260408083206001600160a01b0385168452909152902054806132db5760405162461bcd60e51b8152600401610f17906157c8565b600019811461330f5760008381526011602090815260408083206001600160a01b0386168452909152902080546000190190555b505b60135482106133325760405162461bcd60e51b8152600401610f179061503f565b60006013838154811061334157fe5b90600052602060002090600702019050600061336b60018360020154612c2390919063ffffffff16565b905081600101548111156133915760405162461bcd60e51b8152600401610f17906150b8565b600061339d858361287b565b6002840183905590506133b08682613a2d565b8481876001600160a01b03167f57e2fe3f4d57a597e655a893f43c395d7dc18cb9c9c1898eda75cc0ad760852585886040516133ed9291906158dd565b60405180910390a4505050505050565b613408848484612da8565b61341484848484613b48565b6122b35760405162461bcd60e51b8152600401808060200182810382526032815260200180615a616032913960400191505060405180910390fd5b606081806134765750506040805180820190915260018152600360fc1b6020820152610a12565b8060005b811561348e57600101600a8204915061347a565b6000816001600160401b03811180156134a657600080fd5b506040519080825280601f01601f1916602001820160405280156134d1576020820181803683370190505b50905060001982015b841561351f57600a850660300160f81b828280600190039350815181106134fd57fe5b60200101906001600160f81b031916908160001a905350600a850494506134da565b5095945050505050565b60408051602880825260608281019093526000919060208201818036833701905050905060005b60148110156136175760008160130360080260020a856001600160a01b03168161357657fe5b0460f81b9050600060108260f81c60ff168161358e57fe5b0460f81b905060008160f81c6010028360f81c0360f81b90506135b082613cb0565b8585600202815181106135bf57fe5b60200101906001600160f81b031916908160001a9053506135df81613cb0565b8585600202600101815181106135f157fe5b60200101906001600160f81b031916908160001a90535050600190920191506135509050565b5092915050565b6000613628612a6c565b600080546001600160a01b0319166001600160a01b038316908117825560405192935091600080516020615cf8833981519152908290a350565b6040518060800160405280604f8152602001615afc604f913980519060200120828051906020012082805190602001203061369b6115fd565b60001b60405160200180868152602001858152602001848152602001836001600160a01b031681526020018281526020019550505050505060405160208183030381529060405280519060200120600b819055505050565b81516137069060079060208501906140b7565b50805161371a9060089060208401906140b7565b5061372b6380ac58cd60e01b613ce1565b61373b635b5e139f60e01b613ce1565b61325b63780e9d6360e01b613ce1565b6015805461ff0019166101001790556040517f01b7dcb42d49142a99e4c98da755263c600213a33b780986779405b9823501d390600090a1565b60006115c28383613d67565b6000604051806080016040528060438152602001615a9360439139805190602001208260000151836020015184604001518051906020012060405160200180858152602001848152602001836001600160a01b03168152602001828152602001945050505050604051602081830303815290604052805190602001209050919050565b600b546040805161190160f01b6020808301919091526022820193909352604280820194909452815180820390940184526062019052815191012090565b5490565b60006115c28383613d7f565b60006115c28383613e45565b6000612da084846001600160a01b038516613e8f565b815460009082106138c65760405162461bcd60e51b8152600401808060200182810382526022815260200180615a3f6022913960400191505060405180910390fd5b8260000182815481106138d557fe5b9060005260206000200154905092915050565b81546000908190831061392c5760405162461bcd60e51b8152600401808060200182810382526022815260200180615c636022913960400191505060405180910390fd5b600084600001848154811061393d57fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816139fe5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156139c35781810151838201526020016139ab565b50505050905090810190601f1680156139f05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50846000016001820381548110613a1157fe5b9060005260206000209060020201600101549150509392505050565b6001600160a01b038216613a88576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b613a9181612a5f565b15613ae2576040805162461bcd60e51b815260206004820152601c60248201527b115490cdcc8c4e881d1bdad95b88185b1c9958591e481b5a5b9d195960221b604482015290519081900360640190fd5b613aee60008383610bf0565b6001600160a01b0382166000908152600260205260409020613b109082613862565b50613b1d6003828461386e565b5060405181906001600160a01b03841690600090600080516020615d41833981519152908290a45050565b6000613b5c846001600160a01b0316613f26565b613b6857506001612da0565b6000613c76630a85bd0160e11b613b7d612a6c565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613be4578181015183820152602001613bcc565b50505050905090810190601f168015613c115780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050604051806060016040528060328152602001615a61603291396001600160a01b0388169190613f2c565b90506000818060200190516020811015613c8f57600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b6000600a60f883901c1015613cd0578160f81c60300160f81b9050610a12565b8160f81c60570160f81b9050610a12565b6001600160e01b03198082161415613d3f576040805162461bcd60e51b815260206004820152601c60248201527b115490cc4d8d4e881a5b9d985b1a59081a5b9d195c999858d9481a5960221b604482015290519081900360640190fd5b6001600160e01b0319166000908152600160208190526040909120805460ff19169091179055565b60009081526001919091016020526040902054151590565b60008181526001830160205260408120548015613e3b5783546000198083019190810190600090879083908110613db257fe5b9060005260206000200154905080876000018481548110613dcf57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080613dff57fe5b600190038181906000526020600020016000905590558660010160008781526020019081526020016000206000905560019450505050506115c5565b60009150506115c5565b6000613e518383613d67565b613e87575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556115c5565b5060006115c5565b600082815260018401602052604081205480613ef4575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055612cf2565b82856000016001830381548110613f0757fe5b9060005260206000209060020201600101819055506000915050612cf2565b3b151590565b6060612da0848460008585613f4085613f26565b613f91576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310613fcf5780518252601f199092019160209182019101613fb0565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614031576040519150601f19603f3d011682016040523d82523d6000602084013e614036565b606091505b5091509150614046828286614051565b979650505050505050565b60608315614060575081612cf2565b8251156140705782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156139c35781810151838201526020016139ab565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826140ed5760008555614133565b82601f1061410657805160ff1916838001178555614133565b82800160010185558215614133579182015b82811115614133578251825591602001919060010190614118565b5061413f929150614164565b5090565b60405180606001604052806060815260200160008152602001600081525090565b5b8082111561413f5760008155600101614165565b8035610a1281615a29565b60008083601f840112614195578182fd5b5081356001600160401b038111156141ab578182fd5b602083019150836020808302850101111561324157600080fd5b600082601f8301126141d5578081fd5b813560206141ea6141e5836159b3565b615990565b82815281810190858301855b858110156142ab5781358801608080601f19838d03011215614216578889fd5b604080518281016001600160401b03808211838310171561423357fe5b908352848a01359080821115614247578c8dfd5b6142558f8c848901016142c8565b8352838601358b8401526060915061426e828701614179565b83850152938501359380851115614283578c8dfd5b506142928e8b868801016142c8565b90820152875250505092840192908401906001016141f6565b5090979650505050505050565b80358015158114610a1257600080fd5b600082601f8301126142d8578081fd5b81356142e66141e5826159d0565b8181528460208386010111156142fa578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215614325578081fd5b81356115c281615a29565b60008060408385031215614342578081fd5b823561434d81615a29565b9150602083013561435d81615a29565b809150509250929050565b6000806000806060858703121561437d578182fd5b843561438881615a29565b9350602085013561439881615a29565b925060408501356001600160401b038111156143b2578283fd5b6143be87828801614184565b95989497509550505050565b600080600080608085870312156143df578182fd5b84356143ea81615a29565b93506020858101356143fb81615a29565b935060408601356001600160401b0380821115614416578485fd5b818801915088601f830112614429578485fd5b81356144376141e5826159b3565b81815284810190848601868402860187018d1015614453578889fd5b8895505b83861015614475578035835260019590950194918601918601614457565b5096505050606088013592508083111561448d578384fd5b505061449b878288016142c8565b91505092959194509250565b6000806000606084860312156144bb578081fd5b83356144c681615a29565b925060208401356144d681615a29565b929592945050506040919091013590565b600080600080608085870312156144fc578182fd5b843561450781615a29565b9350602085013561451781615a29565b92506040850135915060608501356001600160401b03811115614538578182fd5b61449b878288016142c8565b60008060408385031215614556578182fd5b823561456181615a29565b915061456f602084016142b8565b90509250929050565b600080600080600060a0868803121561458f578283fd5b853561459a81615a29565b945060208601356001600160401b038111156145b4578384fd5b6145c0888289016142c8565b9450506040860135925060608601359150608086013560ff811681146145e4578182fd5b809150509295509295909350565b60008060408385031215614604578182fd5b823561460f81615a29565b946020939093013593505050565b60008060008060408587031215614632578182fd5b84356001600160401b0380821115614648578384fd5b61465488838901614184565b9096509450602087013591508082111561466c578384fd5b506143be87828801614184565b60006020828403121561468a578081fd5b81356001600160401b0381111561469f578182fd5b612da0848285016141c5565b600080600080600080606087890312156146c3578384fd5b86356001600160401b03808211156146d9578586fd5b6146e58a838b01614184565b909850965060208901359150808211156146fd578586fd5b6147098a838b01614184565b90965094506040890135915080821115614721578283fd5b5061472e89828a01614184565b979a9699509497509295939492505050565b60008060008060008060608789031215614758578384fd5b86356001600160401b038082111561476e578586fd5b61477a8a838b01614184565b90985096506020890135915080821115614792578586fd5b61479e8a838b01614184565b90965094506040890135915080821115614721578384fd5b6000806000806000806000806080898b0312156147d1578586fd5b88356001600160401b03808211156147e7578788fd5b6147f38c838d01614184565b909a50985060208b013591508082111561480b578788fd5b6148178c838d01614184565b909850965060408b013591508082111561482f578384fd5b61483b8c838d01614184565b909650945060608b0135915080821115614853578384fd5b506148608b828c01614184565b999c989b5096995094979396929594505050565b600060208284031215614885578081fd5b6115c2826142b8565b60006020828403121561489f578081fd5b81356001600160e01b0319811681146115c2578182fd5b6000602082840312156148c7578081fd5b81356001600160401b038111156148dc578182fd5b612da0848285016142c8565b600080600080600080600080610100898b031215614904578182fd5b88356001600160401b038082111561491a578384fd5b6149268c838d016142c8565b995060208b013591508082111561493b578384fd5b6149478c838d016142c8565b985060408b013591508082111561495c578384fd5b6149688c838d016142c8565b975061497660608c01614179565b965061498460808c016142b8565b955061499260a08c016142b8565b94506149a060c08c01614179565b935060e08b01359150808211156149b5578283fd5b506149c28b828c016141c5565b9150509295985092959890939650565b600060208083850312156149e4578182fd5b82516001600160401b03808211156149fa578384fd5b9084019060608287031215614a0d578384fd5b604051606081018181108382111715614a2257fe5b604052825182811115614a33578586fd5b83019150601f82018713614a45578485fd5b8151614a536141e5826159d0565b8181528886838601011115614a66578687fd5b614a75828783018887016159fd565b825250828401519381019390935250604090810151908201529392505050565b600060208284031215614aa6578081fd5b5035919050565b60008060408385031215614abf578182fd5b82359150602083013561435d81615a29565b60008060408385031215614ae3578182fd5b50508035926020909101359150565b60008151808452614b0a8160208601602086016159fd565b601f01601f19169290920160200192915050565b60008154600180821660008114614b3c5760018114614b5a57614b98565b60028304607f16865260ff1983166020870152604086019350614b98565b60028304808752614b6a866159f1565b60005b82811015614b8e5781546020828b0101528482019150602081019050614b6d565b8801602001955050505b50505092915050565b60008651614bb3818460208b016159fd565b865190830190614bc7818360208b016159fd565b602f60f81b910181815261060f60f31b60018201528651909190614bf2816003850160208b016159fd565b600392019182018190528551614c0f816004850160208a016159fd565b60049201918201528351614c2a8160058401602088016159fd565b01600501979650505050505050565b6001600160a01b0391909116815260200190565b901515815260200190565b91151582521515602082015260400190565b90815260200190565b6000602082526115c26020830184614af2565b600060408252614c996040830185614af2565b8281036020840152614cab8185614af2565b95945050505050565b600060408252614cc76040830185614af2565b8281036020840152614cab8185614b1e565b600060e08252614cec60e083018a614af2565b6020830189905260408301889052606083018790526001600160a01b038616608084015282810360a0840152614d228186614af2565b905082810360c0840152614d368185614af2565b9a9950505050505050505050565b6000602082526115c26020830184614b1e565b6020808252601e908201527f656469744974656d73446174613a204c454e4754485f4d49534d415443480000604082015260600190565b6020808252601c908201527b0e4cae6c6eaca92e8cadae67440988a9c8ea890be9a92a69a82a886960231b604082015260600190565b6020808252602c908201527f656469744974656d73446174613a20494e56414c49445f50524943455f414e4460408201526b5f42454e454649434941525960a01b606082015260800190565b6020808252601e908201527f7365744564697461626c653a2056414c55455f49535f5448455f53414d450000604082015260600190565b6020808252818101527f656e636f6465546f6b656e49643a20494e56414c49445f4953535545445f4944604082015260600190565b60208082526033908201527f7472616e7366657243726561746f72736869703a2043414c4c45525f49535f4e60408201527227aa2fa7aba722a92fa7a92fa1a922a0aa27a960691b606082015260800190565b60208082526024908201527f7365744d616e61676572733a20494e56414c49445f4d414e414745525f4144446040820152635245535360e01b606082015260800190565b6020808252601d908201527f6973737565546f6b656e733a204d494e545f4e4f545f414c4c4f574544000000604082015260600190565b6020808252601b908201527a34b734ba34b0b634bd329d1024a72b20a624a22fa1a922a0aa27a960291b604082015260600190565b6020808252601e908201527f736574417070726f7665643a2056414c55455f49535f5448455f53414d450000604082015260600190565b60208082526022908201527f7365744d696e746572733a20494e56414c49445f4d494e5445525f4144445245604082015261535360f01b606082015260800190565b60208082526027908201527f7365744974656d734d696e746572733a20494e56414c49445f4d494e5445525f6040820152664144445245535360c81b606082015260800190565b6020808252818101527f5f6973737565546f6b656e3a204954454d5f444f45535f4e4f545f4558495354604082015260600190565b60208082526024908201527f7365744974656d734d696e746572733a204954454d5f444f45535f4e4f545f45604082015263161254d560e21b606082015260800190565b6020808252601b908201527a17da5cdcdd59551bdad95b8e881255115357d15612105554d51151602a1b604082015260600190565b6020808252601f908201527f696e697469616c697a653a20414c52454144595f494e495449414c495a454400604082015260600190565b6020808252601e908201527f5f6164644974656d3a20434f4c4c454354494f4e5f434f4d504c455445440000604082015260600190565b60208082526030908201527f636f6d706c657465436f6c6c656374696f6e3a20434f4c4c454354494f4e5f4160408201526f13149150511657d0d3d354131155115160821b606082015260800190565b6020808252601a90820152791d1bdad95b9554924e881253959053125117d513d2d15397d25160321b604082015260600190565b6020808252818101527f7265736375654974656d733a204954454d5f444f45535f4e4f545f4558495354604082015260600190565b6020808252601e908201527f7365744d616e61676572733a2056414c55455f49535f5448455f53414d450000604082015260600190565b6020808252601b908201527a0e6cae89ad2dce8cae4e67440988a9c8ea890be9a92a69a82a8869602b1b604082015260600190565b60208082526027908201527f5f6164644974656d3a20494e56414c49445f50524943455f414e445f42454e456040820152664649434941525960c81b606082015260800190565b60208082526021908201527f7365744974656d734d616e61676572733a204c454e4754485f4d49534d4154436040820152600960fb1b606082015260800190565b6020808252818101527f7365744974656d734d696e746572733a204c454e4754485f4d49534d41544348604082015260600190565b6020808252601c908201527b0d2e6e6eacaa8ded6cadce67440988a9c8ea890be9a92a69a82a886960231b604082015260600190565b60208082526022908201527f6f6e6c7943726561746f723a2043414c4c45525f49535f4e4f545f435245415460408201526127a960f11b606082015260800190565b6020808252601c908201527b0e6cae89ac2dcc2cecae4e67440988a9c8ea890be9a92a69a82a886960231b604082015260600190565b6020808252601890820152775f6164644974656d3a20494e56414c49445f52415249545960401b604082015260600190565b6020808252601c908201527b696e697469616c697a653a20494e56414c49445f524152495449455360201b604082015260600190565b6020808252601d908201527f656469744974656d73446174613a20454d5054595f4d45544144415441000000604082015260600190565b6020808252601690820152755f6164644974656d733a20454d5054595f4954454d5360501b604082015260600190565b6020808252601890820152775f6164644974656d3a20454d5054595f4d4554414441544160401b604082015260600190565b60208082526022908201527f656469744974656d73446174613a204954454d5f444f45535f4e4f545f45584960408201526114d560f21b606082015260800190565b6020808252602c908201527f7472616e7366657243726561746f72736869703a20494e56414c49445f43524560408201526b41544f525f4144445245535360a01b606082015260800190565b60208082526026908201527f656469744974656d73446174613a20434f4c4c454354494f4e5f4e4f545f4544604082015265495441424c4560d01b606082015260800190565b6020808252602f908201527f656469744974656d73446174613a2043414c4c45525f49535f4e4f545f43524560408201526e20aa27a92fa7a92fa6a0a720a3a2a960891b606082015260800190565b60208082526025908201527f7365744974656d734d616e61676572733a204954454d5f444f45535f4e4f545f60408201526411561254d560da1b606082015260800190565b60208082526029908201527f7365744974656d734d616e61676572733a20494e56414c49445f4d414e414745604082015268525f4144445245535360b81b606082015260800190565b6020808252601d908201527f5f6164644974656d3a204d41585f4954454d5f49445f52454143484544000000604082015260600190565b60208082526024908201527f656469744974656d73446174613a2043414e5f4e4f545f454449545f4d4554416040820152634441544160e01b606082015260800190565b6020808252601e908201527f656e636f6465546f6b656e49643a20494e56414c49445f4954454d5f49440000604082015260600190565b6020808252601d908201527f7365744d696e746572733a2056414c55455f49535f5448455f53414d45000000604082015260600190565b60208082526022908201527f7365744974656d734d696e746572733a2056414c55455f49535f5448455f53416040820152614d4560f01b606082015260800190565b6020808252818101527f5f6973737565546f6b656e3a2043414c4c45525f43414e5f4e4f545f4d494e54604082015260600190565b60208082526023908201527f7365744974656d734d616e61676572733a2056414c55455f49535f5448455f53604082015262414d4560e81b606082015260800190565b600060208252825160e0602084015261585d610100840182614af2565b905060208401516040840152604084015160608401526060840151608084015260018060a01b0360808501511660a084015260a0840151601f19808584030160c08601526158ab8383614af2565b925060c08601519150808584030160e086015250614cab8282614af2565b6001600160d81b0391909116815260200190565b9182526001600160a01b0316602082015260400190565b8381526001600160a01b0383166020820152606060408201819052600090614cab90830184614af2565b918252602082015260400190565b64ffffffffff91909116815260200190565b60ff91909116815260200190565b6000808335601e19843603018112615962578283fd5b8301803591506001600160401b0382111561597b578283fd5b60200191503681900382131561324157600080fd5b6040518181016001600160401b03811182821017156159ab57fe5b604052919050565b60006001600160401b038211156159c657fe5b5060209081020190565b60006001600160401b038211156159e357fe5b50601f01601f191660200190565b60009081526020902090565b60005b83811015615a18578181015183820152602001615a00565b838111156122b35750506000910152565b6001600160a01b0381168114611b7e57600080fdfe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e6174757265294f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c6164647265737320766572696679696e67436f6e74726163742c627974657333322073616c74294552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4e4d5423657865637574654d6574615472616e73616374696f6e3a205349474e45525f414e445f5349474e41545552455f444f5f4e4f545f4d415443484552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734e4d5423657865637574654d6574615472616e73616374696f6e3a2043414c4c5f4641494c45444552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65728be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e04552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a2646970667358221220d745464168210e71c3fdff50a2eaa16478dfce18d2f4490912866698f8e65a9d64736f6c63430007060033
Deployed ByteCode Sourcemap
133:78:16:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;965:148:2;;;;;;;;;;-1:-1:-1;965:148:2;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1405:22:15;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;4918:90:36:-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;7533:209::-;;;;;;;;;;-1:-1:-1;7533:209:36;;;;;:::i;:::-;;:::i;7091:381::-;;;;;;;;;;-1:-1:-1;7091:381:36;;;;;:::i;:::-;;:::i;:::-;;730:1167:21;;;;;;:::i;:::-;;:::i;10050:1752:15:-;;;;;;;;;;-1:-1:-1;10050:1752:15;;;;;:::i;:::-;;:::i;6601:200:36:-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;8087:905:15:-;;;;;;;;;;-1:-1:-1;8087:905:15;;;;;:::i;:::-;;:::i;8381:300:36:-;;;;;;;;;;-1:-1:-1;8381:300:36;;;;;:::i;:::-;;:::i;21597:253:15:-;;;;;;;;;;-1:-1:-1;21597:253:15;;;;;:::i;:::-;;:::i;1839:22::-;;;;;;;;;;;;;:::i;17497:104::-;;;;;;;;;;;;;:::i;18768:210::-;;;;;;;;;;-1:-1:-1;18768:210:15;;;;;:::i;:::-;;:::i;2305:107:21:-;;;;;;;;;;-1:-1:-1;2305:107:21;;;;;:::i;:::-;;:::i;6378:152:36:-;;;;;;;;;;-1:-1:-1;6378:152:36;;;;;:::i;:::-;;:::i;2948:142:15:-;;;;;;;;;;;;;:::i;1043:155:18:-;;;;;;;;;;;;;:::i;1751:25:15:-;;;;;;;;;;;;;:::i;1360:::-;;;;;;;;;;;;;:::i;7211:642::-;;;;;;;;;;-1:-1:-1;7211:642:15;;;;;:::i;:::-;;:::i;16184:929::-;;;;;;;;;;-1:-1:-1;16184:929:15;;;;;:::i;:::-;;:::i;5326:625::-;;;;;;;;;;-1:-1:-1;5326:625:15;;;;;:::i;:::-;;:::i;9703:172::-;;;;;;;;;;-1:-1:-1;9703:172:15;;;;;:::i;:::-;;:::i;8747:149:36:-;;;;;;;;;;-1:-1:-1;8747:149:36;;;;;:::i;:::-;;:::i;18308:218:15:-;;;;;;;;;;-1:-1:-1;18308:218:15;;;;;:::i;:::-;;:::i;782:53::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;6873:161:36:-;;;;;;;;;;-1:-1:-1;6873:161:36;;;;;:::i;:::-;;:::i;19112:142:15:-;;;;;;;;;;-1:-1:-1;19112:142:15;;;;;:::i;:::-;;:::i;689:39::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;4689:167:36:-;;;;;;;;;;-1:-1:-1;4689:167:36;;;;;:::i;:::-;;:::i;6212:87::-;;;;;;;;;;;;;:::i;9156:408:15:-;;;;;;;;;;-1:-1:-1;9156:408:15;;;;;:::i;:::-;;:::i;1536:67::-;;;;;;;;;;-1:-1:-1;1536:67:15;;;;;:::i;:::-;;:::i;4421:211:36:-;;;;;;;;;;-1:-1:-1;4421:211:36;;;;;:::i;:::-;;:::i;1729:145:22:-;;;;;;;;;;;;;:::i;1484:46:15:-;;;;;;;;;;-1:-1:-1;1484:46:15;;;;;:::i;:::-;;:::i;13995:441::-;;;;;;;;;;-1:-1:-1;13995:441:15;;;;;:::i;:::-;;:::i;605:78::-;;;;;;;;;;;;;:::i;22789:315::-;;;;;;;;;;-1:-1:-1;22789:315:15;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;1106:77:22:-;;;;;;;;;;;;;:::i;734:42:15:-;;;;;;;;;;;;;:::i;5072:94:36:-;;;;;;;;;;;;;:::i;7809:290::-;;;;;;;;;;-1:-1:-1;7809:290:36;;;;;:::i;:::-;;:::i;1433:45:15:-;;;;;;;;;;-1:-1:-1;1433:45:15;;;;;:::i;:::-;;:::i;1811:22::-;;;;;;;;;;;;;:::i;8962:282:36:-;;;;;;;;;;-1:-1:-1;8962:282:36;;;;;:::i;:::-;;:::i;1609:65:15:-;;;;;;;;;;-1:-1:-1;1609:65:15;;;;;:::i;:::-;;:::i;1681:19::-;;;;;;;;;;-1:-1:-1;1681:19:15;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;:::i;19484:665::-;;;;;;;;;;-1:-1:-1;19484:665:15;;;;;:::i;:::-;;:::i;1721:24::-;;;;;;;;;;;;;:::i;3604:1053::-;;;;;;;;;;-1:-1:-1;3604:1053:15;;;;;:::i;:::-;;:::i;17244:90::-;;;;;;;;;;;;;:::i;6136:893::-;;;;;;;;;;-1:-1:-1;6136:893:15;;;;;:::i;:::-;;:::i;8165:154:36:-;;;;;;;;;;-1:-1:-1;8165:154:36;;;;;:::i;:::-;;:::i;22130:411:15:-;;;;;;;;;;-1:-1:-1;22130:411:15;;;;;:::i;:::-;;:::i;2023:240:22:-;;;;;;;;;;-1:-1:-1;2023:240:22;;;;;:::i;:::-;;:::i;20643:220:15:-;;;;;;;;;;-1:-1:-1;20643:220:15;;;;;:::i;:::-;;:::i;17784:173::-;;;;;;;;;;;;;:::i;412:30:18:-;;;;;;;;;;;;;:::i;841:57:15:-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;1782:23::-;;;;;;;;;;;;;:::i;965:148:2:-;-1:-1:-1;;;;;;1073:33:2;;1050:4;1073:33;;;:20;:33;;;;;;;;965:148;;;;:::o;1405:22:15:-;;;-1:-1:-1;;;;;1405:22:15;;:::o;4918:90:36:-;4996:5;4989:12;;;;;;;;-1:-1:-1;;4989:12:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4964:13;;4989:12;;4996:5;;4989:12;;4996:5;4989:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4918:90;;:::o;7533:209::-;7601:7;7628:16;7636:7;7628;:16::i;:::-;7620:73;;;;-1:-1:-1;;;7620:73:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;7711:24:36;;;;:15;:24;;;;;;-1:-1:-1;;;;;7711:24:36;;7533:209::o;7091:381::-;7171:13;7187:16;7195:7;7187;:16::i;:::-;7171:32;;7227:5;-1:-1:-1;;;;;7221:11:36;:2;-1:-1:-1;;;;;7221:11:36;;;7213:57;;;;-1:-1:-1;;;7213:57:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7305:5;-1:-1:-1;;;;;7289:21:36;:12;:10;:12::i;:::-;-1:-1:-1;;;;;7289:21:36;;:62;;;;7314:37;7331:5;7338:12;:10;:12::i;7314:37::-;7281:152;;;;-1:-1:-1;;;7281:152:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7444:21;7453:2;7457:7;7444:8;:21::i;:::-;7091:381;;;:::o;730:1167:21:-;983:148;;;927:12;983:148;;;;;-1:-1:-1;;;;;1020:19:21;;951:29;1020:19;;;:6;:19;;;;;;;;;983:148;;;;;;;;;;;1163:45;1027:11;983:148;1191:4;1197;1203;1163:6;:45::i;:::-;1142:153;;;;-1:-1:-1;;;1142:153:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1381:19:21;;;;;;:6;:19;;;;;;:26;;1405:1;1381:23;:26::i;:::-;1359:6;:19;1366:11;-1:-1:-1;;;;;1359:19:21;-1:-1:-1;;;;;1359:19:21;;;;;;;;;;;;:48;;;;1423:113;1460:11;1485:10;1509:17;1423:113;;;;-1:-1:-1;;;;;1423:113:21;;;;;;-1:-1:-1;;;;;1423:113:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1644:12;1658:23;1693:4;-1:-1:-1;;;;;1685:18:21;1711:9;1752:17;1771:11;1735:48;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1735:48:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1735:48:21;;;;;;;;;;;;;;;;;;;;;;;1685:108;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1685:108:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1643:150;;;;1811:7;1803:59;;;;-1:-1:-1;;;1803:59:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1880:10;730:1167;-1:-1:-1;;;;;;;;730:1167:21:o;10050:1752:15:-;10306:33;;;:88;;;;-1:-1:-1;10355:39:15;;;10306:88;:146;;;;-1:-1:-1;10410:42:15;;;10306:146;10285:223;;;;-1:-1:-1;;;10285:223:15;;;;;;;:::i;:::-;;;;;;;;;10540:10;;;;;;;10519:95;;;;-1:-1:-1;;;10519:95:15;;;;;;;:::i;:::-;10655:9;10650:1146;10670:19;;;10650:1146;;;10710:14;10727:8;;10736:1;10727:11;;;;;;;;;;;;;10710:28;;10752:13;10768:7;;10776:1;10768:10;;;;;;;;;;;;;10752:26;;10792:19;10814:14;;10829:1;10814:17;;;;;;;;;;;;;;;;;;;;:::i;:::-;10792:39;;10845:22;10870:10;;10881:1;10870:13;;;;;;;;;;;;;;;;;;:::i;:::-;10845:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;10845:38:15;;-1:-1:-1;10906:12:15;;-1:-1:-1;10906:10:15;;-1:-1:-1;;10906:12:15:i;:::-;:34;;;;10922:18;10933:6;10922:10;:18::i;:::-;10898:94;;;;-1:-1:-1;;;10898:94:15;;;;;;;:::i;:::-;11023:5;:12;11014:21;;11006:68;;;;-1:-1:-1;;;11006:68:15;;;;;;;:::i;:::-;11121:1;11113:5;:9;:38;;;;-1:-1:-1;;;;;;11126:25:15;;;;11113:38;:81;;;-1:-1:-1;11155:10:15;;:39;;;;-1:-1:-1;;;;;;11169:25:15;;;11155:39;11088:184;;;;-1:-1:-1;;;11088:184:15;;;;;;;:::i;:::-;11319:1;11300:8;11294:22;:26;11286:68;;;;-1:-1:-1;;;11286:68:15;;;;;;;:::i;:::-;11369:17;11389:5;11395:6;11389:13;;;;;;;;;;;;;;;;;;11369:33;;11443:10;;;;;;;;;;;11442:11;:86;;;;11518:8;11507:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;11497:31;;;;;;11478:4;:13;;11467:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;11457:36;;;;;;:71;11442:86;11417:181;;;;-1:-1:-1;;;11417:181:15;;;;;;;:::i;:::-;11613:10;;;:18;;;11645:16;;;:30;;-1:-1:-1;;;;;;11645:30:15;-1:-1:-1;;;;;11645:30:15;;;;;11689:24;;;;:13;;;;:24;;;;;:::i;:::-;;11748:6;11733:52;11756:5;11763:11;11776:8;11733:52;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;10691:3:15;;;;;-1:-1:-1;10650:1146:15;;-1:-1:-1;;10650:1146:15;;;10050:1752;;;;;;;;:::o;6601:200:36:-;6654:7;6773:21;:12;:19;:21::i;:::-;6766:28;;6601:200;:::o;8087:905:15:-;5047:12;:10;:12::i;:::-;5026:93;;;;-1:-1:-1;;;5026:93:15;;;;;;;:::i;:::-;8279:35;;::::1;:73:::0;::::1;;;-1:-1:-1::0;8318:34:15;;::::1;8279:73;8258:153;;;;-1:-1:-1::0;;;8258:153:15::1;;;;;;;:::i;:::-;8427:9;8422:564;8442:20:::0;;::::1;8422:564;;;8483:15;8501:9;;8511:1;8501:12;;;;;;;;;;;;;;;;;;;;:::i;:::-;8483:30;;8527:14;8544:8;;8553:1;8544:11;;;;;;;;;;;;;8527:28;;8569:10;8582:7;;8590:1;8582:10;;;;;;;;;;;;;;;;;;;;:::i;:::-;8569:23:::0;-1:-1:-1;;;;;;8614:21:15;::::1;8606:75;;;;-1:-1:-1::0;;;8606:75:15::1;;;;;;;:::i;:::-;8712:5;:12:::0;8703:21;::::1;8695:71;;;;-1:-1:-1::0;;;8695:71:15::1;;;;;;;:::i;:::-;8788:20;::::0;;;:12:::1;:20;::::0;;;;;;;-1:-1:-1;;;;;8788:29:15;::::1;::::0;;;;;;;;::::1;;:38;;::::0;::::1;;;;8780:86;;;;-1:-1:-1::0;;;8780:86:15::1;;;;;;;:::i;:::-;8881:20;::::0;;;:12:::1;:20;::::0;;;;;;;-1:-1:-1;;;;;8881:29:15;::::1;::::0;;;;;;;;;:37;;-1:-1:-1;;8881:37:15::1;::::0;::::1;;;::::0;;8937:38;;8881:20;;8937:38:::1;::::0;::::1;::::0;8881:37;;8937:38:::1;:::i;:::-;;;;;;;;-1:-1:-1::0;;;8464:3:15::1;;8422:564;;;;8087:905:::0;;;;;;:::o;8381:300:36:-;8540:41;8559:12;:10;:12::i;:::-;8573:7;8540:18;:41::i;:::-;8532:103;;;;-1:-1:-1;;;8532:103:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8646:28;8656:4;8662:2;8666:7;8646:9;:28::i;21597:253:15:-;21728:9;21723:121;21747:9;:16;21743:1;:20;21723:121;;;21784:49;21801:5;21808:3;21813:9;21823:1;21813:12;;;;;;;;;;;;;;21827:5;21784:16;:49::i;:::-;21765:3;;21723:121;;;;21597:253;;;;:::o;1839:22::-;;;;;;;;;:::o;17497:104::-;17569:11;;17546:4;;17569:11;;;;;:25;;;;-1:-1:-1;;17584:10:15;;;;;;;;17497:104::o;18768:210::-;1320:12:22;:10;:12::i;:::-;1310:6;;-1:-1:-1;;;;;1310:6:22;;;:22;;;1302:67;;;;;-1:-1:-1;;;1302:67:22;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1302:67:22;;;;;;;;;;;;;;;18839:10:15::1;::::0;::::1;::::0;;;::::1;;:20;;::::0;::::1;;;;18831:63;;;;-1:-1:-1::0;;;18831:63:15::1;;;;;;;:::i;:::-;18910:31;18922:10;;;;;;;;;;;18934:6;18910:31;;;;;;;:::i;:::-;;;;;;;;18952:10;:19:::0;;;::::1;;::::0;::::1;-1:-1:-1::0;;18952:19:15;;::::1;::::0;;;::::1;::::0;;18768:210::o;2305:107:21:-;-1:-1:-1;;;;;2393:12:21;2360:13;2393:12;;;:6;:12;;;;;;;2305:107::o;6378:152:36:-;-1:-1:-1;;;;;6493:20:36;;6467:7;6493:20;;;:13;:20;;;;;:30;;6517:5;6493:23;:30::i;:::-;6486:37;;6378:152;;;;;:::o;2948:142:15:-;3004:13;;;;3003:14;2995:58;;;;-1:-1:-1;;;2995:58:15;;;;;;;:::i;:::-;3063:13;:20;;-1:-1:-1;;3063:20:15;3079:4;3063:20;;;2948:142::o;1043:155:18:-;1154:9;1043:155;:::o;1751:25:15:-;;;;;;:::o;1360:::-;;;-1:-1:-1;;;;;1360:25:15;;:::o;7211:642::-;5047:12;:10;:12::i;:::-;5026:93;;;;-1:-1:-1;;;5026:93:15;;;;;;;:::i;:::-;7339:34;;::::1;7318:109;;;;-1:-1:-1::0;;;7318:109:15::1;;;;;;;:::i;:::-;7443:9;7438:409;7458:20:::0;;::::1;7438:409;;;7499:15;7517:9;;7527:1;7517:12;;;;;;;;;;;;;;;;;;;;:::i;:::-;7499:30;;7543:10;7556:7;;7564:1;7556:10;;;;;;;;;;;;;;;;;;;;:::i;:::-;7543:23:::0;-1:-1:-1;;;;;;7588:21:15;::::1;7580:70;;;;-1:-1:-1::0;;;7580:70:15::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;7672:23:15;::::1;;::::0;;;:14:::1;:23;::::0;;;;;::::1;;:32;;::::0;::::1;;;;7664:75;;;;-1:-1:-1::0;;;7664:75:15::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;7754:23:15;::::1;;::::0;;;:14:::1;:23;::::0;;;;;;:31;;-1:-1:-1;;7754:31:15::1;::::0;::::1;;;::::0;;7804:32;::::1;::::0;::::1;::::0;7754:31;;7804:32:::1;:::i;:::-;;;;;;;;-1:-1:-1::0;;7480:3:15::1;;7438:409;;16184:929:::0;1320:12:22;:10;:12::i;:::-;1310:6;;-1:-1:-1;;;;;1310:6:22;;;:22;;;1302:67;;;;;-1:-1:-1;;;1302:67:22;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1302:67:22;;;;;;;;;;;;;;;16403:40:15;;::::1;:86:::0;::::1;;;-1:-1:-1::0;16447:42:15;;::::1;16403:86;16382:161;;;;-1:-1:-1::0;;;16382:161:15::1;;;;;;;:::i;:::-;16559:9;16554:553;16574:19:::0;;::::1;16554:553;;;16614:14;16631:8;;16640:1;16631:11;;;;;;;;;;;;;16614:28;;16673:5;:12;;;;16664:6;:21;16656:66;;;;-1:-1:-1::0;;;16656:66:15::1;;;;;;;:::i;:::-;16737:17;16757:5;16763:6;16757:13;;;;;;;;;;;;;;;;;;16737:33;;16785:25;16813:14;;16828:1;16813:17;;;;;;;;;;;;;;;;;;:::i;:::-;16785:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;-1:-1:-1;16785:45:15;;-1:-1:-1;16869:10:15;;-1:-1:-1;16869:10:15;;-1:-1:-1;16880:1:15;;-1:-1:-1;16869:13:15;;::::1;;;;;;;;;;;;;;;;:::i;:::-;16844:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;;16897:30:15;;16844:38;;-1:-1:-1;16897:30:15::1;::::0;:16:::1;::::0;::::1;::::0;-1:-1:-1;16897:30:15::1;::::0;::::1;::::0;-1:-1:-1;16897:30:15::1;:::i;:::-;-1:-1:-1::0;16946:22:15;;:26;16942:89:::1;;16992:24:::0;;::::1;::::0;:13:::1;::::0;::::1;::::0;:24:::1;::::0;::::1;::::0;::::1;:::i;:::-;;16942:89;17061:6;17050:46;17069:11;17082:4;:13;;17050:46;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1::0;;16595:3:15::1;::::0;;::::1;::::0;-1:-1:-1;16554:553:15::1;::::0;-1:-1:-1;16554:553:15::1;5326:625:::0;5047:12;:10;:12::i;:::-;5026:93;;;;-1:-1:-1;;;5026:93:15;;;;;;;:::i;:::-;5452:33;;::::1;5431:107;;;;-1:-1:-1::0;;;5431:107:15::1;;;;;;;:::i;:::-;5554:9;5549:396;5569:19:::0;;::::1;5549:396;;;5609:14;5626:8;;5635:1;5626:11;;;;;;;;;;;;;;;;;;;;:::i;:::-;5609:28;;5651:10;5664:7;;5672:1;5664:10;;;;;;;;;;;;;;;;;;;;:::i;:::-;5651:23:::0;-1:-1:-1;;;;;;5696:20:15;::::1;5688:67;;;;-1:-1:-1::0;;;5688:67:15::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;5777:21:15;::::1;;::::0;;;:13:::1;:21;::::0;;;;;::::1;;:30;;::::0;::::1;;;;5769:72;;;;-1:-1:-1::0;;;5769:72:15::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;5856:21:15;::::1;;::::0;;;:13:::1;:21;::::0;;;;;;:29;;-1:-1:-1;;5856:29:15::1;::::0;::::1;;;::::0;;5904:30;::::1;::::0;::::1;::::0;5856:29;;5904:30:::1;:::i;:::-;;;;;;;;-1:-1:-1::0;;5590:3:15::1;;5549:396;;9703:172:::0;1320:12:22;:10;:12::i;:::-;1310:6;;-1:-1:-1;;;;;1310:6:22;;;:22;;;1302:67;;;;;-1:-1:-1;;;1302:67:22;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1302:67:22;;;;;;;;;;;;;;;9794:11:15::1;::::0;::::1;::::0;::::1;;;9793:12;9785:55;;;;-1:-1:-1::0;;;9785:55:15::1;;;;;;;:::i;:::-;9851:17;9861:6;9851:9;:17::i;:::-;9703:172:::0;:::o;8747:149:36:-;8850:39;8867:4;8873:2;8877:7;8850:39;;;;;;;;;;;;:16;:39::i;18308:218:15:-;1320:12:22;:10;:12::i;:::-;1310:6;;-1:-1:-1;;;;;1310:6:22;;;:22;;;1302:67;;;;;-1:-1:-1;;;1302:67:22;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1302:67:22;;;;;;;;;;;;;;;18387:10:15::1;::::0;::::1;::::0;;;::::1;;:20;;::::0;::::1;;;;18379:63;;;;-1:-1:-1::0;;;18379:63:15::1;;;;;;;:::i;:::-;18458:31;18470:10;;;;;;;;;;;18482:6;18458:31;;;;;;;:::i;:::-;;;;;;;;18500:10;:19:::0;;;::::1;;::::0;::::1;-1:-1:-1::0;;18500:19:15;;::::1;::::0;;;::::1;::::0;;18308:218::o;782:53::-;819:16;782:53;:::o;6873:161:36:-;6940:7;;6981:22;:12;6997:5;6981:15;:22::i;:::-;-1:-1:-1;6959:44:36;6873:161;-1:-1:-1;;;6873:161:36:o;19112:142:15:-;1320:12:22;:10;:12::i;:::-;1310:6;;-1:-1:-1;;;;;1310:6:22;;;:22;;;1302:67;;;;;-1:-1:-1;;;1302:67:22;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1302:67:22;;;;;;;;;;;;;;;19188:28:15::1;19196:9;:7;:9::i;:::-;19207:8;19188:28;;;;;;;:::i;:::-;;;;;;;;19226:21;19238:8;19226:11;:21::i;689:39::-:0;726:2;689:39;:::o;4689:167:36:-;4753:7;4779:70;4796:7;4779:70;;;;;;;;;;;;;;;;;:12;;:70;:16;:70::i;6212:87::-;6284:8;6277:15;;;;;;;;-1:-1:-1;;6277:15:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6252:13;;6277:15;;6284:8;;6277:15;;6284:8;6277:15;;;;;;;;;;;;;;;;;;;;;;;;9156:408:15;9233:14;9250:12;:10;:12::i;:::-;9233:29;;9290:7;:5;:7::i;:::-;-1:-1:-1;;;;;9280:17:15;:6;-1:-1:-1;;;;;9280:17:15;;:38;;;-1:-1:-1;9311:7:15;;-1:-1:-1;;;;;9301:17:15;;;9311:7;;9301:17;9280:38;9272:102;;;;-1:-1:-1;;;9272:102:15;;;;;;;:::i;:::-;-1:-1:-1;;;;;9392:25:15;;9384:82;;;;-1:-1:-1;;;9384:82:15;;;;;;;:::i;:::-;9505:7;;9482:44;;-1:-1:-1;;;;;9482:44:15;;;;9505:7;;9482:44;;9505:7;;9482:44;-1:-1:-1;9536:7:15;:21;;-1:-1:-1;;;;;;9536:21:15;-1:-1:-1;;;;;9536:21:15;;;;;;;;;;9156:408::o;1536:67::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;4421:211:36:-;4485:7;-1:-1:-1;;;;;4512:19:36;;4504:74;;;;-1:-1:-1;;;4504:74:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4596:20:36;;;;;;:13;:20;;;;;:29;;:27;:29::i;1729:145:22:-;1320:12;:10;:12::i;:::-;1310:6;;-1:-1:-1;;;;;1310:6:22;;;:22;;;1302:67;;;;;-1:-1:-1;;;1302:67:22;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1302:67:22;;;;;;;;;;;;;;;1835:1:::1;1819:6:::0;;1798:40:::1;::::0;-1:-1:-1;;;;;1819:6:22;;::::1;::::0;-1:-1:-1;;;;;;;;;;;1798:40:22;1835:1;;1798:40:::1;1865:1;1848:19:::0;;-1:-1:-1;;;;;;1848:19:22::1;::::0;;1729:145::o;1484:46:15:-;;;;;;;;;;;;;;;:::o;13995:441::-;14115:18;:16;:18::i;:::-;14107:60;;;;-1:-1:-1;;;14107:60:15;;;;;;;:::i;:::-;14185:40;;;14177:81;;;;-1:-1:-1;;;14177:81:15;;;;;;;:::i;:::-;14269:14;14286:12;:10;:12::i;:::-;14269:29;;14313:9;14308:122;14328:19;;;14308:122;;;14368:51;14380:14;;14395:1;14380:17;;;;;;;;;;;;;;;;;;;;:::i;:::-;14399:8;;14408:1;14399:11;;;;;;;;;;;;;14412:6;14368:11;:51::i;:::-;14349:3;;14308:122;;;;13995:441;;;;;:::o;605:78::-;647:36;605:78;:::o;22789:315::-;23029:14;23025:24;;;;-1:-1:-1;;;;;23074:14:15;;;;23001:97::o;1106:77:22:-;1144:7;1170:6;-1:-1:-1;;;;;1170:6:22;1106:77;:::o;734:42:15:-;773:3;734:42;:::o;5072:94:36:-;5152:7;5145:14;;;;;;;;-1:-1:-1;;5145:14:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5120:13;;5145:14;;5152:7;;5145:14;;5152:7;5145:14;;;;;;;;;;;;;;;;;;;;;;;;7809:290;7923:12;:10;:12::i;:::-;-1:-1:-1;;;;;7911:24:36;:8;-1:-1:-1;;;;;7911:24:36;;;7903:62;;;;;-1:-1:-1;;;7903:62:36;;;;;;;;;;;;-1:-1:-1;;;7903:62:36;;;;;;;;;;;;;;;8021:8;7976:18;:32;7995:12;:10;:12::i;:::-;-1:-1:-1;;;;;7976:32:36;;;;;;;;;;;;;;;;;-1:-1:-1;7976:32:36;;;:42;;;;;;;;;;;;:53;;-1:-1:-1;;7976:53:36;;;;;;;;;;;8059:12;:10;:12::i;:::-;-1:-1:-1;;;;;8044:48:36;;8083:8;8044:48;;;;;;;;;;;;;;;;;;;;7809:290;;:::o;1433:45:15:-;;;;;;;;;;;;;;;:::o;1811:22::-;;;;;;;;;:::o;8962:282:36:-;9093:41;9112:12;:10;:12::i;:::-;9126:7;9093:18;:41::i;:::-;9085:103;;;;-1:-1:-1;;;9085:103:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9198:39;9212:4;9218:2;9222:7;9231:5;9198:13;:39::i;:::-;8962:282;;;;:::o;1609:65:15:-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1681:19::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1681:19:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1681:19:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1681:19:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1681:19:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1681:19:15;;-1:-1:-1;;;;;;1681:19:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;1681:19:15;;;;;;;;;;;;;;;;-1:-1:-1;;1681:19:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1681:19:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;19484:665::-;19558:13;19591:17;19599:8;19591:7;:17::i;:::-;19583:56;;;;-1:-1:-1;;;19583:56:15;;;;;;;:::i;:::-;19651:14;19667:16;19687:23;19701:8;19687:13;:23::i;:::-;19650:60;;-1:-1:-1;19650:60:15;-1:-1:-1;19770:9:15;19860;:7;:9::i;:::-;19887:17;:2;:15;:17::i;:::-;19965:31;19973:4;19965:29;:31::i;:::-;20035:21;:6;:19;:21::i;:::-;20095:23;:8;:21;:23::i;:::-;19826:306;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;19799:343;;;;;19484:665;;;:::o;1721:24::-;;;;:::o;3604:1053::-;3895:20;:18;:20::i;:::-;-1:-1:-1;;;;;3934:22:15;;3926:62;;;;-1:-1:-1;;;3926:62:15;;;;;;;:::i;:::-;-1:-1:-1;;;;;4006:32:15;;3998:73;;;;-1:-1:-1;;;3998:73:15;;;;;;;:::i;:::-;4106:14;:12;:14::i;:::-;4153:49;;;;;;;;;;;;;;-1:-1:-1;;;4153:49:15;;;;;;;;;;;;;;;;-1:-1:-1;;;4153:49:15;;;:17;:49::i;:::-;4235:27;4247:5;4254:7;4235:11;:27::i;:::-;4297:20;4308:8;4297:10;:20::i;:::-;4351:7;:18;;-1:-1:-1;;;;;4351:18:15;;;-1:-1:-1;;;;;;4351:18:15;;;;;;;4404:8;:20;;;;;;;;;;;;;;;4456:17;4466:6;4456:9;:17::i;:::-;4488:15;4484:67;;;4519:21;:19;:21::i;:::-;-1:-1:-1;;4561:10:15;:24;;-1:-1:-1;;4561:24:15;;;;;-1:-1:-1;;4561:24:15;;;;4596:17;;;;;;;;-1:-1:-1;;4635:15:15;4623:9;:27;-1:-1:-1;;;3604:1053:15:o;17244:90::-;17315:5;:12;17244:90;:::o;6136:893::-;5047:12;:10;:12::i;:::-;5026:93;;;;-1:-1:-1;;;5026:93:15;;;;;;;:::i;:::-;6329:34;;::::1;:72:::0;::::1;;;-1:-1:-1::0;6368:33:15;;::::1;6329:72;6308:151;;;;-1:-1:-1::0;;;6308:151:15::1;;;;;;;:::i;:::-;6475:9;6470:553;6490:19:::0;;::::1;6470:553;;;6530:14;6547:8;;6556:1;6547:11;;;;;;;;;;;;;;;;;;;;:::i;:::-;6530:28;;6572:14;6589:8;;6598:1;6589:11;;;;;;;;;;;;;6572:28;;6614:13;6630:7;;6638:1;6630:10;;;;;;;;;::::0;;;::::1;;::::0;-1:-1:-1;;;;;;;6662:20:15;::::1;6654:72;;;;-1:-1:-1::0;;;6654:72:15::1;;;;;;;:::i;:::-;6757:5;:12:::0;6748:21;::::1;6740:70;;;;-1:-1:-1::0;;;6740:70:15::1;;;;;;;:::i;:::-;6832:19;::::0;;;:11:::1;:19;::::0;;;;;;;-1:-1:-1;;;;;6832:27:15;::::1;::::0;;;;;;;;:36;::::1;;6824:83;;;;-1:-1:-1::0;;;6824:83:15::1;;;;;;;:::i;:::-;6922:19;::::0;;;:11:::1;:19;::::0;;;;;;;-1:-1:-1;;;;;6922:27:15;::::1;::::0;;;;;;;;;:35;;;6976:36;;6934:6;;6976:36:::1;::::0;::::1;::::0;6952:5;;6976:36:::1;:::i;:::-;;;;;;;;-1:-1:-1::0;;;6511:3:15::1;;6470:553;;8165:154:36::0;-1:-1:-1;;;;;8277:25:36;;;8254:4;8277:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;8165:154::o;22130:411:15:-;22210:10;819:16;22240:22;;;22232:65;;;;-1:-1:-1;;;22232:65:15;;;;;;;:::i;:::-;-1:-1:-1;;;;;22315:26:15;;;22307:71;;;;-1:-1:-1;;;22307:71:15;;;;;;;:::i;:::-;-1:-1:-1;22489:14:15;22485:28;;;;22482:43;;22462:73::o;2023:240:22:-;1320:12;:10;:12::i;:::-;1310:6;;-1:-1:-1;;;;;1310:6:22;;;:22;;;1302:67;;;;;-1:-1:-1;;;1302:67:22;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;1302:67:22;;;;;;;;;;;;;;;-1:-1:-1;;;;;2111:22:22;::::1;2103:73;;;;-1:-1:-1::0;;;2103:73:22::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2212:6;::::0;;2191:38:::1;::::0;-1:-1:-1;;;;;2191:38:22;;::::1;::::0;2212:6;::::1;::::0;-1:-1:-1;;;;;;;;;;;2191:38:22;::::1;2239:6;:17:::0;;-1:-1:-1;;;;;;2239:17:22::1;-1:-1:-1::0;;;;;2239:17:22;;;::::1;::::0;;;::::1;::::0;;2023:240::o;20643:220:15:-;20752:9;20747:110;20767:20;;;20747:110;;;20808:38;20821:5;20828:3;20833:9;;20843:1;20833:12;;;;;;;;;;;;;20808;:38::i;:::-;20789:3;;20747:110;;17784:173;5047:12;:10;:12::i;:::-;5026:93;;;;-1:-1:-1;;;5026:93:15;;;;;;;:::i;:::-;17854:11:::1;::::0;::::1;::::0;::::1;;;17853:12;17845:73;;;;-1:-1:-1::0;;;17845:73:15::1;;;;;;;:::i;:::-;17929:21;:19;:21::i;:::-;17784:173::o:0;412:30:18:-;;;;:::o;841:57:15:-;-1:-1:-1;;;;;841:57:15;:::o;1782:23::-;;;;;;;;;:::o;10677:117:36:-;10734:4;10757:30;:12;10779:7;10757:21;:30::i;96:639:17:-;181:22;223:10;245:4;223:27;219:487;;;266:18;287:8;;266:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;325:8:17;532:17;526:24;-1:-1:-1;;;;;501:131:17;;-1:-1:-1;363:283:17;;-1:-1:-1;363:283:17;;-1:-1:-1;685:10:17;96:639;:::o;16333:155:36:-;16398:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;16398:29:36;-1:-1:-1;;;;;16398:29:36;;;;;;;;:24;;16451:16;16398:24;16451:7;:16::i;:::-;-1:-1:-1;;;;;16442:39:36;;;;;;;;;;;16333:155;;:::o;2418:459:21:-;2590:4;-1:-1:-1;;;;;2614:20:21;;2606:59;;;;;-1:-1:-1;;;2606:59:21;;;;;;;;;;;;-1:-1:-1;;;2606:59:21;;;;;;;;;;;;;;;2716:154;2743:47;2762:27;2782:6;2762:19;:27::i;:::-;2743:18;:47::i;:::-;2808:4;2830;2852;2716:154;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2694:176:21;:6;-1:-1:-1;;;;;2694:176:21;;2675:195;;2418:459;;;;;;;:::o;2690:175:5:-;2748:7;2779:5;;;2802:6;;;;2794:46;;;;;-1:-1:-1;;;2794:46:5;;;;;;;;;;;;-1:-1:-1;;;2794:46:5;;;;;;;;;;;;;;4699:98:15;4744:4;4778:12;:10;:12::i;:::-;4767:7;;-1:-1:-1;;;;;4767:7:15;;;:23;;;;-1:-1:-1;4699:98:15;:::o;4803:184::-;4863:4;4879:14;4896:12;:10;:12::i;:::-;-1:-1:-1;;;;;4925:22:15;;;;;;:14;:22;;;;;;4879:29;;-1:-1:-1;4925:22:15;;;:55;;-1:-1:-1;4951:21:15;;;;:12;:21;;;;;;;;-1:-1:-1;;;;;4951:29:15;;;;;;;;;;;;4925:55;4918:62;4803:184;-1:-1:-1;;;4803:184:15:o;7820:121:12:-;7889:7;7915:19;7923:3;7915:7;:19::i;10952:329:36:-;11037:4;11061:16;11069:7;11061;:16::i;:::-;11053:73;;;;-1:-1:-1;;;11053:73:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11136:13;11152:16;11160:7;11152;:16::i;:::-;11136:32;;11197:5;-1:-1:-1;;;;;11186:16:36;:7;-1:-1:-1;;;;;11186:16:36;;:51;;;;11230:7;-1:-1:-1;;;;;11206:31:36;:20;11218:7;11206:11;:20::i;:::-;-1:-1:-1;;;;;11206:31:36;;11186:51;:87;;;;11241:32;11258:5;11265:7;11241:16;:32::i;:::-;11178:96;10952:329;-1:-1:-1;;;;10952:329:36:o;13946:559::-;14063:4;-1:-1:-1;;;;;14043:24:36;:16;14051:7;14043;:16::i;:::-;-1:-1:-1;;;;;14043:24:36;;14035:78;;;;-1:-1:-1;;;14035:78:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;14131:16:36;;14123:65;;;;-1:-1:-1;;;14123:65:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14199:39;14220:4;14226:2;14230:7;14199:20;:39::i;:::-;14300:29;14317:1;14321:7;14300:8;:29::i;:::-;-1:-1:-1;;;;;14340:19:36;;;;;;:13;:19;;;;;:35;;14367:7;14340:26;:35::i;:::-;-1:-1:-1;;;;;;14385:17:36;;;;;;:13;:17;;;;;:30;;14407:7;14385:21;:30::i;:::-;-1:-1:-1;14426:29:36;:12;14443:7;14452:2;14426:16;:29::i;:::-;;14490:7;14486:2;-1:-1:-1;;;;;14471:27:36;14480:4;-1:-1:-1;;;;;14471:27:36;-1:-1:-1;;;;;;;;;;;14471:27:36;;;;;;;;;13946:559;;;:::o;9250:135:13:-;9321:7;9355:22;9359:3;9371:5;9355:3;:22::i;12230:1542:15:-;12319:1;12303:6;:13;:17;12295:52;;;;-1:-1:-1;;;12295:52:15;;;;;;;:::i;:::-;12358:30;;:::i;:::-;12398:21;;12430:1336;12454:6;:13;12450:1;:17;12430:1336;;;12488:22;12513:6;12520:1;12513:9;;;;;;;;;;;;;;12488:34;;12536:17;12572:5;:12;;;12556:30;;;;;;12536:50;;12622:9;12605:13;:26;12601:326;;12660:8;;12685:12;;12660:38;;-1:-1:-1;;;12660:38:15;;-1:-1:-1;;;;;12660:8:15;;;;:24;;:38;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;12660:38:15;;;;;;;;;;;;:::i;:::-;12651:47;;12732:9;12716:25;;12808:1;12789:6;:16;;;:20;:57;;;;-1:-1:-1;12813:16:15;;;;-1:-1:-1;;;;;;12813:33:15;12789:57;12760:152;;;;-1:-1:-1;;;12760:152:15;;;;;;;:::i;:::-;12980:1;12955:5;:14;;;12949:28;:32;12941:69;;;;-1:-1:-1;;;12941:69:15;;;;;;;:::i;:::-;13063:1;13049:5;:11;;;:15;:50;;;;-1:-1:-1;13068:17:15;;;;-1:-1:-1;;;;;13068:31:15;;;13049:50;:105;;;-1:-1:-1;13103:11:15;;;;:16;:51;;;;-1:-1:-1;13123:17:15;;;;-1:-1:-1;;;;;13123:31:15;;13103:51;13024:203;;;;-1:-1:-1;;;13024:203:15;;;;;;;:::i;:::-;13262:5;:12;819:16;13296:23;;13288:65;;;;-1:-1:-1;;;13288:65:15;;;;;;;:::i;:::-;13387:293;;;;;;;;13418:11;;13387:293;;;13458:16;;;;13387:293;;;;13368:16;13387:293;;;;;;13531:11;;;;13387:293;;;;;;;;13573:17;;;;-1:-1:-1;;;;;13387:293:15;;;;;13618:14;;;13387:293;;;;;;;;;;;;;;;;;;;;;;13695:5;:16;;;;;;;;;;;;;13387:293;;;;13695:16;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;13695:16:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;13695:16:15;-1:-1:-1;;;;;13695:16:15;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;13695:16:15;;;;;;;;;;;;;;;;;;:::i;:::-;;;;13739:9;13731:24;13750:4;13731:24;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;12469:3:15;;;;;-1:-1:-1;12430:1336:15;;-1:-1:-1;12430:1336:15;8269:233:12;8349:7;;;;8408:22;8412:3;8424:5;8408:3;:22::i;:::-;8377:53;;-1:-1:-1;8377:53:12;-1:-1:-1;;;8269:233:12;;;;;;:::o;15087:98:36:-;15159:19;;;;:8;;:19;;;;;:::i;:::-;;15087:98;:::o;9522:211:12:-;9629:7;9679:44;9684:3;9704;9710:12;9679:4;:44::i;14710:1081:15:-;14820:12;:10;:12::i;:::-;:38;;;-1:-1:-1;;;;;;14836:22:15;;;;;;:13;:22;;;;;;;;14820:38;14814:309;;14876:17;14896:20;;;:11;:20;;;;;;;;-1:-1:-1;;;;;14896:29:15;;;;;;;;;;14948:13;14940:58;;;;-1:-1:-1;;;14940:58:15;;;;;;;:::i;:::-;-1:-1:-1;;15017:9:15;:30;15013:100;;15067:20;;;;:11;:20;;;;;;;;-1:-1:-1;;;;;15067:29:15;;;;;;;;;:31;;-1:-1:-1;;15067:31:15;;;15013:100;14814:309;;15176:5;:12;15166:22;;15158:67;;;;-1:-1:-1;;;15158:67:15;;;;;;;:::i;:::-;15236:17;15256:5;15262:7;15256:14;;;;;;;;;;;;;;;;;;15236:34;;15280:23;15306;15327:1;15306:4;:16;;;:20;;:23;;;;:::i;:::-;15280:49;;15393:4;:14;;;15374:15;:33;;15366:73;;;;-1:-1:-1;;;15366:73:15;;;;;;;:::i;:::-;15477:15;15495:39;15509:7;15518:15;15495:13;:39::i;:::-;15574:16;;;:34;;;15477:57;-1:-1:-1;15656:34:15;15668:12;15477:57;15656:11;:34::i;:::-;15750:7;15741;15727:12;-1:-1:-1;;;;;15721:63:15;;15759:15;15776:7;15721:63;;;;;;;:::i;:::-;;;;;;;;14710:1081;;;;;;:::o;10105:269:36:-;10218:28;10228:4;10234:2;10238:7;10218:9;:28::i;:::-;10264:48;10287:4;10293:2;10297:7;10306:5;10264:22;:48::i;:::-;10256:111;;;;-1:-1:-1;;;10256:111:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;995:488:30;1049:27;1097:2;1114:6;1110:47;;-1:-1:-1;;1136:10:30;;;;;;;;;;;;-1:-1:-1;;;1136:10:30;;;;;;1110:47;1175:1;1166:6;1204:66;1211:6;;1204:66;;1233:5;;1257:2;1252:7;;;;1204:66;;;1279:17;1309:3;-1:-1:-1;;;;;1299:14:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1299:14:30;-1:-1:-1;1279:34:30;-1:-1:-1;;;1332:7:30;;1349:99;1356:6;;1349:99;;1412:2;1408:1;:6;1403:2;:11;1390:26;;1378:4;1383:3;;;;;;;1378:9;;;;;;;;;;;:38;-1:-1:-1;;;;;1378:38:30;;;;;;;;-1:-1:-1;1435:2:30;1430:7;;;;1349:99;;;-1:-1:-1;1471:4:30;995:488;-1:-1:-1;;;;;995:488:30:o;1653:439::-;1755:13;;;1765:2;1755:13;;;1713;1755;;;;;;1738:14;;1755:13;;;;;;;;;;;-1:-1:-1;1755:13:30;1738:30;;1783:6;1778:282;1799:2;1795:1;:6;1778:282;;;1822:8;1873:1;1868:2;:6;1865:1;:10;1861:1;:15;1854:2;-1:-1:-1;;;;;1846:31:30;;;;;;;1833:46;;1822:57;;1893:9;1923:2;1918:1;1912:8;;:13;;;;;;;;1905:21;;1893:33;;1940:9;1981:2;1975:9;;1970:2;:14;1965:1;1959:8;;:25;1952:33;;1940:45;;2008:8;2013:2;2008:4;:8::i;:::-;1999:1;2003;2001;:3;1999:6;;;;;;;;;;;:17;-1:-1:-1;;;;;1999:17:30;;;;;;;;;2041:8;2046:2;2041:4;:8::i;:::-;2030:1;2034;2032;:3;2036:1;2032:5;2030:8;;;;;;;;;;;:19;-1:-1:-1;;;;;2030:19:30;;;;;;;;-1:-1:-1;;1803:3:30;;;;;-1:-1:-1;1778:282:30;;-1:-1:-1;1778:282:30;;-1:-1:-1;2083:1:30;1653:439;-1:-1:-1;;1653:439:30:o;861:169:22:-;905:17;925:12;:10;:12::i;:::-;947:6;:18;;-1:-1:-1;;;;;;947:18:22;-1:-1:-1;;;;;947:18:22;;;;;;;980:43;;947:18;;-1:-1:-1;947:18:22;-1:-1:-1;;;;;;;;;;;980:43:22;947:6;;980:43;861:169;:::o;639:398:18:-;290:110;;;;;;;;;;;;;;;;;271:135;;;;;;887:4;871:22;;;;;;927:7;911:25;;;;;;962:4;993:12;:10;:12::i;:::-;985:21;;803:217;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;803:217:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;780:250;;;;;;762:15;:268;;;;639:398;;:::o;3979:383:36:-;4065:14;;;;:5;;:14;;;;;:::i;:::-;-1:-1:-1;4089:18:36;;;;:7;;:18;;;;;:::i;:::-;-1:-1:-1;4195:40:36;-1:-1:-1;;;4195:18:36;:40::i;:::-;4245:49;-1:-1:-1;;;4245:18:36;:49::i;:::-;4304:51;-1:-1:-1;;;4304:18:36;:51::i;18150:100:15:-;18200:11;:18;;-1:-1:-1;;18200:18:15;;;;;18233:10;;;;18200:18;;18233:10;18150:100::o;7588:149:12:-;7672:4;7695:35;7705:3;7725;7695:9;:35::i;1903:396:21:-;2010:7;330:98;;;;;;;;;;;;;;;;;311:123;;;;;;2158:6;:12;;;2192:6;:11;;;2235:6;:24;;;2225:35;;;;;;2079:199;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2079:199:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;2052:240;;;;;;2033:259;;1903:396;;;:::o;1558:244:18:-;1752:15;;1723:58;;;-1:-1:-1;;;1723:58:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1696:99;;;;;;1558:244::o;4491:108:12:-;4573:19;;4491:108::o;8365:135:13:-;8435:4;8458:35;8466:3;8486:5;8458:7;:35::i;8068:129::-;8135:4;8158:32;8163:3;8183:5;8158:4;:32::i;7027:183:12:-;7116:4;7139:64;7144:3;7164;-1:-1:-1;;;;;7178:23:12;;7139:4;:64::i;4452:201:13:-;4546:18;;4519:7;;4546:26;-1:-1:-1;4538:73:13;;;;-1:-1:-1;;;4538:73:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4628:3;:11;;4640:5;4628:18;;;;;;;;;;;;;;;;4621:25;;4452:201;;;;:::o;4942:274:12:-;5045:19;;5009:7;;;;5045:27;-1:-1:-1;5037:74:12;;;;-1:-1:-1;;;5037:74:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5122:22;5147:3;:12;;5160:5;5147:19;;;;;;;;;;;;;;;;;;5122:44;;5184:5;:10;;;5196:5;:12;;;5176:33;;;;;4942:274;;;;;:::o;6403:315::-;6497:7;6535:17;;;:12;;;:17;;;;;;6585:12;6570:13;6562:36;;;;-1:-1:-1;;;6562:36:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6651:3;:12;;6675:1;6664:8;:12;6651:26;;;;;;;;;;;;;;;;;;:33;;;6644:40;;;6403:315;;;;;:::o;12510:393:36:-;-1:-1:-1;;;;;12589:16:36;;12581:61;;;;;-1:-1:-1;;;12581:61:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12661:16;12669:7;12661;:16::i;:::-;12660:17;12652:58;;;;;-1:-1:-1;;;12652:58:36;;;;;;;;;;;;-1:-1:-1;;;12652:58:36;;;;;;;;;;;;;;;12721:45;12750:1;12754:2;12758:7;12721:20;:45::i;:::-;-1:-1:-1;;;;;12777:17:36;;;;;;:13;:17;;;;;:30;;12799:7;12777:21;:30::i;:::-;-1:-1:-1;12818:29:36;:12;12835:7;12844:2;12818:16;:29::i;:::-;-1:-1:-1;12863:33:36;;12888:7;;-1:-1:-1;;;;;12863:33:36;;;12880:1;;-1:-1:-1;;;;;;;;;;;12863:33:36;12880:1;;12863:33;12510:393;;:::o;15738:589::-;15858:4;15883:15;:2;-1:-1:-1;;;;;15883:13:36;;:15::i;:::-;15878:58;;-1:-1:-1;15921:4:36;15914:11;;15878:58;15945:23;15971:246;-1:-1:-1;;;16082:12:36;:10;:12::i;:::-;16108:4;16126:7;16147:5;15987:175;;;;;;-1:-1:-1;;;;;15987:175:36;;;;;;-1:-1:-1;;;;;15987:175:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15987:175:36;;;;;;;-1:-1:-1;;;;;15987:175:36;;;;;;;;;;;15971:246;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15971:15:36;;;:246;:15;:246::i;:::-;15945:272;;16227:13;16254:10;16243:32;;;;;;;;;;;;;;;-1:-1:-1;16243:32:36;-1:-1:-1;;;;;;16293:26:36;-1:-1:-1;;;16293:26:36;;-1:-1:-1;;;15738:589:36;;;;;;:::o;2098:168:30:-;2145:8;2180:2;2169:8;;;;:13;2165:94;;;2204:1;2198:8;;2209:4;2198:15;2191:23;;2184:30;;;;2165:94;2249:1;2243:8;;2254:4;2243:15;2236:23;;2229:30;;;;1507:198:2;-1:-1:-1;;;;;;1590:25:2;;;;;1582:66;;;;;-1:-1:-1;;;1582:66:2;;;;;;;;;;;;-1:-1:-1;;;1582:66:2;;;;;;;;;;;;;;;-1:-1:-1;;;;;;1658:33:2;;;;;1694:4;1658:33;;;;;;;;:40;;-1:-1:-1;;1658:40:2;;;;;;1507:198::o;4278:123:12:-;4349:4;4372:17;;;:12;;;;;:17;;;;;;:22;;;4278:123::o;2212:1512:13:-;2278:4;2415:19;;;:12;;;:19;;;;;;2449:15;;2445:1273;;2878:18;;-1:-1:-1;;2830:14:13;;;;2878:22;;;;2806:21;;2878:3;;:22;;3160;;;;;;;;;;;;;;3140:42;;3303:9;3274:3;:11;;3286:13;3274:26;;;;;;;;;;;;;;;;;;;:38;;;;3378:23;;;3420:1;3378:12;;;:23;;;;;;3404:17;;;3378:43;;3527:17;;3378:3;;3527:17;;;;;;;;;;;;;;;;;;;;;;3619:3;:12;;:19;3632:5;3619:19;;;;;;;;;;;3612:26;;;3660:4;3653:11;;;;;;;;2445:1273;3702:5;3695:12;;;;;1640:404;1703:4;1724:21;1734:3;1739:5;1724:9;:21::i;:::-;1719:319;;-1:-1:-1;1761:23:13;;;;;;;;:11;:23;;;;;;;;;;;;;1941:18;;1919:19;;;:12;;;:19;;;;;;:40;;;;1973:11;;1719:319;-1:-1:-1;2022:5:13;2015:12;;1836:678:12;1912:4;2045:17;;;:12;;;:17;;;;;;2077:13;2073:435;;-1:-1:-1;;2161:38:12;;;;;;;;;;;;;;;;;;2143:57;;;;;;;;:12;:57;;;;;;;;;;;;;;;;;;;;;;;;2355:19;;2335:17;;;:12;;;:17;;;;;;;:39;2388:11;;2073:435;2466:5;2430:3;:12;;2454:1;2443:8;:12;2430:26;;;;;;;;;;;;;;;;;;:33;;:41;;;;2492:5;2485:12;;;;;726:413:10;1086:20;1124:8;;;726:413::o;3581:193::-;3684:12;3715:52;3737:6;3745:4;3751:1;3754:12;3684;4858:18;4869:6;4858:10;:18::i;:::-;4850:60;;;;;-1:-1:-1;;;4850:60:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;4981:12;4995:23;5022:6;-1:-1:-1;;;;;5022:11:10;5042:5;5050:4;5022:33;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;5022:33:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4980:75;;;;5072:52;5090:7;5099:10;5111:12;5072:17;:52::i;:::-;5065:59;4608:523;-1:-1:-1;;;;;;;4608:523:10:o;7091:725::-;7206:12;7234:7;7230:580;;;-1:-1:-1;7264:10:10;7257:17;;7230:580;7375:17;;:21;7371:429;;7633:10;7627:17;7693:15;7680:10;7676:2;7672:19;7665:44;7582:145;7765:20;;-1:-1:-1;;;7765:20:10;;;;;;;;;;;;;;;;;7772:12;;7765:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;14:138:37;84:20;;113:33;84:20;113:33;:::i;157:404::-;;;290:3;283:4;275:6;271:17;267:27;257:2;;315:8;305;298:26;257:2;-1:-1:-1;345:20:37;;-1:-1:-1;;;;;377:30:37;;374:2;;;427:8;417;410:26;374:2;471:4;463:6;459:17;447:29;;534:3;527:4;519;511:6;507:17;499:6;495:30;491:41;488:50;485:2;;;551:1;548;541:12;566:1600;;689:3;682:4;674:6;670:17;666:27;656:2;;711:5;704;697:20;656:2;751:6;738:20;777:4;801:75;816:59;872:2;816:59;:::i;:::-;801:75;:::i;:::-;910:15;;;941:12;;;;973:15;;;1006:5;1020:1117;1034:2;1031:1;1028:9;1020:1117;;;1114:3;1101:17;1093:6;1089:30;1142:4;1194:2;1188;1184:7;1179:2;1174:3;1170:12;1166:26;1162:35;1159:2;;;1214:5;1207;1200:20;1159:2;1245;1274:9;;1314:15;;;-1:-1:-1;;;;;1389:18:37;;;1409:22;;;1386:46;1383:2;;;1435:9;1383:2;1459:22;;;1523:11;;;1510:25;;1551:16;;;1548:2;;;1584:5;1577;1570:20;1548:2;1620:51;1667:3;1662:2;1651:8;1647:2;1643:17;1639:26;1620:51;:::i;:::-;1612:6;1605:67;1730:2;1726;1722:11;1709:25;1704:2;1696:6;1692:15;1685:50;1758:2;1748:12;;1797:33;1826:2;1822;1818:11;1797:33;:::i;:::-;1780:15;;;1773:58;1873:11;;;1860:25;;1901:16;;;1898:2;;;1934:5;1927;1920:20;1898:2;;1979:51;2026:3;2021:2;2010:8;2006:2;2002:17;1998:26;1979:51;:::i;:::-;1962:15;;;1955:76;2044:19;;-1:-1:-1;;;2083:12:37;;;;2115;;;;1052:1;1045:9;1020:1117;;;-1:-1:-1;2155:5:37;;646:1520;-1:-1:-1;;;;;;;646:1520:37:o;2171:162::-;2238:20;;2294:13;;2287:21;2277:32;;2267:2;;2323:1;2320;2313:12;2338:485;;2435:3;2428:4;2420:6;2416:17;2412:27;2402:2;;2457:5;2450;2443:20;2402:2;2497:6;2484:20;2528:49;2543:33;2573:2;2543:33;:::i;2528:49::-;2602:2;2593:7;2586:19;2648:3;2641:4;2636:2;2628:6;2624:15;2620:26;2617:35;2614:2;;;2669:5;2662;2655:20;2614:2;2738;2731:4;2723:6;2719:17;2712:4;2703:7;2699:18;2686:55;2761:16;;;2779:4;2757:27;2750:42;;;;2765:7;2392:431;-1:-1:-1;;2392:431:37:o;2828:259::-;;2940:2;2928:9;2919:7;2915:23;2911:32;2908:2;;;2961:6;2953;2946:22;2908:2;3005:9;2992:23;3024:33;3051:5;3024:33;:::i;3092:402::-;;;3221:2;3209:9;3200:7;3196:23;3192:32;3189:2;;;3242:6;3234;3227:22;3189:2;3286:9;3273:23;3305:33;3332:5;3305:33;:::i;:::-;3357:5;-1:-1:-1;3414:2:37;3399:18;;3386:32;3427:35;3386:32;3427:35;:::i;:::-;3481:7;3471:17;;;3179:315;;;;;:::o;3499:743::-;;;;;3680:2;3668:9;3659:7;3655:23;3651:32;3648:2;;;3701:6;3693;3686:22;3648:2;3745:9;3732:23;3764:33;3791:5;3764:33;:::i;:::-;3816:5;-1:-1:-1;3873:2:37;3858:18;;3845:32;3886:35;3845:32;3886:35;:::i;:::-;3940:7;-1:-1:-1;3998:2:37;3983:18;;3970:32;-1:-1:-1;;;;;4014:30:37;;4011:2;;;4062:6;4054;4047:22;4011:2;4106:76;4174:7;4165:6;4154:9;4150:22;4106:76;:::i;:::-;3638:604;;;;-1:-1:-1;4201:8:37;-1:-1:-1;;;;3638:604:37:o;4247:1475::-;;;;;4444:3;4432:9;4423:7;4419:23;4415:33;4412:2;;;4466:6;4458;4451:22;4412:2;4510:9;4497:23;4529:33;4556:5;4529:33;:::i;:::-;4581:5;-1:-1:-1;4605:2:37;4644:18;;;4631:32;4672:35;4631:32;4672:35;:::i;:::-;4726:7;-1:-1:-1;4784:2:37;4769:18;;4756:32;-1:-1:-1;;;;;4837:14:37;;;4834:2;;;4869:6;4861;4854:22;4834:2;4912:6;4901:9;4897:22;4887:32;;4957:7;4950:4;4946:2;4942:13;4938:27;4928:2;;4984:6;4976;4969:22;4928:2;5025;5012:16;5048:75;5063:59;5119:2;5063:59;:::i;5048:75::-;5157:15;;;5188:12;;;;5220:11;;;5258;;;5250:20;;5246:29;;5243:42;-1:-1:-1;5240:2:37;;;5303:6;5295;5288:22;5240:2;5330:6;5321:15;;5345:163;5359:2;5356:1;5353:9;5345:163;;;5416:17;;5404:30;;5377:1;5370:9;;;;;5454:12;;;;5486;;5345:163;;;-1:-1:-1;5527:5:37;-1:-1:-1;;;5585:2:37;5570:18;;5557:32;;-1:-1:-1;5601:16:37;;;5598:2;;;5635:6;5627;5620:22;5598:2;;;5663:53;5708:7;5697:8;5686:9;5682:24;5663:53;:::i;:::-;5653:63;;;4402:1320;;;;;;;:::o;5727:470::-;;;;5873:2;5861:9;5852:7;5848:23;5844:32;5841:2;;;5894:6;5886;5879:22;5841:2;5938:9;5925:23;5957:33;5984:5;5957:33;:::i;:::-;6009:5;-1:-1:-1;6066:2:37;6051:18;;6038:32;6079:35;6038:32;6079:35;:::i;:::-;5831:366;;6133:7;;-1:-1:-1;;;6187:2:37;6172:18;;;;6159:32;;5831:366::o;6202:691::-;;;;;6374:3;6362:9;6353:7;6349:23;6345:33;6342:2;;;6396:6;6388;6381:22;6342:2;6440:9;6427:23;6459:33;6486:5;6459:33;:::i;:::-;6511:5;-1:-1:-1;6568:2:37;6553:18;;6540:32;6581:35;6540:32;6581:35;:::i;:::-;6635:7;-1:-1:-1;6689:2:37;6674:18;;6661:32;;-1:-1:-1;6744:2:37;6729:18;;6716:32;-1:-1:-1;;;;;6760:30:37;;6757:2;;;6808:6;6800;6793:22;6757:2;6836:51;6879:7;6870:6;6859:9;6855:22;6836:51;:::i;6898:329::-;;;7024:2;7012:9;7003:7;6999:23;6995:32;6992:2;;;7045:6;7037;7030:22;6992:2;7089:9;7076:23;7108:33;7135:5;7108:33;:::i;:::-;7160:5;-1:-1:-1;7184:37:37;7217:2;7202:18;;7184:37;:::i;:::-;7174:47;;6982:245;;;;;:::o;7232:792::-;;;;;;7419:3;7407:9;7398:7;7394:23;7390:33;7387:2;;;7441:6;7433;7426:22;7387:2;7485:9;7472:23;7504:33;7531:5;7504:33;:::i;:::-;7556:5;-1:-1:-1;7612:2:37;7597:18;;7584:32;-1:-1:-1;;;;;7628:30:37;;7625:2;;;7676:6;7668;7661:22;7625:2;7704:51;7747:7;7738:6;7727:9;7723:22;7704:51;:::i;:::-;7694:61;;;7802:2;7791:9;7787:18;7774:32;7764:42;;7853:2;7842:9;7838:18;7825:32;7815:42;;7909:3;7898:9;7894:19;7881:33;7958:4;7949:7;7945:18;7936:7;7933:31;7923:2;;7983:6;7975;7968:22;7923:2;8011:7;8001:17;;;7377:647;;;;;;;;:::o;8029:327::-;;;8158:2;8146:9;8137:7;8133:23;8129:32;8126:2;;;8179:6;8171;8164:22;8126:2;8223:9;8210:23;8242:33;8269:5;8242:33;:::i;:::-;8294:5;8346:2;8331:18;;;;8318:32;;-1:-1:-1;;;8116:240:37:o;8361:812::-;;;;;8557:2;8545:9;8536:7;8532:23;8528:32;8525:2;;;8578:6;8570;8563:22;8525:2;8610:23;;-1:-1:-1;;;;;8682:14:37;;;8679:2;;;8714:6;8706;8699:22;8679:2;8758:76;8826:7;8817:6;8806:9;8802:22;8758:76;:::i;:::-;8853:8;;-1:-1:-1;8732:102:37;-1:-1:-1;8941:2:37;8926:18;;8913:32;;-1:-1:-1;8957:16:37;;;8954:2;;;8991:6;8983;8976:22;8954:2;;9035:78;9105:7;9094:8;9083:9;9079:24;9035:78;:::i;9998:411::-;;10162:2;10150:9;10141:7;10137:23;10133:32;10130:2;;;10183:6;10175;10168:22;10130:2;10215:23;;-1:-1:-1;;;;;10250:30:37;;10247:2;;;10298:6;10290;10283:22;10247:2;10326:77;10395:7;10386:6;10375:9;10371:22;10326:77;:::i;10414:1143::-;;;;;;;10662:2;10650:9;10641:7;10637:23;10633:32;10630:2;;;10683:6;10675;10668:22;10630:2;10715:23;;-1:-1:-1;;;;;10787:14:37;;;10784:2;;;10819:6;10811;10804:22;10784:2;10863:76;10931:7;10922:6;10911:9;10907:22;10863:76;:::i;:::-;10958:8;;-1:-1:-1;10837:102:37;-1:-1:-1;11046:2:37;11031:18;;11018:32;;-1:-1:-1;11062:16:37;;;11059:2;;;11096:6;11088;11081:22;11059:2;11140:78;11210:7;11199:8;11188:9;11184:24;11140:78;:::i;:::-;11237:8;;-1:-1:-1;11114:104:37;-1:-1:-1;11325:2:37;11310:18;;11297:32;;-1:-1:-1;11341:16:37;;;11338:2;;;11375:6;11367;11360:22;11338:2;;11419:78;11489:7;11478:8;11467:9;11463:24;11419:78;:::i;:::-;10620:937;;;;-1:-1:-1;10620:937:37;;-1:-1:-1;10620:937:37;;11516:8;;10620:937;-1:-1:-1;;;10620:937:37:o;11562:1146::-;;;;;;;11813:2;11801:9;11792:7;11788:23;11784:32;11781:2;;;11834:6;11826;11819:22;11781:2;11866:23;;-1:-1:-1;;;;;11938:14:37;;;11935:2;;;11970:6;11962;11955:22;11935:2;12014:76;12082:7;12073:6;12062:9;12058:22;12014:76;:::i;:::-;12109:8;;-1:-1:-1;11988:102:37;-1:-1:-1;12197:2:37;12182:18;;12169:32;;-1:-1:-1;12213:16:37;;;12210:2;;;12247:6;12239;12232:22;12210:2;12291:78;12361:7;12350:8;12339:9;12335:24;12291:78;:::i;:::-;12388:8;;-1:-1:-1;12265:104:37;-1:-1:-1;12476:2:37;12461:18;;12448:32;;-1:-1:-1;12492:16:37;;;12489:2;;;12526:6;12518;12511:22;13888:1490;;;;;;;;;14203:3;14191:9;14182:7;14178:23;14174:33;14171:2;;;14225:6;14217;14210:22;14171:2;14257:23;;-1:-1:-1;;;;;14329:14:37;;;14326:2;;;14361:6;14353;14346:22;14326:2;14405:76;14473:7;14464:6;14453:9;14449:22;14405:76;:::i;:::-;14500:8;;-1:-1:-1;14379:102:37;-1:-1:-1;14588:2:37;14573:18;;14560:32;;-1:-1:-1;14604:16:37;;;14601:2;;;14638:6;14630;14623:22;14601:2;14682:78;14752:7;14741:8;14730:9;14726:24;14682:78;:::i;:::-;14779:8;;-1:-1:-1;14656:104:37;-1:-1:-1;14867:2:37;14852:18;;14839:32;;-1:-1:-1;14883:16:37;;;14880:2;;;14917:6;14909;14902:22;14880:2;14961:78;15031:7;15020:8;15009:9;15005:24;14961:78;:::i;:::-;15058:8;;-1:-1:-1;14935:104:37;-1:-1:-1;15146:2:37;15131:18;;15118:32;;-1:-1:-1;15162:16:37;;;15159:2;;;15196:6;15188;15181:22;15159:2;;15240:78;15310:7;15299:8;15288:9;15284:24;15240:78;:::i;:::-;14161:1217;;;;-1:-1:-1;14161:1217:37;;-1:-1:-1;14161:1217:37;;;;;;15337:8;-1:-1:-1;;;14161:1217:37:o;15383:192::-;;15492:2;15480:9;15471:7;15467:23;15463:32;15460:2;;;15513:6;15505;15498:22;15460:2;15541:28;15559:9;15541:28;:::i;15580:306::-;;15691:2;15679:9;15670:7;15666:23;15662:32;15659:2;;;15712:6;15704;15697:22;15659:2;15743:23;;-1:-1:-1;;;;;;15795:32:37;;15785:43;;15775:2;;15847:6;15839;15832:22;15891:343;;16013:2;16001:9;15992:7;15988:23;15984:32;15981:2;;;16034:6;16026;16019:22;15981:2;16066:23;;-1:-1:-1;;;;;16101:30:37;;16098:2;;;16149:6;16141;16134:22;16098:2;16177:51;16220:7;16211:6;16200:9;16196:22;16177:51;:::i;16239:1380::-;;;;;;;;;16564:3;16552:9;16543:7;16539:23;16535:33;16532:2;;;16586:6;16578;16571:22;16532:2;16618:23;;-1:-1:-1;;;;;16690:14:37;;;16687:2;;;16722:6;16714;16707:22;16687:2;16750:51;16793:7;16784:6;16773:9;16769:22;16750:51;:::i;:::-;16740:61;;16854:2;16843:9;16839:18;16826:32;16810:48;;16883:2;16873:8;16870:16;16867:2;;;16904:6;16896;16889:22;16867:2;16932:53;16977:7;16966:8;16955:9;16951:24;16932:53;:::i;:::-;16922:63;;17038:2;17027:9;17023:18;17010:32;16994:48;;17067:2;17057:8;17054:16;17051:2;;;17088:6;17080;17073:22;17051:2;17116:53;17161:7;17150:8;17139:9;17135:24;17116:53;:::i;:::-;17106:63;;17188:40;17224:2;17213:9;17209:18;17188:40;:::i;:::-;17178:50;;17247:38;17280:3;17269:9;17265:19;17247:38;:::i;:::-;17237:48;;17304:38;17337:3;17326:9;17322:19;17304:38;:::i;:::-;17294:48;;17361:41;17397:3;17386:9;17382:19;17361:41;:::i;:::-;17351:51;;17455:3;17444:9;17440:19;17427:33;17411:49;;17485:2;17475:8;17472:16;17469:2;;;17506:6;17498;17491:22;17469:2;;17534:79;17605:7;17594:8;17583:9;17579:24;17534:79;:::i;:::-;17524:89;;;16522:1097;;;;;;;;;;;:::o;17624:1237::-;;17749:2;17792;17780:9;17771:7;17767:23;17763:32;17760:2;;;17813:6;17805;17798:22;17760:2;17845:16;;-1:-1:-1;;;;;17910:14:37;;;17907:2;;;17942:6;17934;17927:22;17907:2;17970:22;;;;18026:4;18008:16;;;18004:27;18001:2;;;18049:6;18041;18034:22;18001:2;18087;18081:9;18129:4;18121:6;18117:17;18184:6;18172:10;18169:22;18164:2;18152:10;18149:18;18146:46;18143:2;;;18195:9;18143:2;18222;18215:22;18262:9;;18283:16;;;18280:2;;;18317:6;18309;18302:22;18280:2;18345:17;;;-1:-1:-1;18393:4:37;18385:13;;18381:27;-1:-1:-1;18371:2:37;;18427:6;18419;18412:22;18371:2;18461;18455:9;18486:49;18501:33;18531:2;18501:33;:::i;18486:49::-;18558:2;18551:5;18544:17;18598:7;18593:2;18588;18584;18580:11;18576:20;18573:33;18570:2;;;18624:6;18616;18609:22;18570:2;18642:54;18693:2;18688;18681:5;18677:14;18672:2;18668;18664:11;18642:54;:::i;:::-;18705:21;;-1:-1:-1;18765:11:37;;;18759:18;18742:15;;;18735:43;;;;-1:-1:-1;18825:2:37;18817:11;;;18811:18;18794:15;;;18787:43;18712:6;17729:1132;-1:-1:-1;;;17729:1132:37:o;18866:190::-;;18978:2;18966:9;18957:7;18953:23;18949:32;18946:2;;;18999:6;18991;18984:22;18946:2;-1:-1:-1;19027:23:37;;18936:120;-1:-1:-1;18936:120:37:o;19061:327::-;;;19190:2;19178:9;19169:7;19165:23;19161:32;19158:2;;;19211:6;19203;19196:22;19158:2;19252:9;19239:23;19229:33;;19312:2;19301:9;19297:18;19284:32;19325:33;19352:5;19325:33;:::i;19393:258::-;;;19522:2;19510:9;19501:7;19497:23;19493:32;19490:2;;;19543:6;19535;19528:22;19490:2;-1:-1:-1;;19571:23:37;;;19641:2;19626:18;;;19613:32;;-1:-1:-1;19480:171:37:o;19656:259::-;;19737:5;19731:12;19764:6;19759:3;19752:19;19780:63;19836:6;19829:4;19824:3;19820:14;19813:4;19806:5;19802:16;19780:63;:::i;:::-;19897:2;19876:15;-1:-1:-1;;19872:29:37;19863:39;;;;19904:4;19859:50;;19707:208;-1:-1:-1;;19707:208:37:o;19920:758::-;;20013:5;20007:12;20038:1;20070:2;20059:9;20055:18;20087:1;20082:165;;;;20261:1;20256:416;;;;20048:624;;20082:165;20134:1;20119:17;;20138:4;20115:28;20103:41;;-1:-1:-1;;20180:24:37;;20173:4;20164:14;;20157:48;20234:2;20225:12;;;-1:-1:-1;20082:165:37;;20256:416;20306:1;20295:9;20291:17;20333:6;20328:3;20321:19;20368:38;20400:5;20368:38;:::i;:::-;20428:1;20442:178;20456:6;20453:1;20450:13;20442:178;;;20553:7;20547:14;20540:4;20536:1;20531:3;20527:11;20523:22;20516:46;20603:2;20594:7;20590:16;20579:27;;20478:4;20475:1;20471:12;20466:17;;20442:178;;;20644:11;;20657:4;20640:22;;-1:-1:-1;;;20048:624:37;;;;19980:698;;;;:::o;20683:1616::-;;21448:6;21442:13;21464:53;21510:6;21505:3;21498:4;21490:6;21486:17;21464:53;:::i;:::-;21580:13;;21539:16;;;;21602:57;21580:13;21539:16;21636:4;21624:17;;21602:57;:::i;:::-;-1:-1:-1;;;21681:20:37;;21732:17;;;-1:-1:-1;;;21776:1:37;21765:13;;21758:27;21810:13;;21681:20;;21720:3;21832:65;21810:13;21884:1;21873:13;;21866:4;21854:17;;21832:65;:::i;:::-;21960:1;21916:20;;21952:10;;;21945:22;;;21992:13;;22014:62;21992:13;22063:1;22055:10;;22048:4;22036:17;;22014:62;:::i;:::-;22136:1;22095:17;;22128:10;;;22121:22;22168:13;;22190:62;22168:13;22239:1;22231:10;;22224:4;22212:17;;22190:62;:::i;:::-;22272:17;22291:1;22268:25;;21418:881;-1:-1:-1;;;;;;;21418:881:37:o;22304:203::-;-1:-1:-1;;;;;22468:32:37;;;;22450:51;;22438:2;22423:18;;22405:102::o;22512:187::-;22677:14;;22670:22;22652:41;;22640:2;22625:18;;22607:92::o;22704:268::-;22891:14;;22884:22;22866:41;;22950:14;22943:22;22938:2;22923:18;;22916:50;22854:2;22839:18;;22821:151::o;22977:177::-;23123:25;;;23111:2;23096:18;;23078:76::o;23159:219::-;;23306:2;23295:9;23288:21;23326:46;23368:2;23357:9;23353:18;23345:6;23326:46;:::i;23835:385::-;;24032:2;24021:9;24014:21;24058:46;24100:2;24089:9;24085:18;24077:6;24058:46;:::i;:::-;24152:9;24144:6;24140:22;24135:2;24124:9;24120:18;24113:50;24180:34;24207:6;24199;24180:34;:::i;:::-;24172:42;24004:216;-1:-1:-1;;;;;24004:216:37:o;24225:391::-;;24419:2;24408:9;24401:21;24445:46;24487:2;24476:9;24472:18;24464:6;24445:46;:::i;:::-;24539:9;24531:6;24527:22;24522:2;24511:9;24507:18;24500:50;24567:43;24603:6;24595;24567:43;:::i;24621:864::-;;24978:3;24967:9;24960:22;25005:47;25047:3;25036:9;25032:19;25024:6;25005:47;:::i;:::-;25083:2;25068:18;;25061:34;;;25126:2;25111:18;;25104:34;;;25169:2;25154:18;;25147:34;;;-1:-1:-1;;;;;25218:32:37;;25212:3;25197:19;;25190:61;25288:22;;;25238:3;25267:19;;25260:51;25334:34;25292:6;25353;25334:34;:::i;:::-;25320:48;;25417:9;25409:6;25405:22;25399:3;25388:9;25384:19;25377:51;25445:34;25472:6;25464;25445:34;:::i;:::-;25437:42;24950:535;-1:-1:-1;;;;;;;;;;24950:535:37:o;25490:227::-;;25636:2;25625:9;25618:21;25656:55;25707:2;25696:9;25692:18;25684:6;25656:55;:::i;25722:354::-;25924:2;25906:21;;;25963:2;25943:18;;;25936:30;26002:32;25997:2;25982:18;;25975:60;26067:2;26052:18;;25896:180::o;26081:352::-;26283:2;26265:21;;;26322:2;26302:18;;;26295:30;-1:-1:-1;;;26356:2:37;26341:18;;26334:58;26424:2;26409:18;;26255:178::o;26438:408::-;26640:2;26622:21;;;26679:2;26659:18;;;26652:30;26718:34;26713:2;26698:18;;26691:62;-1:-1:-1;;;26784:2:37;26769:18;;26762:42;26836:3;26821:19;;26612:234::o;26851:354::-;27053:2;27035:21;;;27092:2;27072:18;;;27065:30;27131:32;27126:2;27111:18;;27104:60;27196:2;27181:18;;27025:180::o;27210:356::-;27412:2;27394:21;;;27431:18;;;27424:30;27490:34;27485:2;27470:18;;27463:62;27557:2;27542:18;;27384:182::o;27571:415::-;27773:2;27755:21;;;27812:2;27792:18;;;27785:30;27851:34;27846:2;27831:18;;27824:62;-1:-1:-1;;;27917:2:37;27902:18;;27895:49;27976:3;27961:19;;27745:241::o;27991:400::-;28193:2;28175:21;;;28232:2;28212:18;;;28205:30;28271:34;28266:2;28251:18;;28244:62;-1:-1:-1;;;28337:2:37;28322:18;;28315:34;28381:3;28366:19;;28165:226::o;28396:353::-;28598:2;28580:21;;;28637:2;28617:18;;;28610:30;28676:31;28671:2;28656:18;;28649:59;28740:2;28725:18;;28570:179::o;28754:351::-;28956:2;28938:21;;;28995:2;28975:18;;;28968:30;-1:-1:-1;;;29029:2:37;29014:18;;29007:57;29096:2;29081:18;;28928:177::o;29110:354::-;29312:2;29294:21;;;29351:2;29331:18;;;29324:30;29390:32;29385:2;29370:18;;29363:60;29455:2;29440:18;;29284:180::o;29469:398::-;29671:2;29653:21;;;29710:2;29690:18;;;29683:30;29749:34;29744:2;29729:18;;29722:62;-1:-1:-1;;;29815:2:37;29800:18;;29793:32;29857:3;29842:19;;29643:224::o;29872:403::-;30074:2;30056:21;;;30113:2;30093:18;;;30086:30;30152:34;30147:2;30132:18;;30125:62;-1:-1:-1;;;30218:2:37;30203:18;;30196:37;30265:3;30250:19;;30046:229::o;30280:356::-;30482:2;30464:21;;;30501:18;;;30494:30;30560:34;30555:2;30540:18;;30533:62;30627:2;30612:18;;30454:182::o;30641:400::-;30843:2;30825:21;;;30882:2;30862:18;;;30855:30;30921:34;30916:2;30901:18;;30894:62;-1:-1:-1;;;30987:2:37;30972:18;;30965:34;31031:3;31016:19;;30815:226::o;31046:351::-;31248:2;31230:21;;;31287:2;31267:18;;;31260:30;-1:-1:-1;;;31321:2:37;31306:18;;31299:57;31388:2;31373:18;;31220:177::o;31402:355::-;31604:2;31586:21;;;31643:2;31623:18;;;31616:30;31682:33;31677:2;31662:18;;31655:61;31748:2;31733:18;;31576:181::o;31762:354::-;31964:2;31946:21;;;32003:2;31983:18;;;31976:30;32042:32;32037:2;32022:18;;32015:60;32107:2;32092:18;;31936:180::o;32121:412::-;32323:2;32305:21;;;32362:2;32342:18;;;32335:30;32401:34;32396:2;32381:18;;32374:62;-1:-1:-1;;;32467:2:37;32452:18;;32445:46;32523:3;32508:19;;32295:238::o;32538:350::-;32740:2;32722:21;;;32779:2;32759:18;;;32752:30;-1:-1:-1;;;32813:2:37;32798:18;;32791:56;32879:2;32864:18;;32712:176::o;32893:356::-;33095:2;33077:21;;;33114:18;;;33107:30;33173:34;33168:2;33153:18;;33146:62;33240:2;33225:18;;33067:182::o;33254:354::-;33456:2;33438:21;;;33495:2;33475:18;;;33468:30;33534:32;33529:2;33514:18;;33507:60;33599:2;33584:18;;33428:180::o;33613:351::-;33815:2;33797:21;;;33854:2;33834:18;;;33827:30;-1:-1:-1;;;33888:2:37;33873:18;;33866:57;33955:2;33940:18;;33787:177::o;33969:403::-;34171:2;34153:21;;;34210:2;34190:18;;;34183:30;34249:34;34244:2;34229:18;;34222:62;-1:-1:-1;;;34315:2:37;34300:18;;34293:37;34362:3;34347:19;;34143:229::o;34377:397::-;34579:2;34561:21;;;34618:2;34598:18;;;34591:30;34657:34;34652:2;34637:18;;34630:62;-1:-1:-1;;;34723:2:37;34708:18;;34701:31;34764:3;34749:19;;34551:223::o;34779:356::-;34981:2;34963:21;;;35000:18;;;34993:30;35059:34;35054:2;35039:18;;35032:62;35126:2;35111:18;;34953:182::o;35140:352::-;35342:2;35324:21;;;35381:2;35361:18;;;35354:30;-1:-1:-1;;;35415:2:37;35400:18;;35393:58;35483:2;35468:18;;35314:178::o;35497:398::-;35699:2;35681:21;;;35738:2;35718:18;;;35711:30;35777:34;35772:2;35757:18;;35750:62;-1:-1:-1;;;35843:2:37;35828:18;;35821:32;35885:3;35870:19;;35671:224::o;35900:352::-;36102:2;36084:21;;;36141:2;36121:18;;;36114:30;-1:-1:-1;;;36175:2:37;36160:18;;36153:58;36243:2;36228:18;;36074:178::o;36257:348::-;36459:2;36441:21;;;36498:2;36478:18;;;36471:30;-1:-1:-1;;;36532:2:37;36517:18;;36510:54;36596:2;36581:18;;36431:174::o;36610:352::-;36812:2;36794:21;;;36851:2;36831:18;;;36824:30;-1:-1:-1;;;36885:2:37;36870:18;;36863:58;36953:2;36938:18;;36784:178::o;36967:353::-;37169:2;37151:21;;;37208:2;37188:18;;;37181:30;37247:31;37242:2;37227:18;;37220:59;37311:2;37296:18;;37141:179::o;37325:346::-;37527:2;37509:21;;;37566:2;37546:18;;;37539:30;-1:-1:-1;;;37600:2:37;37585:18;;37578:52;37662:2;37647:18;;37499:172::o;37676:348::-;37878:2;37860:21;;;37917:2;37897:18;;;37890:30;-1:-1:-1;;;37951:2:37;37936:18;;37929:54;38015:2;38000:18;;37850:174::o;38029:398::-;38231:2;38213:21;;;38270:2;38250:18;;;38243:30;38309:34;38304:2;38289:18;;38282:62;-1:-1:-1;;;38375:2:37;38360:18;;38353:32;38417:3;38402:19;;38203:224::o;38432:408::-;38634:2;38616:21;;;38673:2;38653:18;;;38646:30;38712:34;38707:2;38692:18;;38685:62;-1:-1:-1;;;38778:2:37;38763:18;;38756:42;38830:3;38815:19;;38606:234::o;38845:402::-;39047:2;39029:21;;;39086:2;39066:18;;;39059:30;39125:34;39120:2;39105:18;;39098:62;-1:-1:-1;;;39191:2:37;39176:18;;39169:36;39237:3;39222:19;;39019:228::o;39252:411::-;39454:2;39436:21;;;39493:2;39473:18;;;39466:30;39532:34;39527:2;39512:18;;39505:62;-1:-1:-1;;;39598:2:37;39583:18;;39576:45;39653:3;39638:19;;39426:237::o;39668:401::-;39870:2;39852:21;;;39909:2;39889:18;;;39882:30;39948:34;39943:2;39928:18;;39921:62;-1:-1:-1;;;40014:2:37;39999:18;;39992:35;40059:3;40044:19;;39842:227::o;40074:405::-;40276:2;40258:21;;;40315:2;40295:18;;;40288:30;40354:34;40349:2;40334:18;;40327:62;-1:-1:-1;;;40420:2:37;40405:18;;40398:39;40469:3;40454:19;;40248:231::o;40484:353::-;40686:2;40668:21;;;40725:2;40705:18;;;40698:30;40764:31;40759:2;40744:18;;40737:59;40828:2;40813:18;;40658:179::o;40842:400::-;41044:2;41026:21;;;41083:2;41063:18;;;41056:30;41122:34;41117:2;41102:18;;41095:62;-1:-1:-1;;;41188:2:37;41173:18;;41166:34;41232:3;41217:19;;41016:226::o;41247:354::-;41449:2;41431:21;;;41488:2;41468:18;;;41461:30;41527:32;41522:2;41507:18;;41500:60;41592:2;41577:18;;41421:180::o;41606:353::-;41808:2;41790:21;;;41847:2;41827:18;;;41820:30;41886:31;41881:2;41866:18;;41859:59;41950:2;41935:18;;41780:179::o;41964:398::-;42166:2;42148:21;;;42205:2;42185:18;;;42178:30;42244:34;42239:2;42224:18;;42217:62;-1:-1:-1;;;42310:2:37;42295:18;;42288:32;42352:3;42337:19;;42138:224::o;42367:356::-;42569:2;42551:21;;;42588:18;;;42581:30;42647:34;42642:2;42627:18;;42620:62;42714:2;42699:18;;42541:182::o;42728:399::-;42930:2;42912:21;;;42969:2;42949:18;;;42942:30;43008:34;43003:2;42988:18;;42981:62;-1:-1:-1;;;43074:2:37;43059:18;;43052:33;43117:3;43102:19;;42902:225::o;43132:1003::-;;43305:2;43294:9;43287:21;43343:6;43337:13;43386:4;43381:2;43370:9;43366:18;43359:32;43414:53;43462:3;43451:9;43447:19;43433:12;43414:53;:::i;:::-;43400:67;;43521:2;43513:6;43509:15;43503:22;43498:2;43487:9;43483:18;43476:50;43580:2;43572:6;43568:15;43562:22;43557:2;43546:9;43542:18;43535:50;43640:2;43632:6;43628:15;43622:22;43616:3;43605:9;43601:19;43594:51;43728:1;43724;43719:3;43715:11;43711:19;43704:3;43696:6;43692:16;43686:23;43682:49;43676:3;43665:9;43661:19;43654:78;43781:3;43773:6;43769:16;43763:23;43809:2;43805:7;43877:2;43865:9;43857:6;43853:22;43849:31;43843:3;43832:9;43828:19;43821:60;43904:42;43939:6;43923:14;43904:42;:::i;:::-;43890:56;;43995:3;43987:6;43983:16;43977:23;43955:45;;44066:2;44054:9;44046:6;44042:22;44038:31;44031:4;44020:9;44016:20;44009:61;;44087:42;44122:6;44106:14;44087:42;:::i;44140:203::-;-1:-1:-1;;;;;44304:32:37;;;;44286:51;;44274:2;44259:18;;44241:102::o;44530:274::-;44704:25;;;-1:-1:-1;;;;;44765:32:37;44760:2;44745:18;;44738:60;44692:2;44677:18;;44659:145::o;44809:389::-;44996:25;;;-1:-1:-1;;;;;45057:32:37;;45052:2;45037:18;;45030:60;45126:2;45121;45106:18;;45099:30;;;44809:389;;45146:46;;45173:18;;45165:6;45146:46;:::i;45203:248::-;45377:25;;;45433:2;45418:18;;45411:34;45365:2;45350:18;;45332:119::o;45456:194::-;45630:12;45618:25;;;;45600:44;;45588:2;45573:18;;45555:95::o;45655:184::-;45827:4;45815:17;;;;45797:36;;45785:2;45770:18;;45752:87::o;45844:534::-;;;45988:11;45975:25;46082:2;46078:7;46067:8;46051:14;46047:29;46043:43;46023:18;46019:68;46009:2;;46104:4;46098;46091:18;46009:2;46134:33;;46186:20;;;-1:-1:-1;;;;;;46218:30:37;;46215:2;;;46264:4;46258;46251:18;46215:2;46300:4;46288:17;;-1:-1:-1;46331:14:37;46327:27;;;46317:38;;46314:2;;;46368:1;46365;46358:12;46383:242;46453:2;46447:9;46483:17;;;-1:-1:-1;;;;;46515:34:37;;46551:22;;;46512:62;46509:2;;;46577:9;46509:2;46604;46597:22;46427:198;;-1:-1:-1;46427:198:37:o;46630:193::-;;-1:-1:-1;;;;;46728:30:37;;46725:2;;;46761:9;46725:2;-1:-1:-1;46812:4:37;46793:17;;;46789:28;;46715:108::o;46828:181::-;;-1:-1:-1;;;;;46900:30:37;;46897:2;;;46933:9;46897:2;-1:-1:-1;46992:2:37;46969:17;-1:-1:-1;;46965:31:37;46998:4;46961:42;;46887:122::o;47014:129::-;;47082:17;;;47132:4;47116:21;;;47072:71::o;47148:258::-;47220:1;47230:113;47244:6;47241:1;47238:13;47230:113;;;47320:11;;;47314:18;47301:11;;;47294:39;47266:2;47259:10;47230:113;;;47361:6;47358:1;47355:13;47352:2;;;-1:-1:-1;;47396:1:37;47378:16;;47371:27;47201:205::o;47411:133::-;-1:-1:-1;;;;;47488:31:37;;47478:42;;47468:2;;47534:1;47531;47524:12
Swarm Source
ipfs://d745464168210e71c3fdff50a2eaa16478dfce18d2f4490912866698f8e65a9d
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.