// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)pragmasolidity ^0.8.0;/**
* @dev Collection of functions related to the address type
*/libraryAddress{
/**
* @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
* ====
*/functionisContract(address account) internalviewreturns (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;
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].
*/functionsendValue(addresspayable recipient, uint256 amount) internal{
require(address(this).balance>= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/functionfunctionCall(address target, bytesmemory data) internalreturns (bytesmemory) {
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._
*/functionfunctionCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
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._
*/functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value
) internalreturns (bytesmemory) {
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._
*/functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value,
stringmemory errorMessage
) internalreturns (bytesmemory) {
require(address(this).balance>= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytesmemory 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._
*/functionfunctionStaticCall(address target, bytesmemory data) internalviewreturns (bytesmemory) {
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._
*/functionfunctionStaticCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalviewreturns (bytesmemory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytesmemory 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._
*/functionfunctionDelegateCall(address target, bytesmemory data) internalreturns (bytesmemory) {
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._
*/functionfunctionDelegateCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytesmemory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/functionverifyCallResult(bool success,
bytesmemory returndata,
stringmemory errorMessage
) internalpurereturns (bytesmemory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if presentif (returndata.length>0) {
// The easiest way to bubble the revert reason is using memory via assemblyassembly {
let returndata_size :=mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
Contract Source Code
File 2 of 17: Context.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^0.8.0;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 3 of 17: ERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)pragmasolidity ^0.8.0;import"./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/abstractcontractERC165isIERC165{
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
return interfaceId ==type(IERC165).interfaceId;
}
}
Contract Source Code
File 4 of 17: ERC721.sol
// SPDX-License-Identifier: MIT/// @title ERC721 Token Implementation/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 8888888888 888 .d88888b. .d88888b. 8888888b. *
* 888 888 d88P" "Y88b d88P" "Y88b 888 Y88b *
* 888 888 888 888 888 888 888 888 *
* 8888888 888 888 888 888 888 888 d88P *
* 888 888 888 888 888 888 8888888P" *
* 888 888 888 888 888 888 888 T88b *
* 888 888 Y88b. .d88P Y88b. .d88P 888 T88b *
* 888 88888888 "Y88888P" "Y88888P" 888 T88b *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */// LICENSE// ERC721.sol modifies OpenZeppelin's ERC721.sol:// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/6618f9f18424ade44116d0221719f4c93be6a078/contracts/token/ERC721/ERC721.sol//// ERC721.sol source code copyright OpenZeppelin licensed under the MIT License.// With modifications by MOCA.////// MODIFICATIONS:// `_safeMint` and `_mint` contain an additional `creator` argument and// emit two `Transfer` logs, rather than one. The first log displays the// transfer (mint) from `address(0)` to the `creator`. The second displays the// transfer from the `creator` to the `to` address. This enables correct// attribution on various NFT marketplaces.pragmasolidity ^0.8.6;import'@openzeppelin/contracts/token/ERC721/IERC721.sol';
import'@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol';
import'@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol';
import'@openzeppelin/contracts/utils/Address.sol';
import'@openzeppelin/contracts/utils/Context.sol';
import'@openzeppelin/contracts/utils/Strings.sol';
import'@openzeppelin/contracts/utils/introspection/ERC165.sol';
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/contractERC721isContext, ERC165, IERC721, IERC721Metadata{
usingAddressforaddress;
usingStringsforuint256;
// Token namestringprivate _name;
// Token symbolstringprivate _symbol;
// Mapping from token ID to owner addressmapping(uint256=>address) private _owners;
// Mapping owner address to token countmapping(address=>uint256) private _balances;
// Mapping from token ID to approved addressmapping(uint256=>address) private _tokenApprovals;
// Mapping from owner to operator approvalsmapping(address=>mapping(address=>bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/constructor(stringmemory name_, stringmemory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(ERC165, IERC165) returns (bool) {
return
interfaceId ==type(IERC721).interfaceId||
interfaceId ==type(IERC721Metadata).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/functionbalanceOf(address owner) publicviewvirtualoverridereturns (uint256) {
require(owner !=address(0), 'ERC721: balance query for the zero address');
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/functionownerOf(uint256 tokenId) publicviewvirtualoverridereturns (address) {
address owner = _owners[tokenId];
require(owner !=address(0), 'ERC721: owner query for nonexistent token');
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/functionname() publicviewvirtualoverridereturns (stringmemory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/functionsymbol() publicviewvirtualoverridereturns (stringmemory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/functiontokenURI(uint256 tokenId) publicviewvirtualoverridereturns (stringmemory) {
require(_exists(tokenId), 'ERC721Metadata: URI query for nonexistent token');
stringmemory baseURI = _baseURI();
returnbytes(baseURI).length>0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : '';
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/function_baseURI() internalviewvirtualreturns (stringmemory) {
return'';
}
/**
* @dev See {IERC721-approve}.
*/functionapprove(address to, uint256 tokenId) publicvirtualoverride{
address owner = ERC721.ownerOf(tokenId);
require(to != owner, 'ERC721: approval to current owner');
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
'ERC721: approve caller is not owner nor approved for all'
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/functiongetApproved(uint256 tokenId) publicviewvirtualoverridereturns (address) {
require(_exists(tokenId), 'ERC721: approved query for nonexistent token');
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/functionsetApprovalForAll(address operator, bool approved) publicvirtualoverride{
require(operator != _msgSender(), 'ERC721: approve to caller');
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/functionisApprovedForAll(address owner, address operator) publicviewvirtualoverridereturns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/functiontransferFrom(addressfrom,
address to,
uint256 tokenId
) publicvirtualoverride{
//solhint-disable-next-line max-line-lengthrequire(_isApprovedOrOwner(_msgSender(), tokenId), 'ERC721: transfer caller is not owner nor approved');
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId
) publicvirtualoverride{
safeTransferFrom(from, to, tokenId, '');
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId,
bytesmemory _data
) publicvirtualoverride{
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(addressfrom,
address to,
uint256 tokenId,
bytesmemory _data
) internalvirtual{
_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) internalviewvirtualreturns (bool) {
return _owners[tokenId] !=address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/function_isApprovedOrOwner(address spender, uint256 tokenId) internalviewvirtualreturns (bool) {
require(_exists(tokenId), 'ERC721: operator query for nonexistent token');
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId`, transfers it to `to`, and emits two log events -
* 1. Credits the `minter` with the mint.
* 2. Shows transfer from the `minter` to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/function_safeMint(address creator,
address to,
uint256 tokenId
) internalvirtual{
_safeMint(creator, 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 creator,
address to,
uint256 tokenId,
bytesmemory _data
) internalvirtual{
_mint(creator, to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
'ERC721: transfer to non ERC721Receiver implementer'
);
}
/**
* @dev Mints `tokenId`, transfers it to `to`, and emits two log events -
* 1. Credits the `creator` with the mint.
* 2. Shows transfer from the `creator` 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 creator,
address to,
uint256 tokenId
) internalvirtual{
require(to !=address(0), 'ERC721: mint to the zero address');
require(!_exists(tokenId), 'ERC721: token already minted');
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] +=1;
_owners[tokenId] = to;
emit Transfer(address(0), creator, tokenId);
emit Transfer(creator, 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) internalvirtual{
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -=1;
delete _owners[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(addressfrom,
address to,
uint256 tokenId
) internalvirtual{
require(ERC721.ownerOf(tokenId) ==from, 'ERC721: transfer of token that is not own');
require(to !=address(0), 'ERC721: transfer to the zero address');
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -=1;
_balances[to] +=1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/function_approve(address to, uint256 tokenId) internalvirtual{
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @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(addressfrom,
address to,
uint256 tokenId,
bytesmemory _data
) privatereturns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver(to).onERC721Received.selector;
} catch (bytesmemory reason) {
if (reason.length==0) {
revert('ERC721: transfer to non ERC721Receiver implementer');
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
returntrue;
}
}
/**
* @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` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/function_beforeTokenTransfer(addressfrom,
address to,
uint256 tokenId
) internalvirtual{}
}
Contract Source Code
File 5 of 17: ERC721Checkpointable.sol
// SPDX-License-Identifier: BSD-3-Clause/// @title Vote checkpointing for an ERC-721 token/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 8888888888 888 .d88888b. .d88888b. 8888888b. *
* 888 888 d88P" "Y88b d88P" "Y88b 888 Y88b *
* 888 888 888 888 888 888 888 888 *
* 8888888 888 888 888 888 888 888 d88P *
* 888 888 888 888 888 888 8888888P" *
* 888 888 888 888 888 888 888 T88b *
* 888 888 Y88b. .d88P Y88b. .d88P 888 T88b *
* 888 88888888 "Y88888P" "Y88888P" 888 T88b *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */// LICENSE// ERC721Checkpointable.sol uses and modifies part of Compound Lab's Comp.sol:// https://github.com/compound-finance/compound-protocol/blob/ae4388e780a8d596d97619d9704a931a2752c2bc/contracts/Governance/Comp.sol//// Comp.sol source code Copyright 2020 Compound Labs, Inc. licensed under the BSD-3-Clause license.// With modifications by MOCA.//// Additional conditions of BSD-3-Clause can be found here: https://opensource.org/licenses/BSD-3-Clause//// MODIFICATIONS// Checkpointing logic from Comp.sol has been used with the following modifications:// - `delegates` is renamed to `_delegates` and is set to private// - `delegates` is a public function that uses the `_delegates` mapping look-up, but unlike// Comp.sol, returns the delegator's own address if there is no delegate.// This avoids the delegator needing to "delegate to self" with an additional transaction// - `_transferTokens()` is renamed `_beforeTokenTransfer()` and adapted to hook into OpenZeppelin's ERC721 hooks.pragmasolidity ^0.8.6;import'./ERC721Enumerable.sol';
abstractcontractERC721CheckpointableisERC721Enumerable{
/// @notice Defines decimals as per ERC-20 convention to make integrations with 3rd party governance platforms easieruint8publicconstant decimals =0;
/// @notice A record of each accounts delegatemapping(address=>address) private _delegates;
/// @notice A checkpoint for marking number of votes from a given blockstructCheckpoint {
uint32 fromBlock;
uint96 votes;
}
/// @notice A record of votes checkpoints for each account, by indexmapping(address=>mapping(uint32=> Checkpoint)) public checkpoints;
/// @notice The number of checkpoints for each accountmapping(address=>uint32) public numCheckpoints;
/// @notice The EIP-712 typehash for the contract's domainbytes32publicconstant DOMAIN_TYPEHASH =keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)');
/// @notice The EIP-712 typehash for the delegation struct used by the contractbytes32publicconstant DELEGATION_TYPEHASH =keccak256('Delegation(address delegatee,uint256 nonce,uint256 expiry)');
/// @notice A record of states for signing / validating signaturesmapping(address=>uint256) public nonces;
/// @notice An event thats emitted when an account changes its delegateeventDelegateChanged(addressindexed delegator, addressindexed fromDelegate, addressindexed toDelegate);
/// @notice An event thats emitted when a delegate account's vote balance changeseventDelegateVotesChanged(addressindexed delegate, uint256 previousBalance, uint256 newBalance);
/**
* @notice The votes a delegator can delegate, which is the current balance of the delegator.
* @dev Used when calling `_delegate()`
*/functionvotesToDelegate(address delegator) publicviewreturns (uint96) {
return safe96(balanceOf(delegator), 'ERC721Checkpointable::votesToDelegate: amount exceeds 96 bits');
}
/**
* @notice Overrides the standard `Comp.sol` delegates mapping to return
* the delegator's own address if they haven't delegated.
* This avoids having to delegate to oneself.
*/functiondelegates(address delegator) publicviewreturns (address) {
address current = _delegates[delegator];
return current ==address(0) ? delegator : current;
}
/**
* @notice Adapted from `_transferTokens()` in `Comp.sol` to update delegate votes.
* @dev hooks into OpenZeppelin's `ERC721._transfer`
*/function_beforeTokenTransfer(addressfrom,
address to,
uint256 tokenId
) internaloverride{
super._beforeTokenTransfer(from, to, tokenId);
/// @notice Differs from `_transferTokens()` to use `delegates` override method to simulate auto-delegation
_moveDelegates(delegates(from), delegates(to), 1);
}
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
*/functiondelegate(address delegatee) public{
if (delegatee ==address(0)) delegatee =msg.sender;
return _delegate(msg.sender, delegatee);
}
/**
* @notice Delegates votes from signatory to `delegatee`
* @param delegatee The address to delegate votes to
* @param nonce The contract state required to match the signature
* @param expiry The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/functiondelegateBySig(address delegatee,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) public{
bytes32 domainSeparator =keccak256(
abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name())), getChainId(), address(this))
);
bytes32 structHash =keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));
bytes32 digest =keccak256(abi.encodePacked('\x19\x01', domainSeparator, structHash));
address signatory =ecrecover(digest, v, r, s);
require(signatory !=address(0), 'ERC721Checkpointable::delegateBySig: invalid signature');
require(nonce == nonces[signatory]++, 'ERC721Checkpointable::delegateBySig: invalid nonce');
require(block.timestamp<= expiry, 'ERC721Checkpointable::delegateBySig: signature expired');
return _delegate(signatory, delegatee);
}
/**
* @notice Gets the current votes balance for `account`
* @param account The address to get votes balance
* @return The number of current votes for `account`
*/functiongetCurrentVotes(address account) externalviewreturns (uint96) {
uint32 nCheckpoints = numCheckpoints[account];
return nCheckpoints >0 ? checkpoints[account][nCheckpoints -1].votes : 0;
}
/**
* @notice Determine the prior number of votes for an account as of a block number
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
* @param account The address of the account to check
* @param blockNumber The block number to get the vote balance at
* @return The number of votes the account had as of the given block
*/functiongetPriorVotes(address account, uint256 blockNumber) publicviewreturns (uint96) {
require(blockNumber <block.number, 'ERC721Checkpointable::getPriorVotes: not yet determined');
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints ==0) {
return0;
}
// First check most recent balanceif (checkpoints[account][nCheckpoints -1].fromBlock <= blockNumber) {
return checkpoints[account][nCheckpoints -1].votes;
}
// Next check implicit zero balanceif (checkpoints[account][0].fromBlock > blockNumber) {
return0;
}
uint32 lower =0;
uint32 upper = nCheckpoints -1;
while (upper > lower) {
uint32 center = upper - (upper - lower) /2; // ceil, avoiding overflow
Checkpoint memory cp = checkpoints[account][center];
if (cp.fromBlock == blockNumber) {
return cp.votes;
} elseif (cp.fromBlock < blockNumber) {
lower = center;
} else {
upper = center -1;
}
}
return checkpoints[account][lower].votes;
}
function_delegate(address delegator, address delegatee) internal{
/// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegationaddress currentDelegate = delegates(delegator);
_delegates[delegator] = delegatee;
emit DelegateChanged(delegator, currentDelegate, delegatee);
uint96 amount = votesToDelegate(delegator);
_moveDelegates(currentDelegate, delegatee, amount);
}
function_moveDelegates(address srcRep,
address dstRep,
uint96 amount
) internal{
if (srcRep != dstRep && amount >0) {
if (srcRep !=address(0)) {
uint32 srcRepNum = numCheckpoints[srcRep];
uint96 srcRepOld = srcRepNum >0 ? checkpoints[srcRep][srcRepNum -1].votes : 0;
uint96 srcRepNew = sub96(srcRepOld, amount, 'ERC721Checkpointable::_moveDelegates: amount underflows');
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
}
if (dstRep !=address(0)) {
uint32 dstRepNum = numCheckpoints[dstRep];
uint96 dstRepOld = dstRepNum >0 ? checkpoints[dstRep][dstRepNum -1].votes : 0;
uint96 dstRepNew = add96(dstRepOld, amount, 'ERC721Checkpointable::_moveDelegates: amount overflows');
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
}
}
}
function_writeCheckpoint(address delegatee,
uint32 nCheckpoints,
uint96 oldVotes,
uint96 newVotes
) internal{
uint32 blockNumber = safe32(
block.number,
'ERC721Checkpointable::_writeCheckpoint: block number exceeds 32 bits'
);
if (nCheckpoints >0&& checkpoints[delegatee][nCheckpoints -1].fromBlock == blockNumber) {
checkpoints[delegatee][nCheckpoints -1].votes = newVotes;
} else {
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
numCheckpoints[delegatee] = nCheckpoints +1;
}
emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
}
functionsafe32(uint256 n, stringmemory errorMessage) internalpurereturns (uint32) {
require(n <2**32, errorMessage);
returnuint32(n);
}
functionsafe96(uint256 n, stringmemory errorMessage) internalpurereturns (uint96) {
require(n <2**96, errorMessage);
returnuint96(n);
}
functionadd96(uint96 a,
uint96 b,
stringmemory errorMessage
) internalpurereturns (uint96) {
uint96 c = a + b;
require(c >= a, errorMessage);
return c;
}
functionsub96(uint96 a,
uint96 b,
stringmemory errorMessage
) internalpurereturns (uint96) {
require(b <= a, errorMessage);
return a - b;
}
functiongetChainId() internalviewreturns (uint256) {
uint256 chainId;
assembly {
chainId :=chainid()
}
return chainId;
}
}
Contract Source Code
File 6 of 17: ERC721Enumerable.sol
// SPDX-License-Identifier: MIT/// @title ERC721 Enumerable Extension/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 8888888888 888 .d88888b. .d88888b. 8888888b. *
* 888 888 d88P" "Y88b d88P" "Y88b 888 Y88b *
* 888 888 888 888 888 888 888 888 *
* 8888888 888 888 888 888 888 888 d88P *
* 888 888 888 888 888 888 8888888P" *
* 888 888 888 888 888 888 888 T88b *
* 888 888 Y88b. .d88P Y88b. .d88P 888 T88b *
* 888 88888888 "Y88888P" "Y88888P" 888 T88b *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */// LICENSE// ERC721.sol modifies OpenZeppelin's ERC721Enumerable.sol:// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/6618f9f18424ade44116d0221719f4c93be6a078/contracts/token/ERC721/extensions/ERC721Enumerable.sol//// ERC721Enumerable.sol source code copyright OpenZeppelin licensed under the MIT License.// With modifications by MOCA.//// MODIFICATIONS:// Consumes modified `ERC721` contract. See notes in `ERC721.sol`.pragmasolidity ^0.8.0;import'./ERC721.sol';
import'@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol';
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds
* enumerability of all the token ids in the contract as well as all token ids owned by each
* account.
*/abstractcontractERC721EnumerableisERC721, IERC721Enumerable{
// Mapping from owner to list of owned token IDsmapping(address=>mapping(uint256=>uint256)) private _ownedTokens;
// Mapping from token ID to index of the owner tokens listmapping(uint256=>uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumerationuint256[] private _allTokens;
// Mapping from token id to position in the allTokens arraymapping(uint256=>uint256) private _allTokensIndex;
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(IERC165, ERC721) returns (bool) {
return interfaceId ==type(IERC721Enumerable).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/functiontokenOfOwnerByIndex(address owner, uint256 index) publicviewvirtualoverridereturns (uint256) {
require(index < ERC721.balanceOf(owner), 'ERC721Enumerable: owner index out of bounds');
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/functiontotalSupply() publicviewvirtualoverridereturns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/functiontokenByIndex(uint256 index) publicviewvirtualoverridereturns (uint256) {
require(index < ERC721Enumerable.totalSupply(), 'ERC721Enumerable: global index out of bounds');
return _allTokens[index];
}
/**
* @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(addressfrom,
address to,
uint256 tokenId
) internalvirtualoverride{
super._beforeTokenTransfer(from, to, tokenId);
if (from==address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} elseif (from!= to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to ==address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} elseif (to !=from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/function_addTokenToOwnerEnumeration(address to, uint256 tokenId) private{
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/function_addTokenToAllTokensEnumeration(uint256 tokenId) private{
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/function_removeTokenFromOwnerEnumeration(addressfrom, uint256 tokenId) private{
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and// then delete the last slot (swap and pop).uint256 lastTokenIndex = ERC721.balanceOf(from) -1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessaryif (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the arraydelete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/function_removeTokenFromAllTokensEnumeration(uint256 tokenId) private{
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and// then delete the last slot (swap and pop).uint256 lastTokenIndex = _allTokens.length-1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding// an 'if' statement (like in _removeTokenFromOwnerEnumeration)uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index// This also deletes the contents at the last position of the arraydelete _allTokensIndex[tokenId];
_allTokens.pop();
}
}
Contract Source Code
File 7 of 17: FloorToken.sol
// SPDX-License-Identifier: GPL-3.0// SPDX-License-Identifier: MIT/*
* @author Hamdi Allam hamdi.allam97@gmail.com
* Please reach out with any questions or concerns
*/pragmasolidity ^0.8.0;libraryRLPReader{
uint8constant STRING_SHORT_START =0x80;
uint8constant STRING_LONG_START =0xb8;
uint8constant LIST_SHORT_START =0xc0;
uint8constant LIST_LONG_START =0xf8;
uint8constant WORD_SIZE =32;
structRLPItem {
uint256 len;
uint256 memPtr;
}
structIterator {
RLPItem item; // Item that's being iterated over.uint256 nextPtr; // Position of the next item in the list.
}
/*
* @dev Returns the next element in the iteration. Reverts if it has not next element.
* @param self The iterator.
* @return The next element in the iteration.
*/functionnext(Iterator memoryself) internalpurereturns (RLPItem memory) {
require(hasNext(self));
uint256 ptr =self.nextPtr;
uint256 itemLength = _itemLength(ptr);
self.nextPtr = ptr + itemLength;
return RLPItem(itemLength, ptr);
}
/*
* @dev Returns true if the iteration has more elements.
* @param self The iterator.
* @return true if the iteration has more elements.
*/functionhasNext(Iterator memoryself) internalpurereturns (bool) {
RLPItem memory item =self.item;
returnself.nextPtr < item.memPtr + item.len;
}
/*
* @param item RLP encoded bytes
*/functiontoRlpItem(bytesmemory item) internalpurereturns (RLPItem memory) {
uint256 memPtr;
assembly {
memPtr :=add(item, 0x20)
}
return RLPItem(item.length, memPtr);
}
/*
* @dev Create an iterator. Reverts if item is not a list.
* @param self The RLP item.
* @return An 'Iterator' over the item.
*/functioniterator(RLPItem memoryself) internalpurereturns (Iterator memory) {
require(isList(self));
uint256 ptr =self.memPtr + _payloadOffset(self.memPtr);
return Iterator(self, ptr);
}
/*
* @param item RLP encoded bytes
*/functionrlpLen(RLPItem memory item) internalpurereturns (uint256) {
return item.len;
}
/*
* @param item RLP encoded bytes
*/functionpayloadLen(RLPItem memory item) internalpurereturns (uint256) {
return item.len - _payloadOffset(item.memPtr);
}
/*
* @param item RLP encoded list in bytes
*/functiontoList(RLPItem memory item) internalpurereturns (RLPItem[] memory) {
require(isList(item));
uint256 items = numItems(item);
RLPItem[] memory result =new RLPItem[](items);
uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr);
uint256 dataLen;
for (uint256 i =0; i < items; i++) {
dataLen = _itemLength(memPtr);
result[i] = RLPItem(dataLen, memPtr);
memPtr = memPtr + dataLen;
}
return result;
}
// @return indicator whether encoded payload is a list. negate this function call for isData.functionisList(RLPItem memory item) internalpurereturns (bool) {
if (item.len ==0) returnfalse;
uint8 byte0;
uint256 memPtr = item.memPtr;
assembly {
byte0 :=byte(0, mload(memPtr))
}
if (byte0 < LIST_SHORT_START) returnfalse;
returntrue;
}
/*
* @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory.
* @return keccak256 hash of RLP encoded bytes.
*/functionrlpBytesKeccak256(RLPItem memory item) internalpurereturns (bytes32) {
uint256 ptr = item.memPtr;
uint256 len = item.len;
bytes32 result;
assembly {
result :=keccak256(ptr, len)
}
return result;
}
functionpayloadLocation(RLPItem memory item) internalpurereturns (uint256, uint256) {
uint256 offset = _payloadOffset(item.memPtr);
uint256 memPtr = item.memPtr + offset;
uint256 len = item.len - offset; // data lengthreturn (memPtr, len);
}
/*
* @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory.
* @return keccak256 hash of the item payload.
*/functionpayloadKeccak256(RLPItem memory item) internalpurereturns (bytes32) {
(uint256 memPtr, uint256 len) = payloadLocation(item);
bytes32 result;
assembly {
result :=keccak256(memPtr, len)
}
return result;
}
/** RLPItem conversions into data types **/// @returns raw rlp encoding in bytesfunctiontoRlpBytes(RLPItem memory item) internalpurereturns (bytesmemory) {
bytesmemory result =newbytes(item.len);
if (result.length==0) return result;
uint256 ptr;
assembly {
ptr :=add(0x20, result)
}
copy(item.memPtr, ptr, item.len);
return result;
}
// any non-zero byte is considered truefunctiontoBoolean(RLPItem memory item) internalpurereturns (bool) {
require(item.len ==1);
uint256 result;
uint256 memPtr = item.memPtr;
assembly {
result :=byte(0, mload(memPtr))
}
return result ==0 ? false : true;
}
functiontoAddress(RLPItem memory item) internalpurereturns (address) {
// 1 byte for the length prefixrequire(item.len ==21);
returnaddress(uint160(toUint(item)));
}
functiontoUint(RLPItem memory item) internalpurereturns (uint256) {
require(item.len >0&& item.len <=33);
uint256 offset = _payloadOffset(item.memPtr);
uint256 len = item.len - offset;
uint256 result;
uint256 memPtr = item.memPtr + offset;
assembly {
result :=mload(memPtr)
// shfit to the correct location if neccesaryiflt(len, 32) {
result :=div(result, exp(256, sub(32, len)))
}
}
return result;
}
// enforces 32 byte lengthfunctiontoUintStrict(RLPItem memory item) internalpurereturns (uint256) {
// one byte prefixrequire(item.len ==33);
uint256 result;
uint256 memPtr = item.memPtr +1;
assembly {
result :=mload(memPtr)
}
return result;
}
functiontoBytes(RLPItem memory item) internalpurereturns (bytesmemory) {
require(item.len >0);
uint256 offset = _payloadOffset(item.memPtr);
uint256 len = item.len - offset; // data lengthbytesmemory result =newbytes(len);
uint256 destPtr;
assembly {
destPtr :=add(0x20, result)
}
copy(item.memPtr + offset, destPtr, len);
return result;
}
/*
* Private Helpers
*/// @return number of payload items inside an encoded list.functionnumItems(RLPItem memory item) privatepurereturns (uint256) {
if (item.len ==0) return0;
uint256 count =0;
uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr);
uint256 endPtr = item.memPtr + item.len;
while (currPtr < endPtr) {
currPtr = currPtr + _itemLength(currPtr); // skip over an item
count++;
}
return count;
}
// @return entire rlp item byte lengthfunction_itemLength(uint256 memPtr) privatepurereturns (uint256) {
uint256 itemLen;
uint256 byte0;
assembly {
byte0 :=byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START) itemLen =1;
elseif (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START +1;
elseif (byte0 < LIST_SHORT_START) {
assembly {
let byteLen :=sub(byte0, 0xb7) // # of bytes the actual length is
memPtr :=add(memPtr, 1) // skip over the first byte/* 32 byte word size */let dataLen :=div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len
itemLen :=add(dataLen, add(byteLen, 1))
}
} elseif (byte0 < LIST_LONG_START) {
itemLen = byte0 - LIST_SHORT_START +1;
} else {
assembly {
let byteLen :=sub(byte0, 0xf7)
memPtr :=add(memPtr, 1)
let dataLen :=div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length
itemLen :=add(dataLen, add(byteLen, 1))
}
}
return itemLen;
}
// @return number of bytes until the datafunction_payloadOffset(uint256 memPtr) privatepurereturns (uint256) {
uint256 byte0;
assembly {
byte0 :=byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START) return0;
elseif (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return1;
elseif (byte0 < LIST_SHORT_START)
// being explicitreturn byte0 - (STRING_LONG_START -1) +1;
elsereturn byte0 - (LIST_LONG_START -1) +1;
}
/*
* @param src Pointer to source
* @param dest Pointer to destination
* @param len Amount of memory to copy from the source
*/functioncopy(uint256 src,
uint256 dest,
uint256 len
) privatepure{
if (len ==0) return;
// copy as many word sizes as possiblefor (; len >= WORD_SIZE; len -= WORD_SIZE) {
assembly {
mstore(dest, mload(src))
}
src += WORD_SIZE;
dest += WORD_SIZE;
}
if (len ==0) return;
// left over bytes. Mask is used to remove unwanted bytes from the worduint256 mask =256**(WORD_SIZE - len) -1;
assembly {
let srcpart :=and(mload(src), not(mask)) // zero out srclet destpart :=and(mload(dest), mask) // retrieve the bytesmstore(dest, or(destpart, srcpart))
}
}
}
pragmasolidity ^0.8.0;libraryMerklePatriciaProof{
/*
* @dev Verifies a merkle patricia proof.
* @param value The terminating value in the trie.
* @param encodedPath The path in the trie leading to value.
* @param rlpParentNodes The rlp encoded stack of nodes.
* @param root The root hash of the trie.
* @return The boolean validity of the proof.
*/functionverify(bytesmemory value,
bytesmemory encodedPath,
bytesmemory rlpParentNodes,
bytes32 root
) internalpurereturns (bool) {
RLPReader.RLPItem memory item = RLPReader.toRlpItem(rlpParentNodes);
RLPReader.RLPItem[] memory parentNodes = RLPReader.toList(item);
bytesmemory currentNode;
RLPReader.RLPItem[] memory currentNodeList;
bytes32 nodeKey = root;
uint256 pathPtr =0;
bytesmemory path = _getNibbleArray(encodedPath);
if (path.length==0) {
returnfalse;
}
for (uint256 i =0; i < parentNodes.length; i++) {
if (pathPtr > path.length) {
returnfalse;
}
currentNode = RLPReader.toRlpBytes(parentNodes[i]);
if (nodeKey !=keccak256(currentNode)) {
returnfalse;
}
currentNodeList = RLPReader.toList(parentNodes[i]);
if (currentNodeList.length==17) {
if (pathPtr == path.length) {
if (keccak256(RLPReader.toBytes(currentNodeList[16])) ==keccak256(value)) {
returntrue;
} else {
returnfalse;
}
}
uint8 nextPathNibble =uint8(path[pathPtr]);
if (nextPathNibble >16) {
returnfalse;
}
nodeKey =bytes32(RLPReader.toUintStrict(currentNodeList[nextPathNibble]));
pathPtr +=1;
} elseif (currentNodeList.length==2) {
uint256 traversed = _nibblesToTraverse(RLPReader.toBytes(currentNodeList[0]), path, pathPtr);
if (pathPtr + traversed == path.length) {
//leaf nodeif (keccak256(RLPReader.toBytes(currentNodeList[1])) ==keccak256(value)) {
returntrue;
} else {
returnfalse;
}
}
//extension nodeif (traversed ==0) {
returnfalse;
}
pathPtr += traversed;
nodeKey =bytes32(RLPReader.toUintStrict(currentNodeList[1]));
} else {
returnfalse;
}
}
}
function_nibblesToTraverse(bytesmemory encodedPartialPath,
bytesmemory path,
uint256 pathPtr
) privatepurereturns (uint256) {
uint256 len =0;
// encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath// and slicedPath have elements that are each one hex character (1 nibble)bytesmemory partialPath = _getNibbleArray(encodedPartialPath);
bytesmemory slicedPath =newbytes(partialPath.length);
// pathPtr counts nibbles in path// partialPath.length is a number of nibblesfor (uint256 i = pathPtr; i < pathPtr + partialPath.length; i++) {
bytes1 pathNibble = path[i];
slicedPath[i - pathPtr] = pathNibble;
}
if (keccak256(partialPath) ==keccak256(slicedPath)) {
len = partialPath.length;
} else {
len =0;
}
return len;
}
// bytes b must be hp encodedfunction_getNibbleArray(bytesmemory b) internalpurereturns (bytesmemory) {
bytesmemory nibbles ="";
if (b.length>0) {
uint8 offset;
uint8 hpNibble =uint8(_getNthNibbleOfBytes(0, b));
if (hpNibble ==1|| hpNibble ==3) {
nibbles =newbytes(b.length*2-1);
bytes1 oddNibble = _getNthNibbleOfBytes(1, b);
nibbles[0] = oddNibble;
offset =1;
} else {
nibbles =newbytes(b.length*2-2);
offset =0;
}
for (uint256 i = offset; i < nibbles.length; i++) {
nibbles[i] = _getNthNibbleOfBytes(i - offset +2, b);
}
}
return nibbles;
}
function_getNthNibbleOfBytes(uint256 n, bytesmemory str) privatepurereturns (bytes1) {
returnbytes1(n %2==0 ? uint8(str[n /2]) /0x10 : uint8(str[n /2]) %0x10);
}
}
pragmasolidity ^0.8.0;libraryMerkle{
functioncheckMembership(bytes32 leaf,
uint256 index,
bytes32 rootHash,
bytesmemory proof
) internalpurereturns (bool) {
require(proof.length%32==0, "Invalid proof length");
uint256 proofHeight = proof.length/32;
// Proof of size n means, height of the tree is n+1.// In a tree of height n+1, max #leafs possible is 2 ^ nrequire(index <2**proofHeight, "Leaf index is too big");
bytes32 proofElement;
bytes32 computedHash = leaf;
for (uint256 i =32; i <= proof.length; i +=32) {
assembly {
proofElement :=mload(add(proof, i))
}
if (index %2==0) {
computedHash =keccak256(abi.encodePacked(computedHash, proofElement));
} else {
computedHash =keccak256(abi.encodePacked(proofElement, computedHash));
}
index = index /2;
}
return computedHash == rootHash;
}
}
pragmasolidity ^0.8.0;libraryExitPayloadReader{
usingRLPReaderforbytes;
usingRLPReaderforRLPReader.RLPItem;
uint8constant WORD_SIZE =32;
structExitPayload {
RLPReader.RLPItem[] data;
}
structReceipt {
RLPReader.RLPItem[] data;
bytes raw;
uint256 logIndex;
}
structLog {
RLPReader.RLPItem data;
RLPReader.RLPItem[] list;
}
structLogTopics {
RLPReader.RLPItem[] data;
}
// copy paste of private copy() from RLPReader to avoid changing of existing contractsfunctioncopy(uint256 src,
uint256 dest,
uint256 len
) privatepure{
if (len ==0) return;
// copy as many word sizes as possiblefor (; len >= WORD_SIZE; len -= WORD_SIZE) {
assembly {
mstore(dest, mload(src))
}
src += WORD_SIZE;
dest += WORD_SIZE;
}
// left over bytes. Mask is used to remove unwanted bytes from the worduint256 mask =256**(WORD_SIZE - len) -1;
assembly {
let srcpart :=and(mload(src), not(mask)) // zero out srclet destpart :=and(mload(dest), mask) // retrieve the bytesmstore(dest, or(destpart, srcpart))
}
}
functiontoExitPayload(bytesmemory data) internalpurereturns (ExitPayload memory) {
RLPReader.RLPItem[] memory payloadData = data.toRlpItem().toList();
return ExitPayload(payloadData);
}
functiongetHeaderNumber(ExitPayload memory payload) internalpurereturns (uint256) {
return payload.data[0].toUint();
}
functiongetBlockProof(ExitPayload memory payload) internalpurereturns (bytesmemory) {
return payload.data[1].toBytes();
}
functiongetBlockNumber(ExitPayload memory payload) internalpurereturns (uint256) {
return payload.data[2].toUint();
}
functiongetBlockTime(ExitPayload memory payload) internalpurereturns (uint256) {
return payload.data[3].toUint();
}
functiongetTxRoot(ExitPayload memory payload) internalpurereturns (bytes32) {
returnbytes32(payload.data[4].toUint());
}
functiongetReceiptRoot(ExitPayload memory payload) internalpurereturns (bytes32) {
returnbytes32(payload.data[5].toUint());
}
functiongetReceipt(ExitPayload memory payload) internalpurereturns (Receipt memory receipt) {
receipt.raw = payload.data[6].toBytes();
RLPReader.RLPItem memory receiptItem = receipt.raw.toRlpItem();
if (receiptItem.isList()) {
// legacy tx
receipt.data = receiptItem.toList();
} else {
// pop first byte before parsting receiptbytesmemory typedBytes = receipt.raw;
bytesmemory result =newbytes(typedBytes.length-1);
uint256 srcPtr;
uint256 destPtr;
assembly {
srcPtr :=add(33, typedBytes)
destPtr :=add(0x20, result)
}
copy(srcPtr, destPtr, result.length);
receipt.data = result.toRlpItem().toList();
}
receipt.logIndex = getReceiptLogIndex(payload);
return receipt;
}
functiongetReceiptProof(ExitPayload memory payload) internalpurereturns (bytesmemory) {
return payload.data[7].toBytes();
}
functiongetBranchMaskAsBytes(ExitPayload memory payload) internalpurereturns (bytesmemory) {
return payload.data[8].toBytes();
}
functiongetBranchMaskAsUint(ExitPayload memory payload) internalpurereturns (uint256) {
return payload.data[8].toUint();
}
functiongetReceiptLogIndex(ExitPayload memory payload) internalpurereturns (uint256) {
return payload.data[9].toUint();
}
// Receipt methodsfunctiontoBytes(Receipt memory receipt) internalpurereturns (bytesmemory) {
return receipt.raw;
}
functiongetLog(Receipt memory receipt) internalpurereturns (Log memory) {
RLPReader.RLPItem memory logData = receipt.data[3].toList()[receipt.logIndex];
return Log(logData, logData.toList());
}
// Log methodsfunctiongetEmitter(Log memory log) internalpurereturns (address) {
return RLPReader.toAddress(log.list[0]);
}
functiongetTopics(Log memory log) internalpurereturns (LogTopics memory) {
return LogTopics(log.list[1].toList());
}
functiongetData(Log memory log) internalpurereturns (bytesmemory) {
return log.list[2].toBytes();
}
functiontoRlpBytes(Log memory log) internalpurereturns (bytesmemory) {
return log.data.toRlpBytes();
}
// LogTopics methodsfunctiongetField(LogTopics memory topics, uint256 index) internalpurereturns (RLPReader.RLPItem memory) {
return topics.data[index];
}
}
pragmasolidity ^0.8.0;interfaceIFxStateSender{
functionsendMessageToChild(address _receiver, bytescalldata _data) external;
}
contractICheckpointManager{
structHeaderBlock {
bytes32 root;
uint256 start;
uint256 end;
uint256 createdAt;
address proposer;
}
/**
* @notice mapping of checkpoint header numbers to block details
* @dev These checkpoints are submited by plasma contracts
*/mapping(uint256=> HeaderBlock) public headerBlocks;
}
abstractcontractFxBaseRootTunnel{
usingRLPReaderforRLPReader.RLPItem;
usingMerkleforbytes32;
usingExitPayloadReaderforbytes;
usingExitPayloadReaderforExitPayloadReader.ExitPayload;
usingExitPayloadReaderforExitPayloadReader.Log;
usingExitPayloadReaderforExitPayloadReader.LogTopics;
usingExitPayloadReaderforExitPayloadReader.Receipt;
// keccak256(MessageSent(bytes))bytes32publicconstant SEND_MESSAGE_EVENT_SIG =0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036;
// state sender contract
IFxStateSender public fxRoot;
// root chain manager
ICheckpointManager public checkpointManager;
// child tunnel contract which receives and sends messagesaddresspublic fxChildTunnel;
// storage to avoid duplicate exitsmapping(bytes32=>bool) public processedExits;
constructor(address _checkpointManager, address _fxRoot) {
checkpointManager = ICheckpointManager(_checkpointManager);
fxRoot = IFxStateSender(_fxRoot);
}
// set fxChildTunnel if not set alreadyfunctionsetFxChildTunnel(address _fxChildTunnel) public{
require(fxChildTunnel ==address(0x0), "FxBaseRootTunnel: CHILD_TUNNEL_ALREADY_SET");
fxChildTunnel = _fxChildTunnel;
}
/**
* @notice Send bytes message to Child Tunnel
* @param message bytes message that will be sent to Child Tunnel
* some message examples -
* abi.encode(tokenId);
* abi.encode(tokenId, tokenMetadata);
* abi.encode(messageType, messageData);
*/function_sendMessageToChild(bytesmemory message) internal{
fxRoot.sendMessageToChild(fxChildTunnel, message);
}
function_validateAndExtractMessage(bytesmemory inputData) internalreturns (bytesmemory) {
ExitPayloadReader.ExitPayload memory payload = inputData.toExitPayload();
bytesmemory branchMaskBytes = payload.getBranchMaskAsBytes();
uint256 blockNumber = payload.getBlockNumber();
// checking if exit has already been processed// unique exit is identified using hash of (blockNumber, branchMask, receiptLogIndex)bytes32 exitHash =keccak256(
abi.encodePacked(
blockNumber,
// first 2 nibbles are dropped while generating nibble array// this allows branch masks that are valid but bypass exitHash check (changing first 2 nibbles only)// so converting to nibble array and then hashing it
MerklePatriciaProof._getNibbleArray(branchMaskBytes),
payload.getReceiptLogIndex()
)
);
require(processedExits[exitHash] ==false, "FxRootTunnel: EXIT_ALREADY_PROCESSED");
processedExits[exitHash] =true;
ExitPayloadReader.Receipt memory receipt = payload.getReceipt();
ExitPayloadReader.Log memory log = receipt.getLog();
// check child tunnelrequire(fxChildTunnel == log.getEmitter(), "FxRootTunnel: INVALID_FX_CHILD_TUNNEL");
bytes32 receiptRoot = payload.getReceiptRoot();
// verify receipt inclusionrequire(
MerklePatriciaProof.verify(receipt.toBytes(), branchMaskBytes, payload.getReceiptProof(), receiptRoot),
"FxRootTunnel: INVALID_RECEIPT_PROOF"
);
// verify checkpoint inclusion
_checkBlockMembershipInCheckpoint(
blockNumber,
payload.getBlockTime(),
payload.getTxRoot(),
receiptRoot,
payload.getHeaderNumber(),
payload.getBlockProof()
);
ExitPayloadReader.LogTopics memory topics = log.getTopics();
require(
bytes32(topics.getField(0).toUint()) == SEND_MESSAGE_EVENT_SIG, // topic0 is event sig"FxRootTunnel: INVALID_SIGNATURE"
);
// received message databytesmemory message =abi.decode(log.getData(), (bytes)); // event decodes params again, so decoding bytes to get messagereturn message;
}
function_checkBlockMembershipInCheckpoint(uint256 blockNumber,
uint256 blockTime,
bytes32 txRoot,
bytes32 receiptRoot,
uint256 headerNumber,
bytesmemory blockProof
) privateviewreturns (uint256) {
(bytes32 headerRoot, uint256 startBlock, , uint256 createdAt, ) = checkpointManager.headerBlocks(headerNumber);
require(
keccak256(abi.encodePacked(blockNumber, blockTime, txRoot, receiptRoot)).checkMembership(
blockNumber - startBlock,
headerRoot,
blockProof
),
"FxRootTunnel: INVALID_HEADER"
);
return createdAt;
}
/**
* @notice receive message from L2 to L1, validated by proof
* @dev This function verifies if the transaction actually happened on child chain
*
* @param inputData RLP encoded data of the reference tx containing following list of fields
* 0 - headerNumber - Checkpoint header block number containing the reference tx
* 1 - blockProof - Proof that the block header (in the child chain) is a leaf in the submitted merkle root
* 2 - blockNumber - Block number containing the reference tx on child chain
* 3 - blockTime - Reference tx block time
* 4 - txRoot - Transactions root of block
* 5 - receiptRoot - Receipts root of block
* 6 - receipt - Receipt of the reference transaction
* 7 - receiptProof - Merkle proof of the reference receipt
* 8 - branchMask - 32 bits denoting the path of receipt in merkle tree
* 9 - receiptLogIndex - Log Index to read from the receipt
*/functionreceiveMessage(bytesmemory inputData) publicvirtual{
bytesmemory message = _validateAndExtractMessage(inputData);
_processMessageFromChild(message);
}
/**
* @notice Process message received from Child Tunnel
* @dev function needs to be implemented to handle message as per requirement
* This is called by onStateReceive function.
* Since it is called via a system call, any event will not be emitted during its execution.
* @param message bytes message that was sent from Child Tunnel
*/function_processMessageFromChild(bytesmemory message) internalvirtual;
}
/// @title The FLOOR ERC-721 token/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 8888888888 888 .d88888b. .d88888b. 8888888b. *
* 888 888 d88P" "Y88b d88P" "Y88b 888 Y88b *
* 888 888 888 888 888 888 888 888 *
* 8888888 888 888 888 888 888 888 d88P *
* 888 888 888 888 888 888 8888888P" *
* 888 888 888 888 888 888 888 T88b *
* 888 888 Y88b. .d88P Y88b. .d88P 888 T88b *
* 888 88888888 "Y88888P" "Y88888P" 888 T88b *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */pragmasolidity ^0.8.6;import { Ownable } from'@openzeppelin/contracts/access/Ownable.sol';
import { ERC721Checkpointable } from'./base/ERC721Checkpointable.sol';
import { IFloorDescriptor } from'./interfaces/IFloorDescriptor.sol';
import { IFloorToken } from'./interfaces/IFloorToken.sol';
import { ERC721 } from'./base/ERC721.sol';
import { IERC721 } from'@openzeppelin/contracts/token/ERC721/IERC721.sol';
import { IProxyRegistry } from'./external/opensea/IProxyRegistry.sol';
contractFloorTokenisIFloorToken, Ownable, ERC721Checkpointable, FxBaseRootTunnel{
// The DAO addressaddresspublic floorsDAO;
// An address who has permissions to mint Flooraddresspublic minter;
// An address who has permissions to mint Flooraddresspublic predicate;
// The Floor token URI descriptor
IFloorDescriptor public descriptor;
// Whether the minter can be updatedboolpublic isMinterLocked;
// Whether the descriptor can be updatedboolpublic isDescriptorLocked;
// The internal floor ID trackeruint256private _currentFloorId;
// IPFS content hash of contract-level metadatastringprivate _contractURIHash ='QmYuMm7YikekmHC3oQcvBP3fZErJPoPiPAdhDfvCt3jsSH';
mapping(uint256=>uint16) public sizes;
mapping (uint256=>bool) public withdrawnTokens;
// OpenSea's Proxy Registry
IProxyRegistry publicimmutable proxyRegistry;
/**
* @notice Require that the minter has not been locked.
*/modifierwhenMinterNotLocked() {
require(!isMinterLocked, 'Minter is locked');
_;
}
/**
* @notice Require that the descriptor has not been locked.
*/modifierwhenDescriptorNotLocked() {
require(!isDescriptorLocked, 'Descriptor is locked');
_;
}
/**
* @notice Require that the sender is the DAO.
*/modifieronlyFloorsDAO() {
require(msg.sender== floorsDAO, 'Sender is not the DAO');
_;
}
/**
* @notice Require that the sender is the minter.
*/modifieronlyMinter() {
require(msg.sender== minter, 'Sender is not the minter');
_;
}
/**
* @notice Require that the sender is the predicate.
*/modifieronlyPredicate() {
require(msg.sender== predicate, 'Sender is not the predicate');
_;
}
constructor(address _floorsDAO,
address _minter,
address _predicate,
IFloorDescriptor _descriptor,
IProxyRegistry _proxyRegistry,
address _checkpointManager,
address _fxRoot
)
ERC721('FLOOR', 'FLOOR')
FxBaseRootTunnel(_checkpointManager, _fxRoot)
{
descriptor = _descriptor;
predicate = _predicate;
floorsDAO = _floorsDAO;
minter = _minter;
proxyRegistry = _proxyRegistry;
}
/**
* @notice Generate a pseudo-random number using the previous blockhash and floor ID.
*/functionrandNumber(uint256 floorId) privateviewreturns(uint256) {
uint256 pseudorandomness =uint256(
keccak256(abi.encodePacked(blockhash(block.number-1), floorId))
);
return (pseudorandomness - ((pseudorandomness /10000) *10000));
}
/**
* @notice Generate a pseudo-random floor size based on pseudo-random number.
* Distribution of Sizes: 8 slots (11%), 16 slots (50%), 32 slots (13%), 64 slots (9%), 128 slots (7%), 256 slots (5%), 1 slots (5%), 3 slots (5%), 7 slots (5%), 33 slots (1%), 69 slots (1%), 420 slots (0.5%)
*/functiongenerateSize(uint256 floorId) privateviewreturns(uint16) {
uint256 x = randNumber(floorId);
if (x <50) return420;
if (x <100) return69;
if (x <200) return33;
if (x <300) return7;
if (x <400) return3;
if (x <500) return1;
if (x <1000) return256;
if (x <1700) return128;
if (x <2600) return64;
if (x <3900) return32;
if (x <8900) return16;
if (x <10000) return8;
return0;
}
/**
* @notice The IPFS URI of contract-level metadata.
*/functioncontractURI() publicviewreturns (stringmemory) {
returnstring(abi.encodePacked('ipfs://', _contractURIHash));
}
/**
* @notice Set the _contractURIHash.
* @dev Only callable by the owner.
*/functionsetContractURIHash(stringmemory newContractURIHash) externalonlyOwner{
_contractURIHash = newContractURIHash;
}
/**
* @notice Override isApprovedForAll to whitelist user's OpenSea proxy accounts to enable gas-less listings.
*/functionisApprovedForAll(address owner, address operator) publicviewoverride(IERC721, ERC721) returns (bool) {
// Whitelist OpenSea proxy contract for easy trading.if (proxyRegistry.proxies(owner) == operator) {
returntrue;
}
returnsuper.isApprovedForAll(owner, operator);
}
/**
* @notice Mint a Floor to the minter.
* Minted every 10 Floors, starting at 0,
* until 110 Floors have been minted (3 years w/ 24 hour auctions).
* @dev Call _mintTo with the to address(es).
*/functionmint() publicoverrideonlyMinterreturns (uint256) {
if (_currentFloorId <=1092&& _currentFloorId %10==0) {
_mintTo(floorsDAO, _currentFloorId++);
}
return _mintTo(minter, _currentFloorId++);
}
/**
* @notice Burn a floor.
*/functionburn(uint256 floorId) overridepubliconlyMinter{
_burn(floorId);
emit FloorBurned(floorId);
}
/**
* @notice A distinct Uniform Resource Identifier (URI) for a given asset.
* @dev See {IERC721Metadata-tokenURI}.
*/functiontokenURI(uint256 tokenId) publicviewoverridereturns (stringmemory) {
require(_exists(tokenId), 'FLOOR: URI query for nonexistent token');
return descriptor.tokenURI(tokenId, sizes[tokenId]);
}
/**
* @notice Similar to `tokenURI`, but always serves a base64 encoded data URI
* with the JSON contents directly inlined.
*/functiondataURI(uint256 tokenId) publicviewoverridereturns (stringmemory) {
require(_exists(tokenId), 'FLOOR: URI query for nonexistent token');
return descriptor.dataURI(tokenId, sizes[tokenId]);
}
/**
* @notice Set the token URI descriptor.
* @dev Only callable by the owner when not locked.
*/functionsetDescriptor(IFloorDescriptor _descriptor) externaloverrideonlyOwnerwhenDescriptorNotLocked{
descriptor = _descriptor;
emit DescriptorUpdated(_descriptor);
}
/**
* @notice Lock the descriptor.
* @dev This cannot be reversed and is only callable by the owner when not locked.
*/functionlockDescriptor() externaloverrideonlyOwnerwhenDescriptorNotLocked{
isDescriptorLocked =true;
emit DescriptorLocked();
}
/**
* @notice Set the DAO.
* @dev Only callable by the DAO when not locked.
*/functionsetFloorsDAO(address _floorsDAO) overrideexternalonlyFloorsDAO{
floorsDAO = _floorsDAO;
emit FloorsDAOUpdated(_floorsDAO);
}
/**
* @notice Set the token minter.
* @dev Only callable by the owner when not locked.
*/functionsetMinter(address _minter) overrideexternalonlyOwnerwhenMinterNotLocked{
minter = _minter;
emit MinterUpdated(_minter);
}
/**
* @notice Lock the minter.
* @dev This cannot be reversed and is only callable by the owner when not locked.
*/functionlockMinter() overrideexternalonlyOwnerwhenMinterNotLocked{
isMinterLocked =true;
emit MinterLocked();
}
/**
* @notice Mint a Floor with `floorId` to the provided `to` address.
*/function_mintTo(address to, uint256 floorId) internalreturns (uint256) {
sizes[floorId] = generateSize(floorId);
_mint(owner(), to, floorId);
sendMessageToChild(abi.encode(floorId, sizes[floorId], tokenURI(floorId)));
emit FloorCreated(floorId, sizes[floorId]);
return floorId;
}
// L1 <> L2functionmint(address user, uint256 tokenId) externalonlyPredicate{
_mint(address(0), user, tokenId);
}
functionexists(uint256 tokenId) externalviewreturns (bool) {
return _exists(tokenId);
}
// Fx-Portalfunction_processMessageFromChild(bytesmemory data) internaloverride{
// NOTHING TO DO HERE
}
functionsendMessageToChild(bytesmemory message) private{
_sendMessageToChild(message);
}
functionupdateMetadata(uint256 floorId) externalonlyOwner{
sendMessageToChild(abi.encode(floorId, sizes[floorId], tokenURI(floorId)));
}
}
Contract Source Code
File 8 of 17: IERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)pragmasolidity ^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}.
*/interfaceIERC165{
/**
* @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.
*/functionsupportsInterface(bytes4 interfaceId) externalviewreturns (bool);
}
Contract Source Code
File 9 of 17: IERC721.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)pragmasolidity ^0.8.0;import"../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/interfaceIERC721isIERC165{
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/eventApproval(addressindexed owner, addressindexed approved, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/eventApprovalForAll(addressindexed owner, addressindexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/functionbalanceOf(address owner) externalviewreturns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functionownerOf(uint256 tokenId) externalviewreturns (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.
*/functionsafeTransferFrom(addressfrom,
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.
*/functiontransferFrom(addressfrom,
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.
*/functionapprove(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functiongetApproved(uint256 tokenId) externalviewreturns (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.
*/functionsetApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/functionisApprovedForAll(address owner, address operator) externalviewreturns (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.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId,
bytescalldata data
) external;
}
Contract Source Code
File 10 of 17: IERC721Enumerable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Enumerable.sol)pragmasolidity ^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
*/interfaceIERC721EnumerableisIERC721{
/**
* @dev Returns the total amount of tokens stored by the contract.
*/functiontotalSupply() externalviewreturns (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.
*/functiontokenOfOwnerByIndex(address owner, uint256 index) externalviewreturns (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.
*/functiontokenByIndex(uint256 index) externalviewreturns (uint256);
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)pragmasolidity ^0.8.0;/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/interfaceIERC721Receiver{
/**
* @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`.
*/functiononERC721Received(address operator,
addressfrom,
uint256 tokenId,
bytescalldata data
) externalreturns (bytes4);
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)pragmasolidity ^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.
*/abstractcontractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
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.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Contract Source Code
File 17 of 17: Strings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)pragmasolidity ^0.8.0;/**
* @dev String operations.
*/libraryStrings{
bytes16privateconstant _HEX_SYMBOLS ="0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/functiontoString(uint256 value) internalpurereturns (stringmemory) {
// Inspired by OraclizeAPI's implementation - MIT licence// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.solif (value ==0) {
return"0";
}
uint256 temp = value;
uint256 digits;
while (temp !=0) {
digits++;
temp /=10;
}
bytesmemory buffer =newbytes(digits);
while (value !=0) {
digits -=1;
buffer[digits] =bytes1(uint8(48+uint256(value %10)));
value /=10;
}
returnstring(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/functiontoHexString(uint256 value) internalpurereturns (stringmemory) {
if (value ==0) {
return"0x00";
}
uint256 temp = value;
uint256 length =0;
while (temp !=0) {
length++;
temp >>=8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/functiontoHexString(uint256 value, uint256 length) internalpurereturns (stringmemory) {
bytesmemory buffer =newbytes(2* length +2);
buffer[0] ="0";
buffer[1] ="x";
for (uint256 i =2* length +1; i >1; --i) {
buffer[i] = _HEX_SYMBOLS[value &0xf];
value >>=4;
}
require(value ==0, "Strings: hex length insufficient");
returnstring(buffer);
}
}