Transaction Hash:
Block:
18145117 at Sep-16-2023 12:19:35 AM +UTC
Transaction Fee:
0.000359102864430837 ETH
$0.92
Gas Used:
46,089 Gas / 7.791509133 Gwei
Emitted Events:
169 |
MoonCatAcclimator.ApprovalForAll( owner=[Sender] 0x7186256cdfa758271128ef50ff8732b4fe88ca06, operator=0x1E004978...d54003c71, approved=True )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x7186256c...4fe88ca06 |
0.059240493467476626 Eth
Nonce: 38
|
0.058881390603045789 Eth
Nonce: 39
| 0.000359102864430837 | ||
0x95222290...5CC4BAfe5
Miner
| (beaverbuild) | 19.151494083999101174 Eth | 19.151498692899101174 Eth | 0.0000046089 | |
0xc3f733ca...2A1A05E69 |
Execution Trace
MoonCatAcclimator.setApprovalForAll( operator=0x1E0049783F008A0085193E00003D00cd54003c71, approved=True )
setApprovalForAll[ERC721 (ln:942)]
_msgSender[ERC721 (ln:943)]
_msgSender[ERC721 (ln:944)]
ApprovalForAll[ERC721 (ln:945)]
_msgSender[ERC721 (ln:945)]
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.7.3; import "./openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/ERC721Holder.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "./IERC998.sol"; import "./MoonCatOrderLookup.sol"; // ## ## // ## ## ## ## // ##.. ###### ..## // #### #### // ## ## // ## () () ## // ## ## // ## \\ ## / ## // ## \\/ \\/ ## // ## ## // ############## // // #AcclimatedMoonCatsGlow // https://mooncat.community/ /** * @title MoonCatAcclimator * @notice Accepts an original MoonCat and wraps it to present an ERC721- and ERC998-compliant asset * @notice Accepts a MoonCat wrapped with the older wrapping contract (at 0x7C40c3...) and re-wraps them * @notice Ownable by an admin address. Rights of the Owner are to pause and unpause the contract, and update metadata URL */ contract MoonCatAcclimator is ERC721, ERC721Holder, Ownable, Pausable, IERC998ERC721TopDown, IERC998ERC721TopDownEnumerable { bytes32 private constant ERC998_MAGIC_VALUE = 0x00000000000000000000000000000000000000000000000000000000cd740db5; bytes4 private constant _INTERFACE_ID_ERC998ERC721TopDown = 0x1efdf36a; MoonCatOrderLookup public rescueOrderLookup; MoonCatRescue MCR = MoonCatRescue(0x60cd862c9C687A9dE49aecdC3A99b74A4fc54aB6); MoonCatsWrapped OLD_MCRW = MoonCatsWrapped(0x7C40c393DC0f283F318791d746d894DdD3693572); constructor(string memory baseURI) ERC721(unicode"AcclimatedMoonCats", unicode"😺") Ownable() { _registerInterface(_INTERFACE_ID_ERC998ERC721TopDown); rescueOrderLookup = new MoonCatOrderLookup(); setBaseURI(baseURI); _pause(); // Start in a paused state } function pause() public whenNotPaused onlyOwner { _pause(); } function unpause() public whenPaused onlyOwner { _unpause(); } /** * @dev Emitted when `catId` token is wrapped into `tokenId`, owned by `owner`. */ event MoonCatAcclimated( uint256 tokenId, address indexed owner ); /** * @dev Emitted when `catId` token is unwrapped from `tokenId`, owned by `owner`. */ event MoonCatDeacclimated( uint256 tokenId, address indexed owner ); /** * @dev returns tokenId of newly minted wrapped MoonCat * * Requirements: * * - Do not need to check if _msgSender() is MoonCat owner as the wrapped token is assigned to owner (even if that's not _msgSender()) * - Owner needs to call makeAdoptionOfferToAddress() in moonCatRescue first. * Emits a {Transfer} ERC721 event. * @param _rescueOrder the minting order of the MoonCat to wrap * @return the ID (rescue order) of the minted token */ function wrap(uint256 _rescueOrder) public returns (uint256) { bytes5 catId = MCR.rescueOrder(_rescueOrder); address _owner = MCR.catOwners(catId); MCR.acceptAdoptionOffer(catId); return _wrap(_owner, _rescueOrder); } /** * @dev returns tokenId of newly minted wrapped MoonCat * * This method must not allow an adoption offer specifically to the new Wrapper address to be buy-able by anyone, * because that is how the real owner sets up a manual wrapping of the MoonCat (where they don't really intend to sell). * * Requirements: * * - MoonCat at `_rescueOrder` must be offered for sale to any address. * - Must have active makeAdoptionOffer() in moonCatRescue contract. * Emits a {Transfer} and {MoonCatAcclimated} event. * @param _rescueOrder the minting order of the MoonCat to wrap * @return the ID (rescue order) of the minted token */ function buyAndWrap(uint256 _rescueOrder) public payable returns (uint256) { bytes5 catId = MCR.rescueOrder(_rescueOrder); (bool exists, , , , address onlyOfferTo) = MCR.adoptionOffers(catId); require( onlyOfferTo == address(0) && exists, "That MoonCat is not for sale" ); MCR.acceptAdoptionOffer{value: msg.value}(catId); return _wrap(_msgSender(), _rescueOrder); } /** * @dev returns tokenId of burned unwrapped MoonCat * * Requirements: * * - msgSender() must be owner. * Emits a {Transfer} and {MoonCatDeacclimated} event. * @param _tokenId the minting order of the MoonCat to unwrap * @return the ID (rescue order) of the burned token */ function unwrap(uint256 _tokenId) public returns (uint256) { require(ownerOf(_tokenId) == _msgSender(), "Not your MoonCat!"); require( super._exists(_tokenId), "That MoonCat is not wrapped in this contract" ); bytes5 catId = MCR.rescueOrder(_tokenId); MCR.giveCat(catId, ownerOf(_tokenId)); _burn(_tokenId); emit MoonCatDeacclimated(_tokenId, _msgSender()); return _tokenId; } /** * @dev wraps MoonCat that was safeTransferFrom() the old MoonCat wrapper directly in one transaction * * Requirements: * - Owner of old wrapped MoonCat must include the rescueOrder in the calldata as a bytes32 * Emits a {Transfer} and {MoonCatAcclimated} event. * @param _to the address that is to be the owner of the newly-wrapped token * @param _oldTokenID the ID of the token in the other wrapping contract * @param _rescueOrder the minting order of the MoonCat being wrapped * @return the ID (rescue order) of the minted token */ function _wrapOnSafeTransferFromReceipt( address _to, uint256 _oldTokenID, uint256 _rescueOrder ) internal returns (uint256) { if ( MCR.rescueOrder(_rescueOrder) != OLD_MCRW._tokenIDToCatID(_oldTokenID) ) { // Look up rescue order in Lookup contract require( rescueOrderLookup.oldTokenIdExists(_oldTokenID), "Unable to determine proper rescueOrder for this old token ID" ); _rescueOrder = rescueOrderLookup.oldTokenIdToRescueOrder( _oldTokenID ); require( MCR.rescueOrder(_rescueOrder) == OLD_MCRW._tokenIDToCatID(_oldTokenID), "_oldTokenID and _rescueOrder do not match same catID" ); } OLD_MCRW.unwrap(_oldTokenID); return _wrap(_to, _rescueOrder); } /** * @dev wraps an unwrapped MoonCat * * notes: * Emits a {Transfer} and {MoonCatAcclimated} event. * @param _owner the address that should be the new owner of the newly-created token * @param _tokenId the ID of the token to create (rescue order of the MoonCat) * @return the ID (rescue order) of the minted token */ function _wrap(address _owner, uint256 _tokenId) internal returns (uint256) { require(!paused(), "Attempted wrap while paused"); _mint(_owner, _tokenId); emit MoonCatAcclimated(_tokenId, _msgSender()); return _tokenId; } /** * @dev Always returns `IERC721Receiver.onERC721Received.selector` * * This function handles both automatic rewrapping of old-wrapped MoonCats, and assigning ERC721 tokens as "child assets" * of MoonCats already wrapped with this contract. * * If the incoming token is an old-wrapped Mooncat, the `_data` variable is structured as * the first 32 bytes are the rescue order of the transferred MoonCat, subsequent 20 bytes * are the new owner's address. If the rescue order is not supplied, the `_oldTokenId` is * looked up in the {MoonCatOrderLookup} contract. If a new owner's address is not * supplied, the new owner will be assigned as the `_from` sender. * Emits a {Transfer} and {MoonCatAcclimated} event. * * If the incoming token is any other type of ERC721, the `_data` variable is structured as * the first 32 bytes are the token ID (rescue order) of the MoonCat that is to receive that assest. * Emits a {ReceivedChild} event. * * @param _operator the _msgSender of the transaction * @param _from the address of the former owner of the incoming token * @param _oldTokenId the ID of the incoming token * @param _data additional metdata */ function onERC721Received( address _operator, address _from, uint256 _oldTokenId, bytes calldata _data ) public override(ERC721Holder, IERC998ERC721TopDown) returns (bytes4) { // Using msg.sender here instead of _operator because we want to know the most recent transaction source, // not the start of the chain if (msg.sender == address(0x7C40c393DC0f283F318791d746d894DdD3693572)) { // This is a Wrapped MoonCat incoming. Don't make it a child, instead unwrap and re-wrap it // Who should own this MoonCat after wrapping? address _to = (_data.length >= 32 + 20 && bytesToAddress(_data, 32) != address(0)) ? bytesToAddress(_data, 32) : _from; require( _to != address(0) && _to != address(this), "Invalid destination owner specified" ); _wrapOnSafeTransferFromReceipt( _to, _oldTokenId, (_data.length >= 32) ? toUint256(_data, 0) : 0 ); return ERC721Holder.onERC721Received(_operator, _from, _oldTokenId, _data); } // Otherwise, handle as ERC998 Child incoming require(_data.length > 0, "_data must contain the uint256 tokenId to transfer the child token to"); // convert up to 32 bytes of_data to uint256, owner NFT tokenId passed as uint in bytes uint256 tokenId; assembly {tokenId := calldataload(164)} if (_data.length < 32) { tokenId = tokenId >> 256 - _data.length * 8; } _receiveChild(_from, tokenId, msg.sender, _oldTokenId); require(ERC721(msg.sender).ownerOf(_oldTokenId) != address(0), "Child token not owned"); return ERC721Holder.onERC721Received(_operator, _from, _oldTokenId, _data); } /** * @dev sets the base URI * * notes: * - only callable by the contract owner */ function setBaseURI(string memory _newBaseURI) public onlyOwner { _setBaseURI(_newBaseURI); } /** * @dev See {IERC721-balanceOf}. * This contract returns the locally-wrapped token count as well as old-wrapped MoonCats * that are mapped in the {MoonCatOrderLookup} contract. */ function balanceOf(address _owner) public view override returns (uint256) { return super.balanceOf(_owner) + rescueOrderLookup.entriesPerAddress(_owner); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. * This contract enumerates the locally-wrapped token count as well as old-wrapped MoonCats * that are mapped in the {MoonCatOrderLookup} contract. */ function tokenOfOwnerByIndex(address _owner, uint256 _index) public view override returns (uint256) { uint256 localBalance = super.balanceOf(_owner); if (_index < localBalance) { // This index is in the range of tokens owned by that address here in this contract return super.tokenOfOwnerByIndex(_owner, _index); } // Looking to enumerate a token that's mapped to the old wrapping contract uint16 countFound = 0; for (uint256 i = 0; i < OLD_MCRW.balanceOf(_owner); i++) { uint256 oldTokenId = OLD_MCRW.tokenOfOwnerByIndex(_owner, i); if (rescueOrderLookup.oldTokenIdExists(oldTokenId)) { countFound++; if (countFound == _index - localBalance + 1) { return rescueOrderLookup.oldTokenIdToRescueOrder(oldTokenId); } } } revert("Cannot find token ID for that index"); } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 _tokenId) public view override returns (address) { if (super._exists(_tokenId)) { return super.ownerOf(_tokenId); } // Check other wrapper // First see if we're dealing with the MoonCat that was the zeroth-wrapped MoonCat in other wrapper bytes5 thisMoonCatID = MCR.rescueOrder(_tokenId); if (thisMoonCatID == OLD_MCRW._tokenIDToCatID(0)) { return OLD_MCRW.ownerOf(0); } uint256 otherID = OLD_MCRW._catIDToTokenID(thisMoonCatID); // We're not dealing with the zeroth-wrapped MoonCat, so a zero here is an indication they don't exist require(otherID > 0, "That MoonCat is not wrapped"); return OLD_MCRW.ownerOf(otherID); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address _owner, address _operator) public view virtual override returns (bool) { return rescueOrderLookup.entriesPerAddress(_owner) == 0 ? super.isApprovedForAll(_owner, _operator) : super.isApprovedForAll(_owner, _operator) && OLD_MCRW.isApprovedForAll(_owner, address(this)); } /** * @dev See {ERC721-_isApprovedOrOwner}. */ function _isApprovedOrOwner(address _spender, uint256 _tokenId) internal view override returns (bool) { require( _exists(_tokenId), "ERC721: operator query for nonexistent token" ); // Differs here from OpenZeppelin standard: // Calls `ownerOf` instead of `ERC721.ownerOf` address _owner = ownerOf(_tokenId); return (_spender == _owner || getApproved(_tokenId) == _spender || ERC721.isApprovedForAll(_owner, _spender)); } /** * @dev See {ERC721-approve}. */ function approve(address _to, uint256 _tokenId) public override { address _owner = ownerOf(_tokenId); require(_to != _owner, "ERC721: approval to current owner"); // Differs here from OpenZeppelin standard: // Calls `isApprovedForAll` instead of `ERC721.isApprovedForAll` require( _msgSender() == _owner || isApprovedForAll(_owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _approve(_to, _tokenId); } /** * @dev rewrap several MoonCats from the old wrapper at once * Owner needs to call setApprovalForAll in old wrapper first. * @param _rescueOrders an array of MoonCats, identified by rescue order, to rewrap * @param _oldTokenIds an array holding the corresponding token ID * in the old wrapper for each MoonCat to be rewrapped */ function batchReWrap( uint256[] memory _rescueOrders, uint256[] memory _oldTokenIds ) public { for (uint16 i = 0; i < _rescueOrders.length; i++) { address _owner = OLD_MCRW.ownerOf(_oldTokenIds[i]); OLD_MCRW.safeTransferFrom( _owner, address(this), _oldTokenIds[i], abi.encodePacked( uintToBytes(_rescueOrders[i]), addressToBytes(_owner) ) ); } } /** * @dev Take a list of unwrapped MoonCat rescue orders and wrap them. * @param _rescueOrders an array of MoonCats, identified by rescue order, to rewrap */ function batchWrap(uint256[] memory _rescueOrders) public { for (uint16 i = 0; i < _rescueOrders.length; i++) { wrap(_rescueOrders[i]); } } /** * @dev Take a list of MoonCats wrapped in this contract and unwrap them. * @param _rescueOrders an array of MoonCats, identified by rescue order, to unwrap */ function batchUnwrap(uint256[] memory _rescueOrders) public { for (uint16 i = 0; i < _rescueOrders.length; i++) { unwrap(_rescueOrders[i]); } } /** * @dev See {ERC721-_transfer}. * If the token being transferred exists in this contract, the standard ERC721 logic is used. * If the token does not exist in this contract, look it up in the old wrapping contract, * and attempt to wrap-then-transfer it. */ function _transfer( address _from, address _to, uint256 _tokenId ) internal override { if (super._exists(_tokenId)) { return super._transfer(_from, _to, _tokenId); } require(_to != address(0), "ERC721: transfer to the zero address"); if (_to == address(this)) { // Sending the token to be owned by this contract? That's not what they meant; make it owned by the original owner after re-wrapping _to = _from; } uint256 oldTokenId = OLD_MCRW._catIDToTokenID(MCR.rescueOrder(_tokenId)); OLD_MCRW.safeTransferFrom( _from, address(this), oldTokenId, abi.encodePacked(uintToBytes(_tokenId), addressToBytes(_to)) ); rescueOrderLookup.removeEntry(oldTokenId); } /** * @dev See {ERC721-_exists}. * If the token being queried exists in this contract, the standard ERC721 logic is used. * If the token does not exist in this contract, look it up in the old wrapping contract, * and see if it exists there. */ function _exists(uint256 _tokenId) internal view override returns (bool) { if (super._exists(_tokenId)) { return true; } // Check if exists in old wrapping contract bytes5 realMoonCatZero = OLD_MCRW._tokenIDToCatID(0); bytes5 thisMoonCatID = MCR.rescueOrder(_tokenId); if (thisMoonCatID == realMoonCatZero) { return true; } return OLD_MCRW._catIDToTokenID(thisMoonCatID) != 0; } ///// ERC998 ///// using EnumerableSet for EnumerableSet.UintSet; using EnumerableSet for EnumerableSet.AddressSet; /// @dev mapping of local token IDs, and which addresses they own children at. /// tokenId => child contract mapping(uint256 => EnumerableSet.AddressSet) private childContracts; /// @dev mapping of local token IDs, addresses they own children at, and IDs of the specific child tokens /// tokenId => (child address => array of child tokens) mapping(uint256 => mapping(address => EnumerableSet.UintSet)) private childTokens; /// @dev mapping of addresses of child tokens, the specific child token IDs, and which local token owns them /// child address => childId => tokenId mapping(address => mapping(uint256 => uint256)) internal childTokenOwner; uint8 constant TOKEN_OWNER_OFFSET = 10; /** * @dev a token has been transferred to this contract mark which local token is to now own it * Emits a {ReceivedChild} event. * * @param _from the address who sent the token to this contract * @param _tokenId the local token ID that is to be the parent * @param _childContract the address of the child token's contract * @param _childTokenId the ID value of teh incoming child token */ function _receiveChild(address _from, uint256 _tokenId, address _childContract, uint256 _childTokenId) private { require(!paused(), "Child received while paused"); require(super._exists(_tokenId), "That MoonCat is not wrapped in this contract"); require(childTokens[_tokenId][_childContract].contains(_childTokenId) == false, "Cannot receive child token because it has already been received"); childContracts[_tokenId].add(_childContract); childTokens[_tokenId][_childContract].add(_childTokenId); childTokenOwner[_childContract][_childTokenId] = _tokenId + TOKEN_OWNER_OFFSET; emit ReceivedChild(_from, _tokenId, _childContract, _childTokenId); } /** * @dev See {IERC998ERC721TopDown-getChild}. */ function getChild( address _from, uint256 _tokenId, address _childContract, uint256 _childTokenId ) public override { _receiveChild(_from, _tokenId, _childContract, _childTokenId); IERC721(_childContract).transferFrom(_from, address(this), _childTokenId); } /** * @dev Given a child address/ID that is owned by some token in this contract, return that owning token's owner * @param _childContract the address of the child asset being queried * @param _childTokenId the specific ID of the child asset being queried * @return parentTokenOwner the address of the owner of that child's parent asset * @return parentTokenId the local token ID that is the parent of that child asset */ function _ownerOfChild(address _childContract, uint256 _childTokenId) internal view returns (address parentTokenOwner, uint256 parentTokenId) { parentTokenId = childTokenOwner[_childContract][_childTokenId]; require(parentTokenId > 0, "That child is not owned by a token in this contract"); return (ownerOf(parentTokenId - TOKEN_OWNER_OFFSET), parentTokenId - TOKEN_OWNER_OFFSET); } /** * @dev See {IERC998ERC721TopDown-ownerOfChild}. */ function ownerOfChild(address _childContract, uint256 _childTokenId) public override view returns (bytes32 parentTokenOwner, uint256 parentTokenId) { parentTokenId = childTokenOwner[_childContract][_childTokenId]; require(parentTokenId > 0, "That child is not owned by a token in this contract"); return (ERC998_MAGIC_VALUE << 224 | bytes32(uint256(ownerOf(parentTokenId - TOKEN_OWNER_OFFSET))), parentTokenId - TOKEN_OWNER_OFFSET); } /** * @dev See {IERC998ERC721TopDown-rootOwnerOf}. */ function rootOwnerOf(uint256 _tokenId) public override view returns (bytes32 rootOwner) { return rootOwnerOfChild(address(0), _tokenId); } /** * @dev See {IERC998ERC721TopDown-rootOwnerOfChild}. */ function rootOwnerOfChild(address _childContract, uint256 _childTokenId) public override view returns (bytes32 rootOwner) { address rootOwnerAddress; if (_childContract != address(0)) { (rootOwnerAddress, _childTokenId) = _ownerOfChild(_childContract, _childTokenId); } else { rootOwnerAddress = ownerOf(_childTokenId); } // Case 1: Token owner is this contract and token. while (rootOwnerAddress == address(this)) { (rootOwnerAddress, _childTokenId) = _ownerOfChild(rootOwnerAddress, _childTokenId); } (bool callSuccess, bytes memory data) = rootOwnerAddress.staticcall(abi.encodeWithSelector(0xed81cdda, address(this), _childTokenId)); if (data.length != 0) { rootOwner = abi.decode(data, (bytes32)); } if(callSuccess == true && rootOwner >> 224 == ERC998_MAGIC_VALUE) { // Case 2: Token owner is other top-down composable return rootOwner; } else { // Case 3: Token owner is other contract // Or // Case 4: Token owner is user return ERC998_MAGIC_VALUE << 224 | bytes32(uint256(rootOwnerAddress)); } } /** * @dev remove internal records linking a given child to a given parent * @param _tokenId the local token ID that is the parent of the child asset * @param _childContract the address of the child asset to remove * @param _childTokenId the specific ID representing the child asset to be removed */ function _removeChild(uint256 _tokenId, address _childContract, uint256 _childTokenId) private { require( childTokens[_tokenId][_childContract].contains(_childTokenId), "Child token not owned by token" ); // remove child token childTokens[_tokenId][_childContract].remove(_childTokenId); delete childTokenOwner[_childContract][_childTokenId]; // remove contract if (childTokens[_tokenId][_childContract].length() == 0) { childContracts[_tokenId].remove(_childContract); } } /** * @dev check permissions are correct for a transfer of a child asset * @param _fromTokenId the local ID of the token that is the parent * @param _to the address this child token is being transferred to * @param _childContract the address of the child asset's contract * @param _childTokenId the specific ID for the child asset being transferred */ function _checkTransferChild( uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId ) private view { require(!paused(), "Child transfer while paused"); uint256 tokenId = childTokenOwner[_childContract][_childTokenId]; require(tokenId > 0, "Child asset is not owned by a token in this contract"); tokenId -= TOKEN_OWNER_OFFSET; require(tokenId == _fromTokenId, "That MoonCat does not own that asset"); require(_to != address(0), "Transfer to zero address"); address rootOwner = address(uint160(uint256(rootOwnerOf(_fromTokenId)))); require( _msgSender() == rootOwner || getApproved(_fromTokenId) == _msgSender() || ERC721.isApprovedForAll(rootOwner, _msgSender()), "Not allowed to transfer child assets of that MoonCat" ); } /** * @dev See {IERC998ERC721TopDown-safeTransferChild}. */ function safeTransferChild( uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId ) public override { _checkTransferChild(_fromTokenId, _to, _childContract, _childTokenId); _removeChild(_fromTokenId, _childContract, _childTokenId); ERC721(_childContract).safeTransferFrom(address(this), _to, _childTokenId); emit TransferChild(_fromTokenId, _to, _childContract, _childTokenId); } /** * @dev See {IERC998ERC721TopDown-safeTransferChild}. */ function safeTransferChild( uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId, bytes calldata _data ) public override { _checkTransferChild(_fromTokenId, _to, _childContract, _childTokenId); _removeChild(_fromTokenId, _childContract, _childTokenId); ERC721(_childContract).safeTransferFrom(address(this), _to, _childTokenId, _data); emit TransferChild(_fromTokenId, _to, _childContract, _childTokenId); } /** * @dev See {IERC998ERC721TopDown-transferChild}. */ function transferChild( uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId ) public override { _checkTransferChild(_fromTokenId, _to, _childContract, _childTokenId); _removeChild(_fromTokenId, _childContract, _childTokenId); //this is here to be compatible with cryptokitties and other old contracts that require being owner and approved // before transferring. //does not work with current standard which does not allow approving self, so we must let it fail in that case. //0x095ea7b3 == "approve(address,uint256)" (bool success, bytes memory data) = _childContract.call(abi.encodeWithSelector(0x095ea7b3, this, _childTokenId)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'Failed to Approve' ); ERC721(_childContract).transferFrom(address(this), _to, _childTokenId); emit TransferChild(_fromTokenId, _to, _childContract, _childTokenId); } /** * @dev See {IERC998ERC721TopDown-transferChildToParent}. */ function transferChildToParent( uint256 _fromTokenId, address _toContract, uint256 _toTokenId, address _childContract, uint256 _childTokenId, bytes calldata _data ) public override { _checkTransferChild(_fromTokenId, _toContract, _childContract, _childTokenId); _removeChild(_fromTokenId, _childContract, _childTokenId); IERC998ERC721BottomUp(_childContract).transferToParent(address(this), _toContract, _toTokenId, _childTokenId, _data); emit TransferChild(_fromTokenId, _toContract, _childContract, _childTokenId); } ///// ERC998 Enumerable /** * @dev See {IERC998ERC721TopDownEnumerable-totalChildContracts}. */ function totalChildContracts(uint256 _tokenId) external override view returns (uint256) { return childContracts[_tokenId].length(); } /** * @dev See {IERC998ERC721TopDownEnumerable-childContractByIndex}. */ function childContractByIndex(uint256 _tokenId, uint256 _index) external override view returns (address childContract) { return childContracts[_tokenId].at(_index); } /** * @dev See {IERC998ERC721TopDownEnumerable-totalChildTokens}. */ function totalChildTokens(uint256 _tokenId, address _childContract) external override view returns (uint256) { return childTokens[_tokenId][_childContract].length(); } /** * @dev See {IERC998ERC721TopDownEnumerable-childTokenByIndex}. */ function childTokenByIndex(uint256 _tokenId, address _childContract, uint256 _index) external override view returns (uint256 childTokenId) { return childTokens[_tokenId][_childContract].at(_index); } } // UTILITIES /** * @dev converts bytes (which is at least 32 bytes long) to uint256 */ function toUint256(bytes memory _bytes, uint256 _start) pure returns (uint256) { require(_start + 32 >= _start, "toUint256_overflow"); require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } /** * @dev converts uint256 to a bytes(32) object */ function uintToBytes(uint256 x) pure returns (bytes memory b) { b = new bytes(32); assembly { mstore(add(b, 32), x) } } /** * @dev converts bytes (which is at least 20 bytes long) to address */ function bytesToAddress(bytes memory bys, uint256 _start) pure returns (address addr) { assembly { addr := mload(add(add(bys, 20), _start)) } } /** * @dev converts address to a bytes(32) object */ function addressToBytes(address a) pure returns (bytes memory) { return abi.encodePacked(a); } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "@openzeppelin/contracts/introspection/ERC165.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/EnumerableSet.sol"; import "@openzeppelin/contracts/utils/EnumerableMap.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; /** * @title ERC721 Non-Fungible Token Standard basic implementation * @dev see https://eips.ethereum.org/EIPS/eip-721 */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable { using SafeMath for uint256; using Address for address; using EnumerableSet for EnumerableSet.UintSet; using EnumerableMap for EnumerableMap.UintToAddressMap; using Strings for uint256; // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; // Mapping from holder address to their (enumerable) set of owned tokens mapping (address => EnumerableSet.UintSet) private _holderTokens; // Enumerable mapping from token ids to their owners EnumerableMap.UintToAddressMap private _tokenOwners; // Mapping from token ID to approved address mapping (uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping (address => mapping (address => bool)) private _operatorApprovals; // Token name string private _name; // Token symbol string private _symbol; // Optional mapping for token URIs mapping (uint256 => string) private _tokenURIs; // Base URI string private _baseURI; /* * bytes4(keccak256('balanceOf(address)')) == 0x70a08231 * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde * * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ * 0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd */ bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; /* * bytes4(keccak256('name()')) == 0x06fdde03 * bytes4(keccak256('symbol()')) == 0x95d89b41 * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd * * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f */ bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; /* * bytes4(keccak256('totalSupply()')) == 0x18160ddd * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 * * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 */ bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor (string memory name_, string memory symbol_) public { _name = name_; _symbol = symbol_; // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_INTERFACE_ID_ERC721); _registerInterface(_INTERFACE_ID_ERC721_METADATA); _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); return _holderTokens[owner].length(); } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token"); } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); string memory _tokenURI = _tokenURIs[tokenId]; string memory base = baseURI(); // If there is no base URI, return the token URI. if (bytes(base).length == 0) { return _tokenURI; } // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked). if (bytes(_tokenURI).length > 0) { return string(abi.encodePacked(base, _tokenURI)); } // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI. return string(abi.encodePacked(base, tokenId.toString())); } /** * @dev Returns the base URI set via {_setBaseURI}. This will be * automatically added as a prefix in {tokenURI} to each token's URI, or * to the token ID if no specific URI is set for that token ID. */ function baseURI() public view virtual returns (string memory) { return _baseURI; } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { return _holderTokens[owner].at(index); } /** * @dev Return an array of all tokens this * CUSTOM FUNCTION, NOT IN OPENZEPPELIN TEMPLATE */ function tokensIdsByOwner(address owner) public view returns (uint256[] memory) { uint256[] memory tokens = new uint256[](_holderTokens[owner].length()); for (uint i = 0; i < _holderTokens[owner].length(); i++) { tokens[i] = _holderTokens[owner].at(i); } return tokens; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds return _tokenOwners.length(); } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { (uint256 tokenId, ) = _tokenOwners.at(index); return tokenId; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { require(operator != _msgSender(), "ERC721: approve to caller"); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransfer(from, to, tokenId, _data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `_data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _tokenOwners.contains(tokenId); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ERC721.ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender)); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: d* * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual { _mint(to, tokenId); require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); // DIFFERENT FROM OPENZEPPELIN STANDARD // Calls `ERC721._exists` rather than `_exists` require(!ERC721._exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _holderTokens[to].add(tokenId); _tokenOwners.set(tokenId, to); emit Transfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); // internal owner _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); // Clear metadata (if any) if (bytes(_tokenURIs[tokenId]).length != 0) { delete _tokenURIs[tokenId]; } _holderTokens[owner].remove(tokenId); _tokenOwners.remove(tokenId); emit Transfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); // internal owner require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _holderTokens[from].remove(tokenId); _holderTokens[to].add(tokenId); _tokenOwners.set(tokenId, to); emit Transfer(from, to, tokenId); } /** * @dev Sets `_tokenURI` as the tokenURI of `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual { require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token"); _tokenURIs[tokenId] = _tokenURI; } /** * @dev Internal function to set the base URI for all token IDs. It is * automatically added as a prefix to the value returned in {tokenURI}, * or to the token ID if {tokenURI} is empty. */ function _setBaseURI(string memory baseURI_) internal virtual { _baseURI = baseURI_; } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) private returns (bool) { if (!to.isContract()) { return true; } bytes memory returndata = to.functionCall(abi.encodeWithSelector( IERC721Receiver(to).onERC721Received.selector, _msgSender(), from, tokenId, _data ), "ERC721: transfer to non ERC721Receiver implementer"); bytes4 retval = abi.decode(returndata, (bytes4)); return (retval == _ERC721_RECEIVED); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; // DIFFERENT FROM OPENZEPPELIN STANDARD // Calls `ownerOf` rather than `ERC721.ownerOf` emit Approval(ownerOf(tokenId), to, tokenId); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { } } // SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.7.3; import "@openzeppelin/contracts/access/Ownable.sol"; import "./IMoonCatRescue.sol"; import "./IMoonCatsWrapped.sol"; /** * @title MoonCat Order Lookup * @notice A space to have an on-chain record mapping token IDs for OLD_MCRW to their original "rescue order" IDs * @dev This contract exists because there is no MoonCat ID => Rescue ID function * on the original MoonCatRescue contract. The only way to tell a given MoonCat's * rescue order if you don't know it is to iterate through the whole `rescueOrder` * array. Looping through that whole array in a smart contract would be * prohibitively high gas-usage, and so this alternative is needed. */ contract MoonCatOrderLookup is Ownable { MoonCatRescue MCR = MoonCatRescue(0x60cd862c9C687A9dE49aecdC3A99b74A4fc54aB6); MoonCatsWrapped OLD_MCRW = MoonCatsWrapped(0x7C40c393DC0f283F318791d746d894DdD3693572); uint256[25600] private _oldTokenIdToRescueOrder; uint8 constant VALUE_OFFSET = 10; constructor() Ownable() {} /** * @dev Submit a batch of token IDs, and their associated rescue orders * This is the primary method for the utility of the contract. Anyone * can submit this pairing information (not just the owners of the token) * and the information can be submitted in batches. * * Submitting pairs of token IDs with their rescue orders is verified with * the original MoonCatRescue contract before recording. * * Within the private array holding this information, a VALUE_OFFSET is used * to differentiate between "not set" and "set to zero" (because Solidity * has no concept of "null" or "undefined"). Because the maximum value of the * rescue ordering can only be 25,600, we can safely shift the stored values * up, and not hit the uint256 limit. */ function submitRescueOrder( uint256[] memory oldTokenIds, uint16[] memory rescueOrders ) public { for (uint256 i = 0; i < oldTokenIds.length; i++) { require( MCR.rescueOrder(rescueOrders[i]) == OLD_MCRW._tokenIDToCatID(oldTokenIds[i]), "Pair does not match!" ); _oldTokenIdToRescueOrder[oldTokenIds[i]] = rescueOrders[i] + VALUE_OFFSET; } } /** * @dev verify a given old token ID is mapped yet or not * * This function can use just a zero-check because internally all values are * stored with a VALUE_OFFSET added onto them (e.g. storing an actual zero * is saved as 0 + VALUE_OFFSET = 10, internally), so anything set to an * actual zero means "unset". */ function _exists(uint256 oldTokenId) internal view returns (bool) { return _oldTokenIdToRescueOrder[oldTokenId] != 0; } /** * @dev public function to verify whether a given old token ID is mapped or not */ function oldTokenIdExists(uint256 oldTokenId) public view returns(bool) { return _exists(oldTokenId); } /** * @dev given an old token ID, return the rescue order of that MoonCat * * Throws an error if that particular token ID does not have a recorded * mapping to a rescue order. */ function oldTokenIdToRescueOrder(uint256 oldTokenId) public view returns(uint256) { require(_exists(oldTokenId), "That token ID is not mapped yet"); return _oldTokenIdToRescueOrder[oldTokenId] - VALUE_OFFSET; } /** * @dev remove a mapping from the data structure * * This allows reclaiming some gas, so as part of the re-wrapping process, * this gets called by the Acclimator contract, to recoup some gas for the * MoonCat owner. */ function removeEntry(uint256 _oldTokenId) public onlyOwner { delete _oldTokenIdToRescueOrder[_oldTokenId]; } /** * @dev for a given address, iterate through all the tokens they own in the * old wrapping contract, and for each of them, determine how many are mapped * in this lookup contract. * * This method is used by the Acclimator `balanceOf` and `tokenOfOwnerByIndex` * to be able to enumerate old-wrapped MoonCats as if they were already * re-wrapped in the Acclimator contract. */ function entriesPerAddress(address _owner) public view returns (uint256) { uint256 countMapped = 0; for (uint256 i = 0; i < OLD_MCRW.balanceOf(_owner); i++) { uint256 oldTokenId = OLD_MCRW.tokenOfOwnerByIndex(_owner, i); if (_exists(oldTokenId)) { countMapped++; } } return countMapped; } } pragma solidity ^0.7.3; /** * @title ERC998ERC721 Top-Down Composable Non-Fungible Token * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-998.md * Note: the ERC-165 identifier for this interface is 0x1efdf36a */ interface IERC998ERC721TopDown { /** * @dev This emits when a token receives a child token. * @param _from The prior owner of the token. * @param _toTokenId The token that receives the child token. */ event ReceivedChild( address indexed _from, uint256 indexed _toTokenId, address indexed _childContract, uint256 _childTokenId ); /** * @dev This emits when a child token is transferred from a token to an address. * @param _fromTokenId The parent token that the child token is being transferred from. * @param _to The new owner address of the child token. */ event TransferChild( uint256 indexed _fromTokenId, address indexed _to, address indexed _childContract, uint256 _childTokenId ); /** * @notice Get the root owner of tokenId. * @param _tokenId The token to query for a root owner address * @return rootOwner The root owner at the top of tree of tokens and ERC998 magic value. */ function rootOwnerOf(uint256 _tokenId) external view returns (bytes32 rootOwner); /** * @notice Get the root owner of a child token. * @param _childContract The contract address of the child token. * @param _childTokenId The tokenId of the child. * @return rootOwner The root owner at the top of tree of tokens and ERC998 magic value. */ function rootOwnerOfChild(address _childContract, uint256 _childTokenId) external view returns (bytes32 rootOwner); /** * @notice Get the parent tokenId of a child token. * @param _childContract The contract address of the child token. * @param _childTokenId The tokenId of the child. * @return parentTokenOwner The parent address of the parent token and ERC998 magic value * @return parentTokenId The parent tokenId of _tokenId */ function ownerOfChild(address _childContract, uint256 _childTokenId) external view returns (bytes32 parentTokenOwner, uint256 parentTokenId); /** * @notice A token receives a child token * @param _operator The address that caused the transfer. * @param _from The owner of the child token. * @param _childTokenId The token that is being transferred to the parent. * @param _data Up to the first 32 bytes contains an integer which is the receiving parent tokenId. */ function onERC721Received( address _operator, address _from, uint256 _childTokenId, bytes calldata _data ) external returns (bytes4); /** * @notice Transfer child token from top-down composable to address. * @param _fromTokenId The owning token to transfer from. * @param _to The address that receives the child token * @param _childContract The ERC721 contract of the child token. * @param _childTokenId The tokenId of the token that is being transferred. */ function transferChild( uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId ) external; /** * @notice Transfer child token from top-down composable to address. * @param _fromTokenId The owning token to transfer from. * @param _to The address that receives the child token * @param _childContract The ERC721 contract of the child token. * @param _childTokenId The tokenId of the token that is being transferred. */ function safeTransferChild( uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId ) external; /** * @notice Transfer child token from top-down composable to address. * @param _fromTokenId The owning token to transfer from. * @param _to The address that receives the child token * @param _childContract The ERC721 contract of the child token. * @param _childTokenId The tokenId of the token that is being transferred. * @param _data Additional data with no specified format */ function safeTransferChild( uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId, bytes calldata _data ) external; /** * @notice Transfer bottom-up composable child token from top-down composable to other ERC721 token. * @param _fromTokenId The owning token to transfer from. * @param _toContract The ERC721 contract of the receiving token * @param _toTokenId The receiving token * @param _childContract The bottom-up composable contract of the child token. * @param _childTokenId The token that is being transferred. * @param _data Additional data with no specified format */ function transferChildToParent( uint256 _fromTokenId, address _toContract, uint256 _toTokenId, address _childContract, uint256 _childTokenId, bytes calldata _data ) external; /** * @notice Get a child token from an ERC721 contract. * @param _from The address that owns the child token. * @param _tokenId The token that becomes the parent owner * @param _childContract The ERC721 contract of the child token * @param _childTokenId The tokenId of the child token */ function getChild( address _from, uint256 _tokenId, address _childContract, uint256 _childTokenId ) external; } /** * @dev The ERC-165 identifier for this interface is 0xa344afe4 */ interface IERC998ERC721TopDownEnumerable { /** * @notice Get the total number of child contracts with tokens that are owned by tokenId. * @param _tokenId The parent token of child tokens in child contracts * @return uint256 The total number of child contracts with tokens owned by tokenId. */ function totalChildContracts(uint256 _tokenId) external view returns (uint256); /** * @notice Get child contract by tokenId and index * @param _tokenId The parent token of child tokens in child contract * @param _index The index position of the child contract * @return childContract The contract found at the tokenId and index. */ function childContractByIndex(uint256 _tokenId, uint256 _index) external view returns (address childContract); /** * @notice Get the total number of child tokens owned by tokenId that exist in a child contract. * @param _tokenId The parent token of child tokens * @param _childContract The child contract containing the child tokens * @return uint256 The total number of child tokens found in child contract that are owned by tokenId. */ function totalChildTokens(uint256 _tokenId, address _childContract) external view returns (uint256); /** * @notice Get child token owned by tokenId, in child contract, at index position * @param _tokenId The parent token of the child token * @param _childContract The child contract of the child token * @param _index The index position of the child token. * @return childTokenId The child tokenId for the parent token, child token and index */ function childTokenByIndex( uint256 _tokenId, address _childContract, uint256 _index ) external view returns (uint256 childTokenId); } interface IERC998ERC721BottomUp { /** * @notice Transfer token from owner address to a token * @param _from The owner address * @param _toContract The ERC721 contract of the receiving token * @param _toTokenId The receiving token * @param _data Additional data with no specified format */ function transferToParent( address _from, address _toContract, uint256 _toTokenId, uint256 _tokenId, bytes calldata _data ) external; }pragma solidity ^0.7.3; interface MoonCatRescue { function getCatDetails(bytes5 catId) external view returns ( bytes5 id, address owner, bytes32 name, address onlyOfferTo, uint256 offerPrice, address requester, uint256 requestPrice ); function rescueOrder(uint256 _rescueOrder) external view returns (bytes5 catId); function acceptAdoptionOffer(bytes5 catId) external payable; function acceptAdoptionRequest(bytes5 catId) external; function adoptionRequests(bytes5 _catId) external view returns ( bool exists, bytes5 catId, address requester, uint256 price ); function adoptionOffers(bytes5 _catId) external view returns ( bool exists, bytes5 catId, address seller, uint256 price, address offerOnlyTo ); function giveCat(bytes5 catId, address to) external; function catOwners(bytes5) external view returns (address); function makeAdoptionOfferToAddress(bytes5 catId, uint256 price, address to) external; function makeAdoptionOffer(bytes5 catId, uint256 price) external; function withdraw() external; } pragma solidity ^0.7.3; interface MoonCatsWrapped { /** * @dev in the original contract, this is a public map property, so is * using the default getter action, which does NOT check for "exists"; * if this returns a zero, it might be referencing token ID #0, or it might * be meaning "that MoonCat ID is not wrapped in this contract". */ function _catIDToTokenID(bytes5 catId) external pure returns (uint256); /** * @dev in the original contract, this is a public map property, so is * using the default getter action, which does NOT check for "exists". * However, no MoonCat has an ID of `0x0000000000`, so if this returns * all zeroes, it means "that token ID does not exist in this contract". */ function _tokenIDToCatID(uint256 _tokenID) external pure returns (bytes5 catId); function safeTransferFrom(address from, address to, uint256 tokenId) external; function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) external; function balanceOf(address owner) external view returns (uint256 balance); function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); function wrap(bytes5 catId) external; function unwrap(uint256 tokenID) external; function ownerOf(uint256 tokenID) external view returns(address); function setApprovalForAll(address operator, bool _approved) external; function isApprovedForAll(address owner, address operator) external view returns (bool); function approve(address to, uint256 tokenId) external; }// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor () internal { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } } // SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; import "../../introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; } // SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; import "./IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); } // SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; import "./IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4); } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC721Receiver.sol"; /** * @dev Implementation of the {IERC721Receiver} interface. * * Accepts all token transfers. * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}. */ contract ERC721Holder is IERC721Receiver { /** * @dev See {IERC721Receiver-onERC721Received}. * * Always returns `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) { return this.onERC721Received.selector; } } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts may inherit from this and call {_registerInterface} to declare * their support of an interface. */ abstract contract ERC165 is IERC165 { /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Mapping of interface ids to whether or not it's supported. */ mapping(bytes4 => bool) private _supportedInterfaces; constructor () internal { // Derived contracts need only register support for their own interfaces, // we register support for ERC165 itself here _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev See {IERC165-supportsInterface}. * * Time complexity O(1), guaranteed to always use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev Registers the contract as an implementer of the interface defined by * `interfaceId`. Support of the actual ERC165 interface is automatic and * registering its interface id is not required. * * See {IERC165-supportsInterface}. * * Requirements: * * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). */ function _registerInterface(bytes4 interfaceId) internal virtual { require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); _supportedInterfaces[interfaceId] = true; } } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } } // SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { require(set._values.length > index, "EnumerableSet: index out of bounds"); return set._values[index]; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Library for managing an enumerable variant of Solidity's * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] * type. * * Maps have the following properties: * * - Entries are added, removed, and checked for existence in constant time * (O(1)). * - Entries are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableMap for EnumerableMap.UintToAddressMap; * * // Declare a set state variable * EnumerableMap.UintToAddressMap private myMap; * } * ``` * * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are * supported. */ library EnumerableMap { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Map type with // bytes32 keys and values. // The Map implementation uses private functions, and user-facing // implementations (such as Uint256ToAddressMap) are just wrappers around // the underlying Map. // This means that we can only create new EnumerableMaps for types that fit // in bytes32. struct MapEntry { bytes32 _key; bytes32 _value; } struct Map { // Storage of map keys and values MapEntry[] _entries; // Position of the entry defined by a key in the `entries` array, plus 1 // because index 0 means a key is not in the map. mapping (bytes32 => uint256) _indexes; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) { // We read and store the key's index to prevent multiple reads from the same storage slot uint256 keyIndex = map._indexes[key]; if (keyIndex == 0) { // Equivalent to !contains(map, key) map._entries.push(MapEntry({ _key: key, _value: value })); // The entry is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value map._indexes[key] = map._entries.length; return true; } else { map._entries[keyIndex - 1]._value = value; return false; } } /** * @dev Removes a key-value pair from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function _remove(Map storage map, bytes32 key) private returns (bool) { // We read and store the key's index to prevent multiple reads from the same storage slot uint256 keyIndex = map._indexes[key]; if (keyIndex != 0) { // Equivalent to contains(map, key) // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one // in the array, and then remove the last entry (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = keyIndex - 1; uint256 lastIndex = map._entries.length - 1; // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. MapEntry storage lastEntry = map._entries[lastIndex]; // Move the last entry to the index where the entry to delete is map._entries[toDeleteIndex] = lastEntry; // Update the index for the moved entry map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved entry was stored map._entries.pop(); // Delete the index for the deleted slot delete map._indexes[key]; return true; } else { return false; } } /** * @dev Returns true if the key is in the map. O(1). */ function _contains(Map storage map, bytes32 key) private view returns (bool) { return map._indexes[key] != 0; } /** * @dev Returns the number of key-value pairs in the map. O(1). */ function _length(Map storage map) private view returns (uint256) { return map._entries.length; } /** * @dev Returns the key-value pair stored at position `index` in the map. O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) { require(map._entries.length > index, "EnumerableMap: index out of bounds"); MapEntry storage entry = map._entries[index]; return (entry._key, entry._value); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) { uint256 keyIndex = map._indexes[key]; if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key) return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function _get(Map storage map, bytes32 key) private view returns (bytes32) { uint256 keyIndex = map._indexes[key]; require(keyIndex != 0, "EnumerableMap: nonexistent key"); // Equivalent to contains(map, key) return map._entries[keyIndex - 1]._value; // All indexes are 1-based } /** * @dev Same as {_get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {_tryGet}. */ function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) { uint256 keyIndex = map._indexes[key]; require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key) return map._entries[keyIndex - 1]._value; // All indexes are 1-based } // UintToAddressMap struct UintToAddressMap { Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { return _remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { return _contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToAddressMap storage map) internal view returns (uint256) { return _length(map._inner); } /** * @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { (bytes32 key, bytes32 value) = _at(map._inner, index); return (uint256(key), address(uint160(uint256(value)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. * * _Available since v3.4._ */ function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key)); return (success, address(uint160(uint256(value)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { return address(uint160(uint256(_get(map._inner, bytes32(key))))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) { return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage)))); } } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev String operations. */ library Strings { /** * @dev Converts a `uint256` to its ASCII `string` representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); uint256 index = digits - 1; temp = value; while (temp != 0) { buffer[index--] = bytes1(uint8(48 + temp % 10)); temp /= 10; } return string(buffer); } }