Overview
GLMR Balance
GLMR Value
$0.00View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SoulEquipFacet
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 175 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import {AppStorage, Modifiers, Staked} from "../libraries/LibAppStorage.sol";
import {LibMeta} from "../libraries/LibMeta.sol";
import "../interfaces/IEquipFacet.sol";
import "../interfaces/IAssetAttributes.sol";
import "@rmrk-team/evm-contracts/contracts/RMRK/equippable/IERC6220.sol";
import "@rmrk-team/evm-contracts/contracts/RMRK/nestable/IERC6059.sol";
import "../libraries/Errors.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}.
*/
contract SoulEquipFacet is IEquipFacet, Modifiers {
constructor() {}
/**
* @notice Used to equip a child into a token.
* @dev The `IntakeEquip` stuct contains the following data:
* [
* tokenId,
* childIndex,
* assetId,
* slotPartId,
* childAssetId
* ]
* @param data An `IntakeEquip` struct specifying the equip data
*/
function callEquip(
address collectionAddress,
IERC6220.IntakeEquip memory data
) public {
uint256 estraTokenId = s.stakedSoulTokens[collectionAddress][
data.tokenId
];
_verifyEstraTokenOwnership(estraTokenId);
IERC6220(collectionAddress).equip(data);
}
/**
* @notice Used to unequip a child from a token.
* @param data An `IntakeEquip` struct specifying the equip data
*/
function callUnEquip(
address collectionAddress,
IERC6220.IntakeEquip memory data
) public {
uint256 estraTokenId = s.stakedSoulTokens[collectionAddress][
data.tokenId
];
_verifyEstraTokenOwnership(estraTokenId);
IERC6220(collectionAddress).unequip(
data.tokenId,
data.assetId,
data.slotPartId
);
}
/**
* @notice calls the multiEquip function on the soul contract
* @dev we must verify estraToken ownership of all tokens supplied in each argument.
* @dev This is to prevent a user from sneaking in a token they do not own,
* @dev since the staking contract will have approval to manage the pool of soul tokens
* @param unequip_ array of unequip structs
* @param transfer_ array of transfer structs
* @param equip_ array of equip structs
*/
function multiEquip(
address collectionAddress,
IERC6220.IntakeEquip[] calldata unequip_,
IntakeChildTransfer[] calldata transfer_,
IERC6220.IntakeEquip[] calldata equip_
) public whenNotPaused {
if (
equip_.length != unequip_.length ||
equip_.length != transfer_.length
) revert BadInputLengths();
for (uint256 i; i < unequip_.length; ) {
uint256 estraTokenIdUnequip = s.stakedSoulTokens[collectionAddress][
unequip_[i].tokenId
];
if (unequip_[i].tokenId > 0) {
_verifyEstraTokenOwnership(estraTokenIdUnequip);
IERC6220(collectionAddress).unequip(
unequip_[i].tokenId,
unequip_[i].assetId,
unequip_[i].slotPartId
);
}
if (transfer_[i].tokenId > 0) {
// Transferring a child to a new parent
// note: estraToken or token ownership (allow child transfer from non-staked souls)
uint256 estraTokenIdTransfer = s.stakedSoulTokens[
collectionAddress
][transfer_[i].tokenId];
if (transfer_[i].childIndex < 99999) {
if (transfer_[i].parentIsStaked == true) {
_verifyEstraTokenOwnership(estraTokenIdTransfer);
} else {
_verifySoulTokenOwnership(
collectionAddress,
transfer_[i].tokenId
);
}
IERC6059(collectionAddress).transferChild(
transfer_[i].tokenId,
transfer_[i].to,
transfer_[i].destinationId,
transfer_[i].childIndex,
transfer_[i].childAddress,
transfer_[i].childId,
transfer_[i].isPending,
""
);
} else {
// Token is not currently nested, so use nestTransfer instead
// note ownership of child token is checked inside nestTransfer
// thus token owner must first approve the loot contract
_verifyNestableTokenOwnership(
transfer_[i].childAddress,
transfer_[i].childId
);
IERC6059(transfer_[i].childAddress).nestTransferFrom(
LibMeta.msgSender(),
transfer_[i].to,
transfer_[i].childId,
transfer_[i].destinationId,
""
);
}
}
unchecked {
++i;
}
}
for (uint256 i; i < equip_.length; ) {
uint256 estraTokenIdEquip = s.stakedSoulTokens[collectionAddress][
equip_[i].tokenId
];
if (equip_[i].tokenId > 0) {
_verifyEstraTokenOwnership(estraTokenIdEquip);
IERC6220(collectionAddress).equip(equip_[i]);
}
unchecked {
++i;
}
}
}
/** Ownership Verifiers */
/**
* @dev See {IERC721-ownerOf}.
*/
function _ownerOf(uint256 tokenId) internal view returns (address) {
address owner = s.stakingTokenOwners[tokenId];
require(owner != address(0), "ERC721: invalid token ID");
return owner;
}
/**
* @notice Verifies that LibMeta.msgSender() owns supplied estraToken tokenId
* @param estraTokenId Estra tokenId to verify ownership against
*/
function _verifyEstraTokenOwnership(uint256 estraTokenId) internal view {
if (_ownerOf(estraTokenId) != LibMeta.msgSender())
revert NotEstraTokenOwner();
}
function _verifySoulTokenOwnership(
address collectionAddress,
uint256 tokenId
) internal view {
if (s.stakedCollectionId[collectionAddress] == 0)
revert NotSupportedCollection();
if (
IERC721Enumerable(collectionAddress).ownerOf(tokenId) !=
LibMeta.msgSender()
) revert NotSoulTokenOwner();
}
function _verifyNestableTokenOwnership(
address childAddress_,
uint256 childTokenId_
) internal view {
if (
IERC6059(childAddress_).ownerOf(childTokenId_) !=
LibMeta.msgSender()
) revert NotChildTokenOwner();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
import "../multiasset/IERC5773.sol";
/**
* @title IERC6220
* @author RMRK team
* @notice Interface smart contract of the RMRK equippable module.
*/
interface IERC6220 is IERC5773 {
/**
* @notice Used to store the core structure of the `Equippable` RMRK lego.
* @return assetId The ID of the asset equipping a child
* @return childAssetId The ID of the asset used as equipment
* @return childId The ID of token that is equipped
* @return childEquippableAddress Address of the collection to which the child asset belongs to
*/
struct Equipment {
uint64 assetId;
uint64 childAssetId;
uint256 childId;
address childEquippableAddress;
}
/**
* @notice Used to provide a struct for inputing equip data.
* @dev Only used for input and not storage of data.
* @return tokenId ID of the token we are managing
* @return childIndex Index of a child in the list of token's active children
* @return assetId ID of the asset that we are equipping into
* @return slotPartId ID of the slot part that we are using to equip
* @return childAssetId ID of the asset that we are equipping
*/
struct IntakeEquip {
uint256 tokenId;
uint256 childIndex;
uint64 assetId;
uint64 slotPartId;
uint64 childAssetId;
}
/**
* @notice Used to notify listeners that a child's asset has been equipped into one of its parent assets.
* @param tokenId ID of the token that had an asset equipped
* @param assetId ID of the asset associated with the token we are equipping into
* @param slotPartId ID of the slot we are using to equip
* @param childId ID of the child token we are equipping into the slot
* @param childAddress Address of the child token's collection
* @param childAssetId ID of the asset associated with the token we are equipping
*/
event ChildAssetEquipped(
uint256 indexed tokenId,
uint64 indexed assetId,
uint64 indexed slotPartId,
uint256 childId,
address childAddress,
uint64 childAssetId
);
/**
* @notice Used to notify listeners that a child's asset has been unequipped from one of its parent assets.
* @param tokenId ID of the token that had an asset unequipped
* @param assetId ID of the asset associated with the token we are unequipping out of
* @param slotPartId ID of the slot we are unequipping from
* @param childId ID of the token being unequipped
* @param childAddress Address of the collection that a token that is being unequipped belongs to
* @param childAssetId ID of the asset associated with the token we are unequipping
*/
event ChildAssetUnequipped(
uint256 indexed tokenId,
uint64 indexed assetId,
uint64 indexed slotPartId,
uint256 childId,
address childAddress,
uint64 childAssetId
);
/**
* @notice Used to notify listeners that the assets belonging to a `equippableGroupId` have been marked as
* equippable into a given slot and parent
* @param equippableGroupId ID of the equippable group being marked as equippable into the slot associated with
* `slotPartId` of the `parentAddress` collection
* @param slotPartId ID of the slot part of the catalog into which the parts belonging to the equippable group
* associated with `equippableGroupId` can be equipped
* @param parentAddress Address of the collection into which the parts belonging to `equippableGroupId` can be
* equipped
*/
event ValidParentEquippableGroupIdSet(
uint64 indexed equippableGroupId,
uint64 indexed slotPartId,
address parentAddress
);
/**
* @notice Used to equip a child into a token.
* @dev The `IntakeEquip` stuct contains the following data:
* [
* tokenId,
* childIndex,
* assetId,
* slotPartId,
* childAssetId
* ]
* @param data An `IntakeEquip` struct specifying the equip data
*/
function equip(IntakeEquip memory data) external;
/**
* @notice Used to unequip child from parent token.
* @dev This can only be called by the owner of the token or by an account that has been granted permission to
* manage the given token by the current owner.
* @param tokenId ID of the parent from which the child is being unequipped
* @param assetId ID of the parent's asset that contains the `Slot` into which the child is equipped
* @param slotPartId ID of the `Slot` from which to unequip the child
*/
function unequip(
uint256 tokenId,
uint64 assetId,
uint64 slotPartId
) external;
/**
* @notice Used to check whether the token has a given child equipped.
* @dev This is used to prevent from transferring a child that is equipped.
* @param tokenId ID of the parent token for which we are querying for
* @param childAddress Address of the child token's smart contract
* @param childId ID of the child token
* @return A boolean value indicating whether the child token is equipped into the given token or not
*/
function isChildEquipped(
uint256 tokenId,
address childAddress,
uint256 childId
) external view returns (bool);
/**
* @notice Used to verify whether a token can be equipped into a given parent's slot.
* @param parent Address of the parent token's smart contract
* @param tokenId ID of the token we want to equip
* @param assetId ID of the asset associated with the token we want to equip
* @param slotId ID of the slot that we want to equip the token into
* @return A boolean indicating whether the token with the given asset can be equipped into the desired slot
*/
function canTokenBeEquippedWithAssetIntoSlot(
address parent,
uint256 tokenId,
uint64 assetId,
uint64 slotId
) external view returns (bool);
/**
* @notice Used to get the Equipment object equipped into the specified slot of the desired token.
* @dev The `Equipment` struct consists of the following data:
* [
* assetId,
* childAssetId,
* childId,
* childEquippableAddress
* ]
* @param tokenId ID of the token for which we are retrieving the equipped object
* @param targetCatalogAddress Address of the `Catalog` associated with the `Slot` part of the token
* @param slotPartId ID of the `Slot` part that we are checking for equipped objects
* @return The `Equipment` struct containing data about the equipped object
*/
function getEquipment(
uint256 tokenId,
address targetCatalogAddress,
uint64 slotPartId
) external view returns (Equipment memory);
/**
* @notice Used to get the asset and equippable data associated with given `assetId`.
* @param tokenId ID of the token for which to retrieve the asset
* @param assetId ID of the asset of which we are retrieving
* @return metadataURI The metadata URI of the asset
* @return equippableGroupId ID of the equippable group this asset belongs to
* @return catalogAddress The address of the catalog the part belongs to
* @return partIds An array of IDs of parts included in the asset
*/
function getAssetAndEquippableData(
uint256 tokenId,
uint64 assetId
)
external
view
returns (
string memory metadataURI,
uint64 equippableGroupId,
address catalogAddress,
uint64[] memory partIds
);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @title IERC5773
* @author RMRK team
* @notice Interface smart contract of the RMRK multi asset module.
*/
interface IERC5773 is IERC165 {
/**
* @notice Used to notify listeners that an asset object is initialized at `assetId`.
* @param assetId ID of the asset that was initialized
*/
event AssetSet(uint64 indexed assetId);
/**
* @notice Used to notify listeners that an asset object at `assetId` is added to token's pending asset
* array.
* @param tokenIds An array of token IDs that received a new pending asset
* @param assetId ID of the asset that has been added to the token's pending assets array
* @param replacesId ID of the asset that would be replaced
*/
event AssetAddedToTokens(
uint256[] tokenIds,
uint64 indexed assetId,
uint64 indexed replacesId
);
/**
* @notice Used to notify listeners that an asset object at `assetId` is accepted by the token and migrated
* from token's pending assets array to active assets array of the token.
* @param tokenId ID of the token that had a new asset accepted
* @param assetId ID of the asset that was accepted
* @param replacesId ID of the asset that was replaced
*/
event AssetAccepted(
uint256 indexed tokenId,
uint64 indexed assetId,
uint64 indexed replacesId
);
/**
* @notice Used to notify listeners that an asset object at `assetId` is rejected from token and is dropped
* from the pending assets array of the token.
* @param tokenId ID of the token that had an asset rejected
* @param assetId ID of the asset that was rejected
*/
event AssetRejected(uint256 indexed tokenId, uint64 indexed assetId);
/**
* @notice Used to notify listeners that token's prioritiy array is reordered.
* @param tokenId ID of the token that had the asset priority array updated
*/
event AssetPrioritySet(uint256 indexed tokenId);
/**
* @notice Used to notify listeners that owner has granted an approval to the user to manage the assets of a
* given token.
* @dev Approvals must be cleared on transfer
* @param owner Address of the account that has granted the approval for all token's assets
* @param approved Address of the account that has been granted approval to manage the token's assets
* @param tokenId ID of the token on which the approval was granted
*/
event ApprovalForAssets(
address indexed owner,
address indexed approved,
uint256 indexed tokenId
);
/**
* @notice Used to notify listeners that owner has granted approval to the user to manage assets of all of their
* tokens.
* @param owner Address of the account that has granted the approval for all assets on all of their tokens
* @param operator Address of the account that has been granted the approval to manage the token's assets on all of
* the tokens
* @param approved Boolean value signifying whether the permission has been granted (`true`) or revoked (`false`)
*/
event ApprovalForAllForAssets(
address indexed owner,
address indexed operator,
bool approved
);
/**
* @notice Accepts an asset at from the pending array of given token.
* @dev Migrates the asset from the token's pending asset array to the token's active asset array.
* @dev Active assets cannot be removed by anyone, but can be replaced by a new asset.
* @dev Requirements:
*
* - The caller must own the token or be approved to manage the token's assets
* - `tokenId` must exist.
* - `index` must be in range of the length of the pending asset array.
* @dev Emits an {AssetAccepted} event.
* @param tokenId ID of the token for which to accept the pending asset
* @param index Index of the asset in the pending array to accept
* @param assetId ID of the asset expected to be in the index
*/
function acceptAsset(
uint256 tokenId,
uint256 index,
uint64 assetId
) external;
/**
* @notice Rejects an asset from the pending array of given token.
* @dev Removes the asset from the token's pending asset array.
* @dev Requirements:
*
* - The caller must own the token or be approved to manage the token's assets
* - `tokenId` must exist.
* - `index` must be in range of the length of the pending asset array.
* @dev Emits a {AssetRejected} event.
* @param tokenId ID of the token that the asset is being rejected from
* @param index Index of the asset in the pending array to be rejected
* @param assetId ID of the asset expected to be in the index
*/
function rejectAsset(
uint256 tokenId,
uint256 index,
uint64 assetId
) external;
/**
* @notice Rejects all assets from the pending array of a given token.
* @dev Effecitvely deletes the pending array.
* @dev Requirements:
*
* - The caller must own the token or be approved to manage the token's assets
* - `tokenId` must exist.
* @dev Emits a {AssetRejected} event with assetId = 0.
* @param tokenId ID of the token of which to clear the pending array.
* @param maxRejections Maximum number of expected assets to reject, used to prevent from rejecting assets which
* arrive just before this operation.
*/
function rejectAllAssets(uint256 tokenId, uint256 maxRejections) external;
/**
* @notice Sets a new priority array for a given token.
* @dev The priority array is a non-sequential list of `uint64`s, where the lowest value is considered highest
* priority.
* @dev Value `0` of a priority is a special case equivalent to unitialized.
* @dev Requirements:
*
* - The caller must own the token or be approved to manage the token's assets
* - `tokenId` must exist.
* - The length of `priorities` must be equal the length of the active assets array.
* @dev Emits a {AssetPrioritySet} event.
* @param tokenId ID of the token to set the priorities for
* @param priorities An array of priorities of active assets. The succesion of items in the priorities array
* matches that of the succesion of items in the active array
*/
function setPriority(
uint256 tokenId,
uint64[] calldata priorities
) external;
/**
* @notice Used to retrieve IDs of the active assets of given token.
* @dev Asset data is stored by reference, in order to access the data corresponding to the ID, call
* `getAssetMetadata(tokenId, assetId)`.
* @dev You can safely get 10k
* @param tokenId ID of the token to retrieve the IDs of the active assets
* @return An array of active asset IDs of the given token
*/
function getActiveAssets(
uint256 tokenId
) external view returns (uint64[] memory);
/**
* @notice Used to retrieve IDs of the pending assets of given token.
* @dev Asset data is stored by reference, in order to access the data corresponding to the ID, call
* `getAssetMetadata(tokenId, assetId)`.
* @param tokenId ID of the token to retrieve the IDs of the pending assets
* @return An array of pending asset IDs of the given token
*/
function getPendingAssets(
uint256 tokenId
) external view returns (uint64[] memory);
/**
* @notice Used to retrieve the priorities of the active resoources of a given token.
* @dev Asset priorities are a non-sequential array of uint64 values with an array size equal to active asset
* priorites.
* @param tokenId ID of the token for which to retrieve the priorities of the active assets
* @return An array of priorities of the active assets of the given token
*/
function getActiveAssetPriorities(
uint256 tokenId
) external view returns (uint64[] memory);
/**
* @notice Used to retrieve the asset that will be replaced if a given asset from the token's pending array
* is accepted.
* @dev Asset data is stored by reference, in order to access the data corresponding to the ID, call
* `getAssetMetadata(tokenId, assetId)`.
* @param tokenId ID of the token to check
* @param newAssetId ID of the pending asset which will be accepted
* @return ID of the asset which will be replaced
*/
function getAssetReplacements(
uint256 tokenId,
uint64 newAssetId
) external view returns (uint64);
/**
* @notice Used to fetch the asset metadata of the specified token's active asset with the given index.
* @dev Assets are stored by reference mapping `_assets[assetId]`.
* @dev Can be overriden to implement enumerate, fallback or other custom logic.
* @param tokenId ID of the token from which to retrieve the asset metadata
* @param assetId Asset Id, must be in the active assets array
* @return The metadata of the asset belonging to the specified index in the token's active assets
* array
*/
function getAssetMetadata(
uint256 tokenId,
uint64 assetId
) external view returns (string memory);
// Approvals
/**
* @notice Used to grant permission to the user to manage token's assets.
* @dev This differs from transfer approvals, as approvals are not cleared when the approved party accepts or
* rejects an asset, or sets asset priorities. This approval is cleared on token transfer.
* @dev Only a single account can be approved at a time, so approving the `0x0` address clears previous approvals.
* @dev Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
* @dev Emits an {ApprovalForAssets} event.
* @param to Address of the account to grant the approval to
* @param tokenId ID of the token for which the approval to manage the assets is granted
*/
function approveForAssets(address to, uint256 tokenId) external;
/**
* @notice Used to retrieve the address of the account approved to manage assets of a given token.
* @dev Requirements:
*
* - `tokenId` must exist.
* @param tokenId ID of the token for which to retrieve the approved address
* @return Address of the account that is approved to manage the specified token's assets
*/
function getApprovedForAssets(
uint256 tokenId
) external view returns (address);
/**
* @notice Used to add or remove an operator of assets for the caller.
* @dev Operators can call {acceptAsset}, {rejectAsset}, {rejectAllAssets} or {setPriority} for any token
* owned by the caller.
* @dev Requirements:
*
* - The `operator` cannot be the caller.
* @dev Emits an {ApprovalForAllForAssets} event.
* @param operator Address of the account to which the operator role is granted or revoked from
* @param approved The boolean value indicating whether the operator role is being granted (`true`) or revoked
* (`false`)
*/
function setApprovalForAllForAssets(
address operator,
bool approved
) external;
/**
* @notice Used to check whether the address has been granted the operator role by a given address or not.
* @dev See {setApprovalForAllForAssets}.
* @param owner Address of the account that we are checking for whether it has granted the operator role
* @param operator Address of the account that we are checking whether it has the operator role or not
* @return A boolean value indicating wehter the account we are checking has been granted the operator role
*/
function isApprovedForAllForAssets(
address owner,
address operator
) external view returns (bool);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @title IERC6059
* @author RMRK team
* @notice Interface smart contract of the RMRK nestable module.
*/
interface IERC6059 is IERC165 {
/**
* @notice The core struct of RMRK ownership.
* @dev The `DirectOwner` struct is used to store information of the next immediate owner, be it the parent token or
* the externally owned account.
* @dev If the token is owned by the externally owned account, the `tokenId` should equal `0`.
* @param tokenId ID of the parent token
* @param ownerAddress Address of the owner of the token. If the owner is another token, then the address should be
* the one of the parent token's collection smart contract. If the owner is externally owned account, the address
* should be the address of this account
* @param isNft A boolean value signifying whether the token is owned by another token (`true`) or by an externally
* owned account (`false`)
*/
struct DirectOwner {
uint256 tokenId;
address ownerAddress;
}
/**
* @notice Used to notify listeners that the token is being transferred.
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
* @param from Address of the previous immediate owner, which is a smart contract if the token was nested.
* @param to Address of the new immediate owner, which is a smart contract if the token is being nested.
* @param fromTokenId ID of the previous parent token. If the token was not nested before, the value should be `0`
* @param toTokenId ID of the new parent token. If the token is not being nested, the value should be `0`
* @param tokenId ID of the token being transferred
*/
event NestTransfer(
address indexed from,
address indexed to,
uint256 fromTokenId,
uint256 toTokenId,
uint256 indexed tokenId
);
/**
* @notice Used to notify listeners that a new token has been added to a given token's pending children array.
* @dev Emitted when a child NFT is added to a token's pending array.
* @param tokenId ID of the token that received a new pending child token
* @param childIndex Index of the proposed child token in the parent token's pending children array
* @param childAddress Address of the proposed child token's collection smart contract
* @param childId ID of the child token in the child token's collection smart contract
*/
event ChildProposed(
uint256 indexed tokenId,
uint256 childIndex,
address indexed childAddress,
uint256 indexed childId
);
/**
* @notice Used to notify listeners that a new child token was accepted by the parent token.
* @dev Emitted when a parent token accepts a token from its pending array, migrating it to the active array.
* @param tokenId ID of the token that accepted a new child token
* @param childIndex Index of the newly accepted child token in the parent token's active children array
* @param childAddress Address of the child token's collection smart contract
* @param childId ID of the child token in the child token's collection smart contract
*/
event ChildAccepted(
uint256 indexed tokenId,
uint256 childIndex,
address indexed childAddress,
uint256 indexed childId
);
/**
* @notice Used to notify listeners that all pending child tokens of a given token have been rejected.
* @dev Emitted when a token removes all a child tokens from its pending array.
* @param tokenId ID of the token that rejected all of the pending children
*/
event AllChildrenRejected(uint256 indexed tokenId);
/**
* @notice Used to notify listeners a child token has been transferred from parent token.
* @dev Emitted when a token transfers a child from itself, transferring ownership to the root owner.
* @param tokenId ID of the token that transferred a child token
* @param childIndex Index of a child in the array from which it is being transferred
* @param childAddress Address of the child token's collection smart contract
* @param childId ID of the child token in the child token's collection smart contract
* @param fromPending A boolean value signifying whether the token was in the pending child tokens array (`true`) or
* in the active child tokens array (`false`)
* @param toZero A boolean value signifying whether the token is being transferred to the `0x0` address (`true`) or
* not (`false`)
*/
event ChildTransferred(
uint256 indexed tokenId,
uint256 childIndex,
address indexed childAddress,
uint256 indexed childId,
bool fromPending,
bool toZero
);
/**
* @notice The core child token struct, holding the information about the child tokens.
* @return tokenId ID of the child token in the child token's collection smart contract
* @return contractAddress Address of the child token's smart contract
*/
struct Child {
uint256 tokenId;
address contractAddress;
}
/**
* @notice Used to retrieve the *root* owner of a given token.
* @dev The *root* owner of the token is an externally owned account (EOA). If the given token is child of another
* NFT, this will return an EOA address. Otherwise, if the token is owned by an EOA, this EOA wil be returned.
* @param tokenId ID of the token for which the *root* owner has been retrieved
* @return owner The *root* owner of the token
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @notice Used to retrieve the immediate owner of the given token.
* @dev If the immediate owner is another token, the address returned, should be the one of the parent token's
* collection smart contract.
* @param tokenId ID of the token for which the RMRK owner is being retrieved
* @return Address of the given token's owner
* @return The ID of the parent token. Should be `0` if the owner is an externally owned account
* @return The boolean value signifying whether the owner is an NFT or not
*/
function directOwnerOf(
uint256 tokenId
) external view returns (address, uint256, bool);
/**
* @notice Used to burn a given token.
* @dev When a token is burned, all of its child tokens are recursively burned as well.
* @dev When specifying the maximum recursive burns, the execution will be reverted if there are more children to be
* burned.
* @dev Setting the `maxRecursiveBurn` value to 0 will only attempt to burn the specified token and revert if there
* are any child tokens present.
* @dev The approvals are cleared when the token is burned.
* @dev Requirements:
*
* - `tokenId` must exist.
* @dev Emits a {Transfer} event.
* @param tokenId ID of the token to burn
* @param maxRecursiveBurns Maximum number of tokens to recursively burn
* @return Number of recursively burned children
*/
function burn(
uint256 tokenId,
uint256 maxRecursiveBurns
) external returns (uint256);
/**
* @notice Used to add a child token to a given parent token.
* @dev This adds the child token into the given parent token's pending child tokens array.
* @dev Requirements:
*
* - `directOwnerOf` on the child contract must resolve to the called contract.
* - the pending array of the parent contract must not be full.
* @param parentId ID of the parent token to receive the new child token
* @param childId ID of the new proposed child token
* @param data Additional data with no specified format
*/
function addChild(
uint256 parentId,
uint256 childId,
bytes memory data
) external;
/**
* @notice Used to accept a pending child token for a given parent token.
* @dev This moves the child token from parent token's pending child tokens array into the active child tokens
* array.
* @param parentId ID of the parent token for which the child token is being accepted
* @param childIndex Index of a child tokem in the given parent's pending children array
* @param childAddress Address of the collection smart contract of the child token expected to be located at the
* specified index of the given parent token's pending children array
* @param childId ID of the child token expected to be located at the specified index of the given parent token's
* pending children array
*/
function acceptChild(
uint256 parentId,
uint256 childIndex,
address childAddress,
uint256 childId
) external;
/**
* @notice Used to reject all pending children of a given parent token.
* @dev Removes the children from the pending array mapping.
* @dev This does not update the ownership storage data on children. If necessary, ownership can be reclaimed by the
* rootOwner of the previous parent.
* @dev Requirements:
*
* Requirements:
*
* - `parentId` must exist
* @param parentId ID of the parent token for which to reject all of the pending tokens.
* @param maxRejections Maximum number of expected children to reject, used to prevent from rejecting children which
* arrive just before this operation.
*/
function rejectAllChildren(
uint256 parentId,
uint256 maxRejections
) external;
/**
* @notice Used to transfer a child token from a given parent token.
* @dev When transferring a child token, the owner of the token is set to `to`, or is not updated in the event of
* `to` being the `0x0` address.
* @param tokenId ID of the parent token from which the child token is being transferred
* @param to Address to which to transfer the token to
* @param destinationId ID of the token to receive this child token (MUST be 0 if the destination is not a token)
* @param childIndex Index of a token we are transferring, in the array it belongs to (can be either active array or
* pending array)
* @param childAddress Address of the child token's collection smart contract.
* @param childId ID of the child token in its own collection smart contract.
* @param isPending A boolean value indicating whether the child token being transferred is in the pending array of
* the parent token (`true`) or in the active array (`false`)
* @param data Additional data with no specified format, sent in call to `_to`
*/
function transferChild(
uint256 tokenId,
address to,
uint256 destinationId,
uint256 childIndex,
address childAddress,
uint256 childId,
bool isPending,
bytes memory data
) external;
/**
* @notice Used to retrieve the active child tokens of a given parent token.
* @dev Returns array of Child structs existing for parent token.
* @dev The Child struct consists of the following values:
* [
* tokenId,
* contractAddress
* ]
* @param parentId ID of the parent token for which to retrieve the active child tokens
* @return An array of Child structs containing the parent token's active child tokens
*/
function childrenOf(
uint256 parentId
) external view returns (Child[] memory);
/**
* @notice Used to retrieve the pending child tokens of a given parent token.
* @dev Returns array of pending Child structs existing for given parent.
* @dev The Child struct consists of the following values:
* [
* tokenId,
* contractAddress
* ]
* @param parentId ID of the parent token for which to retrieve the pending child tokens
* @return An array of Child structs containing the parent token's pending child tokens
*/
function pendingChildrenOf(
uint256 parentId
) external view returns (Child[] memory);
/**
* @notice Used to retrieve a specific active child token for a given parent token.
* @dev Returns a single Child struct locating at `index` of parent token's active child tokens array.
* @dev The Child struct consists of the following values:
* [
* tokenId,
* contractAddress
* ]
* @param parentId ID of the parent token for which the child is being retrieved
* @param index Index of the child token in the parent token's active child tokens array
* @return A Child struct containing data about the specified child
*/
function childOf(
uint256 parentId,
uint256 index
) external view returns (Child memory);
/**
* @notice Used to retrieve a specific pending child token from a given parent token.
* @dev Returns a single Child struct locating at `index` of parent token's active child tokens array.
* @dev The Child struct consists of the following values:
* [
* tokenId,
* contractAddress
* ]
* @param parentId ID of the parent token for which the pending child token is being retrieved
* @param index Index of the child token in the parent token's pending child tokens array
* @return A Child struct containting data about the specified child
*/
function pendingChildOf(
uint256 parentId,
uint256 index
) external view returns (Child memory);
/**
* @notice Used to transfer the token into another token.
* @param from Address of the direct owner of the token to be transferred
* @param to Address of the receiving token's collection smart contract
* @param tokenId ID of the token being transferred
* @param destinationId ID of the token to receive the token being transferred
* @param data Additional data with no specified format, sent in the addChild call
*/
function nestTransferFrom(
address from,
address to,
uint256 tokenId,
uint256 destinationId,
bytes memory data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IAssetAttributes {
function getAttributes(
uint256 tokenId,
bool getTotal
) external view returns (uint16[] memory);
function setAttributes(
uint256 tokenId,
uint16[] memory attributes
) external;
}// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /******************************************************************************\ * Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen) * EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 /******************************************************************************/ interface IDiamond { enum FacetCutAction {Add, Replace, Remove} // Add=0, Replace=1, Remove=2 struct FacetCut { address facetAddress; FacetCutAction action; bytes4[] functionSelectors; } event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /******************************************************************************\ * Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen) * EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 /******************************************************************************/ import {IDiamond} from "./IDiamond.sol"; import {IERC165Updater} from "./IERC165Updater.sol"; interface IDiamondCut is IDiamond, IERC165Updater { /// @notice Add/replace/remove any number of functions and optionally execute /// a function with delegatecall /// @param _diamondCut Contains the facet addresses and function selectors /// @param _init The address of the contract or facet to execute _calldata /// @param _calldata A function call, including function selector and arguments /// _calldata is executed with delegatecall on _init function diamondCut( FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata ) external; }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@rmrk-team/evm-contracts/contracts/RMRK/equippable/IERC6220.sol";
struct IntakeChildTransfer {
uint256 tokenId;
address to;
uint256 destinationId;
uint256 childIndex;
address childAddress;
uint256 childId;
bool isPending;
bool parentIsStaked;
}
interface IEquipFacet {
function multiEquip(
address collectionAddress,
IERC6220.IntakeEquip[] memory unequip_,
IntakeChildTransfer[] memory transfer_,
IERC6220.IntakeEquip[] memory equip_
) external;
function callEquip(
address collectionAddress,
IERC6220.IntakeEquip memory data
) external;
function callUnEquip(
address collectionAddress,
IERC6220.IntakeEquip memory data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
/**
* @title IERC165Updater
* @author Multiple
* @notice An extension of ERC165 Standard Interface Detection that allows contracts to add and remove supported interfaces.
*
* Users can check for interface support via `supportsInterface(bytes4 interfaceID)` as defined in ERC165. Users can add or remove interface support via [`updateSupportedInterfaces()`](#updatesupportedinterfaces).
*/
interface IERC165Updater {
/// @notice Emitted when support for an interface is updated.
event InterfaceSupportUpdated(bytes4 indexed interfaceID, bool supported);
/**
* @notice Adds or removes supported interfaces.
* @dev Add access control in implementation.
* @param interfaceIDs The list of interfaces to update.
* @param support The list of true to signal support, false otherwise.
*/
function updateSupportedInterfaces(
bytes4[] calldata interfaceIDs,
bool[] calldata support
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
/**
* @notice Struct used for claiming rewards.
* @param id is the id of the reward to claim
* @param index is the index of the reward to claim
* @param amount is the amount of the reward to claim
*/
struct claimItem {
uint16 id;
uint16 index;
uint16 amount;
}
/**
* @notice NFT Information used for supplying nfts to startMission function
* @dev The player must provide approval for the contract to transfer the NFT
* @param contractAddress is the address of the NFT contract
* @param tokenId is the token id of the NFT
*/
struct InputNftData {
address contractAddress;
uint256 tokenId;
}
/**
* @notice Each mission contains one or multiple NFT rewards with preset roll characteristics
* @param contractAddress is the address of the NFT contract
* @param poolId is the mint index of the NFT
* @param amount is the amount of the NFT to mint
* @param rollChance rollChance/100_000 chance of rolling this reward
* @param maxRolls Player rolls until they fail, or up to maxRolls
* @param attributeMultipliers array of 16 uint16s multiplied by soul attributes to determine roll benefit
*/
struct NFTRewardChance {
// 2 slots total
address contractAddress;
uint16 itemId;
uint16 amount;
uint32 rollChance;
uint16 maxRolls;
uint8 experienceBenefit; // 256
uint256 attributeMultipliers; // 256
}
/**
* @notice NFT Information use for minting and mission requirements
* @param contractAddress is the address of the NFT contract
* @param poolId is the mint index of the NFT
* @param amount is the amount of the NFT to mint
*/
struct NftByItemId {
// 1 slot
address contractAddress; // 160
uint16 itemId;
uint16 amount; // 208
}
/**
* @notice Earned (already rolled) resource rewards
* @param resourceId is the id of the resource
* @param amount is the amount of the resource
*/
struct ResourceData {
uint16 resourceId;
uint16 amount;
}
/**
* @notice Each mission contains one or multiple Resource rewards with preset roll characteristics
* @param resourceData struct containing the resource id and amount of the reward
* @param rollChance rollChance/100_000 chance of rolling this reward
* @param maxRolls Player rolls until they fail, or up to maxRolls
* @param attributeMultipliers Multiplier for each attribute x10 (Max multipler is 25.5). 0 = no multiplier
* @dev note that attributeMultipliers
*/
struct ResourceRewardChance {
uint16 resourceId;
uint16 amount;
uint32 rollChance;
uint8 maxRolls;
uint8 experienceBenefit; // 80
uint256 attributeMultipliers; // 256
}
/**
* @notice Specific reward amount for an activity associated to a mission.
* @dev ActivityRewards are stored by soul tokenId and incremented following mission completion.
* @param enabled is a bool to enable/disable the mission
* @param blockDuration is the duration of the mission in blocks
* @param activityId is the id of the activity effected by this mission
* @param baseExperience is the base experience reward for completing the mission
* @param collectionId is the id of the supported collection within the staking contract
*/
struct ActivityData {
bool enabled;
uint32 blockDuration;
uint16 activityId;
uint32 baseExperience;
uint32 collectionId; //120
uint256 attributeMultipliers; // 256
}
/**
* @notice PlayerMission struct
* @dev Only the Most recent PlayerMission is stored. It is mapped to the soul tokenId which created it.
* @param missionId is the id of the mission.
* @param playerAddress is the address of the player who started the mission.
* @param endBlock is the block the playerMission completes.
*/
struct PlayerMission {
uint16 missionId; // 16
address playerAddress; // 176
uint32 endBlock; // 240
uint32 rngIndex; // 256
}
interface IEvrlootMissions {
//events
event MissionAdded(uint256 indexed missionId);
event MissionStarted(
uint256 indexed tokenId,
uint16 indexed missionId,
uint256 rngIndex
);
event MissionEnded(uint256 indexed tokenId, uint16 indexed missionId);
event MissionRoll(uint256 rngIndex, uint256 rolledValue);
function getLastMissionsByTokenIds(
uint256[] memory tokenId
) external view returns (PlayerMission[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
struct inputToken {
address contractAddress;
uint256 tokenId;
}
struct RollableAssets {
uint64[] assetIds;
uint16 itemId;
}
interface IIdentify {
event RequestRNG(address playerAddress, uint256 tokenId);
function identify(inputToken[] memory inputTokens) external;
function isIdentifiable(
address[] memory contractAddress,
uint256[] memory tokenId
) external view returns (bool[] memory);
}// SPDX-License-Identifier: MIT pragma solidity 0.8.19; error ZeroAddress(); error UnsupportedMission(); error NotSoulCollection(); error NotSupportedCollection(); error CollectionAlreadyExists(); error MissionDoesNotExist(); error MissionNotEnabled(); error MissionNotStarted(); error MissionNotFinished(); error MissionNotFinalized(); error InsufficientAttributes(); error NotMissionPlayer(); error IncorrectMissionFee(); error InvalidRewardAmount(); error InvalidRewardIndex(); error InvalidRewardAddress(); error SenderIsNotOwnerOfStakedToken(); error SoulHasActiveOrUnclaimedMission(); error InvalidIndex(); error InsufficientSuppliedNfts(); error FeeNotSent(); error RequestedAmountZero(); error NotSoulTokenOwner(); error NotEstraTokenOwner(); error BadInputLengths(); error NotErc721TokenOwner(); error NoFeestoCollect(); error WithdrawalAddressNotSet(); error MaxRollsExceedsLimit(); error AlreadyIdentified(); error PoolIdNotSet(); error ItemIdAlreadySet(); error ContractNotSupported(); error NotTokenOwner(); error NoRngAvailable(); error WithdrawFailed(); error RMRKMintUnderpriced(); error RMRKMintZero(); error NotChildTokenOwner(); error MissionIdMismatch(); error ContractIsPaused(); error ContractIsNotPaused(); error NotAirNode(); error ResourceMetadataNotSet(); error InvalidTokenID();
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {LibDiamond} from "./LibDiamond.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "../interfaces/IIdentify.sol";
import "./Errors.sol";
import "../interfaces/IEvrlootMissions.sol";
struct Staked {
address collectionAddress; // 160
uint32 tokenId; // 192
uint32 collectionId; // 224
}
struct Rental {
uint32 collectionId; // 32
uint32 tokenId; // 64
uint32 estraTokenId; // 96
uint64 rentalPrice; // 160
uint32 rentalStart; // 192
uint32 rentalEnd; // 224
}
struct ActiveRental {
address renter;
uint32 estraTokenId;
uint32 rentalStart;
uint32 rentalEnd;
}
struct AppStorage {
string name;
bool paused;
address missionContract;
address expeditionContract;
address marketContract;
address battleContract;
address resourcesContract;
/**
*
* ====== ERC721 Staking Variables ===== */
// Token name
string stakingTokenName;
// Token symbol
string stakingTokenSymbol;
// Mapping from token ID to owner address
mapping(uint256 => address) stakingTokenOwners;
// Mapping owner address to token count
mapping(address => uint256) stakingTokenBalances;
// Mapping from token ID to approved address
mapping(uint256 => address) stakingTokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) stakingOperatorApprovals;
mapping(address => mapping(uint256 => uint256)) stakingOwnedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) stakingOwnedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] stakingAllTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) stakingAllTokensIndex;
string stakingBaseURIString;
// estraTokenId => Staked
mapping(uint256 => Staked) stakedTokens;
// collectionAddress => tokenId => estraTokenId
mapping(address => mapping(uint256 => uint256)) stakedSoulTokens;
// collectionAddress => collectionId
mapping(address => uint256) stakedCollectionId;
// collectionId => tokenUri
mapping(uint256 => string) stakedTokenURI; // mapping of index to tokenURI
// collectionId => isEnumerable
mapping(uint256 => uint8) stakedIsEnumerable; // mapping of index to isEnumerable
uint256 stakedLastCollectionId;
uint256 stakedLastEstraTokenId;
uint256 soulCollectionIndex;
/**
*
* ====== Mission Variables ====== */
uint256 missionFee;
uint256 airnodeFee;
address evrSoulsContractAddress;
address backendAddress;
address feeWithdrawalAddress;
uint64 missionNextRngIndex; // max index will be 672 (2 weeks of rng values assuming 1 per 30 minutes)
uint256 _pendingMissionTokenId;
uint256[] _availableMissions;
uint256 missionNextId;
/** @dev Mission properties are stored in mappings to uint256 missionId
* The inner mission structs are pulled out int his way to avoid complications with
* nested struct arrays. */
mapping(uint256 => ResourceData[]) missionResourceRequirements; //32
mapping(uint256 => NftByItemId[]) missionNftRequirements;
mapping(uint256 => NFTRewardChance[]) missionNftRewards;
mapping(uint256 => ResourceRewardChance[]) missionResourceRewards;
mapping(uint256 => ActivityData) missionActivityData; // includes blockDuration
/** @dev Most recent player mission mapped to soul tokenId */
mapping(uint256 => PlayerMission) lastPlayerMission;
/** @dev Unclaimed NFT Rewards mapping
* playerAddress => NFT itemId => NftByItemId struct */
mapping(address => mapping(uint16 => NftByItemId)) unclaimedNftRewards;
/** @dev Unclaimed Nfts as an array of itemId (poolId & memberId)
* playerAddress => NFT itemId
* useful for tracking NFT types stored in _unclaimedNftRewards mapping */
mapping(address => uint16[]) _unclaimedNftItemIds;
/** @dev Unclaimed Resource Rewards mapping
* playerAddress => resourceID => count */
mapping(address => mapping(uint256 => uint16)) _unclaimedResourceRewards;
/** @dev Unclaimed Resources as an array of Resource Ids
* playerAddress => resourceID as array
* Useful for tracking resource IDs stored in _unclaimedResourceRewards mapping */
mapping(address => uint16[]) _unclaimedResourceIds;
/** @dev Activity Experience mapping
* soul tokenID => activityId => count */
mapping(address => mapping(uint256 => mapping(uint16 => uint256))) activityExperience;
/** @dev rng is mapped to the soulTokenId once it is received from the qrng contract
* this is necessary to avoid gaming the rng value -- waiting to end mission until a favorable value is received
* Thus the first rng returned since mission start is used for the mission
* note that rng values are returned every n blocks */
mapping(uint256 => uint256) missionRolledRng;
/**
*
* ====== QRNG Variables ====== */
address qrngServerAddress;
address airnodeAddress;
address qrngSponsorWallet;
bytes32 pendingRngRequestId;
/**
*
* ====== Item Identification Variables ====== */
mapping(address => mapping(uint16 => RollableAssets[])) identifyRollableAssets; // address as NFT Contract, uint16 as poolId
address[] identifySupportedContracts;
mapping(address => bool) identifyIsSupportedContract;
mapping(address => mapping(uint256 => bool)) isIdentified;
/**
*
* ====== Soul Trait Variables ====== */
mapping(uint256 => uint256) uint8SoulTraits;
/**
*
* ====== Rental Variables ====== */
mapping(uint256 => Rental) rentableTokens;
mapping(address => uint256) rentableCollections;
/**
*
* ====== Transaction Signing (EIP 712) ====== */
bytes32 domainSeparator;
mapping(address => uint256) metaNonces;
}
library LibAppStorage {
function diamondStorage() internal pure returns (AppStorage storage ds) {
assembly {
ds.slot := 0
}
}
function abs(int256 x) internal pure returns (uint256) {
return uint256(x >= 0 ? x : -x);
}
}
/** ============ Modifiers ============ */
contract Modifiers {
AppStorage internal s;
modifier onlyOwner() {
LibDiamond.enforceIsContractOwner();
_;
}
modifier onlyOwnerOrBackend() {
LibDiamond.enforceIsContractOwnerOrBackendAddress();
_;
}
/**
* @dev Make a function callable only when msg sender owns the supplied estraTokenId
* @param estraTokenId uint256 ID of the receipt token to validate
*/
modifier estraTokenHolder(uint256 estraTokenId) {
if (address(0) == s.stakingTokenOwners[estraTokenId])
revert InvalidTokenID();
if (msg.sender != s.stakingTokenOwners[estraTokenId])
revert SenderIsNotOwnerOfStakedToken();
_;
}
modifier isSoulCollection(address collectionAddress) {
if (s.stakedCollectionId[collectionAddress] != s.soulCollectionIndex)
revert NotSoulCollection();
_;
}
modifier supportedCollection(address collectionAddress) {
if (s.stakedCollectionId[collectionAddress] == 0)
revert NotSupportedCollection();
_;
}
/**
* @dev Make a function callable only when soul estraTokenId is not on an active mission
* @param estraTokenId uint256 ID of the token to validate
*/
modifier noActiveOrUnclaimedMission(uint256 estraTokenId) {
if (s.lastPlayerMission[estraTokenId].endBlock != 0)
revert SoulHasActiveOrUnclaimedMission();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
if (s.paused) revert ContractIsPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
if (!s.paused) revert ContractIsNotPaused();
_;
}
/**
* @dev Make a function callable only by the QRNG contract
*/
modifier onlyAirNode() {
if (msg.sender != s.airnodeAddress) revert NotAirNode();
_;
}
}// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; /******************************************************************************\ * Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen) * EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535 /******************************************************************************/ import {IDiamond} from "../interfaces/IDiamond.sol"; import {IDiamondCut} from "../interfaces/IDiamondCut.sol"; // Remember to add the loupe functions from DiamondLoupeFacet to the diamond. // The loupe functions are required by the EIP2535 Diamonds standard error NoSelectorsGivenToAdd(); error NotContractOwner(address _user, address _contractOwner); error NotPermitted( address _user, address _contractOwner, address _backendAddress ); error NoSelectorsProvidedForFacetForCut(address _facetAddress); error CannotAddSelectorsToZeroAddress(bytes4[] _selectors); error NoBytecodeAtAddress(address _contractAddress, string _message); error IncorrectFacetCutAction(uint8 _action); error CannotAddFunctionToDiamondThatAlreadyExists(bytes4 _selector); error CannotReplaceFunctionsFromFacetWithZeroAddress(bytes4[] _selectors); error CannotReplaceImmutableFunction(bytes4 _selector); error CannotReplaceFunctionWithTheSameFunctionFromTheSameFacet( bytes4 _selector ); error CannotReplaceFunctionThatDoesNotExists(bytes4 _selector); error RemoveFacetAddressMustBeZeroAddress(address _facetAddress); error CannotRemoveFunctionThatDoesNotExist(bytes4 _selector); error CannotRemoveImmutableFunction(bytes4 _selector); error InitializationFunctionReverted( address _initializationContractAddress, bytes _calldata ); library LibDiamond { bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage"); struct FacetAddressAndSelectorPosition { address facetAddress; uint16 selectorPosition; } struct DiamondStorage { // function selector => facet address and selector position in selectors array mapping(bytes4 => FacetAddressAndSelectorPosition) facetAddressAndSelectorPosition; bytes4[] selectors; mapping(bytes4 => bool) supportedInterfaces; // owner of the contract address contractOwner; address backendAddress; } function diamondStorage() internal pure returns (DiamondStorage storage ds) { bytes32 position = DIAMOND_STORAGE_POSITION; assembly { ds.slot := position } } event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); function setContractOwner(address _newOwner) internal { DiamondStorage storage ds = diamondStorage(); address previousOwner = ds.contractOwner; ds.contractOwner = _newOwner; emit OwnershipTransferred(previousOwner, _newOwner); } function contractOwner() internal view returns (address contractOwner_) { contractOwner_ = diamondStorage().contractOwner; } function enforceIsContractOwner() internal view { if (msg.sender != diamondStorage().contractOwner) { revert NotContractOwner(msg.sender, diamondStorage().contractOwner); } } function enforceIsContractOwnerOrBackendAddress() internal view { DiamondStorage storage ds = diamondStorage(); if (msg.sender != ds.backendAddress && msg.sender != ds.contractOwner) { revert NotPermitted( msg.sender, diamondStorage().contractOwner, diamondStorage().backendAddress ); } } event DiamondCut( IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata ); // Internal function version of diamondCut function diamondCut( IDiamondCut.FacetCut[] memory _diamondCut, address _init, bytes memory _calldata ) internal { for ( uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++ ) { bytes4[] memory functionSelectors = _diamondCut[facetIndex] .functionSelectors; address facetAddress = _diamondCut[facetIndex].facetAddress; if (functionSelectors.length == 0) { revert NoSelectorsProvidedForFacetForCut(facetAddress); } IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action; if (action == IDiamond.FacetCutAction.Add) { addFunctions(facetAddress, functionSelectors); } else if (action == IDiamond.FacetCutAction.Replace) { replaceFunctions(facetAddress, functionSelectors); } else if (action == IDiamond.FacetCutAction.Remove) { removeFunctions(facetAddress, functionSelectors); } else { revert IncorrectFacetCutAction(uint8(action)); } } emit DiamondCut(_diamondCut, _init, _calldata); initializeDiamondCut(_init, _calldata); } function addFunctions( address _facetAddress, bytes4[] memory _functionSelectors ) internal { if (_facetAddress == address(0)) { revert CannotAddSelectorsToZeroAddress(_functionSelectors); } DiamondStorage storage ds = diamondStorage(); uint16 selectorCount = uint16(ds.selectors.length); enforceHasContractCode( _facetAddress, "LibDiamondCut: Add facet has no code" ); for ( uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++ ) { bytes4 selector = _functionSelectors[selectorIndex]; address oldFacetAddress = ds .facetAddressAndSelectorPosition[selector] .facetAddress; if (oldFacetAddress != address(0)) { revert CannotAddFunctionToDiamondThatAlreadyExists(selector); } ds.facetAddressAndSelectorPosition[ selector ] = FacetAddressAndSelectorPosition( _facetAddress, selectorCount ); ds.selectors.push(selector); selectorCount++; } } function replaceFunctions( address _facetAddress, bytes4[] memory _functionSelectors ) internal { DiamondStorage storage ds = diamondStorage(); if (_facetAddress == address(0)) { revert CannotReplaceFunctionsFromFacetWithZeroAddress( _functionSelectors ); } enforceHasContractCode( _facetAddress, "LibDiamondCut: Replace facet has no code" ); for ( uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++ ) { bytes4 selector = _functionSelectors[selectorIndex]; address oldFacetAddress = ds .facetAddressAndSelectorPosition[selector] .facetAddress; // can't replace immutable functions -- functions defined directly in the diamond in this case if (oldFacetAddress == address(this)) { revert CannotReplaceImmutableFunction(selector); } if (oldFacetAddress == _facetAddress) { revert CannotReplaceFunctionWithTheSameFunctionFromTheSameFacet( selector ); } if (oldFacetAddress == address(0)) { revert CannotReplaceFunctionThatDoesNotExists(selector); } // replace old facet address ds .facetAddressAndSelectorPosition[selector] .facetAddress = _facetAddress; } } function removeFunctions( address _facetAddress, bytes4[] memory _functionSelectors ) internal { DiamondStorage storage ds = diamondStorage(); uint256 selectorCount = ds.selectors.length; if (_facetAddress != address(0)) { revert RemoveFacetAddressMustBeZeroAddress(_facetAddress); } for ( uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++ ) { bytes4 selector = _functionSelectors[selectorIndex]; FacetAddressAndSelectorPosition memory oldFacetAddressAndSelectorPosition = ds .facetAddressAndSelectorPosition[selector]; if (oldFacetAddressAndSelectorPosition.facetAddress == address(0)) { revert CannotRemoveFunctionThatDoesNotExist(selector); } // can't remove immutable functions -- functions defined directly in the diamond if ( oldFacetAddressAndSelectorPosition.facetAddress == address(this) ) { revert CannotRemoveImmutableFunction(selector); } // replace selector with last selector selectorCount--; if ( oldFacetAddressAndSelectorPosition.selectorPosition != selectorCount ) { bytes4 lastSelector = ds.selectors[selectorCount]; ds.selectors[ oldFacetAddressAndSelectorPosition.selectorPosition ] = lastSelector; ds .facetAddressAndSelectorPosition[lastSelector] .selectorPosition = oldFacetAddressAndSelectorPosition .selectorPosition; } // delete last selector ds.selectors.pop(); delete ds.facetAddressAndSelectorPosition[selector]; } } function initializeDiamondCut( address _init, bytes memory _calldata ) internal { if (_init == address(0)) { return; } enforceHasContractCode( _init, "LibDiamondCut: _init address has no code" ); (bool success, bytes memory error) = _init.delegatecall(_calldata); if (!success) { if (error.length > 0) { // bubble up error /// @solidity memory-safe-assembly assembly { let returndata_size := mload(error) revert(add(32, error), returndata_size) } } else { revert InitializationFunctionReverted(_init, _calldata); } } } function enforceHasContractCode( address _contract, string memory _errorMessage ) internal view { uint256 contractSize; assembly { contractSize := extcodesize(_contract) } if (contractSize == 0) { revert NoBytecodeAtAddress(_contract, _errorMessage); } } }
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
library LibMeta {
bytes32 internal constant EIP712_DOMAIN_TYPEHASH =
keccak256(
bytes(
"EIP712Domain(string name,string version,uint256 salt,address verifyingContract)"
)
);
function domainSeparator(
string memory name,
string memory version
) internal view returns (bytes32 domainSeparator_) {
domainSeparator_ = keccak256(
abi.encode(
EIP712_DOMAIN_TYPEHASH,
keccak256(bytes(name)),
keccak256(bytes(version)),
getChainID(),
address(this)
)
);
}
function getChainID() internal view returns (uint256 id) {
assembly {
id := chainid()
}
}
function msgSender() internal view returns (address sender_) {
if (msg.sender == address(this)) {
bytes memory array = msg.data;
uint256 index = msg.data.length;
assembly {
// Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
sender_ := and(
mload(add(array, index)),
0xffffffffffffffffffffffffffffffffffffffff
)
}
} else {
sender_ = msg.sender;
}
}
}{
"optimizer": {
"enabled": true,
"runs": 175
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BadInputLengths","type":"error"},{"inputs":[],"name":"ContractIsPaused","type":"error"},{"inputs":[],"name":"NotChildTokenOwner","type":"error"},{"inputs":[],"name":"NotEstraTokenOwner","type":"error"},{"inputs":[],"name":"NotSoulTokenOwner","type":"error"},{"inputs":[],"name":"NotSupportedCollection","type":"error"},{"inputs":[{"internalType":"address","name":"collectionAddress","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"childIndex","type":"uint256"},{"internalType":"uint64","name":"assetId","type":"uint64"},{"internalType":"uint64","name":"slotPartId","type":"uint64"},{"internalType":"uint64","name":"childAssetId","type":"uint64"}],"internalType":"struct IERC6220.IntakeEquip","name":"data","type":"tuple"}],"name":"callEquip","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collectionAddress","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"childIndex","type":"uint256"},{"internalType":"uint64","name":"assetId","type":"uint64"},{"internalType":"uint64","name":"slotPartId","type":"uint64"},{"internalType":"uint64","name":"childAssetId","type":"uint64"}],"internalType":"struct IERC6220.IntakeEquip","name":"data","type":"tuple"}],"name":"callUnEquip","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collectionAddress","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"childIndex","type":"uint256"},{"internalType":"uint64","name":"assetId","type":"uint64"},{"internalType":"uint64","name":"slotPartId","type":"uint64"},{"internalType":"uint64","name":"childAssetId","type":"uint64"}],"internalType":"struct IERC6220.IntakeEquip[]","name":"unequip_","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"destinationId","type":"uint256"},{"internalType":"uint256","name":"childIndex","type":"uint256"},{"internalType":"address","name":"childAddress","type":"address"},{"internalType":"uint256","name":"childId","type":"uint256"},{"internalType":"bool","name":"isPending","type":"bool"},{"internalType":"bool","name":"parentIsStaked","type":"bool"}],"internalType":"struct IntakeChildTransfer[]","name":"transfer_","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"childIndex","type":"uint256"},{"internalType":"uint64","name":"assetId","type":"uint64"},{"internalType":"uint64","name":"slotPartId","type":"uint64"},{"internalType":"uint64","name":"childAssetId","type":"uint64"}],"internalType":"struct IERC6220.IntakeEquip[]","name":"equip_","type":"tuple[]"}],"name":"multiEquip","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50610e5f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80634428981d146100465780639a198ab01461005b578063a6798f5c1461006e575b600080fd5b610059610054366004610b55565b610081565b005b610059610069366004610c5a565b610133565b61005961007c366004610b55565b61080e565b6001600160a01b0382166000908152601260209081526040808320845184529091529020546100af816108a0565b81516040808401516060850151915163184b353160e31b8152600481019390935267ffffffffffffffff90811660248401521660448201526001600160a01b0384169063c259a988906064015b600060405180830381600087803b15801561011657600080fd5b505af115801561012a573d6000803e3d6000fd5b50505050505050565b60015460ff1615610157576040516306d39fcd60e41b815260040160405180910390fd5b80851415806101665750808314155b15610184576040516337151d3b60e01b815260040160405180910390fd5b60005b85811015610706576001600160a01b0388166000908152601260205260408120818989858181106101ba576101ba610d38565b905060a0020160000135815260200190815260200160002054905060008888848181106101e9576101e9610d38565b905060a002016000013511156102ea57610202816108a0565b886001600160a01b031663c259a98889898581811061022357610223610d38565b905060a00201600001358a8a8681811061023f5761023f610d38565b905060a0020160400160208101906102579190610d4e565b8b8b8781811061026957610269610d38565b905060a0020160600160208101906102819190610d4e565b6040516001600160e01b031960e086901b168152600481019390935267ffffffffffffffff9182166024840152166044820152606401600060405180830381600087803b1580156102d157600080fd5b505af11580156102e5573d6000803e3d6000fd5b505050505b60008686848181106102fe576102fe610d38565b905061010002016000013511156106fd576001600160a01b03891660009081526012602052604081208188888681811061033a5761033a610d38565b905061010002016000013581526020019081526020016000205490506201869f87878581811061036c5761036c610d38565b905061010002016060013510156105875786868481811061038f5761038f610d38565b9050610100020160e00160208101906103a89190610d70565b15156001036103bf576103ba816108a0565b6103e5565b6103e58a8888868181106103d5576103d5610d38565b90506101000201600001356108e4565b896001600160a01b031663defa80c388888681811061040657610406610d38565b905061010002016000013589898781811061042357610423610d38565b90506101000201602001602081019061043c9190610d92565b8a8a8881811061044e5761044e610d38565b90506101000201604001358b8b8981811061046b5761046b610d38565b90506101000201606001358c8c8a81811061048857610488610d38565b9050610100020160800160208101906104a19190610d92565b8d8d8b8181106104b3576104b3610d38565b9050610100020160a001358e8e8c8181106104d0576104d0610d38565b9050610100020160c00160208101906104e99190610d70565b60405160e089901b6001600160e01b031916815260048101979097526001600160a01b03958616602488015260448701949094526064860192909252909216608484015260a4830191909152151560c482015261010060e4820152600061010482015261012401600060405180830381600087803b15801561056a57600080fd5b505af115801561057e573d6000803e3d6000fd5b505050506106fb565b6105d787878581811061059c5761059c610d38565b9050610100020160800160208101906105b59190610d92565b8888868181106105c7576105c7610d38565b9050610100020160a001356109bc565b8686848181106105e9576105e9610d38565b9050610100020160800160208101906106029190610d92565b6001600160a01b031663064c0a3a610618610a58565b89898781811061062a5761062a610d38565b9050610100020160200160208101906106439190610d92565b8a8a8881811061065557610655610d38565b9050610100020160a001358b8b8981811061067257610672610d38565b604080516001600160e01b031960e08a901b1681526001600160a01b039788166004820152969095166024870152604486019390935250610100909102010135606482015260a06084820152600060a482015260c401600060405180830381600087803b1580156106e257600080fd5b505af11580156106f6573d6000803e3d6000fd5b505050505b505b50600101610187565b5060005b81811015610804576001600160a01b03881660009081526012602052604081208185858581811061073d5761073d610d38565b905060a00201600001358152602001908152602001600020549050600084848481811061076c5761076c610d38565b905060a002016000013511156107fb57610785816108a0565b886001600160a01b03166338dcf74c8585858181106107a6576107a6610d38565b905060a002016040518263ffffffff1660e01b81526004016107c89190610daf565b600060405180830381600087803b1580156107e257600080fd5b505af11580156107f6573d6000803e3d6000fd5b505050505b5060010161070a565b5050505050505050565b6001600160a01b03821660009081526012602090815260408083208451845290915290205461083c816108a0565b60408051630e373dd360e21b815283516004820152602084015160248201529083015167ffffffffffffffff908116604483015260608401518116606483015260808401511660848201526001600160a01b038416906338dcf74c9060a4016100fc565b6108a8610a58565b6001600160a01b03166108ba82610ab4565b6001600160a01b0316146108e157604051630d14346b60e21b815260040160405180910390fd5b50565b6001600160a01b038216600090815260136020526040812054900361091c5760405163c0a1f7ef60e01b815260040160405180910390fd5b610924610a58565b6040516331a9108f60e11b8152600481018390526001600160a01b0391821691841690636352211e90602401602060405180830381865afa15801561096d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109919190610e0c565b6001600160a01b0316146109b8576040516327e0a67f60e11b815260040160405180910390fd5b5050565b6109c4610a58565b6040516331a9108f60e11b8152600481018390526001600160a01b0391821691841690636352211e90602401602060405180830381865afa158015610a0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a319190610e0c565b6001600160a01b0316146109b8576040516318c3c78960e01b815260040160405180910390fd5b6000303303610aae57600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b03169150610ab19050565b50335b90565b6000818152600860205260408120546001600160a01b031680610b1d5760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e2049440000000000000000604482015260640160405180910390fd5b92915050565b6001600160a01b03811681146108e157600080fd5b803567ffffffffffffffff81168114610b5057600080fd5b919050565b60008082840360c0811215610b6957600080fd5b8335610b7481610b23565b925060a0601f1982011215610b8857600080fd5b5060405160a0810181811067ffffffffffffffff82111715610bba57634e487b7160e01b600052604160045260246000fd5b80604052506020840135815260408401356020820152610bdc60608501610b38565b6040820152610bed60808501610b38565b6060820152610bfe60a08501610b38565b6080820152809150509250929050565b60008083601f840112610c2057600080fd5b50813567ffffffffffffffff811115610c3857600080fd5b60208301915083602060a083028501011115610c5357600080fd5b9250929050565b60008060008060008060006080888a031215610c7557600080fd5b8735610c8081610b23565b9650602088013567ffffffffffffffff80821115610c9d57600080fd5b610ca98b838c01610c0e565b909850965060408a0135915080821115610cc257600080fd5b818a0191508a601f830112610cd657600080fd5b813581811115610ce557600080fd5b8b60208260081b8501011115610cfa57600080fd5b6020830196508095505060608a0135915080821115610d1857600080fd5b50610d258a828b01610c0e565b989b979a50959850939692959293505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215610d6057600080fd5b610d6982610b38565b9392505050565b600060208284031215610d8257600080fd5b81358015158114610d6957600080fd5b600060208284031215610da457600080fd5b8135610d6981610b23565b813581526020808301359082015260a08101610dcd60408401610b38565b67ffffffffffffffff808216604085015280610deb60608701610b38565b16606085015280610dfe60808701610b38565b166080850152505092915050565b600060208284031215610e1e57600080fd5b8151610d6981610b2356fea2646970667358221220bc23bfa6f114006a978109c8da5b8cb7d49354d5d5fe1ebe1600d0608e62b4fa64736f6c63430008130033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100415760003560e01c80634428981d146100465780639a198ab01461005b578063a6798f5c1461006e575b600080fd5b610059610054366004610b55565b610081565b005b610059610069366004610c5a565b610133565b61005961007c366004610b55565b61080e565b6001600160a01b0382166000908152601260209081526040808320845184529091529020546100af816108a0565b81516040808401516060850151915163184b353160e31b8152600481019390935267ffffffffffffffff90811660248401521660448201526001600160a01b0384169063c259a988906064015b600060405180830381600087803b15801561011657600080fd5b505af115801561012a573d6000803e3d6000fd5b50505050505050565b60015460ff1615610157576040516306d39fcd60e41b815260040160405180910390fd5b80851415806101665750808314155b15610184576040516337151d3b60e01b815260040160405180910390fd5b60005b85811015610706576001600160a01b0388166000908152601260205260408120818989858181106101ba576101ba610d38565b905060a0020160000135815260200190815260200160002054905060008888848181106101e9576101e9610d38565b905060a002016000013511156102ea57610202816108a0565b886001600160a01b031663c259a98889898581811061022357610223610d38565b905060a00201600001358a8a8681811061023f5761023f610d38565b905060a0020160400160208101906102579190610d4e565b8b8b8781811061026957610269610d38565b905060a0020160600160208101906102819190610d4e565b6040516001600160e01b031960e086901b168152600481019390935267ffffffffffffffff9182166024840152166044820152606401600060405180830381600087803b1580156102d157600080fd5b505af11580156102e5573d6000803e3d6000fd5b505050505b60008686848181106102fe576102fe610d38565b905061010002016000013511156106fd576001600160a01b03891660009081526012602052604081208188888681811061033a5761033a610d38565b905061010002016000013581526020019081526020016000205490506201869f87878581811061036c5761036c610d38565b905061010002016060013510156105875786868481811061038f5761038f610d38565b9050610100020160e00160208101906103a89190610d70565b15156001036103bf576103ba816108a0565b6103e5565b6103e58a8888868181106103d5576103d5610d38565b90506101000201600001356108e4565b896001600160a01b031663defa80c388888681811061040657610406610d38565b905061010002016000013589898781811061042357610423610d38565b90506101000201602001602081019061043c9190610d92565b8a8a8881811061044e5761044e610d38565b90506101000201604001358b8b8981811061046b5761046b610d38565b90506101000201606001358c8c8a81811061048857610488610d38565b9050610100020160800160208101906104a19190610d92565b8d8d8b8181106104b3576104b3610d38565b9050610100020160a001358e8e8c8181106104d0576104d0610d38565b9050610100020160c00160208101906104e99190610d70565b60405160e089901b6001600160e01b031916815260048101979097526001600160a01b03958616602488015260448701949094526064860192909252909216608484015260a4830191909152151560c482015261010060e4820152600061010482015261012401600060405180830381600087803b15801561056a57600080fd5b505af115801561057e573d6000803e3d6000fd5b505050506106fb565b6105d787878581811061059c5761059c610d38565b9050610100020160800160208101906105b59190610d92565b8888868181106105c7576105c7610d38565b9050610100020160a001356109bc565b8686848181106105e9576105e9610d38565b9050610100020160800160208101906106029190610d92565b6001600160a01b031663064c0a3a610618610a58565b89898781811061062a5761062a610d38565b9050610100020160200160208101906106439190610d92565b8a8a8881811061065557610655610d38565b9050610100020160a001358b8b8981811061067257610672610d38565b604080516001600160e01b031960e08a901b1681526001600160a01b039788166004820152969095166024870152604486019390935250610100909102010135606482015260a06084820152600060a482015260c401600060405180830381600087803b1580156106e257600080fd5b505af11580156106f6573d6000803e3d6000fd5b505050505b505b50600101610187565b5060005b81811015610804576001600160a01b03881660009081526012602052604081208185858581811061073d5761073d610d38565b905060a00201600001358152602001908152602001600020549050600084848481811061076c5761076c610d38565b905060a002016000013511156107fb57610785816108a0565b886001600160a01b03166338dcf74c8585858181106107a6576107a6610d38565b905060a002016040518263ffffffff1660e01b81526004016107c89190610daf565b600060405180830381600087803b1580156107e257600080fd5b505af11580156107f6573d6000803e3d6000fd5b505050505b5060010161070a565b5050505050505050565b6001600160a01b03821660009081526012602090815260408083208451845290915290205461083c816108a0565b60408051630e373dd360e21b815283516004820152602084015160248201529083015167ffffffffffffffff908116604483015260608401518116606483015260808401511660848201526001600160a01b038416906338dcf74c9060a4016100fc565b6108a8610a58565b6001600160a01b03166108ba82610ab4565b6001600160a01b0316146108e157604051630d14346b60e21b815260040160405180910390fd5b50565b6001600160a01b038216600090815260136020526040812054900361091c5760405163c0a1f7ef60e01b815260040160405180910390fd5b610924610a58565b6040516331a9108f60e11b8152600481018390526001600160a01b0391821691841690636352211e90602401602060405180830381865afa15801561096d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109919190610e0c565b6001600160a01b0316146109b8576040516327e0a67f60e11b815260040160405180910390fd5b5050565b6109c4610a58565b6040516331a9108f60e11b8152600481018390526001600160a01b0391821691841690636352211e90602401602060405180830381865afa158015610a0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a319190610e0c565b6001600160a01b0316146109b8576040516318c3c78960e01b815260040160405180910390fd5b6000303303610aae57600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b03169150610ab19050565b50335b90565b6000818152600860205260408120546001600160a01b031680610b1d5760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e2049440000000000000000604482015260640160405180910390fd5b92915050565b6001600160a01b03811681146108e157600080fd5b803567ffffffffffffffff81168114610b5057600080fd5b919050565b60008082840360c0811215610b6957600080fd5b8335610b7481610b23565b925060a0601f1982011215610b8857600080fd5b5060405160a0810181811067ffffffffffffffff82111715610bba57634e487b7160e01b600052604160045260246000fd5b80604052506020840135815260408401356020820152610bdc60608501610b38565b6040820152610bed60808501610b38565b6060820152610bfe60a08501610b38565b6080820152809150509250929050565b60008083601f840112610c2057600080fd5b50813567ffffffffffffffff811115610c3857600080fd5b60208301915083602060a083028501011115610c5357600080fd5b9250929050565b60008060008060008060006080888a031215610c7557600080fd5b8735610c8081610b23565b9650602088013567ffffffffffffffff80821115610c9d57600080fd5b610ca98b838c01610c0e565b909850965060408a0135915080821115610cc257600080fd5b818a0191508a601f830112610cd657600080fd5b813581811115610ce557600080fd5b8b60208260081b8501011115610cfa57600080fd5b6020830196508095505060608a0135915080821115610d1857600080fd5b50610d258a828b01610c0e565b989b979a50959850939692959293505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215610d6057600080fd5b610d6982610b38565b9392505050565b600060208284031215610d8257600080fd5b81358015158114610d6957600080fd5b600060208284031215610da457600080fd5b8135610d6981610b23565b813581526020808301359082015260a08101610dcd60408401610b38565b67ffffffffffffffff808216604085015280610deb60608701610b38565b16606085015280610dfe60808701610b38565b166080850152505092915050565b600060208284031215610e1e57600080fd5b8151610d6981610b2356fea2646970667358221220bc23bfa6f114006a978109c8da5b8cb7d49354d5d5fe1ebe1600d0608e62b4fa64736f6c63430008130033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in GLMR
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.