Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 16589196 | 648 days ago | IN | 0 ETH | 0.10395002 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
CapsuleMinter
Compiler Version
v0.8.9+commit.e5eed63a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.9; import "./openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./openzeppelin/contracts/token/ERC721/IERC721.sol"; import "./openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "./openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "./openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; import "./openzeppelin/contracts/proxy/utils/Initializable.sol"; import "./openzeppelin/contracts/security/ReentrancyGuard.sol"; import "./openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "./interfaces/ICapsule.sol"; import "./CapsuleMinterStorage.sol"; import "./access/Governable.sol"; import "./Errors.sol"; contract CapsuleMinter is Initializable, Governable, ReentrancyGuard, IERC721Receiver, ERC1155Holder, CapsuleMinterStorageV3 { using SafeERC20 for IERC20; using EnumerableSet for EnumerableSet.AddressSet; string public constant VERSION = "1.2.0"; uint256 public constant TOKEN_TYPE_LIMIT = 100; uint256 internal constant MAX_CAPSULE_MINT_TAX = 0.1 ether; event AddedToWhitelist(address indexed user); event RemovedFromWhitelist(address indexed user); event FlushedTaxAmount(uint256 taxAmount); event CapsuleMintTaxUpdated(uint256 oldMintTax, uint256 newMintTax); event UpdatedWhitelistedCallers(address indexed caller); event SimpleCapsuleMinted(address indexed account, address indexed capsule, uint256 capsuleId); event SimpleCapsuleBurnt(address indexed account, address indexed capsule, uint256 capsuleId); event SingleERC20CapsuleMinted( address indexed account, address indexed capsule, address indexed token, uint256 amount, uint256 capsuleId ); event SingleERC20CapsuleBurnt( address indexed account, address indexed capsule, address indexed token, uint256 amount, uint256 capsuleId ); event SingleERC721CapsuleMinted( address indexed account, address indexed capsule, address indexed token, uint256 id, uint256 capsuleId ); event SingleERC721CapsuleBurnt( address indexed account, address indexed capsule, address indexed token, uint256 id, uint256 capsuleId ); event MultiERC20CapsuleMinted( address indexed account, address indexed capsule, address[] tokens, uint256[] amounts, uint256 capsuleId ); event MultiERC20CapsuleBurnt( address indexed account, address indexed capsule, address[] tokens, uint256[] amounts, uint256 capsuleId ); event MultiERC721CapsuleMinted( address indexed account, address indexed capsule, address[] tokens, uint256[] ids, uint256 capsuleId ); event MultiERC721CapsuleBurnt( address indexed account, address indexed capsule, address[] tokens, uint256[] ids, uint256 capsuleId ); event MultiERC1155CapsuleMinted( address indexed account, address indexed capsule, address[] tokens, uint256[] ids, uint256[] amounts, uint256 capsuleId ); event MultiERC1155CapsuleBurnt( address indexed account, address indexed capsule, address[] tokens, uint256[] ids, uint256[] amounts, uint256 capsuleId ); function initialize(address _factory) external initializer { require(_factory != address(0), Errors.ZERO_ADDRESS); __Governable_init(); factory = ICapsuleFactory(_factory); capsuleMintTax = 0.001 ether; } modifier checkTaxRequirement() { if (!mintWhitelist.contains(_msgSender())) { require(msg.value == capsuleMintTax, Errors.INCORRECT_TAX_AMOUNT); } _; } /// @dev Using internal function to decrease contract file size. modifier sanityChecks(address _capsule, address _burnFrom) { _sanityChecks(_capsule, _burnFrom); _; } modifier onlyCollectionMinter(address _capsule) { require(factory.isCapsule(_capsule), Errors.NOT_CAPSULE); require(ICapsule(_capsule).isCollectionMinter(_msgSender()), Errors.NOT_COLLECTION_MINTER); _; } /****************************************************************************** * Read functions * *****************************************************************************/ // return the owner of a Capsule by id function getCapsuleOwner(address _capsule, uint256 _id) external view returns (address) { return ICapsule(_capsule).ownerOf(_id); } /// @notice Get list of mint whitelisted address function getMintWhitelist() external view returns (address[] memory) { return mintWhitelist.values(); } /// @notice Get list of whitelisted caller address function getWhitelistedCallers() external view returns (address[] memory) { return whitelistedCallers.values(); } /// @notice Return whether given address is whitelisted caller or not function isWhitelistedCaller(address _caller) external view returns (bool) { return whitelistedCallers.contains(_caller); } function multiERC20Capsule(address _capsule, uint256 _id) external view returns (MultiERC20Capsule memory _data) { return _multiERC20Capsule[_capsule][_id]; } function multiERC721Capsule(address _capsule, uint256 _id) external view returns (MultiERC721Capsule memory _data) { return _multiERC721Capsule[_capsule][_id]; } function multiERC1155Capsule( address _capsule, uint256 _id ) external view returns (MultiERC1155Capsule memory _data) { return _multiERC1155Capsule[_capsule][_id]; } /// @notice Return whether given address is mint whitelisted or not function isMintWhitelisted(address _user) external view returns (bool) { return mintWhitelist.contains(_user); } function onERC721Received(address, address, uint256, bytes calldata) external pure override returns (bytes4) { // `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` return 0x150b7a02; } // ERC1155 Receiving occurs in the ERC1155Holder contract /****************************************************************************** * Write functions * *****************************************************************************/ function mintSimpleCapsule( address _capsule, string calldata _uri, address _receiver ) external payable nonReentrant onlyCollectionMinter(_capsule) checkTaxRequirement { // Mark id as a simple NFT uint256 _capsuleId = ICapsule(_capsule).counter(); isSimpleCapsule[_capsule][_capsuleId] = true; ICapsule(_capsule).mint(_receiver, _uri); emit SimpleCapsuleMinted(_receiver, _capsule, _capsuleId); } function burnSimpleCapsule( address _capsule, uint256 _capsuleId, address _burnFrom ) external nonReentrant sanityChecks(_capsule, _burnFrom) { require(isSimpleCapsule[_capsule][_capsuleId], Errors.NOT_SIMPLE_CAPSULE); delete isSimpleCapsule[_capsule][_capsuleId]; // We do not have to store the token uri in a local variable - we are emitting an event before burn emit SimpleCapsuleBurnt(_burnFrom, _capsule, _capsuleId); ICapsule(_capsule).burn(_burnFrom, _capsuleId); } function mintSingleERC20Capsule( address _capsule, address _token, uint256 _amount, string calldata _uri, address _receiver ) external payable nonReentrant onlyCollectionMinter(_capsule) checkTaxRequirement { require(_amount > 0, Errors.INVALID_TOKEN_AMOUNT); require(_token != address(0), Errors.INVALID_TOKEN_ADDRESS); // get the current top counter uint256 _capsuleId = ICapsule(_capsule).counter(); // transfer tokens from caller to contracts if (!whitelistedCallers.contains(_msgSender())) { // overwrite _amount _amount = _depositToken(IERC20(_token), _msgSender(), _amount); } // then, add user data into the contract (tie NFT to value): // - set the ID of the Capsule NFT at counter to map to the passed in tokenAddress // - set the ID of the Capsule NFT at counter to map to the passed in tokenAmount singleERC20Capsule[_capsule][_capsuleId].tokenAddress = _token; singleERC20Capsule[_capsule][_capsuleId].tokenAmount = _amount; // lastly, mint the Capsule NFT (minted at the current counter (obtained above as id)) ICapsule(_capsule).mint(_receiver, _uri); emit SingleERC20CapsuleMinted(_receiver, _capsule, _token, _amount, _capsuleId); } function burnSingleERC20Capsule( address _capsule, uint256 _capsuleId, address _burnFrom, address _receiver ) public nonReentrant sanityChecks(_capsule, _burnFrom) { // get the amount of tokens held by the Capsule NFT id uint256 tokensHeldById = singleERC20Capsule[_capsule][_capsuleId].tokenAmount; // If there is no token amount in stored data then provided id is not ERC20 Capsule id require(tokensHeldById > 0, Errors.NOT_ERC20_CAPSULE_ID); // get the token address held at the Capsule NFT id address heldTokenAddress = singleERC20Capsule[_capsule][_capsuleId].tokenAddress; // then, delete the Capsule NFT data at id delete singleERC20Capsule[_capsule][_capsuleId]; // burn the Capsule NFT at id ICapsule(_capsule).burn(_burnFrom, _capsuleId); // send tokens back to the user IERC20(heldTokenAddress).safeTransfer(_receiver, tokensHeldById); emit SingleERC20CapsuleBurnt(_burnFrom, _capsule, heldTokenAddress, tokensHeldById, _capsuleId); } function mintSingleERC721Capsule( address _capsule, address _token, uint256 _id, string calldata _uri, address _receiver ) external payable nonReentrant onlyCollectionMinter(_capsule) checkTaxRequirement { // get the current top counter uint256 _capsuleId = ICapsule(_capsule).counter(); if (!whitelistedCallers.contains(_msgSender())) { // transfer input NFT to contract. safeTransferFrom does check that from, _msgSender in this case, is owner. IERC721(_token).safeTransferFrom(_msgSender(), address(this), _id); // check that the contract owns that NFT require(IERC721(_token).ownerOf(_id) == address(this), Errors.NOT_NFT_OWNER); } // then, add user data into the contract (tie Capsule NFT to input token): // - set the ID of the Capsule NFT at counter to map to the passed in tokenAddress // - set the ID of the Capsule NFT at counter to map to the passed in id singleERC721Capsule[_capsule][_capsuleId].tokenAddress = _token; singleERC721Capsule[_capsule][_capsuleId].id = _id; // lastly, mint the Capsule NFT ICapsule(_capsule).mint(_receiver, _uri); emit SingleERC721CapsuleMinted(_receiver, _capsule, _token, _id, _capsuleId); } function burnSingleERC721Capsule( address _capsule, uint256 _capsuleId, address _burnFrom, address _receiver ) public nonReentrant sanityChecks(_capsule, _burnFrom) { // get the token address held at the Capsule NFT id address heldTokenAddress = singleERC721Capsule[_capsule][_capsuleId].tokenAddress; // If there is no token address in stored data then provided id is not ERC721 Capsule id require(heldTokenAddress != address(0), Errors.NOT_ERC721_CAPSULE_ID); // get the amount of token Id held by the Capsule NFT id uint256 tokenId = singleERC721Capsule[_capsule][_capsuleId].id; // then, delete the Capsule NFT data at id delete singleERC721Capsule[_capsule][_capsuleId]; // burn the Capsule NFT ICapsule(_capsule).burn(_burnFrom, _capsuleId); // send token back to the user IERC721(heldTokenAddress).safeTransferFrom(address(this), _receiver, tokenId); emit SingleERC721CapsuleBurnt(_burnFrom, _capsule, heldTokenAddress, tokenId, _capsuleId); } function mintMultiERC20Capsule( address _capsule, address[] calldata _tokens, uint256[] calldata _amounts, string calldata _uri, address _receiver ) external payable nonReentrant onlyCollectionMinter(_capsule) checkTaxRequirement { uint256 _len = _tokens.length; require(_len > 0 && _len <= TOKEN_TYPE_LIMIT, Errors.INVALID_TOKEN_ARRAY_LENGTH); require(_len == _amounts.length, Errors.LENGTH_MISMATCH); // get the current top counter uint256 _capsuleId = ICapsule(_capsule).counter(); _multiERC20Capsule[_capsule][_capsuleId].tokenAddresses = _tokens; if (whitelistedCallers.contains(_msgSender())) { _multiERC20Capsule[_capsule][_capsuleId].tokenAmounts = _amounts; emit MultiERC20CapsuleMinted(_receiver, _capsule, _tokens, _amounts, _capsuleId); } else { // Some tokens, like USDT, may have a transfer fee, so we want to record actual transfer amount uint256[] memory _actualAmounts = new uint256[](_len); // loop assumes that the token address and amount is mapped to the same index in both arrays // meaning: the user is sending _amounts[0] of _tokens[0] for (uint256 i; i < _len; i++) { address _token = _tokens[i]; uint256 _amount = _amounts[i]; require(_amount > 0, Errors.INVALID_TOKEN_AMOUNT); require(_token != address(0), Errors.INVALID_TOKEN_ADDRESS); // transfer tokens from caller to contract _actualAmounts[i] = _depositToken(IERC20(_token), _msgSender(), _amount); } // then add user data into the contract (tie Capsule NFT to input): _multiERC20Capsule[_capsule][_capsuleId].tokenAmounts = _actualAmounts; emit MultiERC20CapsuleMinted(_receiver, _capsule, _tokens, _actualAmounts, _capsuleId); } // lastly, mint the Capsule NFT ICapsule(_capsule).mint(_receiver, _uri); } function burnMultiERC20Capsule( address _capsule, uint256 _capsuleId, address _burnFrom, address _receiver ) public nonReentrant sanityChecks(_capsule, _burnFrom) { address[] memory tokens = _multiERC20Capsule[_capsule][_capsuleId].tokenAddresses; uint256[] memory amounts = _multiERC20Capsule[_capsule][_capsuleId].tokenAmounts; // If there is no tokens in stored data then provided id is not ERC20 Capsule id require(tokens.length > 0, Errors.NOT_ERC20_CAPSULE_ID); // then, delete the Capsule NFT data at id delete _multiERC20Capsule[_capsule][_capsuleId]; // burn the Capsule NFT ICapsule(_capsule).burn(_burnFrom, _capsuleId); for (uint256 i; i < tokens.length; i++) { // send tokens to the _receiver IERC20(tokens[i]).safeTransfer(_receiver, amounts[i]); } emit MultiERC20CapsuleBurnt(_burnFrom, _capsule, tokens, amounts, _capsuleId); } function mintMultiERC721Capsule( address _capsule, address[] calldata _tokens, uint256[] calldata _ids, string calldata _uri, address _receiver ) external payable nonReentrant onlyCollectionMinter(_capsule) checkTaxRequirement { uint256 _len = _tokens.length; require(_len > 0 && _len <= TOKEN_TYPE_LIMIT, Errors.INVALID_TOKEN_ARRAY_LENGTH); require(_len == _ids.length, Errors.LENGTH_MISMATCH); // get the current top counter uint256 _capsuleId = ICapsule(_capsule).counter(); if (!whitelistedCallers.contains(_msgSender())) { // loop assumes that the token address and id are mapped to the same index in both arrays // meaning: the user is sending _ids[0] of _tokens[0] for (uint256 i; i < _len; i++) { address _token = _tokens[i]; uint256 _id = _ids[i]; // no require check necessary for id require(_token != address(0), Errors.INVALID_TOKEN_ADDRESS); // transfer token to contract, safeTransferFrom does check from is the owner of id IERC721(_token).safeTransferFrom(_msgSender(), address(this), _id); // check the contract owns that NFT require(IERC721(_token).ownerOf(_id) == address(this), Errors.NOT_NFT_OWNER); } } // then, add user data into the contract (tie Capsule NFT to input): // - set the ID of the NFT (counter) to map to the passed in tokenAddresses // - set the ID of the NFT (counter) to map to the passed in ids _multiERC721Capsule[_capsule][_capsuleId].tokenAddresses = _tokens; _multiERC721Capsule[_capsule][_capsuleId].ids = _ids; // lastly, mint the Capsule NFT ICapsule(_capsule).mint(_receiver, _uri); emit MultiERC721CapsuleMinted(_receiver, _capsule, _tokens, _ids, _capsuleId); } function burnMultiERC721Capsule( address _capsule, uint256 _capsuleId, address _burnFrom, address _receiver ) public nonReentrant sanityChecks(_capsule, _burnFrom) { address[] memory tokens = _multiERC721Capsule[_capsule][_capsuleId].tokenAddresses; uint256[] memory ids = _multiERC721Capsule[_capsule][_capsuleId].ids; // If there is no tokens in stored data then provided id is not ERC721 Capsule id require(tokens.length > 0, Errors.NOT_ERC721_CAPSULE_ID); // then, delete the Capsule NFT data at id delete _multiERC721Capsule[_capsule][_capsuleId]; // burn the Capsule NFT ICapsule(_capsule).burn(_burnFrom, _capsuleId); for (uint256 i; i < tokens.length; i++) { // send tokens to the _receiver IERC721(tokens[i]).safeTransferFrom(address(this), _receiver, ids[i]); } emit MultiERC721CapsuleBurnt(_burnFrom, _capsule, tokens, ids, _capsuleId); } function mintMultiERC1155Capsule( address _capsule, address[] calldata _tokens, uint256[] calldata _ids, uint256[] calldata _amounts, string calldata _uri, address _receiver ) external payable nonReentrant onlyCollectionMinter(_capsule) checkTaxRequirement { uint256 _len = _tokens.length; require(_len > 0 && _len <= TOKEN_TYPE_LIMIT, Errors.INVALID_TOKEN_ARRAY_LENGTH); require(_len == _ids.length && _len == _amounts.length, Errors.LENGTH_MISMATCH); if (!whitelistedCallers.contains(_msgSender())) { // loop assumes that the token address, id and amount are mapped to the same index in both arrays // meaning: the user is sending _amounts[0] of _tokens[0] at _ids[0] for (uint256 i; i < _len; i++) { address _token = _tokens[i]; uint256 _id = _ids[i]; // no require check necessary for id require(_token != address(0), Errors.INVALID_TOKEN_ADDRESS); uint256 _balanceBefore = IERC1155(_token).balanceOf(address(this), _id); // transfer token to contract, safeTransferFrom does check from is the owner of id IERC1155(_token).safeTransferFrom(_msgSender(), address(this), _id, _amounts[i], ""); // check that this contract owns the ERC-1155 token require( IERC1155(_token).balanceOf(address(this), _id) == _balanceBefore + _amounts[i], Errors.NOT_NFT_OWNER ); } } uint256 _capsuleId = ICapsule(_capsule).counter(); // then, add user data into the contract (tie Capsule NFT to input): // - set the ID of the NFT (counter) to map to the passed in tokenAddresses // - set the ID of the NFT (counter) to map to the passed in ids // - set the ID of the NFT (counter) to map to the passed in amounts (1155) _multiERC1155Capsule[_capsule][_capsuleId] = MultiERC1155Capsule({ tokenAddresses: _tokens, ids: _ids, tokenAmounts: _amounts }); // lastly, mint the Capsule NFT ICapsule(_capsule).mint(_receiver, _uri); emit MultiERC1155CapsuleMinted(_receiver, _capsule, _tokens, _ids, _amounts, _capsuleId); } function burnMultiERC1155Capsule( address _capsule, uint256 _capsuleId, address _burnFrom, address _receiver ) public nonReentrant sanityChecks(_capsule, _burnFrom) { address[] memory _tokens = _multiERC1155Capsule[_capsule][_capsuleId].tokenAddresses; uint256[] memory _ids = _multiERC1155Capsule[_capsule][_capsuleId].ids; uint256[] memory _amounts = _multiERC1155Capsule[_capsule][_capsuleId].tokenAmounts; // If there is no tokens in stored data then provided id is not ERC1155 Capsule id require(_tokens.length > 0, Errors.NOT_ERC1155_CAPSULE_ID); // then, delete the Capsule NFT data at id delete _multiERC1155Capsule[_capsule][_capsuleId]; // burn the Capsule NFT ICapsule(_capsule).burn(_burnFrom, _capsuleId); for (uint256 i; i < _tokens.length; i++) { // send tokens to the _receiver IERC1155(_tokens[i]).safeTransferFrom(address(this), _receiver, _ids[i], _amounts[i], ""); } emit MultiERC1155CapsuleBurnt(_burnFrom, _capsule, _tokens, _ids, _amounts, _capsuleId); } /****************************************************************************** * Governor functions * *****************************************************************************/ function flushTaxAmount() external { address _taxCollector = factory.taxCollector(); require(_msgSender() == governor || _msgSender() == _taxCollector, Errors.UNAUTHORIZED); uint256 _taxAmount = address(this).balance; emit FlushedTaxAmount(_taxAmount); Address.sendValue(payable(_taxCollector), _taxAmount); } function addToWhitelist(address _user) external onlyGovernor { require(_user != address(0), Errors.ZERO_ADDRESS); require(mintWhitelist.add(_user), Errors.ADDRESS_ALREADY_EXIST); emit AddedToWhitelist(_user); } function removeFromWhitelist(address _user) external onlyGovernor { require(_user != address(0), Errors.ZERO_ADDRESS); require(mintWhitelist.remove(_user), Errors.ADDRESS_DOES_NOT_EXIST); emit RemovedFromWhitelist(_user); } /// @notice update Capsule NFT mint tax function updateCapsuleMintTax(uint256 _newTax) external onlyGovernor { require(_newTax <= MAX_CAPSULE_MINT_TAX, Errors.INCORRECT_TAX_AMOUNT); require(_newTax != capsuleMintTax, Errors.SAME_AS_EXISTING); emit CapsuleMintTaxUpdated(capsuleMintTax, _newTax); capsuleMintTax = _newTax; } function updateWhitelistedCallers(address _caller) external onlyGovernor { require(_caller != address(0), Errors.ZERO_ADDRESS); if (whitelistedCallers.contains(_caller)) { whitelistedCallers.remove(_caller); } else { whitelistedCallers.add(_caller); } emit UpdatedWhitelistedCallers(_caller); } /****************************************************************************** * Internal functions * *****************************************************************************/ function _depositToken( IERC20 _token, address _depositor, uint256 _amount ) internal returns (uint256 _actualAmount) { uint256 _balanceBefore = _token.balanceOf(address(this)); _token.safeTransferFrom(_depositor, address(this), _amount); _actualAmount = _token.balanceOf(address(this)) - _balanceBefore; require(_actualAmount > 0, Errors.INVALID_TOKEN_AMOUNT); } /** * @dev These checks will run as first thing in each burn functions. * These checks will make sure that * - Capsule address is valid * - If caller is trying to burn other users NFT then caller should be whitelisted * - Caller is collection burner meaning caller can burn NFT from this collection. */ function _sanityChecks(address _capsule, address _burnFrom) internal view { require(factory.isCapsule(_capsule), Errors.NOT_CAPSULE); if (msg.sender != _burnFrom) { require(whitelistedCallers.contains(msg.sender), Errors.NOT_WHITELISTED_CALLERS); } require(factory.isCollectionBurner(_capsule, msg.sender), Errors.NOT_COLLECTION_BURNER); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.9; import "./openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "./interfaces/ICapsuleFactory.sol"; import "./interfaces/ICapsuleMinter.sol"; abstract contract CapsuleMinterStorage is ICapsuleMinter { /// @notice Capsule factory address ICapsuleFactory public factory; uint256 public capsuleMintTax; /// @notice Mapping of a Capsule NFT address -> id -> bool, indicating if the address is a simple Capsule mapping(address => mapping(uint256 => bool)) public isSimpleCapsule; /// @notice Mapping of a Capsule NFT address -> id -> SingleERC20Capsule struct mapping(address => mapping(uint256 => SingleERC20Capsule)) public singleERC20Capsule; /// @notice Mapping of a Capsule NFT address -> id -> SingleERC721Capsule struct mapping(address => mapping(uint256 => SingleERC721Capsule)) public singleERC721Capsule; // Mapping of a Capsule NFT address -> id -> MultiERC20Capsule struct // It cannot be public because it contains a nested array. Instead, it has a getter function below mapping(address => mapping(uint256 => MultiERC20Capsule)) internal _multiERC20Capsule; // Mapping of a Capsule NFT address -> id -> MultiERC721Capsule struct // It cannot be public because it contains a nested array. Instead it has a getter function below mapping(address => mapping(uint256 => MultiERC721Capsule)) internal _multiERC721Capsule; // List of addresses which can mint Capsule NFTs without a mint tax EnumerableSet.AddressSet internal mintWhitelist; } abstract contract CapsuleMinterStorageV2 is CapsuleMinterStorage { // Mapping of a Capsule NFT address -> id -> MultiERC1155Capsule struct // It cannot be public because it contains a nested array. Instead it has a getter function below mapping(address => mapping(uint256 => MultiERC1155Capsule)) internal _multiERC1155Capsule; } abstract contract CapsuleMinterStorageV3 is CapsuleMinterStorageV2 { /** * @notice List of whitelisted callers. * WhitelistedCallers: Contracts which mints and burns on behalf of users * can be added to this list. Such contracts are part of Capsule ecosystem * and can be consider as extension/wrapper of CapsuleMinter contract. * * @dev WhitelistedCallers can, * - Send tokens before calling mint, which enable them to send tokens * from users to this contract. This eliminate 1 intermediate transfer. * - Burn Capsule from given address. This eliminates approval and intermediate * transfer. * */ EnumerableSet.AddressSet internal whitelistedCallers; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.9; /// @title Errors library library Errors { string public constant INVALID_TOKEN_AMOUNT = "1"; // Input token amount must be greater than 0 string public constant INVALID_TOKEN_ADDRESS = "2"; // Input token address is zero string public constant INVALID_TOKEN_ARRAY_LENGTH = "3"; // Invalid tokenAddresses array length. 0 < length <= 100. Max 100 elements string public constant INVALID_AMOUNT_ARRAY_LENGTH = "4"; // Invalid tokenAmounts array length. 0 < length <= 100. Max 100 elements string public constant INVALID_IDS_ARRAY_LENGTH = "5"; // Invalid tokenIds array length. 0 < length <= 100. Max 100 elements string public constant LENGTH_MISMATCH = "6"; // Array length must be same string public constant NOT_NFT_OWNER = "7"; // Caller/Minter is not NFT owner string public constant NOT_CAPSULE = "8"; // Provided address or caller is not a valid Capsule address string public constant NOT_MINTER = "9"; // Provided address or caller is not Capsule minter string public constant NOT_COLLECTION_MINTER = "10"; // Provided address or caller is not collection minter string public constant ZERO_ADDRESS = "11"; // Input/provided address is zero. string public constant NON_ZERO_ADDRESS = "12"; // Address under check must be 0 string public constant SAME_AS_EXISTING = "13"; // Provided address/value is same as stored in state string public constant NOT_SIMPLE_CAPSULE = "14"; // Provided Capsule id is not simple Capsule string public constant NOT_ERC20_CAPSULE_ID = "15"; // Provided token id is not the id of single/multi ERC20 Capsule string public constant NOT_ERC721_CAPSULE_ID = "16"; // Provided token id is not the id of single/multi ERC721 Capsule string public constant ADDRESS_DOES_NOT_EXIST = "17"; // Provided address does not exist in valid address list string public constant ADDRESS_ALREADY_EXIST = "18"; // Provided address does exist in valid address lists string public constant INCORRECT_TAX_AMOUNT = "19"; // Tax amount is incorrect string public constant UNAUTHORIZED = "20"; // Caller is not authorized to perform this task string public constant BLACKLISTED = "21"; // Caller is blacklisted and can not interact with Capsule protocol string public constant WHITELISTED = "22"; // Caller is whitelisted string public constant NOT_TOKEN_URI_OWNER = "23"; // Provided address or caller is not tokenUri owner string public constant NOT_ERC1155_CAPSULE_ID = "24"; // Provided token id is not the id of single/multi ERC1155 Capsule string public constant NOT_WHITELISTED_CALLERS = "25"; // Caller is not whitelisted string public constant NOT_COLLECTION_BURNER = "26"; // Caller is not collection burner string public constant NOT_PRIVATE_COLLECTION = "27"; // Provided address is not private Capsule collection }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../openzeppelin/contracts/proxy/utils/Initializable.sol"; import "../openzeppelin/contracts/utils/Context.sol"; import "../interfaces/IGovernable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (governor) that can be granted exclusive access to * specific functions. * * By default, the governor account will be the one that deploys the contract. This * can later be changed with {transferGovernorship}. * */ abstract contract Governable is IGovernable, Context, Initializable { address public governor; address private proposedGovernor; event UpdatedGovernor(address indexed previousGovernor, address indexed proposedGovernor); /** * @dev Initializes the contract setting the deployer as the initial governor. */ constructor() { address msgSender = _msgSender(); governor = msgSender; emit UpdatedGovernor(address(0), msgSender); } /** * @dev Initializes the contract setting the deployer as the initial governor. */ // solhint-disable-next-line func-name-mixedcase function __Governable_init() internal onlyInitializing { address msgSender = _msgSender(); governor = msgSender; emit UpdatedGovernor(address(0), msgSender); } /** * @dev Throws if called by any account other than the governor. */ modifier onlyGovernor() { require(governor == _msgSender(), "not governor"); _; } /** * @dev Transfers governorship of the contract to a new account (`proposedGovernor`). * Can only be called by the current governor. */ function transferGovernorship(address _proposedGovernor) external onlyGovernor { require(_proposedGovernor != address(0), "invalid proposed governor"); proposedGovernor = _proposedGovernor; } /** * @dev Allows new governor to accept governorship of the contract. */ function acceptGovernorship() external { require(proposedGovernor == _msgSender(), "not the proposed governor"); emit UpdatedGovernor(governor, proposedGovernor); governor = proposedGovernor; proposedGovernor = address(0); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../openzeppelin/contracts/token/ERC721/IERC721.sol"; import "../openzeppelin/contracts/interfaces/IERC2981.sol"; interface ICapsule is IERC721, IERC2981 { function mint(address account, string memory _uri) external; function burn(address owner, uint256 tokenId) external; function setMetadataProvider(address _metadataAddress) external; // Read functions function baseURI() external view returns (string memory); function counter() external view returns (uint256); function exists(uint256 tokenId) external view returns (bool); function isCollectionPrivate() external view returns (bool); function isCollectionMinter(address _account) external view returns (bool); function maxId() external view returns (uint256); function royaltyRate() external view returns (uint256); function royaltyReceiver() external view returns (address); function tokenURIOwner() external view returns (address); // Admin functions function lockCollectionCount(uint256 _nftCount) external; function setBaseURI(string calldata baseURI_) external; function setTokenURI(uint256 _tokenId, string memory _newTokenURI) external; function updateTokenURIOwner(address _newTokenURIOwner) external; function updateRoyaltyConfig(address _royaltyReceiver, uint256 _royaltyRate) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./IGovernable.sol"; interface ICapsuleFactory is IGovernable { function capsuleMinter() external view returns (address); function createCapsuleCollection( string memory _name, string memory _symbol, address _tokenURIOwner, bool _isCollectionPrivate ) external payable returns (address); function collectionBurner(address _capsule) external view returns (address); function getAllCapsuleCollections() external view returns (address[] memory); function getCapsuleCollectionsOf(address _owner) external view returns (address[] memory); function getBlacklist() external view returns (address[] memory); function getWhitelist() external view returns (address[] memory); function isBlacklisted(address _user) external view returns (bool); function isCapsule(address _capsule) external view returns (bool); function isCollectionBurner(address _capsuleCollection, address _account) external view returns (bool); function isWhitelisted(address _user) external view returns (bool); function taxCollector() external view returns (address); //solhint-disable-next-line func-name-mixedcase function VERSION() external view returns (string memory); // Special permission functions function addToWhitelist(address _user) external; function removeFromWhitelist(address _user) external; function addToBlacklist(address _user) external; function removeFromBlacklist(address _user) external; function flushTaxAmount() external; function setCapsuleMinter(address _newCapsuleMinter) external; function updateCapsuleCollectionBurner(address _capsuleCollection, address _newBurner) external; function updateCapsuleCollectionOwner(address _previousOwner, address _newOwner) external; function updateCapsuleCollectionTax(uint256 _newTax) external; function updateTaxCollector(address _newTaxCollector) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./IGovernable.sol"; import "./ICapsuleFactory.sol"; interface ICapsuleMinter is IGovernable { struct SingleERC20Capsule { address tokenAddress; uint256 tokenAmount; } struct MultiERC20Capsule { address[] tokenAddresses; uint256[] tokenAmounts; } struct SingleERC721Capsule { address tokenAddress; uint256 id; } struct MultiERC721Capsule { address[] tokenAddresses; uint256[] ids; } struct MultiERC1155Capsule { address[] tokenAddresses; uint256[] ids; uint256[] tokenAmounts; } function factory() external view returns (ICapsuleFactory); function getMintWhitelist() external view returns (address[] memory); function getCapsuleOwner(address _capsule, uint256 _id) external view returns (address); function getWhitelistedCallers() external view returns (address[] memory); function isMintWhitelisted(address _user) external view returns (bool); function isWhitelistedCaller(address _caller) external view returns (bool); function multiERC20Capsule(address _capsule, uint256 _id) external view returns (MultiERC20Capsule memory _data); function multiERC721Capsule(address _capsule, uint256 _id) external view returns (MultiERC721Capsule memory _data); function multiERC1155Capsule( address _capsule, uint256 _id ) external view returns (MultiERC1155Capsule memory _data); function singleERC20Capsule(address _capsule, uint256 _id) external view returns (address _token, uint256 _amount); function mintSimpleCapsule(address _capsule, string memory _uri, address _receiver) external payable; function burnSimpleCapsule(address _capsule, uint256 _id, address _burnFrom) external; function mintSingleERC20Capsule( address _capsule, address _token, uint256 _amount, string memory _uri, address _receiver ) external payable; function burnSingleERC20Capsule(address _capsule, uint256 _id, address _burnFrom, address _receiver) external; function mintSingleERC721Capsule( address _capsule, address _token, uint256 _id, string memory _uri, address _receiver ) external payable; function burnSingleERC721Capsule(address _capsule, uint256 _id, address _burnFrom, address _receiver) external; function mintMultiERC20Capsule( address _capsule, address[] memory _tokens, uint256[] memory _amounts, string memory _uri, address _receiver ) external payable; function burnMultiERC20Capsule(address _capsule, uint256 _id, address _burnFrom, address _receiver) external; function mintMultiERC721Capsule( address _capsule, address[] memory _tokens, uint256[] memory _ids, string memory _uri, address _receiver ) external payable; function burnMultiERC721Capsule(address _capsule, uint256 _id, address _burnFrom, address _receiver) external; function mintMultiERC1155Capsule( address _capsule, address[] memory _tokens, uint256[] memory _ids, uint256[] memory _amounts, string memory _uri, address _receiver ) external payable; function burnMultiERC1155Capsule(address _capsule, uint256 _id, address _burnFrom, address _receiver) external; // Special permission functions function addToWhitelist(address _user) external; function removeFromWhitelist(address _user) external; function flushTaxAmount() external; function updateCapsuleMintTax(uint256 _newTax) external; function updateWhitelistedCallers(address _caller) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; /** * @notice Governable interface */ interface IGovernable { function governor() external view returns (address _governor); function transferGovernorship(address _proposedGovernor) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/Address.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = _setInitializedVersion(1); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { bool isTopLevelCall = _setInitializedVersion(version); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(version); } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { _setInitializedVersion(type(uint8).max); } function _setInitializedVersion(uint8 version) private returns (bool) { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level // of initializers, because in other contexts the contract may have been reentered. if (_initializing) { require( version == 1 && !Address.isContract(address(this)), "Initializable: contract is already initialized" ); return false; } else { require(_initialized < version, "Initializable: contract is already initialized"); _initialized = version; return true; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol) pragma solidity ^0.8.0; import "./ERC1155Receiver.sol"; /** * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens. * * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be * stuck. * * @dev _Available since v3.1._ */ contract ERC1155Holder is ERC1155Receiver { function onERC1155Received( address, address, uint256, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol) pragma solidity ^0.8.0; import "../IERC1155Receiver.sol"; import "../../../utils/introspection/ERC165.sol"; /** * @dev _Available since v3.1._ */ abstract contract ERC1155Receiver is ERC165, IERC1155Receiver { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must 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 Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^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.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { 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.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^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; if (lastIndex != toDeleteIndex) { 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] = valueIndex; // Replace lastvalue's index to valueIndex } // 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) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // 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); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // 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)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // 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)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"AddedToWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMintTax","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMintTax","type":"uint256"}],"name":"CapsuleMintTaxUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"taxAmount","type":"uint256"}],"name":"FlushedTaxAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"MultiERC1155CapsuleBurnt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"MultiERC1155CapsuleMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"MultiERC20CapsuleBurnt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"MultiERC20CapsuleMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"MultiERC721CapsuleBurnt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"MultiERC721CapsuleMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"RemovedFromWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"SimpleCapsuleBurnt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"SimpleCapsuleMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"SingleERC20CapsuleBurnt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"SingleERC20CapsuleMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"SingleERC721CapsuleBurnt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"capsule","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"capsuleId","type":"uint256"}],"name":"SingleERC721CapsuleMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGovernor","type":"address"},{"indexed":true,"internalType":"address","name":"proposedGovernor","type":"address"}],"name":"UpdatedGovernor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"UpdatedWhitelistedCallers","type":"event"},{"inputs":[],"name":"TOKEN_TYPE_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptGovernorship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"addToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"uint256","name":"_capsuleId","type":"uint256"},{"internalType":"address","name":"_burnFrom","type":"address"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"burnMultiERC1155Capsule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"uint256","name":"_capsuleId","type":"uint256"},{"internalType":"address","name":"_burnFrom","type":"address"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"burnMultiERC20Capsule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"uint256","name":"_capsuleId","type":"uint256"},{"internalType":"address","name":"_burnFrom","type":"address"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"burnMultiERC721Capsule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"uint256","name":"_capsuleId","type":"uint256"},{"internalType":"address","name":"_burnFrom","type":"address"}],"name":"burnSimpleCapsule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"uint256","name":"_capsuleId","type":"uint256"},{"internalType":"address","name":"_burnFrom","type":"address"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"burnSingleERC20Capsule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"uint256","name":"_capsuleId","type":"uint256"},{"internalType":"address","name":"_burnFrom","type":"address"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"burnSingleERC721Capsule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"capsuleMintTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract ICapsuleFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flushTaxAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getCapsuleOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintWhitelist","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWhitelistedCallers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"isMintWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"isSimpleCapsule","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_caller","type":"address"}],"name":"isWhitelistedCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"string","name":"_uri","type":"string"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"mintMultiERC1155Capsule","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"string","name":"_uri","type":"string"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"mintMultiERC20Capsule","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"},{"internalType":"string","name":"_uri","type":"string"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"mintMultiERC721Capsule","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"string","name":"_uri","type":"string"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"mintSimpleCapsule","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"string","name":"_uri","type":"string"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"mintSingleERC20Capsule","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"string","name":"_uri","type":"string"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"mintSingleERC721Capsule","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"multiERC1155Capsule","outputs":[{"components":[{"internalType":"address[]","name":"tokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"}],"internalType":"struct ICapsuleMinter.MultiERC1155Capsule","name":"_data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"multiERC20Capsule","outputs":[{"components":[{"internalType":"address[]","name":"tokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"}],"internalType":"struct ICapsuleMinter.MultiERC20Capsule","name":"_data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_capsule","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"multiERC721Capsule","outputs":[{"components":[{"internalType":"address[]","name":"tokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"internalType":"struct ICapsuleMinter.MultiERC721Capsule","name":"_data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"removeFromWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"singleERC20Capsule","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"singleERC721Capsule","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_proposedGovernor","type":"address"}],"name":"transferGovernorship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newTax","type":"uint256"}],"name":"updateCapsuleMintTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_caller","type":"address"}],"name":"updateWhitelistedCallers","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506000805462010000600160b01b03191633620100008102919091178255604051909182917fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d0908290a350600160335561597f80620000706000396000f3fe60806040526004361061023b5760003560e01c8063aee6a2fe1161012e578063d6bee134116100ab578063f23a6e611161006f578063f23a6e6114610736578063f3b27bc314610762578063f79c004214610777578063f91afc9414610797578063ffa1ad74146107b757600080fd5b8063d6bee134146106b0578063d7e954e4146106d0578063e43252d7146106e3578063e5c0f24e14610703578063ed32e3f51461072357600080fd5b8063c45a0155116100f2578063c45a0155146105f0578063c4d66de814610610578063c6698ea714610630578063cabfa28414610645578063d1a5d9051461066557600080fd5b8063aee6a2fe1461054e578063b42fae261461056e578063b6aa515b1461058e578063bc197c81146105ae578063c068f7e2146105da57600080fd5b806362fa9158116101bc57806382cd81bc1161018057806382cd81bc146104bb5780638ab1d681146104ce578063aba0676c146104ee578063ad0305ce1461050e578063ad7a69dd1461052e57600080fd5b806362fa9158146104245780636ca9670d1461045f57806371dbf284146104725780637438ff42146104955780637b5af90a146104a857600080fd5b80634d4a5862116102035780634d4a58621461037e5780634e18b3d9146103a057806350761020146103c257806359557304146103ef5780635fb84fd11461040f57600080fd5b806301ffc9a7146102405780630c340a2414610275578063150b7a02146102b3578063265b87f2146102f857806333349fb414610325575b600080fd5b34801561024c57600080fd5b5061026061025b366004614ca9565b6107f5565b60405190151581526020015b60405180910390f35b34801561028157600080fd5b5060005461029b906201000090046001600160a01b031681565b6040516001600160a01b03909116815260200161026c565b3480156102bf57600080fd5b506102df6102ce366004614d3b565b630a85bd0160e11b95945050505050565b6040516001600160e01b0319909116815260200161026c565b34801561030457600080fd5b50610318610313366004614dad565b61082c565b60405161026c9190614e4d565b34801561033157600080fd5b50610370610340366004614dad565b6037602090815260009283526040808420909152908252902080546001909101546001600160a01b039091169082565b60405161026c929190614eae565b34801561038a57600080fd5b5061039e610399366004614ec7565b61098d565b005b3480156103ac57600080fd5b506103b5610d44565b60405161026c9190614f1a565b3480156103ce57600080fd5b506103e26103dd366004614dad565b610d55565b60405161026c9190614f5b565b3480156103fb57600080fd5b5061039e61040a366004614ec7565b610e45565b34801561041b57600080fd5b5061039e611154565b34801561043057600080fd5b5061026061043f366004614dad565b603660209081526000928352604080842090915290825290205460ff1681565b61039e61046d366004614fb2565b611281565b34801561047e57600080fd5b50610487606481565b60405190815260200161026c565b61039e6104a3366004615071565b611889565b61039e6104b63660046150f5565b611d1f565b61039e6104c9366004615071565b6124c7565b3480156104da57600080fd5b5061039e6104e93660046151d9565b6128ab565b3480156104fa57600080fd5b5061029b610509366004614dad565b612999565b34801561051a57600080fd5b506102606105293660046151d9565b612a1b565b34801561053a57600080fd5b5061039e6105493660046151d9565b612a28565b34801561055a57600080fd5b5061039e6105693660046151f6565b612aff565b34801561057a57600080fd5b506103e2610589366004614dad565b612c60565b34801561059a57600080fd5b5061039e6105a93660046151d9565b612d4e565b3480156105ba57600080fd5b506102df6105c9366004615361565b63bc197c8160e01b95945050505050565b3480156105e657600080fd5b5061048760355481565b3480156105fc57600080fd5b5060345461029b906001600160a01b031681565b34801561061c57600080fd5b5061039e61062b3660046151d9565b612df7565b34801561063c57600080fd5b506103b5612ed3565b34801561065157600080fd5b506102606106603660046151d9565b612edf565b34801561067157600080fd5b50610370610680366004614dad565b6038602090815260009283526040808420909152908252902080546001909101546001600160a01b039091169082565b3480156106bc57600080fd5b5061039e6106cb366004614ec7565b612eec565b61039e6106de36600461540e565b6130cf565b3480156106ef57600080fd5b5061039e6106fe3660046151d9565b613411565b34801561070f57600080fd5b5061039e61071e36600461546a565b6134ff565b61039e610731366004614fb2565b6135f4565b34801561074257600080fd5b506102df610751366004615483565b63f23a6e6160e01b95945050505050565b34801561076e57600080fd5b5061039e613be6565b34801561078357600080fd5b5061039e610792366004614ec7565b613cb8565b3480156107a357600080fd5b5061039e6107b2366004614ec7565b613e4d565b3480156107c357600080fd5b506107e8604051806040016040528060058152602001640312e322e360dc1b81525081565b60405161026c9190615517565b60006001600160e01b03198216630271189760e51b148061082657506301ffc9a760e01b6001600160e01b03198316145b92915050565b61085060405180606001604052806060815260200160608152602001606081525090565b6001600160a01b0383166000908152603d60209081526040808320858452825291829020825181546080938102820184019094526060810184815290939192849284918401828280156108cc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116108ae575b505050505081526020016001820180548060200260200160405190810160405280929190818152602001828054801561092457602002820191906000526020600020905b815481526020019060010190808311610910575b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561097c57602002820191906000526020600020905b815481526020019060010190808311610968575b505050505081525050905092915050565b600260335414156109b95760405162461bcd60e51b81526004016109b09061554a565b60405180910390fd5b600260335583826109ca8282614100565b6001600160a01b0386166000908152603d60209081526040808320888452825280832080548251818502810185019093528083529192909190830182828015610a3c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a1e575b505050506001600160a01b0389166000908152603d602090815260408083208b845282528083206001018054825181850281018501909352808352959650929490935090830182828015610aaf57602002820191906000526020600020905b815481526020019060010190808311610a9b575b505050506001600160a01b038a166000908152603d602090815260408083208c845282528083206002018054825181850281018501909352808352959650929490935090830182828015610b2257602002820191906000526020600020905b815481526020019060010190808311610b0e575b505050505090506000835111604051806040016040528060028152602001610c8d60f21b81525090610b675760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0389166000908152603d602090815260408083208b8452909152812090610b968282614b45565b610ba4600183016000614b45565b610bb2600283016000614b45565b5050604051632770a7eb60e21b81526001600160a01b038a1690639dc29fac90610be2908a908c90600401614eae565b600060405180830381600087803b158015610bfc57600080fd5b505af1158015610c10573d6000803e3d6000fd5b5050505060005b8351811015610ce257838181518110610c3257610c32615581565b60200260200101516001600160a01b031663f242432a3089868581518110610c5c57610c5c615581565b6020026020010151868681518110610c7657610c76615581565b60200260200101516040518563ffffffff1660e01b8152600401610c9d9493929190615597565b600060405180830381600087803b158015610cb757600080fd5b505af1158015610ccb573d6000803e3d6000fd5b505050508080610cda906155e5565b915050610c17565b50886001600160a01b0316876001600160a01b03167fda2b8b59f3ee1abd151d454a3a9d9a3c4ce8e18151c5e62c292344122744ca0d8585858d604051610d2c9493929190615600565b60405180910390a35050600160335550505050505050565b6060610d50603e6142cd565b905090565b604080518082018252606080825260208083018290526001600160a01b0386166000908152603a8252848120868252825284902084518154928302810184018652948501828152939493909284928491840182828015610dde57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610dc0575b505050505081526020016001820180548060200260200160405190810160405280929190818152602001828054801561097c576020028201919060005260206000209081548152602001906001019080831161096857505050505081525050905092915050565b60026033541415610e685760405162461bcd60e51b81526004016109b09061554a565b60026033558382610e798282614100565b6001600160a01b0386166000908152603a60209081526040808320888452825280832080548251818502810185019093528083529192909190830182828015610eeb57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ecd575b505050506001600160a01b0389166000908152603a602090815260408083208b845282528083206001018054825181850281018501909352808352959650929490935090830182828015610f5e57602002820191906000526020600020905b815481526020019060010190808311610f4a575b50505050509050600082511160405180604001604052806002815260200161189b60f11b81525090610fa35760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0388166000908152603a602090815260408083208a8452909152812090610fd28282614b45565b610fe0600183016000614b45565b5050604051632770a7eb60e21b81526001600160a01b03891690639dc29fac906110109089908b90600401614eae565b600060405180830381600087803b15801561102a57600080fd5b505af115801561103e573d6000803e3d6000fd5b5050505060005b82518110156110f55782818151811061106057611060615581565b60200260200101516001600160a01b03166342842e0e308885858151811061108a5761108a615581565b60200260200101516040518463ffffffff1660e01b81526004016110b09392919061564b565b600060405180830381600087803b1580156110ca57600080fd5b505af11580156110de573d6000803e3d6000fd5b5050505080806110ed906155e5565b915050611045565b50876001600160a01b0316866001600160a01b03167f4324ef2315b0ac160aae9f8ac838949e23168c728a4c28f3009bb8853e3083b184848b60405161113d9392919061566f565b60405180910390a350506001603355505050505050565b603454604080516317d43b9f60e31b815290516000926001600160a01b03169163bea1dcf8916004808301926020929190829003018186803b15801561119957600080fd5b505afa1580156111ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d191906156a5565b6000549091506201000090046001600160a01b0316336001600160a01b031614806112045750336001600160a01b038216145b60405180604001604052806002815260200161032360f41b8152509061123d5760405162461bcd60e51b81526004016109b09190615517565b5060405147808252907f2af28626f494b1c155787b0089b658f2a5b3d9c010df886483e601ab92c804ce9060200160405180910390a161127d82826142da565b5050565b600260335414156112a45760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b03808b1660048301528a92169063696f345d9060240160206040518083038186803b1580156112ee57600080fd5b505afa158015611302573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132691906156c2565b604051806040016040528060018152602001600760fb1b8152509061135e5760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156113ae57600080fd5b505afa1580156113c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e691906156c2565b60405180604001604052806002815260200161031360f41b8152509061141f5760405162461bcd60e51b81526004016109b09190615517565b5061142d335b603b906143f3565b61147157603554341460405180604001604052806002815260200161313960f01b8152509061146f5760405162461bcd60e51b81526004016109b09190615517565b505b868015801590611482575060648111155b604051806040016040528060018152602001603360f81b815250906114ba5760405162461bcd60e51b81526004016109b09190615517565b506040805180820190915260018152601b60f91b60208201528187146114f35760405162461bcd60e51b81526004016109b09190615517565b5060008a6001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561152f57600080fd5b505afa158015611543573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156791906156e4565b6001600160a01b038c1660009081526039602090815260408083208484529091529020909150611598908b8b614b66565b506115a6335b603e906143f3565b15611635576001600160a01b038b16600090815260396020908152604080832084845290915290206115dc906001018989614bc9565b508a6001600160a01b0316846001600160a01b03167f4416146c05a6d85e921ca2cd45d2214a3e2661528176ea33ac7e45b7a28879d08c8c8c8c87604051611628959493929190615771565b60405180910390a3611815565b6000826001600160401b0381111561164f5761164f615238565b604051908082528060200260200182016040528015611678578160200160208202803683370190505b50905060005b838110156117895760008c8c8381811061169a5761169a615581565b90506020020160208101906116af91906151d9565b905060008b8b848181106116c5576116c5615581565b90506020020135905060008111604051806040016040528060018152602001603160f81b8152509061170a5760405162461bcd60e51b81526004016109b09190615517565b506040805180820190915260018152601960f91b60208201526001600160a01b03831661174a5760405162461bcd60e51b81526004016109b09190615517565b50611756823383614415565b84848151811061176857611768615581565b60200260200101818152505050508080611781906155e5565b91505061167e565b506001600160a01b038c166000908152603960209081526040808320858452825290912082516117c192600190920191840190614c04565b508b6001600160a01b0316856001600160a01b03167f4416146c05a6d85e921ca2cd45d2214a3e2661528176ea33ac7e45b7a28879d08d8d858760405161180b94939291906157ab565b60405180910390a3505b60405163d0def52160e01b81526001600160a01b038c169063d0def521906118459087908a908a906004016157e3565b600060405180830381600087803b15801561185f57600080fd5b505af1158015611873573d6000803e3d6000fd5b5050600160335550505050505050505050505050565b600260335414156118ac5760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b0380891660048301528892169063696f345d9060240160206040518083038186803b1580156118f657600080fd5b505afa15801561190a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061192e91906156c2565b604051806040016040528060018152602001600760fb1b815250906119665760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156119b657600080fd5b505afa1580156119ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ee91906156c2565b60405180604001604052806002815260200161031360f41b81525090611a275760405162461bcd60e51b81526004016109b09190615517565b50611a3133611425565b611a7557603554341460405180604001604052806002815260200161313960f01b81525090611a735760405162461bcd60e51b81526004016109b09190615517565b505b6000876001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611ab057600080fd5b505afa158015611ac4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae891906156e4565b9050611af33361159e565b611c1757604051632142170760e11b81526001600160a01b038816906342842e0e90611b2790339030908b9060040161564b565b600060405180830381600087803b158015611b4157600080fd5b505af1158015611b55573d6000803e3d6000fd5b50506040516331a9108f60e11b8152600481018990523092506001600160a01b038a169150636352211e9060240160206040518083038186803b158015611b9b57600080fd5b505afa158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd391906156a5565b6001600160a01b031614604051806040016040528060018152602001603760f81b81525090611c155760405162461bcd60e51b81526004016109b09190615517565b505b6001600160a01b0388811660008181526038602090815260408083208684529091529081902080546001600160a01b031916938b169390931783556001909201889055905163d0def52160e01b815263d0def52190611c7e908690899089906004016157e3565b600060405180830381600087803b158015611c9857600080fd5b505af1158015611cac573d6000803e3d6000fd5b50505050866001600160a01b0316886001600160a01b0316846001600160a01b03167fcd663b969127fbda25c2717fbf6b672d51c5d25f226bb98470a4e9ce748a09638985604051611d08929190918252602082015260400190565b60405180910390a450506001603355505050505050565b60026033541415611d425760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b03808d1660048301528c92169063696f345d9060240160206040518083038186803b158015611d8c57600080fd5b505afa158015611da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc491906156c2565b604051806040016040528060018152602001600760fb1b81525090611dfc5760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015611e4c57600080fd5b505afa158015611e60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8491906156c2565b60405180604001604052806002815260200161031360f41b81525090611ebd5760405162461bcd60e51b81526004016109b09190615517565b50611ec733611425565b611f0b57603554341460405180604001604052806002815260200161313960f01b81525090611f095760405162461bcd60e51b81526004016109b09190615517565b505b888015801590611f1c575060648111155b604051806040016040528060018152602001603360f81b81525090611f545760405162461bcd60e51b81526004016109b09190615517565b508088148015611f6357508086145b604051806040016040528060018152602001601b60f91b81525090611f9b5760405162461bcd60e51b81526004016109b09190615517565b50611fa53361159e565b61223b5760005b818110156122395760008c8c83818110611fc857611fc8615581565b9050602002016020810190611fdd91906151d9565b905060008b8b84818110611ff357611ff3615581565b90506020020135905060006001600160a01b0316826001600160a01b03161415604051806040016040528060018152602001601960f91b8152509061204b5760405162461bcd60e51b81526004016109b09190615517565b50604051627eeac760e11b81526000906001600160a01b0384169062fdd58e9061207b9030908690600401614eae565b60206040518083038186803b15801561209357600080fd5b505afa1580156120a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cb91906156e4565b90506001600160a01b03831663f242432a3330858f8f8a8181106120f1576120f1615581565b905060200201356040518563ffffffff1660e01b81526004016121179493929190615597565b600060405180830381600087803b15801561213157600080fd5b505af1158015612145573d6000803e3d6000fd5b505050508a8a8581811061215b5761215b615581565b905060200201358161216d9190615823565b604051627eeac760e11b81526001600160a01b0385169062fdd58e906121999030908790600401614eae565b60206040518083038186803b1580156121b157600080fd5b505afa1580156121c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e991906156e4565b14604051806040016040528060018152602001603760f81b815250906122225760405162461bcd60e51b81526004016109b09190615517565b505050508080612231906155e5565b915050611fac565b505b60008c6001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561227657600080fd5b505afa15801561228a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ae91906156e4565b905060405180606001604052808d8d808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208d810282810182019093528d82529283019290918e918e9182918501908490808284376000920191909152505050908252506040805160208b810282810182019093528b82529283019290918c918c918291850190849080828437600081840152601f19601f82011690508083019250505050505050815250603d60008f6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002060008201518160000190805190602001906123c2929190614c3f565b5060208281015180516123db9260018501920190614c04565b50604082015180516123f7916002840191602090910190614c04565b505060405163d0def52160e01b81526001600160a01b038f16915063d0def5219061242a9087908a908a906004016157e3565b600060405180830381600087803b15801561244457600080fd5b505af1158015612458573d6000803e3d6000fd5b505050508c6001600160a01b0316846001600160a01b03167fe564a803b77781693e8cfa25b28d4258d106eef1885c92fd0dbe4aee9f6c63c38e8e8e8e8e8e896040516124ab979695949392919061583b565b60405180910390a3505060016033555050505050505050505050565b600260335414156124ea5760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b0380891660048301528892169063696f345d9060240160206040518083038186803b15801561253457600080fd5b505afa158015612548573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256c91906156c2565b604051806040016040528060018152602001600760fb1b815250906125a45760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156125f457600080fd5b505afa158015612608573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262c91906156c2565b60405180604001604052806002815260200161031360f41b815250906126655760405162461bcd60e51b81526004016109b09190615517565b5061266f33611425565b6126b357603554341460405180604001604052806002815260200161313960f01b815250906126b15760405162461bcd60e51b81526004016109b09190615517565b505b6040805180820190915260018152603160f81b6020820152856126e95760405162461bcd60e51b81526004016109b09190615517565b506040805180820190915260018152601960f91b60208201526001600160a01b0387166127295760405162461bcd60e51b81526004016109b09190615517565b506000876001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561276557600080fd5b505afa158015612779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061279d91906156e4565b90506127a83361159e565b6127ba576127b7873388614415565b95505b6001600160a01b0388811660008181526037602090815260408083208684529091529081902080546001600160a01b031916938b169390931783556001909201889055905163d0def52160e01b815263d0def52190612821908690899089906004016157e3565b600060405180830381600087803b15801561283b57600080fd5b505af115801561284f573d6000803e3d6000fd5b50505050866001600160a01b0316886001600160a01b0316846001600160a01b03167f79ac13d0d960f612f8d7b052a21447a4b3cb93c8d95b550746a0f84f1ed0d57a8985604051611d08929190918252602082015260400190565b6000546001600160a01b03620100009091041633146128dc5760405162461bcd60e51b81526004016109b09061588c565b604080518082019091526002815261313160f01b60208201526001600160a01b03821661291c5760405162461bcd60e51b81526004016109b09190615517565b50612928603b82614572565b60405180604001604052806002815260200161313760f01b815250906129615760405162461bcd60e51b81526004016109b09190615517565b506040516001600160a01b038216907fcdd2e9b91a56913d370075169cefa1602ba36be5301664f752192bb1709df75790600090a250565b6040516331a9108f60e11b8152600481018290526000906001600160a01b03841690636352211e9060240160206040518083038186803b1580156129dc57600080fd5b505afa1580156129f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a1491906156a5565b9392505050565b6000610826603b836143f3565b6000546001600160a01b0362010000909104163314612a595760405162461bcd60e51b81526004016109b09061588c565b604080518082019091526002815261313160f01b60208201526001600160a01b038216612a995760405162461bcd60e51b81526004016109b09190615517565b50612aa5603e826143f3565b15612abb57612ab5603e82614572565b50612ac8565b612ac6603e82614587565b505b6040516001600160a01b038216907f3e4c0ce6297bf984156b60851857f36768c460cc4b5c5bf602a42d9fad186ea490600090a250565b60026033541415612b225760405162461bcd60e51b81526004016109b09061554a565b60026033558281612b338282614100565b6001600160a01b038516600090815260366020908152604080832087845282529182902054825180840190935260028352610c4d60f21b9183019190915260ff16612b915760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b038581166000818152603660209081526040808320898452825291829020805460ff19169055905187815291928616917f369fb8e0e292df89faae5f8b02b8254a8bba1d7284209886d7bc31b20796113c910160405180910390a3604051632770a7eb60e21b81526001600160a01b03861690639dc29fac90612c229086908890600401614eae565b600060405180830381600087803b158015612c3c57600080fd5b505af1158015612c50573d6000803e3d6000fd5b5050600160335550505050505050565b604080518082018252606080825260208083018290526001600160a01b038616600090815260398252848120868252825284902084518154928302810184018652948501828152939493909284928491840182828015610dde576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610dc057505050505081526020016001820180548060200260200160405190810160405280929190818152602001828054801561097c576020028201919060005260206000209081548152602001906001019080831161096857505050505081525050905092915050565b6000546001600160a01b0362010000909104163314612d7f5760405162461bcd60e51b81526004016109b09061588c565b6001600160a01b038116612dd55760405162461bcd60e51b815260206004820152601960248201527f696e76616c69642070726f706f73656420676f7665726e6f720000000000000060448201526064016109b0565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000612e03600161459c565b90508015612e1b576000805461ff0019166101001790555b604080518082019091526002815261313160f01b60208201526001600160a01b038316612e5b5760405162461bcd60e51b81526004016109b09190615517565b50612e64614629565b603480546001600160a01b0319166001600160a01b03841617905566038d7ea4c68000603555801561127d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6060610d50603b6142cd565b6000610826603e836143f3565b60026033541415612f0f5760405162461bcd60e51b81526004016109b09061554a565b60026033558382612f208282614100565b6001600160a01b0380871660009081526038602090815260408083208984528252918290205482518084019093526002835261189b60f11b918301919091529091169081612f815760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b03871660008181526038602090815260408083208a845290915280822060018101805482546001600160a01b0319169092559290925551632770a7eb60e21b8152909190639dc29fac90612fe39089908b90600401614eae565b600060405180830381600087803b158015612ffd57600080fd5b505af1158015613011573d6000803e3d6000fd5b5050604051632142170760e11b81526001600160a01b03851692506342842e0e91506130459030908990869060040161564b565b600060405180830381600087803b15801561305f57600080fd5b505af1158015613073573d6000803e3d6000fd5b50505050816001600160a01b0316886001600160a01b0316876001600160a01b03167fdd211b39049950d7216395989579818241a461da30cf6a42b2d8305b8205cfff848b604051611d08929190918252602082015260400190565b600260335414156130f25760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b0380871660048301528692169063696f345d9060240160206040518083038186803b15801561313c57600080fd5b505afa158015613150573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061317491906156c2565b604051806040016040528060018152602001600760fb1b815250906131ac5760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156131fc57600080fd5b505afa158015613210573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061323491906156c2565b60405180604001604052806002815260200161031360f41b8152509061326d5760405162461bcd60e51b81526004016109b09190615517565b5061327733611425565b6132bb57603554341460405180604001604052806002815260200161313960f01b815250906132b95760405162461bcd60e51b81526004016109b09190615517565b505b6000856001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156132f657600080fd5b505afa15801561330a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061332e91906156e4565b6001600160a01b038716600081815260366020908152604080832085845290915290819020805460ff191660011790555163d0def52160e01b81529192509063d0def52190613385908690899089906004016157e3565b600060405180830381600087803b15801561339f57600080fd5b505af11580156133b3573d6000803e3d6000fd5b50505050856001600160a01b0316836001600160a01b03167fdc8a2e2a073bc1ff78027b5481b30fc20dc92bd9faae378c3411b25838ab2bf3836040516133fc91815260200190565b60405180910390a35050600160335550505050565b6000546001600160a01b03620100009091041633146134425760405162461bcd60e51b81526004016109b09061588c565b604080518082019091526002815261313160f01b60208201526001600160a01b0382166134825760405162461bcd60e51b81526004016109b09190615517565b5061348e603b82614587565b60405180604001604052806002815260200161062760f31b815250906134c75760405162461bcd60e51b81526004016109b09190615517565b506040516001600160a01b038216907fa850ae9193f515cbae8d35e8925bd2be26627fc91bce650b8652ed254e9cab0390600090a250565b6000546001600160a01b03620100009091041633146135305760405162461bcd60e51b81526004016109b09061588c565b604080518082019091526002815261313960f01b602082015267016345785d8a00008211156135725760405162461bcd60e51b81526004016109b09190615517565b5060355481141560405180604001604052806002815260200161313360f01b815250906135b25760405162461bcd60e51b81526004016109b09190615517565b5060355460408051918252602082018390527f67f043b257fe2539966e18910ca7fd99876bcce5e659ff3cf23245320f4de67b910160405180910390a1603555565b600260335414156136175760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b03808b1660048301528a92169063696f345d9060240160206040518083038186803b15801561366157600080fd5b505afa158015613675573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369991906156c2565b604051806040016040528060018152602001600760fb1b815250906136d15760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b15801561372157600080fd5b505afa158015613735573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061375991906156c2565b60405180604001604052806002815260200161031360f41b815250906137925760405162461bcd60e51b81526004016109b09190615517565b5061379c33611425565b6137e057603554341460405180604001604052806002815260200161313960f01b815250906137de5760405162461bcd60e51b81526004016109b09190615517565b505b8680158015906137f1575060648111155b604051806040016040528060018152602001603360f81b815250906138295760405162461bcd60e51b81526004016109b09190615517565b506040805180820190915260018152601b60f91b60208201528187146138625760405162461bcd60e51b81526004016109b09190615517565b5060008a6001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561389e57600080fd5b505afa1580156138b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138d691906156e4565b90506138e13361159e565b613abe5760005b82811015613abc5760008b8b8381811061390457613904615581565b905060200201602081019061391991906151d9565b905060008a8a8481811061392f5761392f615581565b90506020020135905060006001600160a01b0316826001600160a01b03161415604051806040016040528060018152602001601960f91b815250906139875760405162461bcd60e51b81526004016109b09190615517565b50604051632142170760e11b81526001600160a01b038316906342842e0e906139b89033903090869060040161564b565b600060405180830381600087803b1580156139d257600080fd5b505af11580156139e6573d6000803e3d6000fd5b50506040516331a9108f60e11b8152600481018490523092506001600160a01b0385169150636352211e9060240160206040518083038186803b158015613a2c57600080fd5b505afa158015613a40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a6491906156a5565b6001600160a01b031614604051806040016040528060018152602001603760f81b81525090613aa65760405162461bcd60e51b81526004016109b09190615517565b5050508080613ab4906155e5565b9150506138e8565b505b6001600160a01b038b166000908152603a602090815260408083208484529091529020613aec908b8b614b66565b506001600160a01b038b166000908152603a602090815260408083208484529091529020613b1e906001018989614bc9565b5060405163d0def52160e01b81526001600160a01b038c169063d0def52190613b4f9087908a908a906004016157e3565b600060405180830381600087803b158015613b6957600080fd5b505af1158015613b7d573d6000803e3d6000fd5b505050508a6001600160a01b0316846001600160a01b03167faba856cf36fc0adf76e7d75992b5f3472e43d6b68ae6a2f90ecbe063cd7163ee8c8c8c8c87604051613bcc959493929190615771565b60405180910390a350506001603355505050505050505050565b6001546001600160a01b03163314613c405760405162461bcd60e51b815260206004820152601960248201527f6e6f74207468652070726f706f73656420676f7665726e6f720000000000000060448201526064016109b0565b600154600080546040516001600160a01b039384169362010000909204909116917fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d091a3600180546000805462010000600160b01b0319166001600160a01b03831662010000021790556001600160a01b0319169055565b60026033541415613cdb5760405162461bcd60e51b81526004016109b09061554a565b60026033558382613cec8282614100565b6001600160a01b03861660009081526037602090815260408083208884528252918290206001015482518084019093526002835261313560f01b918301919091529081613d4c5760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0387811660008181526037602090815260408083208b845290915280822080546001600160a01b03198116825560019091019290925551632770a7eb60e21b8152921691639dc29fac90613dae9089908b90600401614eae565b600060405180830381600087803b158015613dc857600080fd5b505af1158015613ddc573d6000803e3d6000fd5b50613df5925050506001600160a01b03821686846146e0565b806001600160a01b0316886001600160a01b0316876001600160a01b03167f627cb524b52ac408bea8da9f6f92949a5c4f8be2966a9a288951a154511ccc87858b604051611d08929190918252602082015260400190565b60026033541415613e705760405162461bcd60e51b81526004016109b09061554a565b60026033558382613e818282614100565b6001600160a01b0386166000908152603960209081526040808320888452825280832080548251818502810185019093528083529192909190830182828015613ef357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613ed5575b505050506001600160a01b03891660009081526039602090815260408083208b845282528083206001018054825181850281018501909352808352959650929490935090830182828015613f6657602002820191906000526020600020905b815481526020019060010190808311613f52575b50505050509050600082511160405180604001604052806002815260200161313560f01b81525090613fab5760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b03881660009081526039602090815260408083208a8452909152812090613fda8282614b45565b613fe8600183016000614b45565b5050604051632770a7eb60e21b81526001600160a01b03891690639dc29fac906140189089908b90600401614eae565b600060405180830381600087803b15801561403257600080fd5b505af1158015614046573d6000803e3d6000fd5b5050505060005b82518110156140b8576140a68683838151811061406c5761406c615581565b602002602001015185848151811061408657614086615581565b60200260200101516001600160a01b03166146e09092919063ffffffff16565b806140b0816155e5565b91505061404d565b50876001600160a01b0316866001600160a01b03167f4cb316182a29e84cde5ecbceaba26ba941408b4df06dc637c8675b39799a938e84848b60405161113d9392919061566f565b60345460405163696f345d60e01b81526001600160a01b0384811660048301529091169063696f345d9060240160206040518083038186803b15801561414557600080fd5b505afa158015614159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061417d91906156c2565b604051806040016040528060018152602001600760fb1b815250906141b55760405162461bcd60e51b81526004016109b09190615517565b50336001600160a01b0382161461420c576141d1603e336143f3565b60405180604001604052806002815260200161323560f01b8152509061420a5760405162461bcd60e51b81526004016109b09190615517565b505b603454604051632571e0af60e21b81526001600160a01b038481166004830152336024830152909116906395c782bc9060440160206040518083038186803b15801561425757600080fd5b505afa15801561426b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061428f91906156c2565b60405180604001604052806002815260200161191b60f11b815250906142c85760405162461bcd60e51b81526004016109b09190615517565b505050565b60606000612a1483614736565b8047101561432a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016109b0565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114614377576040519150601f19603f3d011682016040523d82523d6000602084013e61437c565b606091505b50509050806142c85760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016109b0565b6001600160a01b03811660009081526001830160205260408120541515612a14565b6040516370a0823160e01b815230600482015260009081906001600160a01b038616906370a082319060240160206040518083038186803b15801561445957600080fd5b505afa15801561446d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061449191906156e4565b90506144a86001600160a01b038616853086614792565b6040516370a0823160e01b815230600482015281906001600160a01b038716906370a082319060240160206040518083038186803b1580156144e957600080fd5b505afa1580156144fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061452191906156e4565b61452b91906158b2565b915060008211604051806040016040528060018152602001603160f81b815250906145695760405162461bcd60e51b81526004016109b09190615517565b50509392505050565b6000612a14836001600160a01b0384166147b9565b6000612a14836001600160a01b0384166148ac565b60008054610100900460ff16156145e3578160ff1660011480156145bf5750303b155b6145db5760405162461bcd60e51b81526004016109b0906158c9565b506000919050565b60005460ff80841691161061460a5760405162461bcd60e51b81526004016109b0906158c9565b506000805460ff191660ff92909216919091179055600190565b919050565b600054610100900460ff166146945760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016109b0565b6000805462010000600160b01b03191633620100008102919091178255604051909182917fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d0908290a350565b6142c88363a9059cbb60e01b84846040516024016146ff929190614eae565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526148fb565b60608160000180548060200260200160405190810160405280929190818152602001828054801561478657602002820191906000526020600020905b815481526020019060010190808311614772575b50505050509050919050565b6147b3846323b872dd60e01b8585856040516024016146ff9392919061564b565b50505050565b600081815260018301602052604081205480156148a25760006147dd6001836158b2565b85549091506000906147f1906001906158b2565b905081811461485657600086600001828154811061481157614811615581565b906000526020600020015490508087600001848154811061483457614834615581565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061486757614867615917565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610826565b6000915050610826565b60008181526001830160205260408120546148f357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610826565b506000610826565b6000614950826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166149cd9092919063ffffffff16565b8051909150156142c8578080602001905181019061496e91906156c2565b6142c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109b0565b60606149dc84846000856149e4565b949350505050565b606082471015614a455760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109b0565b843b614a935760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109b0565b600080866001600160a01b03168587604051614aaf919061592d565b60006040518083038185875af1925050503d8060008114614aec576040519150601f19603f3d011682016040523d82523d6000602084013e614af1565b606091505b5091509150614b01828286614b0c565b979650505050505050565b60608315614b1b575081612a14565b825115614b2b5782518084602001fd5b8160405162461bcd60e51b81526004016109b09190615517565b5080546000825590600052602060002090810190614b639190614c94565b50565b828054828255906000526020600020908101928215614bb9579160200282015b82811115614bb95781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190614b86565b50614bc5929150614c94565b5090565b828054828255906000526020600020908101928215614bb9579160200282015b82811115614bb9578235825591602001919060010190614be9565b828054828255906000526020600020908101928215614bb9579160200282015b82811115614bb9578251825591602001919060010190614c24565b828054828255906000526020600020908101928215614bb9579160200282015b82811115614bb957825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614c5f565b5b80821115614bc55760008155600101614c95565b600060208284031215614cbb57600080fd5b81356001600160e01b031981168114612a1457600080fd5b6001600160a01b0381168114614b6357600080fd5b803561462481614cd3565b60008083601f840112614d0557600080fd5b5081356001600160401b03811115614d1c57600080fd5b602083019150836020828501011115614d3457600080fd5b9250929050565b600080600080600060808688031215614d5357600080fd5b8535614d5e81614cd3565b94506020860135614d6e81614cd3565b93506040860135925060608601356001600160401b03811115614d9057600080fd5b614d9c88828901614cf3565b969995985093965092949392505050565b60008060408385031215614dc057600080fd5b8235614dcb81614cd3565b946020939093013593505050565b600081518084526020808501945080840160005b83811015614e125781516001600160a01b031687529582019590820190600101614ded565b509495945050505050565b600081518084526020808501945080840160005b83811015614e1257815187529582019590820190600101614e31565b602081526000825160606020840152614e696080840182614dd9565b90506020840151601f1980858403016040860152614e878383614e1d565b9250604086015191508085840301606086015250614ea58282614e1d565b95945050505050565b6001600160a01b03929092168252602082015260400190565b60008060008060808587031215614edd57600080fd5b8435614ee881614cd3565b9350602085013592506040850135614eff81614cd3565b91506060850135614f0f81614cd3565b939692955090935050565b602081526000612a146020830184614dd9565b6000815160408452614f426040850182614dd9565b905060208301518482036020860152614ea58282614e1d565b602081526000612a146020830184614f2d565b60008083601f840112614f8057600080fd5b5081356001600160401b03811115614f9757600080fd5b6020830191508360208260051b8501011115614d3457600080fd5b60008060008060008060008060a0898b031215614fce57600080fd5b8835614fd981614cd3565b975060208901356001600160401b0380821115614ff557600080fd5b6150018c838d01614f6e565b909950975060408b013591508082111561501a57600080fd5b6150268c838d01614f6e565b909750955060608b013591508082111561503f57600080fd5b5061504c8b828c01614cf3565b909450925050608089013561506081614cd3565b809150509295985092959890939650565b60008060008060008060a0878903121561508a57600080fd5b863561509581614cd3565b955060208701356150a581614cd3565b94506040870135935060608701356001600160401b038111156150c757600080fd5b6150d389828a01614cf3565b90945092505060808701356150e781614cd3565b809150509295509295509295565b60008060008060008060008060008060c08b8d03121561511457600080fd5b61511d8b614ce8565b995060208b01356001600160401b038082111561513957600080fd5b6151458e838f01614f6e565b909b50995060408d013591508082111561515e57600080fd5b61516a8e838f01614f6e565b909950975060608d013591508082111561518357600080fd5b61518f8e838f01614f6e565b909750955060808d01359150808211156151a857600080fd5b506151b58d828e01614cf3565b90945092506151c8905060a08c01614ce8565b90509295989b9194979a5092959850565b6000602082840312156151eb57600080fd5b8135612a1481614cd3565b60008060006060848603121561520b57600080fd5b833561521681614cd3565b925060208401359150604084013561522d81614cd3565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561527657615276615238565b604052919050565b600082601f83011261528f57600080fd5b813560206001600160401b038211156152aa576152aa615238565b8160051b6152b982820161524e565b92835284810182019282810190878511156152d357600080fd5b83870192505b84831015614b01578235825291830191908301906152d9565b600082601f83011261530357600080fd5b81356001600160401b0381111561531c5761531c615238565b61532f601f8201601f191660200161524e565b81815284602083860101111561534457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561537957600080fd5b853561538481614cd3565b9450602086013561539481614cd3565b935060408601356001600160401b03808211156153b057600080fd5b6153bc89838a0161527e565b945060608801359150808211156153d257600080fd5b6153de89838a0161527e565b935060808801359150808211156153f457600080fd5b50615401888289016152f2565b9150509295509295909350565b6000806000806060858703121561542457600080fd5b843561542f81614cd3565b935060208501356001600160401b0381111561544a57600080fd5b61545687828801614cf3565b9094509250506040850135614f0f81614cd3565b60006020828403121561547c57600080fd5b5035919050565b600080600080600060a0868803121561549b57600080fd5b85356154a681614cd3565b945060208601356154b681614cd3565b9350604086013592506060860135915060808601356001600160401b038111156154df57600080fd5b615401888289016152f2565b60005b838110156155065781810151838201526020016154ee565b838111156147b35750506000910152565b60208152600082518060208401526155368160408501602087016154eb565b601f01601f19169190910160400192915050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b634e487b7160e01b600052601160045260246000fd5b60006000198214156155f9576155f96155cf565b5060010190565b6080815260006156136080830187614dd9565b82810360208401526156258187614e1d565b905082810360408401526156398186614e1d565b91505082606083015295945050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6060815260006156826060830186614dd9565b82810360208401526156948186614e1d565b915050826040830152949350505050565b6000602082840312156156b757600080fd5b8151612a1481614cd3565b6000602082840312156156d457600080fd5b81518015158114612a1457600080fd5b6000602082840312156156f657600080fd5b5051919050565b8183526000602080850194508260005b85811015614e1257813561572081614cd3565b6001600160a01b03168752958201959082019060010161570d565b81835260006001600160fb1b0383111561575457600080fd5b8260051b8083602087013760009401602001938452509192915050565b6060815260006157856060830187896156fd565b828103602084015261579881868861573b565b9150508260408301529695505050505050565b6060815260006157bf6060830186886156fd565b82810360208401526157d18186614e1d565b91505082604083015295945050505050565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008219821115615836576158366155cf565b500190565b60808152600061584f60808301898b6156fd565b828103602084015261586281888a61573b565b9050828103604084015261587781868861573b565b91505082606083015298975050505050505050565b6020808252600c908201526b3737ba1033b7bb32b93737b960a11b604082015260600190565b6000828210156158c4576158c46155cf565b500390565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b634e487b7160e01b600052603160045260246000fd5b6000825161593f8184602087016154eb565b919091019291505056fea2646970667358221220dbdf443101f6d16409d76e475d9f2b6c2ba960b213cb0297ca541e64689127c164736f6c63430008090033
Deployed Bytecode
0x60806040526004361061023b5760003560e01c8063aee6a2fe1161012e578063d6bee134116100ab578063f23a6e611161006f578063f23a6e6114610736578063f3b27bc314610762578063f79c004214610777578063f91afc9414610797578063ffa1ad74146107b757600080fd5b8063d6bee134146106b0578063d7e954e4146106d0578063e43252d7146106e3578063e5c0f24e14610703578063ed32e3f51461072357600080fd5b8063c45a0155116100f2578063c45a0155146105f0578063c4d66de814610610578063c6698ea714610630578063cabfa28414610645578063d1a5d9051461066557600080fd5b8063aee6a2fe1461054e578063b42fae261461056e578063b6aa515b1461058e578063bc197c81146105ae578063c068f7e2146105da57600080fd5b806362fa9158116101bc57806382cd81bc1161018057806382cd81bc146104bb5780638ab1d681146104ce578063aba0676c146104ee578063ad0305ce1461050e578063ad7a69dd1461052e57600080fd5b806362fa9158146104245780636ca9670d1461045f57806371dbf284146104725780637438ff42146104955780637b5af90a146104a857600080fd5b80634d4a5862116102035780634d4a58621461037e5780634e18b3d9146103a057806350761020146103c257806359557304146103ef5780635fb84fd11461040f57600080fd5b806301ffc9a7146102405780630c340a2414610275578063150b7a02146102b3578063265b87f2146102f857806333349fb414610325575b600080fd5b34801561024c57600080fd5b5061026061025b366004614ca9565b6107f5565b60405190151581526020015b60405180910390f35b34801561028157600080fd5b5060005461029b906201000090046001600160a01b031681565b6040516001600160a01b03909116815260200161026c565b3480156102bf57600080fd5b506102df6102ce366004614d3b565b630a85bd0160e11b95945050505050565b6040516001600160e01b0319909116815260200161026c565b34801561030457600080fd5b50610318610313366004614dad565b61082c565b60405161026c9190614e4d565b34801561033157600080fd5b50610370610340366004614dad565b6037602090815260009283526040808420909152908252902080546001909101546001600160a01b039091169082565b60405161026c929190614eae565b34801561038a57600080fd5b5061039e610399366004614ec7565b61098d565b005b3480156103ac57600080fd5b506103b5610d44565b60405161026c9190614f1a565b3480156103ce57600080fd5b506103e26103dd366004614dad565b610d55565b60405161026c9190614f5b565b3480156103fb57600080fd5b5061039e61040a366004614ec7565b610e45565b34801561041b57600080fd5b5061039e611154565b34801561043057600080fd5b5061026061043f366004614dad565b603660209081526000928352604080842090915290825290205460ff1681565b61039e61046d366004614fb2565b611281565b34801561047e57600080fd5b50610487606481565b60405190815260200161026c565b61039e6104a3366004615071565b611889565b61039e6104b63660046150f5565b611d1f565b61039e6104c9366004615071565b6124c7565b3480156104da57600080fd5b5061039e6104e93660046151d9565b6128ab565b3480156104fa57600080fd5b5061029b610509366004614dad565b612999565b34801561051a57600080fd5b506102606105293660046151d9565b612a1b565b34801561053a57600080fd5b5061039e6105493660046151d9565b612a28565b34801561055a57600080fd5b5061039e6105693660046151f6565b612aff565b34801561057a57600080fd5b506103e2610589366004614dad565b612c60565b34801561059a57600080fd5b5061039e6105a93660046151d9565b612d4e565b3480156105ba57600080fd5b506102df6105c9366004615361565b63bc197c8160e01b95945050505050565b3480156105e657600080fd5b5061048760355481565b3480156105fc57600080fd5b5060345461029b906001600160a01b031681565b34801561061c57600080fd5b5061039e61062b3660046151d9565b612df7565b34801561063c57600080fd5b506103b5612ed3565b34801561065157600080fd5b506102606106603660046151d9565b612edf565b34801561067157600080fd5b50610370610680366004614dad565b6038602090815260009283526040808420909152908252902080546001909101546001600160a01b039091169082565b3480156106bc57600080fd5b5061039e6106cb366004614ec7565b612eec565b61039e6106de36600461540e565b6130cf565b3480156106ef57600080fd5b5061039e6106fe3660046151d9565b613411565b34801561070f57600080fd5b5061039e61071e36600461546a565b6134ff565b61039e610731366004614fb2565b6135f4565b34801561074257600080fd5b506102df610751366004615483565b63f23a6e6160e01b95945050505050565b34801561076e57600080fd5b5061039e613be6565b34801561078357600080fd5b5061039e610792366004614ec7565b613cb8565b3480156107a357600080fd5b5061039e6107b2366004614ec7565b613e4d565b3480156107c357600080fd5b506107e8604051806040016040528060058152602001640312e322e360dc1b81525081565b60405161026c9190615517565b60006001600160e01b03198216630271189760e51b148061082657506301ffc9a760e01b6001600160e01b03198316145b92915050565b61085060405180606001604052806060815260200160608152602001606081525090565b6001600160a01b0383166000908152603d60209081526040808320858452825291829020825181546080938102820184019094526060810184815290939192849284918401828280156108cc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116108ae575b505050505081526020016001820180548060200260200160405190810160405280929190818152602001828054801561092457602002820191906000526020600020905b815481526020019060010190808311610910575b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561097c57602002820191906000526020600020905b815481526020019060010190808311610968575b505050505081525050905092915050565b600260335414156109b95760405162461bcd60e51b81526004016109b09061554a565b60405180910390fd5b600260335583826109ca8282614100565b6001600160a01b0386166000908152603d60209081526040808320888452825280832080548251818502810185019093528083529192909190830182828015610a3c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610a1e575b505050506001600160a01b0389166000908152603d602090815260408083208b845282528083206001018054825181850281018501909352808352959650929490935090830182828015610aaf57602002820191906000526020600020905b815481526020019060010190808311610a9b575b505050506001600160a01b038a166000908152603d602090815260408083208c845282528083206002018054825181850281018501909352808352959650929490935090830182828015610b2257602002820191906000526020600020905b815481526020019060010190808311610b0e575b505050505090506000835111604051806040016040528060028152602001610c8d60f21b81525090610b675760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0389166000908152603d602090815260408083208b8452909152812090610b968282614b45565b610ba4600183016000614b45565b610bb2600283016000614b45565b5050604051632770a7eb60e21b81526001600160a01b038a1690639dc29fac90610be2908a908c90600401614eae565b600060405180830381600087803b158015610bfc57600080fd5b505af1158015610c10573d6000803e3d6000fd5b5050505060005b8351811015610ce257838181518110610c3257610c32615581565b60200260200101516001600160a01b031663f242432a3089868581518110610c5c57610c5c615581565b6020026020010151868681518110610c7657610c76615581565b60200260200101516040518563ffffffff1660e01b8152600401610c9d9493929190615597565b600060405180830381600087803b158015610cb757600080fd5b505af1158015610ccb573d6000803e3d6000fd5b505050508080610cda906155e5565b915050610c17565b50886001600160a01b0316876001600160a01b03167fda2b8b59f3ee1abd151d454a3a9d9a3c4ce8e18151c5e62c292344122744ca0d8585858d604051610d2c9493929190615600565b60405180910390a35050600160335550505050505050565b6060610d50603e6142cd565b905090565b604080518082018252606080825260208083018290526001600160a01b0386166000908152603a8252848120868252825284902084518154928302810184018652948501828152939493909284928491840182828015610dde57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610dc0575b505050505081526020016001820180548060200260200160405190810160405280929190818152602001828054801561097c576020028201919060005260206000209081548152602001906001019080831161096857505050505081525050905092915050565b60026033541415610e685760405162461bcd60e51b81526004016109b09061554a565b60026033558382610e798282614100565b6001600160a01b0386166000908152603a60209081526040808320888452825280832080548251818502810185019093528083529192909190830182828015610eeb57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ecd575b505050506001600160a01b0389166000908152603a602090815260408083208b845282528083206001018054825181850281018501909352808352959650929490935090830182828015610f5e57602002820191906000526020600020905b815481526020019060010190808311610f4a575b50505050509050600082511160405180604001604052806002815260200161189b60f11b81525090610fa35760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0388166000908152603a602090815260408083208a8452909152812090610fd28282614b45565b610fe0600183016000614b45565b5050604051632770a7eb60e21b81526001600160a01b03891690639dc29fac906110109089908b90600401614eae565b600060405180830381600087803b15801561102a57600080fd5b505af115801561103e573d6000803e3d6000fd5b5050505060005b82518110156110f55782818151811061106057611060615581565b60200260200101516001600160a01b03166342842e0e308885858151811061108a5761108a615581565b60200260200101516040518463ffffffff1660e01b81526004016110b09392919061564b565b600060405180830381600087803b1580156110ca57600080fd5b505af11580156110de573d6000803e3d6000fd5b5050505080806110ed906155e5565b915050611045565b50876001600160a01b0316866001600160a01b03167f4324ef2315b0ac160aae9f8ac838949e23168c728a4c28f3009bb8853e3083b184848b60405161113d9392919061566f565b60405180910390a350506001603355505050505050565b603454604080516317d43b9f60e31b815290516000926001600160a01b03169163bea1dcf8916004808301926020929190829003018186803b15801561119957600080fd5b505afa1580156111ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d191906156a5565b6000549091506201000090046001600160a01b0316336001600160a01b031614806112045750336001600160a01b038216145b60405180604001604052806002815260200161032360f41b8152509061123d5760405162461bcd60e51b81526004016109b09190615517565b5060405147808252907f2af28626f494b1c155787b0089b658f2a5b3d9c010df886483e601ab92c804ce9060200160405180910390a161127d82826142da565b5050565b600260335414156112a45760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b03808b1660048301528a92169063696f345d9060240160206040518083038186803b1580156112ee57600080fd5b505afa158015611302573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132691906156c2565b604051806040016040528060018152602001600760fb1b8152509061135e5760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156113ae57600080fd5b505afa1580156113c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e691906156c2565b60405180604001604052806002815260200161031360f41b8152509061141f5760405162461bcd60e51b81526004016109b09190615517565b5061142d335b603b906143f3565b61147157603554341460405180604001604052806002815260200161313960f01b8152509061146f5760405162461bcd60e51b81526004016109b09190615517565b505b868015801590611482575060648111155b604051806040016040528060018152602001603360f81b815250906114ba5760405162461bcd60e51b81526004016109b09190615517565b506040805180820190915260018152601b60f91b60208201528187146114f35760405162461bcd60e51b81526004016109b09190615517565b5060008a6001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561152f57600080fd5b505afa158015611543573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156791906156e4565b6001600160a01b038c1660009081526039602090815260408083208484529091529020909150611598908b8b614b66565b506115a6335b603e906143f3565b15611635576001600160a01b038b16600090815260396020908152604080832084845290915290206115dc906001018989614bc9565b508a6001600160a01b0316846001600160a01b03167f4416146c05a6d85e921ca2cd45d2214a3e2661528176ea33ac7e45b7a28879d08c8c8c8c87604051611628959493929190615771565b60405180910390a3611815565b6000826001600160401b0381111561164f5761164f615238565b604051908082528060200260200182016040528015611678578160200160208202803683370190505b50905060005b838110156117895760008c8c8381811061169a5761169a615581565b90506020020160208101906116af91906151d9565b905060008b8b848181106116c5576116c5615581565b90506020020135905060008111604051806040016040528060018152602001603160f81b8152509061170a5760405162461bcd60e51b81526004016109b09190615517565b506040805180820190915260018152601960f91b60208201526001600160a01b03831661174a5760405162461bcd60e51b81526004016109b09190615517565b50611756823383614415565b84848151811061176857611768615581565b60200260200101818152505050508080611781906155e5565b91505061167e565b506001600160a01b038c166000908152603960209081526040808320858452825290912082516117c192600190920191840190614c04565b508b6001600160a01b0316856001600160a01b03167f4416146c05a6d85e921ca2cd45d2214a3e2661528176ea33ac7e45b7a28879d08d8d858760405161180b94939291906157ab565b60405180910390a3505b60405163d0def52160e01b81526001600160a01b038c169063d0def521906118459087908a908a906004016157e3565b600060405180830381600087803b15801561185f57600080fd5b505af1158015611873573d6000803e3d6000fd5b5050600160335550505050505050505050505050565b600260335414156118ac5760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b0380891660048301528892169063696f345d9060240160206040518083038186803b1580156118f657600080fd5b505afa15801561190a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061192e91906156c2565b604051806040016040528060018152602001600760fb1b815250906119665760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156119b657600080fd5b505afa1580156119ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ee91906156c2565b60405180604001604052806002815260200161031360f41b81525090611a275760405162461bcd60e51b81526004016109b09190615517565b50611a3133611425565b611a7557603554341460405180604001604052806002815260200161313960f01b81525090611a735760405162461bcd60e51b81526004016109b09190615517565b505b6000876001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611ab057600080fd5b505afa158015611ac4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae891906156e4565b9050611af33361159e565b611c1757604051632142170760e11b81526001600160a01b038816906342842e0e90611b2790339030908b9060040161564b565b600060405180830381600087803b158015611b4157600080fd5b505af1158015611b55573d6000803e3d6000fd5b50506040516331a9108f60e11b8152600481018990523092506001600160a01b038a169150636352211e9060240160206040518083038186803b158015611b9b57600080fd5b505afa158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd391906156a5565b6001600160a01b031614604051806040016040528060018152602001603760f81b81525090611c155760405162461bcd60e51b81526004016109b09190615517565b505b6001600160a01b0388811660008181526038602090815260408083208684529091529081902080546001600160a01b031916938b169390931783556001909201889055905163d0def52160e01b815263d0def52190611c7e908690899089906004016157e3565b600060405180830381600087803b158015611c9857600080fd5b505af1158015611cac573d6000803e3d6000fd5b50505050866001600160a01b0316886001600160a01b0316846001600160a01b03167fcd663b969127fbda25c2717fbf6b672d51c5d25f226bb98470a4e9ce748a09638985604051611d08929190918252602082015260400190565b60405180910390a450506001603355505050505050565b60026033541415611d425760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b03808d1660048301528c92169063696f345d9060240160206040518083038186803b158015611d8c57600080fd5b505afa158015611da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc491906156c2565b604051806040016040528060018152602001600760fb1b81525090611dfc5760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015611e4c57600080fd5b505afa158015611e60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8491906156c2565b60405180604001604052806002815260200161031360f41b81525090611ebd5760405162461bcd60e51b81526004016109b09190615517565b50611ec733611425565b611f0b57603554341460405180604001604052806002815260200161313960f01b81525090611f095760405162461bcd60e51b81526004016109b09190615517565b505b888015801590611f1c575060648111155b604051806040016040528060018152602001603360f81b81525090611f545760405162461bcd60e51b81526004016109b09190615517565b508088148015611f6357508086145b604051806040016040528060018152602001601b60f91b81525090611f9b5760405162461bcd60e51b81526004016109b09190615517565b50611fa53361159e565b61223b5760005b818110156122395760008c8c83818110611fc857611fc8615581565b9050602002016020810190611fdd91906151d9565b905060008b8b84818110611ff357611ff3615581565b90506020020135905060006001600160a01b0316826001600160a01b03161415604051806040016040528060018152602001601960f91b8152509061204b5760405162461bcd60e51b81526004016109b09190615517565b50604051627eeac760e11b81526000906001600160a01b0384169062fdd58e9061207b9030908690600401614eae565b60206040518083038186803b15801561209357600080fd5b505afa1580156120a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cb91906156e4565b90506001600160a01b03831663f242432a3330858f8f8a8181106120f1576120f1615581565b905060200201356040518563ffffffff1660e01b81526004016121179493929190615597565b600060405180830381600087803b15801561213157600080fd5b505af1158015612145573d6000803e3d6000fd5b505050508a8a8581811061215b5761215b615581565b905060200201358161216d9190615823565b604051627eeac760e11b81526001600160a01b0385169062fdd58e906121999030908790600401614eae565b60206040518083038186803b1580156121b157600080fd5b505afa1580156121c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e991906156e4565b14604051806040016040528060018152602001603760f81b815250906122225760405162461bcd60e51b81526004016109b09190615517565b505050508080612231906155e5565b915050611fac565b505b60008c6001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561227657600080fd5b505afa15801561228a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ae91906156e4565b905060405180606001604052808d8d808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208d810282810182019093528d82529283019290918e918e9182918501908490808284376000920191909152505050908252506040805160208b810282810182019093528b82529283019290918c918c918291850190849080828437600081840152601f19601f82011690508083019250505050505050815250603d60008f6001600160a01b03166001600160a01b03168152602001908152602001600020600083815260200190815260200160002060008201518160000190805190602001906123c2929190614c3f565b5060208281015180516123db9260018501920190614c04565b50604082015180516123f7916002840191602090910190614c04565b505060405163d0def52160e01b81526001600160a01b038f16915063d0def5219061242a9087908a908a906004016157e3565b600060405180830381600087803b15801561244457600080fd5b505af1158015612458573d6000803e3d6000fd5b505050508c6001600160a01b0316846001600160a01b03167fe564a803b77781693e8cfa25b28d4258d106eef1885c92fd0dbe4aee9f6c63c38e8e8e8e8e8e896040516124ab979695949392919061583b565b60405180910390a3505060016033555050505050505050505050565b600260335414156124ea5760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b0380891660048301528892169063696f345d9060240160206040518083038186803b15801561253457600080fd5b505afa158015612548573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256c91906156c2565b604051806040016040528060018152602001600760fb1b815250906125a45760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156125f457600080fd5b505afa158015612608573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262c91906156c2565b60405180604001604052806002815260200161031360f41b815250906126655760405162461bcd60e51b81526004016109b09190615517565b5061266f33611425565b6126b357603554341460405180604001604052806002815260200161313960f01b815250906126b15760405162461bcd60e51b81526004016109b09190615517565b505b6040805180820190915260018152603160f81b6020820152856126e95760405162461bcd60e51b81526004016109b09190615517565b506040805180820190915260018152601960f91b60208201526001600160a01b0387166127295760405162461bcd60e51b81526004016109b09190615517565b506000876001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561276557600080fd5b505afa158015612779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061279d91906156e4565b90506127a83361159e565b6127ba576127b7873388614415565b95505b6001600160a01b0388811660008181526037602090815260408083208684529091529081902080546001600160a01b031916938b169390931783556001909201889055905163d0def52160e01b815263d0def52190612821908690899089906004016157e3565b600060405180830381600087803b15801561283b57600080fd5b505af115801561284f573d6000803e3d6000fd5b50505050866001600160a01b0316886001600160a01b0316846001600160a01b03167f79ac13d0d960f612f8d7b052a21447a4b3cb93c8d95b550746a0f84f1ed0d57a8985604051611d08929190918252602082015260400190565b6000546001600160a01b03620100009091041633146128dc5760405162461bcd60e51b81526004016109b09061588c565b604080518082019091526002815261313160f01b60208201526001600160a01b03821661291c5760405162461bcd60e51b81526004016109b09190615517565b50612928603b82614572565b60405180604001604052806002815260200161313760f01b815250906129615760405162461bcd60e51b81526004016109b09190615517565b506040516001600160a01b038216907fcdd2e9b91a56913d370075169cefa1602ba36be5301664f752192bb1709df75790600090a250565b6040516331a9108f60e11b8152600481018290526000906001600160a01b03841690636352211e9060240160206040518083038186803b1580156129dc57600080fd5b505afa1580156129f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a1491906156a5565b9392505050565b6000610826603b836143f3565b6000546001600160a01b0362010000909104163314612a595760405162461bcd60e51b81526004016109b09061588c565b604080518082019091526002815261313160f01b60208201526001600160a01b038216612a995760405162461bcd60e51b81526004016109b09190615517565b50612aa5603e826143f3565b15612abb57612ab5603e82614572565b50612ac8565b612ac6603e82614587565b505b6040516001600160a01b038216907f3e4c0ce6297bf984156b60851857f36768c460cc4b5c5bf602a42d9fad186ea490600090a250565b60026033541415612b225760405162461bcd60e51b81526004016109b09061554a565b60026033558281612b338282614100565b6001600160a01b038516600090815260366020908152604080832087845282529182902054825180840190935260028352610c4d60f21b9183019190915260ff16612b915760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b038581166000818152603660209081526040808320898452825291829020805460ff19169055905187815291928616917f369fb8e0e292df89faae5f8b02b8254a8bba1d7284209886d7bc31b20796113c910160405180910390a3604051632770a7eb60e21b81526001600160a01b03861690639dc29fac90612c229086908890600401614eae565b600060405180830381600087803b158015612c3c57600080fd5b505af1158015612c50573d6000803e3d6000fd5b5050600160335550505050505050565b604080518082018252606080825260208083018290526001600160a01b038616600090815260398252848120868252825284902084518154928302810184018652948501828152939493909284928491840182828015610dde576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610dc057505050505081526020016001820180548060200260200160405190810160405280929190818152602001828054801561097c576020028201919060005260206000209081548152602001906001019080831161096857505050505081525050905092915050565b6000546001600160a01b0362010000909104163314612d7f5760405162461bcd60e51b81526004016109b09061588c565b6001600160a01b038116612dd55760405162461bcd60e51b815260206004820152601960248201527f696e76616c69642070726f706f73656420676f7665726e6f720000000000000060448201526064016109b0565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000612e03600161459c565b90508015612e1b576000805461ff0019166101001790555b604080518082019091526002815261313160f01b60208201526001600160a01b038316612e5b5760405162461bcd60e51b81526004016109b09190615517565b50612e64614629565b603480546001600160a01b0319166001600160a01b03841617905566038d7ea4c68000603555801561127d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6060610d50603b6142cd565b6000610826603e836143f3565b60026033541415612f0f5760405162461bcd60e51b81526004016109b09061554a565b60026033558382612f208282614100565b6001600160a01b0380871660009081526038602090815260408083208984528252918290205482518084019093526002835261189b60f11b918301919091529091169081612f815760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b03871660008181526038602090815260408083208a845290915280822060018101805482546001600160a01b0319169092559290925551632770a7eb60e21b8152909190639dc29fac90612fe39089908b90600401614eae565b600060405180830381600087803b158015612ffd57600080fd5b505af1158015613011573d6000803e3d6000fd5b5050604051632142170760e11b81526001600160a01b03851692506342842e0e91506130459030908990869060040161564b565b600060405180830381600087803b15801561305f57600080fd5b505af1158015613073573d6000803e3d6000fd5b50505050816001600160a01b0316886001600160a01b0316876001600160a01b03167fdd211b39049950d7216395989579818241a461da30cf6a42b2d8305b8205cfff848b604051611d08929190918252602082015260400190565b600260335414156130f25760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b0380871660048301528692169063696f345d9060240160206040518083038186803b15801561313c57600080fd5b505afa158015613150573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061317491906156c2565b604051806040016040528060018152602001600760fb1b815250906131ac5760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b1580156131fc57600080fd5b505afa158015613210573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061323491906156c2565b60405180604001604052806002815260200161031360f41b8152509061326d5760405162461bcd60e51b81526004016109b09190615517565b5061327733611425565b6132bb57603554341460405180604001604052806002815260200161313960f01b815250906132b95760405162461bcd60e51b81526004016109b09190615517565b505b6000856001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156132f657600080fd5b505afa15801561330a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061332e91906156e4565b6001600160a01b038716600081815260366020908152604080832085845290915290819020805460ff191660011790555163d0def52160e01b81529192509063d0def52190613385908690899089906004016157e3565b600060405180830381600087803b15801561339f57600080fd5b505af11580156133b3573d6000803e3d6000fd5b50505050856001600160a01b0316836001600160a01b03167fdc8a2e2a073bc1ff78027b5481b30fc20dc92bd9faae378c3411b25838ab2bf3836040516133fc91815260200190565b60405180910390a35050600160335550505050565b6000546001600160a01b03620100009091041633146134425760405162461bcd60e51b81526004016109b09061588c565b604080518082019091526002815261313160f01b60208201526001600160a01b0382166134825760405162461bcd60e51b81526004016109b09190615517565b5061348e603b82614587565b60405180604001604052806002815260200161062760f31b815250906134c75760405162461bcd60e51b81526004016109b09190615517565b506040516001600160a01b038216907fa850ae9193f515cbae8d35e8925bd2be26627fc91bce650b8652ed254e9cab0390600090a250565b6000546001600160a01b03620100009091041633146135305760405162461bcd60e51b81526004016109b09061588c565b604080518082019091526002815261313960f01b602082015267016345785d8a00008211156135725760405162461bcd60e51b81526004016109b09190615517565b5060355481141560405180604001604052806002815260200161313360f01b815250906135b25760405162461bcd60e51b81526004016109b09190615517565b5060355460408051918252602082018390527f67f043b257fe2539966e18910ca7fd99876bcce5e659ff3cf23245320f4de67b910160405180910390a1603555565b600260335414156136175760405162461bcd60e51b81526004016109b09061554a565b600260335560345460405163696f345d60e01b81526001600160a01b03808b1660048301528a92169063696f345d9060240160206040518083038186803b15801561366157600080fd5b505afa158015613675573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369991906156c2565b604051806040016040528060018152602001600760fb1b815250906136d15760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0381166364d24ed8336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b15801561372157600080fd5b505afa158015613735573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061375991906156c2565b60405180604001604052806002815260200161031360f41b815250906137925760405162461bcd60e51b81526004016109b09190615517565b5061379c33611425565b6137e057603554341460405180604001604052806002815260200161313960f01b815250906137de5760405162461bcd60e51b81526004016109b09190615517565b505b8680158015906137f1575060648111155b604051806040016040528060018152602001603360f81b815250906138295760405162461bcd60e51b81526004016109b09190615517565b506040805180820190915260018152601b60f91b60208201528187146138625760405162461bcd60e51b81526004016109b09190615517565b5060008a6001600160a01b03166361bc221a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561389e57600080fd5b505afa1580156138b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138d691906156e4565b90506138e13361159e565b613abe5760005b82811015613abc5760008b8b8381811061390457613904615581565b905060200201602081019061391991906151d9565b905060008a8a8481811061392f5761392f615581565b90506020020135905060006001600160a01b0316826001600160a01b03161415604051806040016040528060018152602001601960f91b815250906139875760405162461bcd60e51b81526004016109b09190615517565b50604051632142170760e11b81526001600160a01b038316906342842e0e906139b89033903090869060040161564b565b600060405180830381600087803b1580156139d257600080fd5b505af11580156139e6573d6000803e3d6000fd5b50506040516331a9108f60e11b8152600481018490523092506001600160a01b0385169150636352211e9060240160206040518083038186803b158015613a2c57600080fd5b505afa158015613a40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a6491906156a5565b6001600160a01b031614604051806040016040528060018152602001603760f81b81525090613aa65760405162461bcd60e51b81526004016109b09190615517565b5050508080613ab4906155e5565b9150506138e8565b505b6001600160a01b038b166000908152603a602090815260408083208484529091529020613aec908b8b614b66565b506001600160a01b038b166000908152603a602090815260408083208484529091529020613b1e906001018989614bc9565b5060405163d0def52160e01b81526001600160a01b038c169063d0def52190613b4f9087908a908a906004016157e3565b600060405180830381600087803b158015613b6957600080fd5b505af1158015613b7d573d6000803e3d6000fd5b505050508a6001600160a01b0316846001600160a01b03167faba856cf36fc0adf76e7d75992b5f3472e43d6b68ae6a2f90ecbe063cd7163ee8c8c8c8c87604051613bcc959493929190615771565b60405180910390a350506001603355505050505050505050565b6001546001600160a01b03163314613c405760405162461bcd60e51b815260206004820152601960248201527f6e6f74207468652070726f706f73656420676f7665726e6f720000000000000060448201526064016109b0565b600154600080546040516001600160a01b039384169362010000909204909116917fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d091a3600180546000805462010000600160b01b0319166001600160a01b03831662010000021790556001600160a01b0319169055565b60026033541415613cdb5760405162461bcd60e51b81526004016109b09061554a565b60026033558382613cec8282614100565b6001600160a01b03861660009081526037602090815260408083208884528252918290206001015482518084019093526002835261313560f01b918301919091529081613d4c5760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b0387811660008181526037602090815260408083208b845290915280822080546001600160a01b03198116825560019091019290925551632770a7eb60e21b8152921691639dc29fac90613dae9089908b90600401614eae565b600060405180830381600087803b158015613dc857600080fd5b505af1158015613ddc573d6000803e3d6000fd5b50613df5925050506001600160a01b03821686846146e0565b806001600160a01b0316886001600160a01b0316876001600160a01b03167f627cb524b52ac408bea8da9f6f92949a5c4f8be2966a9a288951a154511ccc87858b604051611d08929190918252602082015260400190565b60026033541415613e705760405162461bcd60e51b81526004016109b09061554a565b60026033558382613e818282614100565b6001600160a01b0386166000908152603960209081526040808320888452825280832080548251818502810185019093528083529192909190830182828015613ef357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613ed5575b505050506001600160a01b03891660009081526039602090815260408083208b845282528083206001018054825181850281018501909352808352959650929490935090830182828015613f6657602002820191906000526020600020905b815481526020019060010190808311613f52575b50505050509050600082511160405180604001604052806002815260200161313560f01b81525090613fab5760405162461bcd60e51b81526004016109b09190615517565b506001600160a01b03881660009081526039602090815260408083208a8452909152812090613fda8282614b45565b613fe8600183016000614b45565b5050604051632770a7eb60e21b81526001600160a01b03891690639dc29fac906140189089908b90600401614eae565b600060405180830381600087803b15801561403257600080fd5b505af1158015614046573d6000803e3d6000fd5b5050505060005b82518110156140b8576140a68683838151811061406c5761406c615581565b602002602001015185848151811061408657614086615581565b60200260200101516001600160a01b03166146e09092919063ffffffff16565b806140b0816155e5565b91505061404d565b50876001600160a01b0316866001600160a01b03167f4cb316182a29e84cde5ecbceaba26ba941408b4df06dc637c8675b39799a938e84848b60405161113d9392919061566f565b60345460405163696f345d60e01b81526001600160a01b0384811660048301529091169063696f345d9060240160206040518083038186803b15801561414557600080fd5b505afa158015614159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061417d91906156c2565b604051806040016040528060018152602001600760fb1b815250906141b55760405162461bcd60e51b81526004016109b09190615517565b50336001600160a01b0382161461420c576141d1603e336143f3565b60405180604001604052806002815260200161323560f01b8152509061420a5760405162461bcd60e51b81526004016109b09190615517565b505b603454604051632571e0af60e21b81526001600160a01b038481166004830152336024830152909116906395c782bc9060440160206040518083038186803b15801561425757600080fd5b505afa15801561426b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061428f91906156c2565b60405180604001604052806002815260200161191b60f11b815250906142c85760405162461bcd60e51b81526004016109b09190615517565b505050565b60606000612a1483614736565b8047101561432a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016109b0565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114614377576040519150601f19603f3d011682016040523d82523d6000602084013e61437c565b606091505b50509050806142c85760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016109b0565b6001600160a01b03811660009081526001830160205260408120541515612a14565b6040516370a0823160e01b815230600482015260009081906001600160a01b038616906370a082319060240160206040518083038186803b15801561445957600080fd5b505afa15801561446d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061449191906156e4565b90506144a86001600160a01b038616853086614792565b6040516370a0823160e01b815230600482015281906001600160a01b038716906370a082319060240160206040518083038186803b1580156144e957600080fd5b505afa1580156144fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061452191906156e4565b61452b91906158b2565b915060008211604051806040016040528060018152602001603160f81b815250906145695760405162461bcd60e51b81526004016109b09190615517565b50509392505050565b6000612a14836001600160a01b0384166147b9565b6000612a14836001600160a01b0384166148ac565b60008054610100900460ff16156145e3578160ff1660011480156145bf5750303b155b6145db5760405162461bcd60e51b81526004016109b0906158c9565b506000919050565b60005460ff80841691161061460a5760405162461bcd60e51b81526004016109b0906158c9565b506000805460ff191660ff92909216919091179055600190565b919050565b600054610100900460ff166146945760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016109b0565b6000805462010000600160b01b03191633620100008102919091178255604051909182917fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d0908290a350565b6142c88363a9059cbb60e01b84846040516024016146ff929190614eae565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526148fb565b60608160000180548060200260200160405190810160405280929190818152602001828054801561478657602002820191906000526020600020905b815481526020019060010190808311614772575b50505050509050919050565b6147b3846323b872dd60e01b8585856040516024016146ff9392919061564b565b50505050565b600081815260018301602052604081205480156148a25760006147dd6001836158b2565b85549091506000906147f1906001906158b2565b905081811461485657600086600001828154811061481157614811615581565b906000526020600020015490508087600001848154811061483457614834615581565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061486757614867615917565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610826565b6000915050610826565b60008181526001830160205260408120546148f357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610826565b506000610826565b6000614950826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166149cd9092919063ffffffff16565b8051909150156142c8578080602001905181019061496e91906156c2565b6142c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109b0565b60606149dc84846000856149e4565b949350505050565b606082471015614a455760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109b0565b843b614a935760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109b0565b600080866001600160a01b03168587604051614aaf919061592d565b60006040518083038185875af1925050503d8060008114614aec576040519150601f19603f3d011682016040523d82523d6000602084013e614af1565b606091505b5091509150614b01828286614b0c565b979650505050505050565b60608315614b1b575081612a14565b825115614b2b5782518084602001fd5b8160405162461bcd60e51b81526004016109b09190615517565b5080546000825590600052602060002090810190614b639190614c94565b50565b828054828255906000526020600020908101928215614bb9579160200282015b82811115614bb95781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190614b86565b50614bc5929150614c94565b5090565b828054828255906000526020600020908101928215614bb9579160200282015b82811115614bb9578235825591602001919060010190614be9565b828054828255906000526020600020908101928215614bb9579160200282015b82811115614bb9578251825591602001919060010190614c24565b828054828255906000526020600020908101928215614bb9579160200282015b82811115614bb957825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614c5f565b5b80821115614bc55760008155600101614c95565b600060208284031215614cbb57600080fd5b81356001600160e01b031981168114612a1457600080fd5b6001600160a01b0381168114614b6357600080fd5b803561462481614cd3565b60008083601f840112614d0557600080fd5b5081356001600160401b03811115614d1c57600080fd5b602083019150836020828501011115614d3457600080fd5b9250929050565b600080600080600060808688031215614d5357600080fd5b8535614d5e81614cd3565b94506020860135614d6e81614cd3565b93506040860135925060608601356001600160401b03811115614d9057600080fd5b614d9c88828901614cf3565b969995985093965092949392505050565b60008060408385031215614dc057600080fd5b8235614dcb81614cd3565b946020939093013593505050565b600081518084526020808501945080840160005b83811015614e125781516001600160a01b031687529582019590820190600101614ded565b509495945050505050565b600081518084526020808501945080840160005b83811015614e1257815187529582019590820190600101614e31565b602081526000825160606020840152614e696080840182614dd9565b90506020840151601f1980858403016040860152614e878383614e1d565b9250604086015191508085840301606086015250614ea58282614e1d565b95945050505050565b6001600160a01b03929092168252602082015260400190565b60008060008060808587031215614edd57600080fd5b8435614ee881614cd3565b9350602085013592506040850135614eff81614cd3565b91506060850135614f0f81614cd3565b939692955090935050565b602081526000612a146020830184614dd9565b6000815160408452614f426040850182614dd9565b905060208301518482036020860152614ea58282614e1d565b602081526000612a146020830184614f2d565b60008083601f840112614f8057600080fd5b5081356001600160401b03811115614f9757600080fd5b6020830191508360208260051b8501011115614d3457600080fd5b60008060008060008060008060a0898b031215614fce57600080fd5b8835614fd981614cd3565b975060208901356001600160401b0380821115614ff557600080fd5b6150018c838d01614f6e565b909950975060408b013591508082111561501a57600080fd5b6150268c838d01614f6e565b909750955060608b013591508082111561503f57600080fd5b5061504c8b828c01614cf3565b909450925050608089013561506081614cd3565b809150509295985092959890939650565b60008060008060008060a0878903121561508a57600080fd5b863561509581614cd3565b955060208701356150a581614cd3565b94506040870135935060608701356001600160401b038111156150c757600080fd5b6150d389828a01614cf3565b90945092505060808701356150e781614cd3565b809150509295509295509295565b60008060008060008060008060008060c08b8d03121561511457600080fd5b61511d8b614ce8565b995060208b01356001600160401b038082111561513957600080fd5b6151458e838f01614f6e565b909b50995060408d013591508082111561515e57600080fd5b61516a8e838f01614f6e565b909950975060608d013591508082111561518357600080fd5b61518f8e838f01614f6e565b909750955060808d01359150808211156151a857600080fd5b506151b58d828e01614cf3565b90945092506151c8905060a08c01614ce8565b90509295989b9194979a5092959850565b6000602082840312156151eb57600080fd5b8135612a1481614cd3565b60008060006060848603121561520b57600080fd5b833561521681614cd3565b925060208401359150604084013561522d81614cd3565b809150509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561527657615276615238565b604052919050565b600082601f83011261528f57600080fd5b813560206001600160401b038211156152aa576152aa615238565b8160051b6152b982820161524e565b92835284810182019282810190878511156152d357600080fd5b83870192505b84831015614b01578235825291830191908301906152d9565b600082601f83011261530357600080fd5b81356001600160401b0381111561531c5761531c615238565b61532f601f8201601f191660200161524e565b81815284602083860101111561534457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561537957600080fd5b853561538481614cd3565b9450602086013561539481614cd3565b935060408601356001600160401b03808211156153b057600080fd5b6153bc89838a0161527e565b945060608801359150808211156153d257600080fd5b6153de89838a0161527e565b935060808801359150808211156153f457600080fd5b50615401888289016152f2565b9150509295509295909350565b6000806000806060858703121561542457600080fd5b843561542f81614cd3565b935060208501356001600160401b0381111561544a57600080fd5b61545687828801614cf3565b9094509250506040850135614f0f81614cd3565b60006020828403121561547c57600080fd5b5035919050565b600080600080600060a0868803121561549b57600080fd5b85356154a681614cd3565b945060208601356154b681614cd3565b9350604086013592506060860135915060808601356001600160401b038111156154df57600080fd5b615401888289016152f2565b60005b838110156155065781810151838201526020016154ee565b838111156147b35750506000910152565b60208152600082518060208401526155368160408501602087016154eb565b601f01601f19169190910160400192915050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b634e487b7160e01b600052601160045260246000fd5b60006000198214156155f9576155f96155cf565b5060010190565b6080815260006156136080830187614dd9565b82810360208401526156258187614e1d565b905082810360408401526156398186614e1d565b91505082606083015295945050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6060815260006156826060830186614dd9565b82810360208401526156948186614e1d565b915050826040830152949350505050565b6000602082840312156156b757600080fd5b8151612a1481614cd3565b6000602082840312156156d457600080fd5b81518015158114612a1457600080fd5b6000602082840312156156f657600080fd5b5051919050565b8183526000602080850194508260005b85811015614e1257813561572081614cd3565b6001600160a01b03168752958201959082019060010161570d565b81835260006001600160fb1b0383111561575457600080fd5b8260051b8083602087013760009401602001938452509192915050565b6060815260006157856060830187896156fd565b828103602084015261579881868861573b565b9150508260408301529695505050505050565b6060815260006157bf6060830186886156fd565b82810360208401526157d18186614e1d565b91505082604083015295945050505050565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008219821115615836576158366155cf565b500190565b60808152600061584f60808301898b6156fd565b828103602084015261586281888a61573b565b9050828103604084015261587781868861573b565b91505082606083015298975050505050505050565b6020808252600c908201526b3737ba1033b7bb32b93737b960a11b604082015260600190565b6000828210156158c4576158c46155cf565b500390565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b634e487b7160e01b600052603160045260246000fd5b6000825161593f8184602087016154eb565b919091019291505056fea2646970667358221220dbdf443101f6d16409d76e475d9f2b6c2ba960b213cb0297ca541e64689127c164736f6c63430008090033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.