文件 1 的 35:AccessControl.sol
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
文件 2 的 35:AccessControlEnumerable.sol
pragma solidity ^0.8.0;
import "./IAccessControlEnumerable.sol";
import "./AccessControl.sol";
import "../utils/structs/EnumerableSet.sol";
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
using EnumerableSet for EnumerableSet.AddressSet;
mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);
}
function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {
return _roleMembers[role].at(index);
}
function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {
return _roleMembers[role].length();
}
function _grantRole(bytes32 role, address account) internal virtual override {
super._grantRole(role, account);
_roleMembers[role].add(account);
}
function _revokeRole(bytes32 role, address account) internal virtual override {
super._revokeRole(role, account);
_roleMembers[role].remove(account);
}
}
文件 3 的 35:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
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");
}
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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 4 的 35:BaseTokenURI.sol
pragma solidity >=0.8.0 <0.9.0;
import "@openzeppelin/contracts/access/Ownable.sol";
contract BaseTokenURI is Ownable {
string public baseTokenURI;
constructor(string memory _baseTokenURI) {
setBaseTokenURI(_baseTokenURI);
}
function setBaseTokenURI(string memory _baseTokenURI) public onlyOwner {
baseTokenURI = _baseTokenURI;
}
function _baseURI() internal view virtual returns (string memory) {
return baseTokenURI;
}
}
文件 5 的 35:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 6 的 35:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 7 的 35:ERC2981.sol
pragma solidity ^0.8.0;
import "../../interfaces/IERC2981.sol";
import "../../utils/introspection/ERC165.sol";
abstract contract ERC2981 is IERC2981, ERC165 {
struct RoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
}
function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) {
RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];
if (royalty.receiver == address(0)) {
royalty = _defaultRoyaltyInfo;
}
uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();
return (royalty.receiver, royaltyAmount);
}
function _feeDenominator() internal pure virtual returns (uint96) {
return 10000;
}
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: invalid receiver");
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
function _deleteDefaultRoyalty() internal virtual {
delete _defaultRoyaltyInfo;
}
function _setTokenRoyalty(
uint256 tokenId,
address receiver,
uint96 feeNumerator
) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: Invalid parameters");
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
function _resetTokenRoyalty(uint256 tokenId) internal virtual {
delete _tokenRoyaltyInfo[tokenId];
}
}
文件 8 的 35:ERC5058.sol
pragma solidity ^0.8.8;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "./IERC5058.sol";
abstract contract ERC5058 is ERC721, IERC5058 {
mapping(uint256 => uint256) public lockedTokens;
mapping(uint256 => address) private _lockApprovals;
mapping(address => mapping(address => bool)) private _lockOperatorApprovals;
function lockApprove(address to, uint256 tokenId) public virtual override {
require(!isLocked(tokenId), "ERC5058: token is locked");
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC5058: lock approval to current owner");
require(
_msgSender() == owner || isLockApprovedForAll(owner, _msgSender()),
"ERC5058: lock approve caller is not owner nor approved for all"
);
_lockApprove(owner, to, tokenId);
}
function getLockApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC5058: lock approved query for nonexistent token");
return _lockApprovals[tokenId];
}
function lockerOf(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC5058: locker query for nonexistent token");
require(isLocked(tokenId), "ERC5058: locker query for non-locked token");
return _lockApprovals[tokenId];
}
function setLockApprovalForAll(address operator, bool approved) public virtual override {
_setLockApprovalForAll(_msgSender(), operator, approved);
}
function isLockApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _lockOperatorApprovals[owner][operator];
}
function isLocked(uint256 tokenId) public view virtual override returns (bool) {
return lockedTokens[tokenId] > block.timestamp;
}
function lockFrom(
address from,
uint256 tokenId,
uint256 expired
) public virtual override {
require(_isLockApprovedOrOwner(_msgSender(), tokenId), "ERC5058: lock caller is not owner nor approved");
require(expired > block.timestamp, "ERC5058: expired time must be greater than current block time");
require(!isLocked(tokenId), "ERC5058: token is locked");
_lock(_msgSender(), from, tokenId, expired);
}
function unlockFrom(address from, uint256 tokenId) public virtual override {
require(lockerOf(tokenId) == _msgSender(), "ERC5058: unlock caller is not lock operator");
require(ERC721.ownerOf(tokenId) == from, "ERC5058: unlock from incorrect owner");
_beforeTokenLock(_msgSender(), from, tokenId, 0);
delete lockedTokens[tokenId];
emit Unlocked(_msgSender(), from, tokenId);
_afterTokenLock(_msgSender(), from, tokenId, 0);
}
function _lock(
address operator,
address from,
uint256 tokenId,
uint256 expired
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC5058: lock from incorrect owner");
_beforeTokenLock(operator, from, tokenId, expired);
lockedTokens[tokenId] = expired;
_lockApprovals[tokenId] = _msgSender();
emit Locked(operator, from, tokenId, expired);
_afterTokenLock(operator, from, tokenId, expired);
}
function _safeLockMint(
address to,
uint256 tokenId,
uint256 expired,
bytes memory _data
) internal virtual {
require(expired > block.timestamp, "ERC5058: lock mint for invalid lock block time");
_safeMint(to, tokenId, _data);
_lock(address(0), to, tokenId, expired);
}
function _burn(uint256 tokenId) internal virtual override {
address owner = ERC721.ownerOf(tokenId);
super._burn(tokenId);
_beforeTokenLock(_msgSender(), owner, tokenId, 0);
delete lockedTokens[tokenId];
delete _lockApprovals[tokenId];
_afterTokenLock(_msgSender(), owner, tokenId, 0);
}
function _lockApprove(
address owner,
address to,
uint256 tokenId
) internal virtual {
_lockApprovals[tokenId] = to;
emit LockApproval(owner, to, tokenId);
}
function _setLockApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC5058: lock approve to caller");
_lockOperatorApprovals[owner][operator] = approved;
emit LockApprovalForAll(owner, operator, approved);
}
function _isLockApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC5058: lock operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isLockApprovedForAll(owner, spender) || getLockApproved(tokenId) == spender);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
require(!isLocked(tokenId), "ERC5058: token transfer while locked");
}
function _beforeTokenLock(
address operator,
address from,
uint256 tokenId,
uint256 expired
) internal virtual {}
function _afterTokenLock(
address operator,
address from,
uint256 tokenId,
uint256 expired
) internal virtual {}
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC5058).interfaceId || super.supportsInterface(interfaceId);
}
}
文件 9 的 35:ERC5058Bound.sol
pragma solidity ^0.8.8;
import "../factory/IERC5058Factory.sol";
import "../factory/IERC721Bound.sol";
import "../ERC5058.sol";
abstract contract ERC5058Bound is ERC5058 {
address public bound;
function _setFactory(address _factory) internal {
bound = IERC5058Factory(_factory).boundOf(address(this));
}
function _setBoundBaseTokenURI(string memory uri) internal {
IERC721Bound(bound).setBaseTokenURI(uri);
}
function _setBoundContractURI(string memory uri) internal {
IERC721Bound(bound).setContractURI(uri);
}
function burnBound(uint256 tokenId) external {
IERC721Bound(bound).burn(tokenId);
}
function _afterTokenLock(
address operator,
address from,
uint256 tokenId,
uint256 expired
) internal virtual override {
super._afterTokenLock(operator, from, tokenId, expired);
if (bound != address(0)) {
if (expired != 0) {
if (operator != address(0)) {
IERC721Bound(bound).safeMint(msg.sender, tokenId, "");
}
} else {
if (IERC721Bound(bound).exists(tokenId)) {
IERC721Bound(bound).burn(tokenId);
}
}
}
}
}
文件 10 的 35:ERC721.sol
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
string private _name;
string private _symbol;
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
function _baseURI() internal view virtual returns (string memory) {
return "";
}
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
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);
}
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");
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
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 || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
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"
);
}
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
文件 11 的 35:ERC721Attachable.sol
pragma solidity ^0.8.8;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
interface IBoundERC721Receiver {
function onBoundERC721Received(
address operator,
address to,
uint256 boundTokenId,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
interface IERC721Burnable {
function burn(uint256 tokenId) external;
function removeSlave(uint256 tokenId) external;
}
abstract contract ERC721Attachable is Ownable, ERC721 {
using EnumerableSet for EnumerableSet.AddressSet;
struct BoundToken {
address collection;
uint256 tokenId;
}
mapping(uint256 => BoundToken) public slaveTokens;
mapping(uint256 => BoundToken[]) private _masterTokens;
mapping(address => mapping(uint256 => uint256)) private _slaveTokenIndex;
EnumerableSet.AddressSet private _slaveCollections;
EnumerableSet.AddressSet private _transferApprovals;
event CollectionRemoved(address indexed collection);
event CollectionAdded(address indexed collection);
event TransferApprove(address indexed operator);
event TransferDisapprove(address indexed operator);
function allSlaveTokenLength(uint256 tokenId) public view returns (uint256) {
return _masterTokens[tokenId].length;
}
function addCollection(address collection) external onlyOwner {
require(!_slaveCollections.contains(collection), "ERC721Attachable: collection already slave");
_slaveCollections.add(collection);
emit CollectionAdded(collection);
}
function removeCollection(address collection) external onlyOwner {
require(_slaveCollections.contains(collection), "ERC721Attachable: collection not slave");
_slaveCollections.remove(collection);
emit CollectionRemoved(collection);
}
function isSlaveCollection(address collection) public view returns (bool) {
return _slaveCollections.contains(collection);
}
function addTransferApproval(address operator) external onlyOwner {
require(!_transferApprovals.contains(operator), "ERC721Attachable: already approved");
_transferApprovals.add(operator);
emit TransferApprove(operator);
}
function removeTransferApproval(address operator) external onlyOwner {
require(_transferApprovals.contains(operator), "ERC721Attachable: not approved");
_transferApprovals.remove(operator);
emit TransferDisapprove(operator);
}
function isTransferApproval(address operator) public view returns (bool) {
return _transferApprovals.contains(operator);
}
function isSlaveToken(uint256 tokenId) public view returns (bool) {
return slaveTokens[tokenId].collection != address(0);
}
function masterOf(uint256 tokenId) public view returns (address) {
require(isSlaveToken(tokenId), "ERC721Attachable: not slave token");
return slaveTokens[tokenId].collection;
}
function slaveTokenByIndex(uint256 tokenId, uint256 index) public view returns (BoundToken memory) {
require(index < _masterTokens[tokenId].length, "ERC721Attachable: tokenId index out of bounds");
return _masterTokens[tokenId][index];
}
function _slaveMint(
address to,
uint256 tokenId,
address collection,
uint256 masterTokenId
) internal virtual {
BoundToken storage at = slaveTokens[tokenId];
at.collection = collection;
at.tokenId = masterTokenId;
require(
_checkOnBoundERC721Received(collection, to, tokenId, masterTokenId, ""),
"ERC721Attachable: transfer to non BoundERC721Receiver implementer"
);
_mint(to, tokenId);
}
function _removeSlave(uint256 tokenId) internal virtual {
require(isSlaveToken(tokenId), "ERC721Attachable: not slave token");
BoundToken storage at = slaveTokens[tokenId];
require(
_checkOnBoundERC721Received(at.collection, address(0), tokenId, at.tokenId, ""),
"ERC721Attachable: transfer to non BoundERC721Receiver implementer"
);
delete slaveTokens[tokenId];
}
function _removeMaster(uint256 tokenId) internal virtual {
require(allSlaveTokenLength(tokenId) > 0, "ERC721Attachable: no slave token");
uint256 slaveNum = allSlaveTokenLength(tokenId);
for (uint256 i = 0; i < slaveNum; i++) {
IERC721Burnable(_masterTokens[tokenId][i].collection).removeSlave(_masterTokens[tokenId][i].tokenId);
}
delete _masterTokens[tokenId];
}
function _burn(uint256 tokenId) internal virtual override {
super._burn(tokenId);
BoundToken storage at = slaveTokens[tokenId];
if (at.collection != address(0)) {
require(
_checkOnBoundERC721Received(at.collection, address(0), tokenId, at.tokenId, ""),
"ERC721Attachable: transfer to non BoundERC721Receiver implementer"
);
delete slaveTokens[tokenId];
}
uint256 slaveNum = allSlaveTokenLength(tokenId);
if (slaveNum > 0) {
for (uint256 i = 0; i < slaveNum; i++) {
IERC721Burnable(_masterTokens[tokenId][i].collection).burn(_masterTokens[tokenId][i].tokenId);
}
delete _masterTokens[tokenId];
}
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
if (slaveTokens[tokenId].collection != address(0)) {
if (msg.sender == slaveTokens[tokenId].collection) {
_transfer(from, to, tokenId);
} else {
require(_transferApprovals.contains(msg.sender), "ERC721Attachable: slave token transfer not allowed");
super.transferFrom(from, to, tokenId);
}
} else {
super.transferFrom(from, to, tokenId);
for (uint256 i = 0; i < _masterTokens[tokenId].length; i++) {
IERC721(_masterTokens[tokenId][i].collection).transferFrom(from, to, _masterTokens[tokenId][i].tokenId);
}
}
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public virtual override {
if (slaveTokens[tokenId].collection != address(0)) {
if (msg.sender == slaveTokens[tokenId].collection) {
_safeTransfer(from, to, tokenId, data);
} else {
require(_transferApprovals.contains(msg.sender), "ERC721Attachable: slave token transfer not allowed");
super.safeTransferFrom(from, to, tokenId, data);
}
} else {
super.safeTransferFrom(from, to, tokenId, data);
for (uint256 i = 0; i < _masterTokens[tokenId].length; i++) {
IERC721(_masterTokens[tokenId][i].collection).safeTransferFrom(
from,
to,
_masterTokens[tokenId][i].tokenId,
data
);
}
}
}
function onBoundERC721Received(
address,
address to,
uint256 boundTokenId,
uint256 tokenId,
bytes calldata
) external returns (bytes4) {
require(isSlaveCollection(msg.sender), "ERC721Attachable: slave to non boundERC721 receiver");
if (to != address(0)) {
require(ownerOf(tokenId) == to, "ERC721Attachable: slave to incorrect owner");
_slaveTokenIndex[msg.sender][boundTokenId] = _masterTokens[tokenId].length;
_masterTokens[tokenId].push(BoundToken(msg.sender, boundTokenId));
} else {
_removeTokenFromMasterTokens(tokenId, msg.sender, boundTokenId);
}
return this.onBoundERC721Received.selector;
}
function _checkOnBoundERC721Received(
address from,
address to,
uint256 tokenId,
uint256 masterTokenId,
bytes memory _data
) private returns (bool) {
try IBoundERC721Receiver(from).onBoundERC721Received(msg.sender, to, tokenId, masterTokenId, _data) returns (
bytes4 retval
) {
return retval == IBoundERC721Receiver.onBoundERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721Attachable: transfer to non BoundERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
function _removeTokenFromMasterTokens(
uint256 tokenId,
address collection,
uint256 boundTokenId
) private {
uint256 lastTokenIndex = _masterTokens[tokenId].length - 1;
uint256 tokenIndex = _slaveTokenIndex[collection][boundTokenId];
BoundToken storage bToken = _masterTokens[tokenId][lastTokenIndex];
_masterTokens[tokenId][tokenIndex] = BoundToken(bToken.collection, bToken.tokenId);
_slaveTokenIndex[bToken.collection][bToken.tokenId] = tokenIndex;
delete _slaveTokenIndex[collection][boundTokenId];
_masterTokens[tokenId].pop();
}
}
文件 12 的 35:ERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "./IERC721Enumerable.sol";
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
mapping(uint256 => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 => uint256) private _allTokensIndex;
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
if (from == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (from != to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (to != from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId;
_ownedTokensIndex[lastTokenId] = tokenIndex;
}
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId;
_allTokensIndex[lastTokenId] = tokenIndex;
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
}
文件 13 的 35:ERC721Pausable.sol
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "../../../security/Pausable.sol";
abstract contract ERC721Pausable is ERC721, Pausable {
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
require(!paused(), "ERC721Pausable: token transfer while paused");
}
}
文件 14 的 35:ERC721Royalty.sol
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "../../common/ERC2981.sol";
import "../../../utils/introspection/ERC165.sol";
abstract contract ERC721Royalty is ERC2981, ERC721 {
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) {
return super.supportsInterface(interfaceId);
}
function _burn(uint256 tokenId) internal virtual override {
super._burn(tokenId);
_resetTokenRoyalty(tokenId);
}
}
文件 15 的 35:EnumerableSet.sol
pragma solidity ^0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
set._values[toDeleteIndex] = lastValue;
set._indexes[lastValue] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
return _values(set._inner);
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
文件 16 的 35:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 17 的 35:IAccessControlEnumerable.sol
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
interface IAccessControlEnumerable is IAccessControl {
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
function getRoleMemberCount(bytes32 role) external view returns (uint256);
}
文件 18 的 35:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 19 的 35:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
文件 20 的 35:IERC2981.sol
pragma solidity ^0.8.0;
import "../utils/introspection/IERC165.sol";
interface IERC2981 is IERC165 {
function royaltyInfo(uint256 tokenId, uint256 salePrice)
external
view
returns (address receiver, uint256 royaltyAmount);
}
文件 21 的 35:IERC5058.sol
pragma solidity ^0.8.8;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IERC5058 is IERC721 {
event Locked(address indexed operator, address indexed from, uint256 indexed tokenId, uint256 expired);
event Unlocked(address indexed operator, address indexed from, uint256 indexed tokenId);
event LockApproval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event LockApprovalForAll(address indexed owner, address indexed operator, bool approved);
function lockerOf(uint256 tokenId) external view returns (address locker);
function lockFrom(
address from,
uint256 tokenId,
uint256 expired
) external;
function unlockFrom(address from, uint256 tokenId) external;
function lockApprove(address to, uint256 tokenId) external;
function setLockApprovalForAll(address operator, bool approved) external;
function getLockApproved(uint256 tokenId) external view returns (address operator);
function isLockApprovedForAll(address owner, address operator) external view returns (bool);
function isLocked(uint256 tokenId) external view returns (bool);
}
文件 22 的 35:IERC5058Factory.sol
pragma solidity ^0.8.8;
interface IERC5058Factory {
event DeployedBound(address indexed preimage, address bound);
function allBoundsLength() external view returns (uint256);
function boundByIndex(uint256 index) external view returns (address);
function existBound(address preimage) external view returns (bool);
function boundOf(address preimage) external view returns (address);
function boundDeploy(address preimage) external returns (address);
}
文件 23 的 35:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function setApprovalForAll(address operator, bool _approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
文件 24 的 35:IERC721Bound.sol
pragma solidity ^0.8.8;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IERC721Bound is IERC721 {
function preimage() external view returns (address);
function contractURI() external view returns (string memory);
function exists(uint256 tokenId) external view returns (bool);
function setBaseTokenURI(string memory _baseTokenURI) external;
function setContractURI(string memory uri) external;
function safeMint(
address to,
uint256 tokenId,
bytes memory data
) external;
function burn(uint256 tokenId) external;
}
文件 25 的 35:IERC721Enumerable.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Enumerable is IERC721 {
function totalSupply() external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
function tokenByIndex(uint256 index) external view returns (uint256);
}
文件 26 的 35:IERC721Metadata.sol
pragma solidity ^0.8.0;
import "../IERC721.sol";
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 27 的 35:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 28 的 35:MatrixPlusBox.sol
pragma solidity ^0.8.8;
import "@divergencetech/ethier/contracts/erc721/BaseTokenURI.sol";
import "@divergencetech/ethier/contracts/utils/OwnerPausable.sol";
import "@openzeppelin/contracts/access/AccessControlEnumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol";
import "../EIP5058/extensions/ERC5058Bound.sol";
import "../utils/ERC721Attachable.sol";
import "../utils/TokenWithdraw.sol";
contract MatrixPlusBox is
Context,
OwnerPausable,
BaseTokenURI,
ERC721Enumerable,
ERC721Pausable,
ERC5058Bound,
ERC721Attachable,
ERC721Royalty,
AccessControlEnumerable,
TokenWithdraw
{
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
bytes32 public constant UNBIND_ROLE = keccak256("UNBIND_ROLE");
constructor() ERC721("Matrix Plus Box", "MPB") BaseTokenURI("https://api.bakeryswap.org/nft/matrix-plus-box/") {
_grantRole(DEFAULT_ADMIN_ROLE, _msgSender());
_grantRole(MINTER_ROLE, _msgSender());
_grantRole(BURNER_ROLE, _msgSender());
_grantRole(UNBIND_ROLE, _msgSender());
}
function exists(uint256 tokenId) external view returns (bool) {
return _exists(tokenId);
}
function safeMint(
address to,
uint256 tokenId,
bytes memory data
) external onlyRole(MINTER_ROLE) {
_safeMint(to, tokenId, data);
}
function lockMint(
address to,
uint256 tokenId,
uint256 expired,
bytes memory data
) external onlyRole(MINTER_ROLE) {
_safeLockMint(to, tokenId, expired, data);
}
function mint(address to, uint256 tokenId) external onlyRole(MINTER_ROLE) {
_mint(to, tokenId);
}
function mintBatch(address to, uint256[] calldata tokenIds) external onlyRole(MINTER_ROLE) {
for (uint256 i = 0; i < tokenIds.length; i++) {
_mint(to, tokenIds[i]);
}
}
function mintRange(
address to,
uint256 fromId,
uint256 toId
) external onlyRole(MINTER_ROLE) {
for (; fromId <= toId; fromId++) {
_mint(to, fromId);
}
}
function burn(uint256 tokenId) external {
require(
_isApprovedOrOwner(_msgSender(), tokenId) ||
hasRole(BURNER_ROLE, _msgSender()) ||
masterOf(tokenId) == _msgSender(),
"ERC721: caller is not owner nor approved"
);
_burn(tokenId);
}
function slaveMint(
address to,
uint256 tokenId,
address collection,
uint256 hostTokenId
) external onlyRole(MINTER_ROLE) {
_slaveMint(to, tokenId, collection, hostTokenId);
}
function removeSlave(uint256 tokenId) external {
require(hasRole(UNBIND_ROLE, _msgSender()) || masterOf(tokenId) == _msgSender(), "ERC721: not unbind role");
_removeSlave(tokenId);
}
function removeMaster(uint256 tokenId) external onlyRole(UNBIND_ROLE) {
_removeMaster(tokenId);
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override(ERC721, ERC721Attachable) {
super.transferFrom(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override(ERC721, ERC721Attachable) {
super.safeTransferFrom(from, to, tokenId, _data);
}
function setRoleAdmin(bytes32 roleId, bytes32 adminRoleId) external onlyOwner {
_setRoleAdmin(roleId, adminRoleId);
}
function setFactory(address factory) external onlyOwner {
_setFactory(factory);
}
function setDefaultRoyaltyInfo(address receiver, uint96 feeNumerator) external onlyOwner {
_setDefaultRoyalty(receiver, feeNumerator);
}
function deleteDefaultRoyalty() external onlyOwner {
_deleteDefaultRoyalty();
}
function setTokenRoyalty(
uint256 tokenId,
address recipient,
uint96 fraction
) external onlyOwner {
_setTokenRoyalty(tokenId, recipient, fraction);
}
function resetTokenRoyalty(uint256 tokenId) external onlyOwner {
_resetTokenRoyalty(tokenId);
}
function _baseURI() internal view override(BaseTokenURI, ERC721) returns (string memory) {
return BaseTokenURI._baseURI();
}
function _burn(uint256 tokenId) internal virtual override(ERC721, ERC721Royalty, ERC5058, ERC721Attachable) {
super._burn(tokenId);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override(ERC721, ERC721Enumerable, ERC721Pausable, ERC5058) {
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(ERC721, ERC721Enumerable, ERC5058, ERC721Royalty, AccessControlEnumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
文件 29 的 35:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 30 的 35:OwnerPausable.sol
pragma solidity >=0.8.0 <0.9.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
contract OwnerPausable is Ownable, Pausable {
function pause() public onlyOwner {
Pausable._pause();
}
function unpause() public onlyOwner {
Pausable._unpause();
}
}
文件 31 的 35:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
function paused() public view virtual returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 32 的 35:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 33 的 35:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 34 的 35:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
文件 35 的 35:TokenWithdraw.sol
pragma solidity ^0.8.8;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
abstract contract TokenWithdraw is Ownable, ReentrancyGuard {
using SafeERC20 for IERC20;
function withdraw(address payable to, uint256 amount) external onlyOwner nonReentrant {
Address.sendValue(to, amount);
}
function withdrawERC20(
address token,
address to,
uint256 amount
) external onlyOwner nonReentrant {
IERC20(token).safeTransfer(to, amount);
}
function withdrawERC721(
address token,
address to,
uint256 tokenId
) external onlyOwner nonReentrant {
IERC721(token).safeTransferFrom(address(this), to, tokenId);
}
}
{
"compilationTarget": {
"contracts/NFTs/MatrixPlusBox.sol": "MatrixPlusBox"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"}],"name":"CollectionAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"}],"name":"CollectionRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"LockApproval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"LockApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expired","type":"uint256"}],"name":"Locked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"}],"name":"TransferApprove","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"}],"name":"TransferDisapprove","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Unlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"BURNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNBIND_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"addCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"addTransferApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"allSlaveTokenLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bound","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burnBound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deleteDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getLockApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isLockApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"isSlaveCollection","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isSlaveToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isTransferApproval","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"lockApprove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"expired","type":"uint256"}],"name":"lockFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"expired","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"lockMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"lockerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"masterOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"mintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"fromId","type":"uint256"},{"internalType":"uint256","name":"toId","type":"uint256"}],"name":"mintRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"boundTokenId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onBoundERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"removeCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"removeMaster","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"removeSlave","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"removeTransferApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"resetTokenRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseTokenURI","type":"string"}],"name":"setBaseTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyaltyInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"factory","type":"address"}],"name":"setFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setLockApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"roleId","type":"bytes32"},{"internalType":"bytes32","name":"adminRoleId","type":"bytes32"}],"name":"setRoleAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint96","name":"fraction","type":"uint96"}],"name":"setTokenRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"hostTokenId","type":"uint256"}],"name":"slaveMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"slaveTokenByIndex","outputs":[{"components":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct ERC721Attachable.BoundToken","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"slaveTokens","outputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"unlockFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawERC721","outputs":[],"stateMutability":"nonpayable","type":"function"}]