Source Code
Overview
GLMR Balance
GLMR Value
$0.00Latest 25 from a total of 126 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Manage Access Co... | 9758242 | 335 days ago | IN | 0 GLMR | 0.045032 | ||||
| Manage Access Co... | 9758238 | 335 days ago | IN | 0 GLMR | 0.045032 | ||||
| Manage Access Co... | 9758236 | 335 days ago | IN | 0 GLMR | 0.045032 | ||||
| Manage Access Co... | 9758229 | 335 days ago | IN | 0 GLMR | 0.045032 | ||||
| Manage Access Co... | 9364450 | 363 days ago | IN | 0 GLMR | 0.180128 | ||||
| Manage Access Co... | 9364445 | 363 days ago | IN | 0 GLMR | 0.180128 | ||||
| Manage Access Co... | 9364440 | 363 days ago | IN | 0 GLMR | 0.180128 | ||||
| Manage Access Co... | 9364435 | 363 days ago | IN | 0 GLMR | 0.180128 | ||||
| Manage Access Co... | 9364212 | 363 days ago | IN | 0 GLMR | 0.180128 | ||||
| Manage Access Co... | 9364208 | 363 days ago | IN | 0 GLMR | 0.180128 | ||||
| Manage Access Co... | 9364204 | 363 days ago | IN | 0 GLMR | 0.180128 | ||||
| Manage Access Co... | 9364197 | 363 days ago | IN | 0 GLMR | 0.180128 | ||||
| Set Uint Attribu... | 6584555 | 560 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6584552 | 560 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6584551 | 560 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6584549 | 560 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6584534 | 560 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6578433 | 561 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6578433 | 561 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6578433 | 561 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6578432 | 561 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6578368 | 561 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6578367 | 561 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6578367 | 561 days ago | IN | 0 GLMR | 0.0101095 | ||||
| Set Uint Attribu... | 6578366 | 561 days ago | IN | 0 GLMR | 0.0101095 |
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 6169237 | 619 days ago | Contract Creation | 0 GLMR |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
RMRKTokenAttributesRepositoryDraft
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.21;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {IERC7508Draft} from "./IERC7508Draft.sol";
/**
* @title RMRKTokenAttributesRepository
* @author RMRK team
* @notice Smart contract of the RMRK Token property repository module.
*/
contract RMRKTokenAttributesRepositoryDraft is IERC7508Draft, Context {
bytes32 public immutable DOMAIN_SEPARATOR =
keccak256(
abi.encode(
"ERC-7508: Public On-Chain NFT Attributes Repository",
"1",
block.chainid,
address(this)
)
);
bytes32 public immutable SET_UINT_ATTRIBUTE_TYPEHASH =
keccak256(
"setUintAttribute(address collection,uint256 tokenId,string memory key,uint256 value)"
);
bytes32 public immutable SET_STRING_ATTRIBUTE_TYPEHASH =
keccak256(
"setStringAttribute(address collection,uint256 tokenId,string memory key,string memory value)"
);
bytes32 public immutable SET_BOOL_ATTRIBUTE_TYPEHASH =
keccak256(
"setBoolAttribute(address collection,uint256 tokenId,string memory key,bool value)"
);
bytes32 public immutable SET_BYTES_ATTRIBUTE_TYPEHASH =
keccak256(
"setBytesAttribute(address collection,uint256 tokenId,string memory key,bytes memory value)"
);
bytes32 public immutable SET_ADDRESS_ATTRIBUTE_TYPEHASH =
keccak256(
"setAddressAttribute(address collection,uint256 tokenId,string memory key,address value)"
);
mapping(address collection => mapping(uint256 parameterId => AccessType accessType))
private _parameterAccessType;
mapping(address collection => mapping(uint256 parameterId => address specificAddress))
private _parameterSpecificAddress;
mapping(address collection => IssuerSetting setting)
private _issuerSettings;
mapping(address collection => mapping(address collaborator => bool isCollaborator))
private _collaborators;
// For keys, we use a mapping from strings to IDs.
// The purpose is to store unique string keys only once, since they are more expensive.
mapping(string key => uint256 id) private _keysToIds;
uint256 private _nextKeyId;
mapping(address collection => string attributesMetadataURI)
private _attributesMetadataURIs;
mapping(address collection => mapping(uint256 => mapping(uint256 => address)))
private _addressValues;
mapping(address collection => mapping(uint256 => mapping(uint256 => bytes)))
private _bytesValues;
mapping(address collection => mapping(uint256 => mapping(uint256 => uint256)))
private _uintValues;
mapping(address collection => mapping(uint256 => mapping(uint256 => bool)))
private _boolValues;
mapping(address collection => mapping(uint256 => mapping(uint256 => string)))
private _stringValues;
struct IssuerSetting {
bool registered;
bool useOwnable;
address issuer;
}
/// Used to signal that the length of the arrays is not equal.
error LengthsMismatch();
/// Used to signal that the smart contract interacting with the repository does not implement Ownable pattern.
error OwnableNotImplemented();
/// Used to signal that the caller is not the issuer of the collection.
error NotCollectionIssuer();
/// Used to signal that the collaborator and collaborator rights array are not of equal length.
error CollaboratorArraysNotEqualLength();
/// Used to signal that the collection is not registered in the repository yet.
error CollectionNotRegistered();
/// Used to signal that the caller is not aa collaborator of the collection.
error NotCollectionCollaborator();
/// Used to signal that the caller is not the issuer or a collaborator of the collection.
error NotCollectionIssuerOrCollaborator();
/// Used to signal that the caller is not the owner of the token.
error NotTokenOwner();
/// Used to signal that the caller is not the specific address allowed to manage the attribute.
error NotSpecificAddress();
/// Used to signal that the presigned message's signature is invalid.
error InvalidSignature();
/// Used to signal that the presigned message's deadline has expired.
error ExpiredDeadline();
/**
* @inheritdoc IERC7508Draft
*/
function registerAccessControl(
address collection,
address issuer,
bool useOwnable
) external {
(bool ownableSuccess, bytes memory ownableReturn) = collection.call(
abi.encodeWithSignature("owner()")
);
if (address(uint160(uint256(bytes32(ownableReturn)))) == address(0)) {
revert OwnableNotImplemented();
}
if (
ownableSuccess &&
address(uint160(uint256(bytes32(ownableReturn)))) != _msgSender()
) {
revert NotCollectionIssuer();
}
_issuerSettings[collection] = IssuerSetting({
registered: true,
issuer: issuer,
useOwnable: useOwnable
});
emit AccessControlRegistration(
collection,
issuer,
_msgSender(),
useOwnable
);
}
/**
* @inheritdoc IERC7508Draft
*/
function manageAccessControl(
address collection,
string memory key,
AccessType accessType,
address specificAddress
) external onlyRegisteredCollection(collection) onlyIssuer(collection) {
uint256 parameterId = _getIdForKey(key);
_parameterAccessType[collection][parameterId] = accessType;
_parameterSpecificAddress[collection][parameterId] = specificAddress;
emit AccessControlUpdate(collection, key, accessType, specificAddress);
}
/**
* @inheritdoc IERC7508Draft
*/
function manageCollaborators(
address collection,
address[] memory collaboratorAddresses,
bool[] memory collaboratorAddressAccess
) external onlyRegisteredCollection(collection) onlyIssuer(collection) {
uint256 length = collaboratorAddresses.length;
if (length != collaboratorAddressAccess.length) {
revert CollaboratorArraysNotEqualLength();
}
for (uint256 i; i < length; ) {
_collaborators[collection][
collaboratorAddresses[i]
] = collaboratorAddressAccess[i];
emit CollaboratorUpdate(
collection,
collaboratorAddresses[i],
collaboratorAddressAccess[i]
);
unchecked {
++i;
}
}
}
/**
* @inheritdoc IERC7508Draft
*/
function getAttributesMetadataURI(
address collection
) external view returns (string memory attributesMetadataURI) {
attributesMetadataURI = _attributesMetadataURIs[collection];
}
/**
* @inheritdoc IERC7508Draft
*/
function setAttributesMetadataURI(
address collection,
string memory attributesMetadataURI
) external onlyIssuer(collection) {
_attributesMetadataURIs[collection] = attributesMetadataURI;
emit MetadataURIUpdated(collection, attributesMetadataURI);
}
/**
* @inheritdoc IERC7508Draft
*/
function isCollaborator(
address collaborator,
address collection
) external view returns (bool isCollaborator_) {
isCollaborator_ = _collaborators[collection][collaborator];
}
/**
* @inheritdoc IERC7508Draft
*/
function isSpecificAddress(
address specificAddress,
address collection,
string memory key
) external view returns (bool isSpecificAddress_) {
isSpecificAddress_ =
_parameterSpecificAddress[collection][_keysToIds[key]] ==
specificAddress;
}
/**
* @notice Modifier to check if the caller is authorized to call the function.
* @dev If the authorization is set to TokenOwner and the tokenId provided is of the non-existent token, the
* execution will revert with `ERC721InvalidTokenId` rather than `NotTokenOwner`.
* @dev The tokenId parameter is only needed for the TokenOwner authorization type, other authorization types ignore
* it.
* @param collection The address of the collection.
* @param key Key of the attribute.
* @param tokenId The ID of the token.
*/
modifier onlyAuthorizedCaller(
address collection,
string memory key,
uint256 tokenId
) {
_onlyAuthorizedCaller(_msgSender(), collection, key, tokenId);
_;
}
/**
* @notice Modifier to check if the collection is registered.
* @param collection Address of the collection.
*/
modifier onlyRegisteredCollection(address collection) {
if (!_issuerSettings[collection].registered) {
revert CollectionNotRegistered();
}
_;
}
/**
* @notice Modifier to check if the caller is the issuer of the collection.
* @param collection Address of the collection.
*/
modifier onlyIssuer(address collection) {
if (_issuerSettings[collection].useOwnable) {
if (Ownable(collection).owner() != _msgSender()) {
revert NotCollectionIssuer();
}
} else if (_issuerSettings[collection].issuer != _msgSender()) {
revert NotCollectionIssuer();
}
_;
}
/**
* @notice Function to check if the caller is authorized to mamage a given parameter.
* @param collection The address of the collection.
* @param key Key of the attribute.
* @param tokenId The ID of the token.
*/
function _onlyAuthorizedCaller(
address caller,
address collection,
string memory key,
uint256 tokenId
) private view {
AccessType accessType = _parameterAccessType[collection][
_keysToIds[key]
];
if (
accessType == AccessType.Issuer &&
((_issuerSettings[collection].useOwnable &&
Ownable(collection).owner() != caller) ||
(!_issuerSettings[collection].useOwnable &&
_issuerSettings[collection].issuer != caller))
) {
revert NotCollectionIssuer();
} else if (
accessType == AccessType.Collaborator &&
!_collaborators[collection][caller]
) {
revert NotCollectionCollaborator();
} else if (
accessType == AccessType.IssuerOrCollaborator &&
((_issuerSettings[collection].useOwnable &&
Ownable(collection).owner() != caller) ||
(!_issuerSettings[collection].useOwnable &&
_issuerSettings[collection].issuer != caller)) &&
!_collaborators[collection][caller]
) {
revert NotCollectionIssuerOrCollaborator();
} else if (
accessType == AccessType.TokenOwner &&
IERC721(collection).ownerOf(tokenId) != caller
) {
revert NotTokenOwner();
} else if (
accessType == AccessType.SpecificAddress &&
!(_parameterSpecificAddress[collection][_keysToIds[key]] == caller)
) {
revert NotSpecificAddress();
}
}
/**
* @inheritdoc IERC7508Draft
*/
function getStringAttribute(
address collection,
uint256 tokenId,
string memory key
) public view returns (string memory attribute) {
attribute = _stringValues[collection][tokenId][_keysToIds[key]];
}
/**
* @inheritdoc IERC7508Draft
*/
function getUintAttribute(
address collection,
uint256 tokenId,
string memory key
) public view returns (uint256 attribute) {
attribute = _uintValues[collection][tokenId][_keysToIds[key]];
}
/**
* @inheritdoc IERC7508Draft
*/
function getBoolAttribute(
address collection,
uint256 tokenId,
string memory key
) public view returns (bool attribute) {
attribute = _boolValues[collection][tokenId][_keysToIds[key]];
}
/**
* @inheritdoc IERC7508Draft
*/
function getAddressAttribute(
address collection,
uint256 tokenId,
string memory key
) public view returns (address attribute) {
attribute = _addressValues[collection][tokenId][_keysToIds[key]];
}
/**
* @inheritdoc IERC7508Draft
*/
function getBytesAttribute(
address collection,
uint256 tokenId,
string memory key
) public view returns (bytes memory attribute) {
attribute = _bytesValues[collection][tokenId][_keysToIds[key]];
}
/**
* @inheritdoc IERC7508Draft
*/
function getAttributes(
address collection,
uint256 tokenId,
string[] memory stringKeys,
string[] memory uintKeys,
string[] memory boolKeys,
string[] memory addressKeys,
string[] memory bytesKeys
)
external
view
returns (
string[] memory stringAttributes,
uint256[] memory uintAttributes,
bool[] memory boolAttributes,
address[] memory addressAttributes,
bytes[] memory bytesAttributes
)
{
address[] memory collections = new address[](1);
uint256[] memory tokenIds = new uint256[](1);
collections[0] = collection;
tokenIds[0] = tokenId;
stringAttributes = getStringAttributes(
collections,
tokenIds,
stringKeys
);
uintAttributes = getUintAttributes(collections, tokenIds, uintKeys);
boolAttributes = getBoolAttributes(collections, tokenIds, boolKeys);
addressAttributes = getAddressAttributes(
collections,
tokenIds,
addressKeys
);
bytesAttributes = getBytesAttributes(collections, tokenIds, bytesKeys);
}
/**
* @inheritdoc IERC7508Draft
*/
function getStringAttributes(
address[] memory collections,
uint256[] memory tokenIds,
string[] memory attributeKeys
) public view returns (string[] memory attributes) {
(
bool multipleCollections,
bool multipleTokens,
bool multipleAttributes,
uint256 loopLength
) = _checkIfMultipleCollectionsAndTokens(
collections,
tokenIds,
attributeKeys.length
);
attributes = new string[](loopLength);
for (uint256 i; i < loopLength; ) {
attributes[i] = getStringAttribute(
multipleCollections ? collections[i] : collections[0],
multipleTokens ? tokenIds[i] : tokenIds[0],
multipleAttributes ? attributeKeys[i] : attributeKeys[0]
);
unchecked {
++i;
}
}
}
/**
* @inheritdoc IERC7508Draft
*/
function getUintAttributes(
address[] memory collections,
uint256[] memory tokenIds,
string[] memory attributeKeys
) public view returns (uint256[] memory attributes) {
(
bool multipleCollections,
bool multipleTokens,
bool multipleAttributes,
uint256 loopLength
) = _checkIfMultipleCollectionsAndTokens(
collections,
tokenIds,
attributeKeys.length
);
attributes = new uint256[](loopLength);
for (uint256 i; i < loopLength; ) {
attributes[i] = getUintAttribute(
multipleCollections ? collections[i] : collections[0],
multipleTokens ? tokenIds[i] : tokenIds[0],
multipleAttributes ? attributeKeys[i] : attributeKeys[0]
);
unchecked {
++i;
}
}
}
/**
* @inheritdoc IERC7508Draft
*/
function getBoolAttributes(
address[] memory collections,
uint256[] memory tokenIds,
string[] memory attributeKeys
) public view returns (bool[] memory attributes) {
(
bool multipleCollections,
bool multipleTokens,
bool multipleAttributes,
uint256 loopLength
) = _checkIfMultipleCollectionsAndTokens(
collections,
tokenIds,
attributeKeys.length
);
attributes = new bool[](loopLength);
for (uint256 i; i < loopLength; ) {
attributes[i] = getBoolAttribute(
multipleCollections ? collections[i] : collections[0],
multipleTokens ? tokenIds[i] : tokenIds[0],
multipleAttributes ? attributeKeys[i] : attributeKeys[0]
);
unchecked {
++i;
}
}
}
/**
* @inheritdoc IERC7508Draft
*/
function getAddressAttributes(
address[] memory collections,
uint256[] memory tokenIds,
string[] memory attributeKeys
) public view returns (address[] memory attributes) {
(
bool multipleCollections,
bool multipleTokens,
bool multipleAttributes,
uint256 loopLength
) = _checkIfMultipleCollectionsAndTokens(
collections,
tokenIds,
attributeKeys.length
);
attributes = new address[](loopLength);
for (uint256 i; i < loopLength; ) {
attributes[i] = getAddressAttribute(
multipleCollections ? collections[i] : collections[0],
multipleTokens ? tokenIds[i] : tokenIds[0],
multipleAttributes ? attributeKeys[i] : attributeKeys[0]
);
unchecked {
++i;
}
}
}
/**
* @inheritdoc IERC7508Draft
*/
function getBytesAttributes(
address[] memory collections,
uint256[] memory tokenIds,
string[] memory attributeKeys
) public view returns (bytes[] memory attributes) {
(
bool multipleCollections,
bool multipleTokens,
bool multipleAttributes,
uint256 loopLength
) = _checkIfMultipleCollectionsAndTokens(
collections,
tokenIds,
attributeKeys.length
);
attributes = new bytes[](loopLength);
for (uint256 i; i < loopLength; ) {
attributes[i] = getBytesAttribute(
multipleCollections ? collections[i] : collections[0],
multipleTokens ? tokenIds[i] : tokenIds[0],
multipleAttributes ? attributeKeys[i] : attributeKeys[0]
);
unchecked {
++i;
}
}
}
/**
* @inheritdoc IERC7508Draft
*/
function prepareMessageToPresignUintAttribute(
address collection,
uint256 tokenId,
string memory key,
uint256 value,
uint256 deadline
) public view returns (bytes32 message) {
message = keccak256(
abi.encode(
DOMAIN_SEPARATOR,
SET_UINT_ATTRIBUTE_TYPEHASH,
collection,
tokenId,
key,
value,
deadline
)
);
}
/**
* @inheritdoc IERC7508Draft
*/
function prepareMessageToPresignStringAttribute(
address collection,
uint256 tokenId,
string memory key,
string memory value,
uint256 deadline
) public view returns (bytes32 message) {
message = keccak256(
abi.encode(
DOMAIN_SEPARATOR,
SET_STRING_ATTRIBUTE_TYPEHASH,
collection,
tokenId,
key,
value,
deadline
)
);
}
/**
* @inheritdoc IERC7508Draft
*/
function prepareMessageToPresignBoolAttribute(
address collection,
uint256 tokenId,
string memory key,
bool value,
uint256 deadline
) public view returns (bytes32 message) {
message = keccak256(
abi.encode(
DOMAIN_SEPARATOR,
SET_BOOL_ATTRIBUTE_TYPEHASH,
collection,
tokenId,
key,
value,
deadline
)
);
}
/**
* @inheritdoc IERC7508Draft
*/
function prepareMessageToPresignBytesAttribute(
address collection,
uint256 tokenId,
string memory key,
bytes memory value,
uint256 deadline
) public view returns (bytes32 message) {
message = keccak256(
abi.encode(
DOMAIN_SEPARATOR,
SET_BYTES_ATTRIBUTE_TYPEHASH,
collection,
tokenId,
key,
value,
deadline
)
);
}
/**
* @inheritdoc IERC7508Draft
*/
function prepareMessageToPresignAddressAttribute(
address collection,
uint256 tokenId,
string memory key,
address value,
uint256 deadline
) public view returns (bytes32 message) {
message = keccak256(
abi.encode(
DOMAIN_SEPARATOR,
SET_ADDRESS_ATTRIBUTE_TYPEHASH,
collection,
tokenId,
key,
value,
deadline
)
);
}
/**
* @inheritdoc IERC7508Draft
*/
function setBoolAttribute(
address collection,
uint256 tokenId,
string memory key,
bool value
) external {
_setBoolAttribute(_msgSender(), collection, tokenId, key, value);
}
/**
* @inheritdoc IERC7508Draft
*/
function setBytesAttribute(
address collection,
uint256 tokenId,
string memory key,
bytes memory value
) external {
_setBytesAttribute(_msgSender(), collection, tokenId, key, value);
}
/**
* @inheritdoc IERC7508Draft
*/
function setAddressAttribute(
address collection,
uint256 tokenId,
string memory key,
address value
) external {
_setAddressAttribute(_msgSender(), collection, tokenId, key, value);
}
/**
* @inheritdoc IERC7508Draft
*/
function setUintAttribute(
address collection,
uint256 tokenId,
string memory key,
uint256 value
) external {
_setUintAttribute(_msgSender(), collection, tokenId, key, value);
}
/**
* @inheritdoc IERC7508Draft
*/
function setStringAttribute(
address collection,
uint256 tokenId,
string memory key,
string memory value
) external {
_setStringAttribute(_msgSender(), collection, tokenId, key, value);
}
/**
* @inheritdoc IERC7508Draft
*/
function setBoolAttributes(
address[] memory collections,
uint256[] memory tokenIds,
BoolAttribute[] memory attributes
) external {
(
bool multipleCollections,
bool multipleTokens,
bool multipleAttributes,
uint256 loopLength
) = _checkIfMultipleCollectionsAndTokens(
collections,
tokenIds,
attributes.length
);
for (uint256 i; i < loopLength; ) {
BoolAttribute memory attribute = multipleAttributes
? attributes[i]
: attributes[0];
_setBoolAttribute(
_msgSender(),
multipleCollections ? collections[i] : collections[0],
multipleTokens ? tokenIds[i] : tokenIds[0],
attribute.key,
attribute.value
);
unchecked {
++i;
}
}
}
/**
* @inheritdoc IERC7508Draft
*/
function setBytesAttributes(
address[] memory collections,
uint256[] memory tokenIds,
BytesAttribute[] memory attributes
) external {
(
bool multipleCollections,
bool multipleTokens,
bool multipleAttributes,
uint256 loopLength
) = _checkIfMultipleCollectionsAndTokens(
collections,
tokenIds,
attributes.length
);
for (uint256 i; i < loopLength; ) {
BytesAttribute memory attribute = multipleAttributes
? attributes[i]
: attributes[0];
_setBytesAttribute(
_msgSender(),
multipleCollections ? collections[i] : collections[0],
multipleTokens ? tokenIds[i] : tokenIds[0],
attribute.key,
attribute.value
);
unchecked {
++i;
}
}
}
/**
* @inheritdoc IERC7508Draft
*/
function setStringAttributes(
address[] memory collections,
uint256[] memory tokenIds,
StringAttribute[] memory attributes
) external {
(
bool multipleCollections,
bool multipleTokens,
bool multipleAttributes,
uint256 loopLength
) = _checkIfMultipleCollectionsAndTokens(
collections,
tokenIds,
attributes.length
);
for (uint256 i; i < loopLength; ) {
StringAttribute memory attribute = multipleAttributes
? attributes[i]
: attributes[0];
_setStringAttribute(
_msgSender(),
multipleCollections ? collections[i] : collections[0],
multipleTokens ? tokenIds[i] : tokenIds[0],
attribute.key,
attribute.value
);
unchecked {
++i;
}
}
}
/**
* @inheritdoc IERC7508Draft
*/
function setUintAttributes(
address[] memory collections,
uint256[] memory tokenIds,
UintAttribute[] memory attributes
) external {
(
bool multipleCollections,
bool multipleTokens,
bool multipleAttributes,
uint256 loopLength
) = _checkIfMultipleCollectionsAndTokens(
collections,
tokenIds,
attributes.length
);
for (uint256 i; i < loopLength; ) {
UintAttribute memory attribute = multipleAttributes
? attributes[i]
: attributes[0];
_setUintAttribute(
_msgSender(),
multipleCollections ? collections[i] : collections[0],
multipleTokens ? tokenIds[i] : tokenIds[0],
attribute.key,
attribute.value
);
unchecked {
++i;
}
}
}
/**
* @inheritdoc IERC7508Draft
*/
function setAddressAttributes(
address[] memory collections,
uint256[] memory tokenIds,
AddressAttribute[] memory attributes
) external {
(
bool multipleCollections,
bool multipleTokens,
bool multipleAttributes,
uint256 loopLength
) = _checkIfMultipleCollectionsAndTokens(
collections,
tokenIds,
attributes.length
);
for (uint256 i; i < loopLength; ) {
AddressAttribute memory attribute = multipleAttributes
? attributes[i]
: attributes[0];
_setAddressAttribute(
_msgSender(),
multipleCollections ? collections[i] : collections[0],
multipleTokens ? tokenIds[i] : tokenIds[0],
attribute.key,
attribute.value
);
unchecked {
++i;
}
}
}
/**
* @inheritdoc IERC7508Draft
*/
function setAttributes(
address collection,
uint256 tokenId,
StringAttribute[] memory stringAttributes,
UintAttribute[] memory uintAttributes,
BoolAttribute[] memory boolAttributes,
AddressAttribute[] memory addressAttributes,
BytesAttribute[] memory bytesAttributes
) external {
uint256 length = stringAttributes.length;
for (uint256 i; i < length; ) {
_setStringAttribute(
_msgSender(),
collection,
tokenId,
stringAttributes[i].key,
stringAttributes[i].value
);
unchecked {
++i;
}
}
length = uintAttributes.length;
for (uint256 i; i < length; ) {
_setUintAttribute(
_msgSender(),
collection,
tokenId,
uintAttributes[i].key,
uintAttributes[i].value
);
unchecked {
++i;
}
}
length = boolAttributes.length;
for (uint256 i; i < length; ) {
_setBoolAttribute(
_msgSender(),
collection,
tokenId,
boolAttributes[i].key,
boolAttributes[i].value
);
unchecked {
++i;
}
}
length = addressAttributes.length;
for (uint256 i; i < length; ) {
_setAddressAttribute(
_msgSender(),
collection,
tokenId,
addressAttributes[i].key,
addressAttributes[i].value
);
unchecked {
++i;
}
}
length = bytesAttributes.length;
for (uint256 i; i < length; ) {
_setBytesAttribute(
_msgSender(),
collection,
tokenId,
bytesAttributes[i].key,
bytesAttributes[i].value
);
unchecked {
++i;
}
}
}
function _checkIfMultipleCollectionsAndTokens(
address[] memory collections,
uint256[] memory tokenIds,
uint256 attributesLength
)
internal
pure
returns (
bool multipleCollections,
bool multipleTokens,
bool multipleAttributes,
uint256 loopLength
)
{
multipleCollections = collections.length != 1;
multipleTokens = tokenIds.length != 1;
multipleAttributes = attributesLength != 1;
if (
(multipleCollections &&
multipleAttributes &&
collections.length != attributesLength) ||
(multipleTokens &&
multipleAttributes &&
tokenIds.length != attributesLength) ||
(multipleCollections &&
multipleTokens &&
collections.length != tokenIds.length)
) {
revert LengthsMismatch();
}
if (multipleCollections) {
loopLength = collections.length;
} else if (multipleTokens) {
loopLength = tokenIds.length;
} else {
loopLength = attributesLength;
}
}
function _setBoolAttribute(
address caller,
address collection,
uint256 tokenId,
string memory key,
bool value
) internal {
_onlyAuthorizedCaller(caller, collection, key, tokenId);
_boolValues[collection][tokenId][_getIdForKey(key)] = value;
emit BoolAttributeUpdated(collection, tokenId, key, value);
}
function _setBytesAttribute(
address caller,
address collection,
uint256 tokenId,
string memory key,
bytes memory value
) internal {
_onlyAuthorizedCaller(caller, collection, key, tokenId);
_bytesValues[collection][tokenId][_getIdForKey(key)] = value;
emit BytesAttributeUpdated(collection, tokenId, key, value);
}
function _setAddressAttribute(
address caller,
address collection,
uint256 tokenId,
string memory key,
address value
) internal {
_onlyAuthorizedCaller(caller, collection, key, tokenId);
_addressValues[collection][tokenId][_getIdForKey(key)] = value;
emit AddressAttributeUpdated(collection, tokenId, key, value);
}
function _setStringAttribute(
address caller,
address collection,
uint256 tokenId,
string memory key,
string memory value
) internal {
_onlyAuthorizedCaller(caller, collection, key, tokenId);
_stringValues[collection][tokenId][_getIdForKey(key)] = value;
emit StringAttributeUpdated(collection, tokenId, key, value);
}
function _setUintAttribute(
address caller,
address collection,
uint256 tokenId,
string memory key,
uint256 value
) internal {
_onlyAuthorizedCaller(caller, collection, key, tokenId);
_uintValues[collection][tokenId][_getIdForKey(key)] = value;
emit UintAttributeUpdated(collection, tokenId, key, value);
}
/**
* @inheritdoc IERC7508Draft
*/
function presignedSetUintAttribute(
address setter,
address collection,
uint256 tokenId,
string memory key,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
keccak256(
abi.encode(
DOMAIN_SEPARATOR,
SET_UINT_ATTRIBUTE_TYPEHASH,
collection,
tokenId,
key,
value,
deadline
)
)
)
);
_checkDeadlineAndSigner(setter, deadline, digest, v, r, s);
_setUintAttribute(setter, collection, tokenId, key, value);
}
/**
* @inheritdoc IERC7508Draft
*/
function presignedSetStringAttribute(
address setter,
address collection,
uint256 tokenId,
string memory key,
string memory value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
keccak256(
abi.encode(
DOMAIN_SEPARATOR,
SET_STRING_ATTRIBUTE_TYPEHASH,
collection,
tokenId,
key,
value,
deadline
)
)
)
);
_checkDeadlineAndSigner(setter, deadline, digest, v, r, s);
_setStringAttribute(setter, collection, tokenId, key, value);
}
/**
* @inheritdoc IERC7508Draft
*/
function presignedSetBoolAttribute(
address setter,
address collection,
uint256 tokenId,
string memory key,
bool value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
keccak256(
abi.encode(
DOMAIN_SEPARATOR,
SET_BOOL_ATTRIBUTE_TYPEHASH,
collection,
tokenId,
key,
value,
deadline
)
)
)
);
_checkDeadlineAndSigner(setter, deadline, digest, v, r, s);
_setBoolAttribute(setter, collection, tokenId, key, value);
}
/**
* @inheritdoc IERC7508Draft
*/
function presignedSetBytesAttribute(
address setter,
address collection,
uint256 tokenId,
string memory key,
bytes memory value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
keccak256(
abi.encode(
DOMAIN_SEPARATOR,
SET_BYTES_ATTRIBUTE_TYPEHASH,
collection,
tokenId,
key,
value,
deadline
)
)
)
);
_checkDeadlineAndSigner(setter, deadline, digest, v, r, s);
_setBytesAttribute(setter, collection, tokenId, key, value);
}
/**
* @inheritdoc IERC7508Draft
*/
function presignedSetAddressAttribute(
address setter,
address collection,
uint256 tokenId,
string memory key,
address value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
keccak256(
abi.encode(
DOMAIN_SEPARATOR,
SET_ADDRESS_ATTRIBUTE_TYPEHASH,
collection,
tokenId,
key,
value,
deadline
)
)
)
);
_checkDeadlineAndSigner(setter, deadline, digest, v, r, s);
_setAddressAttribute(setter, collection, tokenId, key, value);
}
function _checkDeadlineAndSigner(
address setter,
uint256 deadline,
bytes32 digest,
uint8 v,
bytes32 r,
bytes32 s
) internal view {
if (block.timestamp > deadline) {
revert ExpiredDeadline();
}
address signer = ecrecover(digest, v, r, s);
if (signer != setter) {
revert InvalidSignature();
}
}
/**
* @notice Used to get the Id for a key. If the key does not exist, a new ID is created.
* IDs are shared among all tokens and types
* @dev The ID of 0 is not used as it represents the default value.
* @param key The attribute key
* @return keyID The ID of the key
*/
function _getIdForKey(string memory key) internal returns (uint256 keyID) {
if (_keysToIds[key] == 0) {
_nextKeyId++;
_keysToIds[key] = _nextKeyId;
keyID = _nextKeyId;
} else {
keyID = _keysToIds[key];
}
}
/**
* @inheritdoc IERC165
*/
function supportsInterface(
bytes4 interfaceId
) public view virtual returns (bool) {
return
interfaceId == type(IERC7508Draft).interfaceId ||
interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../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 address zero.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @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: Apache-2.0
pragma solidity ^0.8.21;
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @title IERC7508Draft
* @author RMRK team
* @notice Interface smart contract of the RMRK token properties extension.
*/
interface IERC7508Draft is IERC165 {
/**
* @notice A list of supported access types.
* @return The `Issuer` type, where only the issuer can manage the parameter.
* @return The `Collaborator` type, where only the collaborators can manage the parameter.
* @return The `IssuerOrCollaborator` type, where only the issuer or collaborators can manage the parameter.
* @return The `TokenOwner` type, where only the token owner can manage the parameters of their tokens.
* @return The `SpecificAddress` type, where only specific addresses can manage the parameter.
*/
enum AccessType {
Issuer,
Collaborator,
IssuerOrCollaborator,
TokenOwner,
SpecificAddress
}
/**
* @notice Structure used to represent a string attribute.
* @return key The key of the attribute
* @return value The value of the attribute
*/
struct StringAttribute {
string key;
string value;
}
/**
* @notice Structure used to represent an uint attribute.
* @return key The key of the attribute
* @return value The value of the attribute
*/
struct UintAttribute {
string key;
uint256 value;
}
/**
* @notice Structure used to represent a boolean attribute.
* @return key The key of the attribute
* @return value The value of the attribute
*/
struct BoolAttribute {
string key;
bool value;
}
/**
* @notice Structure used to represent an address attribute.
* @return key The key of the attribute
* @return value The value of the attribute
*/
struct AddressAttribute {
string key;
address value;
}
/**
* @notice Structure used to represent a bytes attribute.
* @return key The key of the attribute
* @return value The value of the attribute
*/
struct BytesAttribute {
string key;
bytes value;
}
/**
* @notice Used to notify listeners that a new collection has been registered to use the repository.
* @param collection Address of the collection
* @param issuer Address of the issuer of the collection; the addess authorized to manage the access control
* @param registeringAddress Address that registered the collection
* @param useOwnable A boolean value indicating whether the collection uses the Ownable extension to verify the
* issuer (`true`) or not (`false`)
*/
event AccessControlRegistration(
address indexed collection,
address indexed issuer,
address indexed registeringAddress,
bool useOwnable
);
/**
* @notice Used to notify listeners that the access control settings for a specific parameter have been updated.
* @param collection Address of the collection
* @param key The name of the parameter for which the access control settings have been updated
* @param accessType The AccessType of the parameter for which the access control settings have been updated
* @param specificAddress The specific addresses that has been updated
*/
event AccessControlUpdate(
address indexed collection,
string key,
AccessType accessType,
address specificAddress
);
/**
* @notice Used to notify listeners that the metadata URI for a collection has been updated.
* @param collection Address of the collection
* @param attributesMetadataURI The new attributes metadata URI
*/
event MetadataURIUpdated(
address indexed collection,
string attributesMetadataURI
);
/**
* @notice Used to notify listeners that a new collaborator has been added or removed.
* @param collection Address of the collection
* @param collaborator Address of the collaborator
* @param isCollaborator A boolean value indicating whether the collaborator has been added (`true`) or removed
* (`false`)
*/
event CollaboratorUpdate(
address indexed collection,
address indexed collaborator,
bool isCollaborator
);
/**
* @notice Used to notify listeners that a string attribute has been updated.
* @param collection The collection address
* @param tokenId The token ID
* @param key The key of the attribute
* @param value The new value of the attribute
*/
event StringAttributeUpdated(
address indexed collection,
uint256 indexed tokenId,
string key,
string value
);
/**
* @notice Used to notify listeners that an uint attribute has been updated.
* @param collection The collection address
* @param tokenId The token ID
* @param key The key of the attribute
* @param value The new value of the attribute
*/
event UintAttributeUpdated(
address indexed collection,
uint256 indexed tokenId,
string key,
uint256 value
);
/**
* @notice Used to notify listeners that a boolean attribute has been updated.
* @param collection The collection address
* @param tokenId The token ID
* @param key The key of the attribute
* @param value The new value of the attribute
*/
event BoolAttributeUpdated(
address indexed collection,
uint256 indexed tokenId,
string key,
bool value
);
/**
* @notice Used to notify listeners that an address attribute has been updated.
* @param collection The collection address
* @param tokenId The token ID
* @param key The key of the attribute
* @param value The new value of the attribute
*/
event AddressAttributeUpdated(
address indexed collection,
uint256 indexed tokenId,
string key,
address value
);
/**
* @notice Used to notify listeners that a bytes attribute has been updated.
* @param collection The collection address
* @param tokenId The token ID
* @param key The key of the attribute
* @param value The new value of the attribute
*/
event BytesAttributeUpdated(
address indexed collection,
uint256 indexed tokenId,
string key,
bytes value
);
/**
* @notice Used to register a collection to use the RMRK token attributes repository.
* @dev If the collection does not implement the Ownable interface, the `useOwnable` value must be set to `false`.
* @dev Emits an {AccessControlRegistration} event.
* @param collection The address of the collection that will use the RMRK token attributes repository.
* @param issuer The address of the issuer of the collection.
* @param useOwnable The boolean value to indicate if the collection implements the Ownable interface and whether it
* should be used to validate that the caller is the issuer (`true`) or to use the manually set issuer address
* (`false`).
*/
function registerAccessControl(
address collection,
address issuer,
bool useOwnable
) external;
/**
* @notice Used to manage the access control settings for a specific parameter.
* @dev Only the `issuer` of the collection can call this function.
* @dev The possible `accessType` values are:
* [
* Issuer,
* Collaborator,
* IssuerOrCollaborator,
* TokenOwner,
* SpecificAddress,
* ]
* @dev Emits an {AccessControlUpdated} event.
* @param collection The address of the collection being managed.
* @param key The key of the attribute
* @param accessType The type of access control to be applied to the parameter.
* @param specificAddress The address to be added as a specific addresses allowed to manage the given
* parameter.
*/
function manageAccessControl(
address collection,
string memory key,
AccessType accessType,
address specificAddress
) external;
/**
* @notice Used to manage the collaborators of a collection.
* @dev The `collaboratorAddresses` and `collaboratorAddressAccess` arrays must be of the same length.
* @dev Emits a {CollaboratorUpdate} event.
* @param collection The address of the collection
* @param collaboratorAddresses The array of collaborator addresses being managed
* @param collaboratorAddressAccess The array of boolean values indicating if the collaborator address should
* receive the permission (`true`) or not (`false`).
*/
function manageCollaborators(
address collection,
address[] memory collaboratorAddresses,
bool[] memory collaboratorAddressAccess
) external;
/**
* @notice Used to retrieve the attributes metadata URI for a collection, which contains all the information about the collection attributes.
* @param collection Address of the collection
* @return attributesMetadataURI The URI of the attributes metadata
*/
function getAttributesMetadataURI(
address collection
) external view returns (string memory attributesMetadataURI);
/**
* @notice Used to set the metadata URI for a collection, which contains all the information about the collection attributes.
* @dev Emits a {MetadataURIUpdated} event.
* @param collection Address of the collection
* @param attributesMetadataURI The URI of the attributes metadata
*/
function setAttributesMetadataURI(
address collection,
string memory attributesMetadataURI
) external;
/**
* @notice Used to set a number attribute.
* @dev Emits a {UintAttributeUpdated} event.
* @param collection Address of the collection receiving the attribute
* @param tokenId The token ID
* @param key The attribute key
* @param value The attribute value
*/
function setUintAttribute(
address collection,
uint256 tokenId,
string memory key,
uint256 value
) external;
/**
* @notice Used to set a string attribute.
* @dev Emits a {StringAttributeUpdated} event.
* @param collection Address of the collection receiving the attribute
* @param tokenId The token ID
* @param key The attribute key
* @param value The attribute value
*/
function setStringAttribute(
address collection,
uint256 tokenId,
string memory key,
string memory value
) external;
/**
* @notice Used to set a boolean attribute.
* @dev Emits a {BoolAttributeUpdated} event.
* @param collection Address of the collection receiving the attribute
* @param tokenId The token ID
* @param key The attribute key
* @param value The attribute value
*/
function setBoolAttribute(
address collection,
uint256 tokenId,
string memory key,
bool value
) external;
/**
* @notice Used to set an bytes attribute.
* @dev Emits a {BytesAttributeUpdated} event.
* @param collection Address of the collection receiving the attribute
* @param tokenId The token ID
* @param key The attribute key
* @param value The attribute value
*/
function setBytesAttribute(
address collection,
uint256 tokenId,
string memory key,
bytes memory value
) external;
/**
* @notice Used to set an address attribute.
* @dev Emits a {AddressAttributeUpdated} event.
* @param collection Address of the collection receiving the attribute
* @param tokenId The token ID
* @param key The attribute key
* @param value The attribute value
*/
function setAddressAttribute(
address collection,
uint256 tokenId,
string memory key,
address value
) external;
/**
* @notice Sets multiple string attributes for a token at once.
* @dev The `StringAttribute` struct contains the following fields:
* [
* string key,
* string value
* ]
* @param collections Addresses of the collections, in the same order as the attributes. If all tokens are from the same collection the array can contain a single element with the collection address.
* @param tokenIds IDs of the tokens, in the same order as the attributes. If all attributes are for the same token the array can contain a single element with the token ID.
* @param attributes An array of `StringAttribute` structs to be assigned to the given token
*/
function setStringAttributes(
address[] memory collections,
uint256[] memory tokenIds,
StringAttribute[] memory attributes
) external;
/**
* @notice Sets multiple uint attributes for a token at once.
* @dev The `UintAttribute` struct contains the following fields:
* [
* string key,
* uint value
* ]
* @param collections Addresses of the collections, in the same order as the attributes. If all tokens are from the same collection the array can contain a single element with the collection address.
* @param tokenIds IDs of the tokens, in the same order as the attributes. If all attributes are for the same token the array can contain a single element with the token ID.
* @param attributes An array of `UintAttribute` structs to be assigned to the given token
*/
function setUintAttributes(
address[] memory collections,
uint256[] memory tokenIds,
UintAttribute[] memory attributes
) external;
/**
* @notice Sets multiple bool attributes for a token at once.
* @dev The `BoolAttribute` struct contains the following fields:
* [
* string key,
* bool value
* ]
* @param collections Addresses of the collections, in the same order as the attributes. If all tokens are from the same collection the array can contain a single element with the collection address.
* @param tokenIds IDs of the tokens, in the same order as the attributes. If all attributes are for the same token the array can contain a single element with the token ID.
* @param attributes An array of `BoolAttribute` structs to be assigned to the given token
*/
function setBoolAttributes(
address[] memory collections,
uint256[] memory tokenIds,
BoolAttribute[] memory attributes
) external;
/**
* @notice Sets multiple address attributes for a token at once.
* @dev The `AddressAttribute` struct contains the following fields:
* [
* string key,
* address value
* ]
* @param collections Addresses of the collections, in the same order as the attributes. If all tokens are from the same collection the array can contain a single element with the collection address.
* @param tokenIds IDs of the tokens, in the same order as the attributes. If all attributes are for the same token the array can contain a single element with the token ID.
* @param attributes An array of `AddressAttribute` structs to be assigned to the given token
*/
function setAddressAttributes(
address[] memory collections,
uint256[] memory tokenIds,
AddressAttribute[] memory attributes
) external;
/**
* @notice Sets multiple bytes attributes for a token at once.
* @dev The `BytesAttribute` struct contains the following fields:
* [
* string key,
* bytes value
* ]
* @param collections Addresses of the collections, in the same order as the attributes. If all tokens are from the same collection the array can contain a single element with the collection address.
* @param tokenIds IDs of the tokens, in the same order as the attributes. If all attributes are for the same token the array can contain a single element with the token ID.
* @param attributes An array of `BytesAttribute` structs to be assigned to the given token
*/
function setBytesAttributes(
address[] memory collections,
uint256[] memory tokenIds,
BytesAttribute[] memory attributes
) external;
/**
* @notice Sets multiple attributes of multiple types for a token at the same time.
* @dev Emits a separate event for each attribute set.
* @dev The `StringAttribute`, `UintAttribute`, `BoolAttribute`, `AddressAttribute` and `BytesAttribute` structs consists
* to the following fields (where `value` is of the appropriate type):
* [
* key,
* value,
* ]
* @param collection The address of the collection
* @param tokenId The token ID
* @param stringAttributes An array of `StringAttribute` structs containing string attributes to set
* @param uintAttributes An array of `UintAttribute` structs containing uint attributes to set
* @param boolAttributes An array of `BoolAttribute` structs containing bool attributes to set
* @param addressAttributes An array of `AddressAttribute` structs containing address attributes to set
* @param bytesAttributes An array of `BytesAttribute` structs containing bytes attributes to set
*/
function setAttributes(
address collection,
uint256 tokenId,
StringAttribute[] memory stringAttributes,
UintAttribute[] memory uintAttributes,
BoolAttribute[] memory boolAttributes,
AddressAttribute[] memory addressAttributes,
BytesAttribute[] memory bytesAttributes
) external;
/**
* @notice Used to set the uint attribute on behalf of an authorized account.
* @dev Emits a {UintAttributeUpdated} event.
* @param setter Address of the account that presigned the attribute change
* @param collection Address of the collection receiving the attribute
* @param tokenId The ID of the token receiving the attribute
* @param key The attribute key
* @param value The attribute value
* @param deadline The deadline timestamp for the presigned transaction
* @param v `v` value of an ECDSA signature of the presigned message
* @param r `r` value of an ECDSA signature of the presigned message
* @param s `s` value of an ECDSA signature of the presigned message
*/
function presignedSetUintAttribute(
address setter,
address collection,
uint256 tokenId,
string memory key,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @notice Used to set the string attribute on behalf of an authorized account.
* @dev Emits a {StringAttributeUpdated} event.
* @param setter Address of the account that presigned the attribute change
* @param collection Address of the collection receiving the attribute
* @param tokenId The ID of the token receiving the attribute
* @param key The attribute key
* @param value The attribute value
* @param deadline The deadline timestamp for the presigned transaction
* @param v `v` value of an ECDSA signature of the presigned message
* @param r `r` value of an ECDSA signature of the presigned message
* @param s `s` value of an ECDSA signature of the presigned message
*/
function presignedSetStringAttribute(
address setter,
address collection,
uint256 tokenId,
string memory key,
string memory value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @notice Used to set the bool attribute on behalf of an authorized account.
* @dev Emits a {BoolAttributeUpdated} event.
* @param setter Address of the account that presigned the attribute change
* @param collection Address of the collection receiving the attribute
* @param tokenId The ID of the token receiving the attribute
* @param key The attribute key
* @param value The attribute value
* @param deadline The deadline timestamp for the presigned transaction
* @param v `v` value of an ECDSA signature of the presigned message
* @param r `r` value of an ECDSA signature of the presigned message
* @param s `s` value of an ECDSA signature of the presigned message
*/
function presignedSetBoolAttribute(
address setter,
address collection,
uint256 tokenId,
string memory key,
bool value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @notice Used to set the bytes attribute on behalf of an authorized account.
* @dev Emits a {BytesAttributeUpdated} event.
* @param setter Address of the account that presigned the attribute change
* @param collection Address of the collection receiving the attribute
* @param tokenId The ID of the token receiving the attribute
* @param key The attribute key
* @param value The attribute value
* @param deadline The deadline timestamp for the presigned transaction
* @param v `v` value of an ECDSA signature of the presigned message
* @param r `r` value of an ECDSA signature of the presigned message
* @param s `s` value of an ECDSA signature of the presigned message
*/
function presignedSetBytesAttribute(
address setter,
address collection,
uint256 tokenId,
string memory key,
bytes memory value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @notice Used to set the address attribute on behalf of an authorized account.
* @dev Emits a {AddressAttributeUpdated} event.
* @param setter Address of the account that presigned the attribute change
* @param collection Address of the collection receiving the attribute
* @param tokenId The ID of the token receiving the attribute
* @param key The attribute key
* @param value The attribute value
* @param deadline The deadline timestamp for the presigned transaction
* @param v `v` value of an ECDSA signature of the presigned message
* @param r `r` value of an ECDSA signature of the presigned message
* @param s `s` value of an ECDSA signature of the presigned message
*/
function presignedSetAddressAttribute(
address setter,
address collection,
uint256 tokenId,
string memory key,
address value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @notice Used to check if the specified address is listed as a collaborator of the given collection's parameter.
* @param collaborator Address to be checked.
* @param collection Address of the collection.
* @return isCollaborator_ Boolean value indicating if the address is a collaborator of the given collection's (`true`) or not
* (`false`).
*/
function isCollaborator(
address collaborator,
address collection
) external view returns (bool isCollaborator_);
/**
* @notice Used to check if the specified address is listed as a specific address of the given collection's
* parameter.
* @param specificAddress Address to be checked.
* @param collection Address of the collection.
* @param key The key of the attribute
* @return isSpecificAddress_ Boolean value indicating if the address is a specific address of the given collection's parameter
* (`true`) or not (`false`).
*/
function isSpecificAddress(
address specificAddress,
address collection,
string memory key
) external view returns (bool isSpecificAddress_);
/**
* @notice Used to retrieve the string type token attributes.
* @param collection The collection address
* @param tokenId The token ID
* @param key The key of the attribute
* @return attribute The value of the string attribute
*/
function getStringAttribute(
address collection,
uint256 tokenId,
string memory key
) external view returns (string memory attribute);
/**
* @notice Used to retrieve the uint type token attributes.
* @param collection The collection address
* @param tokenId The token ID
* @param key The key of the attribute
* @return attribute The value of the uint attribute
*/
function getUintAttribute(
address collection,
uint256 tokenId,
string memory key
) external view returns (uint256 attribute);
/**
* @notice Used to retrieve the bool type token attributes.
* @param collection The collection address
* @param tokenId The token ID
* @param key The key of the attribute
* @return attribute The value of the bool attribute
*/
function getBoolAttribute(
address collection,
uint256 tokenId,
string memory key
) external view returns (bool attribute);
/**
* @notice Used to retrieve the address type token attributes.
* @param collection The collection address
* @param tokenId The token ID
* @param key The key of the attribute
* @return attribute The value of the address attribute
*/
function getAddressAttribute(
address collection,
uint256 tokenId,
string memory key
) external view returns (address attribute);
/**
* @notice Used to retrieve the bytes type token attributes.
* @param collection The collection address
* @param tokenId The token ID
* @param key The key of the attribute
* @return attribute The value of the bytes attribute
*/
function getBytesAttribute(
address collection,
uint256 tokenId,
string memory key
) external view returns (bytes memory attribute);
/**
* @notice Used to retrieve the message to be signed for submitting a presigned uint attribute change.
* @param collection The address of the collection smart contract of the token receiving the attribute
* @param tokenId The ID of the token receiving the attribute
* @param key The attribute key
* @param value The attribute value
* @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
* @return message Raw message to be signed by the authorized account
*/
function prepareMessageToPresignUintAttribute(
address collection,
uint256 tokenId,
string memory key,
uint256 value,
uint256 deadline
) external view returns (bytes32 message);
/**
* @notice Used to retrieve the message to be signed for submitting a presigned string attribute change.
* @param collection The address of the collection smart contract of the token receiving the attribute
* @param tokenId The ID of the token receiving the attribute
* @param key The attribute key
* @param value The attribute value
* @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
* @return message Raw message to be signed by the authorized account
*/
function prepareMessageToPresignStringAttribute(
address collection,
uint256 tokenId,
string memory key,
string memory value,
uint256 deadline
) external view returns (bytes32 message);
/**
* @notice Used to retrieve the message to be signed for submitting a presigned bool attribute change.
* @param collection The address of the collection smart contract of the token receiving the attribute
* @param tokenId The ID of the token receiving the attribute
* @param key The attribute key
* @param value The attribute value
* @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
* @return message Raw message to be signed by the authorized account
*/
function prepareMessageToPresignBoolAttribute(
address collection,
uint256 tokenId,
string memory key,
bool value,
uint256 deadline
) external view returns (bytes32 message);
/**
* @notice Used to retrieve the message to be signed for submitting a presigned bytes attribute change.
* @param collection The address of the collection smart contract of the token receiving the attribute
* @param tokenId The ID of the token receiving the attribute
* @param key The attribute key
* @param value The attribute value
* @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
* @return message Raw message to be signed by the authorized account
*/
function prepareMessageToPresignBytesAttribute(
address collection,
uint256 tokenId,
string memory key,
bytes memory value,
uint256 deadline
) external view returns (bytes32 message);
/**
* @notice Used to retrieve the message to be signed for submitting a presigned address attribute change.
* @param collection The address of the collection smart contract of the token receiving the attribute
* @param tokenId The ID of the token receiving the attribute
* @param key The attribute key
* @param value The attribute value
* @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
* @return message Raw message to be signed by the authorized account
*/
function prepareMessageToPresignAddressAttribute(
address collection,
uint256 tokenId,
string memory key,
address value,
uint256 deadline
) external view returns (bytes32 message);
/**
* @notice Used to retrieve multiple token attributes of any type at once.
* @dev The `StringAttribute`, `UintAttribute`, `BoolAttribute`, `AddressAttribute` and `BytesAttribute` structs consists
* to the following fields (where `value` is of the appropriate type):
* [
* key,
* value,
* ]
* @param collection The collection address
* @param tokenId The token ID
* @param stringKeys An array of string type attribute keys to retrieve
* @param uintKeys An array of uint type attribute keys to retrieve
* @param boolKeys An array of bool type attribute keys to retrieve
* @param addressKeys An array of address type attribute keys to retrieve
* @param bytesKeys An array of bytes type attribute keys to retrieve
* @return stringAttributes An array of strings, in the same order as the stringKeys
* @return uintAttributes An array of uints, in the same order as the uintKeys
* @return boolAttributes An array of bools, in the same order as the boolKeys
* @return addressAttributes An array of addresses, in the same order as the addressKeys
* @return bytesAttributes An array of bytes, in the same order as the bytesKeys
*/
function getAttributes(
address collection,
uint256 tokenId,
string[] memory stringKeys,
string[] memory uintKeys,
string[] memory boolKeys,
string[] memory addressKeys,
string[] memory bytesKeys
)
external
view
returns (
string[] memory stringAttributes,
uint256[] memory uintAttributes,
bool[] memory boolAttributes,
address[] memory addressAttributes,
bytes[] memory bytesAttributes
);
/**
* @notice Used to get multiple sting parameter values for a token.
* @dev The `StringAttribute` struct contains the following fields:
* [
* string key,
* string value
* ]
* @param collections Addresses of the collections, in the same order as the attribute keys. If all tokens are from the same collection the array can contain a single element with the collection address.
* @param tokenIds IDs of the tokens, in the same order as the attribute keys. If all attributes are for the same token the array can contain a single element with the token ID.
* @param attributeKeys An array of string keys to retrieve
* @return attributes An array of strings, in the same order as the attribute keys
*/
function getStringAttributes(
address[] memory collections,
uint256[] memory tokenIds,
string[] memory attributeKeys
) external view returns (string[] memory attributes);
/**
* @notice Used to get multiple uint parameter values for a token.
* @dev The `UintAttribute` struct contains the following fields:
* [
* string key,
* uint value
* ]
* @param collections Addresses of the collections, in the same order as the attribute keys. If all tokens are from the same collection the array can contain a single element with the collection address.
* @param tokenIds IDs of the tokens, in the same order as the attribute keys. If all attributes are for the same token the array can contain a single element with the token ID.
* @param attributeKeys An array of uint keys to retrieve
* @return attributes An array of uints, in the same order as the attribute keys
*/
function getUintAttributes(
address[] memory collections,
uint256[] memory tokenIds,
string[] memory attributeKeys
) external view returns (uint256[] memory attributes);
/**
* @notice Used to get multiple bool parameter values for a token.
* @dev The `BoolAttribute` struct contains the following fields:
* [
* string key,
* bool value
* ]
* @param collections Addresses of the collections, in the same order as the attribute keys. If all tokens are from the same collection the array can contain a single element with the collection address.
* @param tokenIds IDs of the tokens, in the same order as the attribute keys. If all attributes are for the same token the array can contain a single element with the token ID.
* @param attributeKeys An array of bool keys to retrieve
* @return attributes An array of bools, in the same order as the attribute keys
*/
function getBoolAttributes(
address[] memory collections,
uint256[] memory tokenIds,
string[] memory attributeKeys
) external view returns (bool[] memory attributes);
/**
* @notice Used to get multiple address parameter values for a token.
* @dev The `AddressAttribute` struct contains the following fields:
* [
* string key,
* address value
* ]
* @param collections Addresses of the collections, in the same order as the attribute keys. If all tokens are from the same collection the array can contain a single element with the collection address.
* @param tokenIds IDs of the tokens, in the same order as the attribute keys. If all attributes are for the same token the array can contain a single element with the token ID.
* @param attributeKeys An array of address keys to retrieve
* @return attributes An array of addresses, in the same order as the attribute keys
*/
function getAddressAttributes(
address[] memory collections,
uint256[] memory tokenIds,
string[] memory attributeKeys
) external view returns (address[] memory attributes);
/**
* @notice Used to get multiple bytes parameter values for a token.
* @dev The `BytesAttribute` struct contains the following fields:
* [
* string key,
* bytes value
* ]
* @param collections Addresses of the collections, in the same order as the attribute keys. If all tokens are from the same collection the array can contain a single element with the collection address.
* @param tokenIds IDs of the tokens, in the same order as the attribute keys. If all attributes are for the same token the array can contain a single element with the token ID.
* @param attributeKeys An array of bytes keys to retrieve
* @return attributes An array of bytes, in the same order as the attribute keys
*/
function getBytesAttributes(
address[] memory collections,
uint256[] memory tokenIds,
string[] memory attributeKeys
) external view returns (bytes[] memory attributes);
}{
"evmVersion": "london",
"optimizer": {
"enabled": true,
"runs": 200
},
"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":[],"name":"CollaboratorArraysNotEqualLength","type":"error"},{"inputs":[],"name":"CollectionNotRegistered","type":"error"},{"inputs":[],"name":"ExpiredDeadline","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"LengthsMismatch","type":"error"},{"inputs":[],"name":"NotCollectionCollaborator","type":"error"},{"inputs":[],"name":"NotCollectionIssuer","type":"error"},{"inputs":[],"name":"NotCollectionIssuerOrCollaborator","type":"error"},{"inputs":[],"name":"NotSpecificAddress","type":"error"},{"inputs":[],"name":"NotTokenOwner","type":"error"},{"inputs":[],"name":"OwnableNotImplemented","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"address","name":"issuer","type":"address"},{"indexed":true,"internalType":"address","name":"registeringAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"useOwnable","type":"bool"}],"name":"AccessControlRegistration","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"enum IERC7508Draft.AccessType","name":"accessType","type":"uint8"},{"indexed":false,"internalType":"address","name":"specificAddress","type":"address"}],"name":"AccessControlUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"address","name":"value","type":"address"}],"name":"AddressAttributeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"BoolAttributeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"bytes","name":"value","type":"bytes"}],"name":"BytesAttributeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"address","name":"collaborator","type":"address"},{"indexed":false,"internalType":"bool","name":"isCollaborator","type":"bool"}],"name":"CollaboratorUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"string","name":"attributesMetadataURI","type":"string"}],"name":"MetadataURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"string","name":"value","type":"string"}],"name":"StringAttributeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collection","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"key","type":"string"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"UintAttributeUpdated","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SET_ADDRESS_ATTRIBUTE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SET_BOOL_ATTRIBUTE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SET_BYTES_ATTRIBUTE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SET_STRING_ATTRIBUTE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SET_UINT_ATTRIBUTE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"}],"name":"getAddressAttribute","outputs":[{"internalType":"address","name":"attribute","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"attributeKeys","type":"string[]"}],"name":"getAddressAttributes","outputs":[{"internalType":"address[]","name":"attributes","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string[]","name":"stringKeys","type":"string[]"},{"internalType":"string[]","name":"uintKeys","type":"string[]"},{"internalType":"string[]","name":"boolKeys","type":"string[]"},{"internalType":"string[]","name":"addressKeys","type":"string[]"},{"internalType":"string[]","name":"bytesKeys","type":"string[]"}],"name":"getAttributes","outputs":[{"internalType":"string[]","name":"stringAttributes","type":"string[]"},{"internalType":"uint256[]","name":"uintAttributes","type":"uint256[]"},{"internalType":"bool[]","name":"boolAttributes","type":"bool[]"},{"internalType":"address[]","name":"addressAttributes","type":"address[]"},{"internalType":"bytes[]","name":"bytesAttributes","type":"bytes[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"getAttributesMetadataURI","outputs":[{"internalType":"string","name":"attributesMetadataURI","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"}],"name":"getBoolAttribute","outputs":[{"internalType":"bool","name":"attribute","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"attributeKeys","type":"string[]"}],"name":"getBoolAttributes","outputs":[{"internalType":"bool[]","name":"attributes","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"}],"name":"getBytesAttribute","outputs":[{"internalType":"bytes","name":"attribute","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"attributeKeys","type":"string[]"}],"name":"getBytesAttributes","outputs":[{"internalType":"bytes[]","name":"attributes","type":"bytes[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"}],"name":"getStringAttribute","outputs":[{"internalType":"string","name":"attribute","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"attributeKeys","type":"string[]"}],"name":"getStringAttributes","outputs":[{"internalType":"string[]","name":"attributes","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"}],"name":"getUintAttribute","outputs":[{"internalType":"uint256","name":"attribute","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"attributeKeys","type":"string[]"}],"name":"getUintAttributes","outputs":[{"internalType":"uint256[]","name":"attributes","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collaborator","type":"address"},{"internalType":"address","name":"collection","type":"address"}],"name":"isCollaborator","outputs":[{"internalType":"bool","name":"isCollaborator_","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"specificAddress","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"string","name":"key","type":"string"}],"name":"isSpecificAddress","outputs":[{"internalType":"bool","name":"isSpecificAddress_","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"string","name":"key","type":"string"},{"internalType":"enum IERC7508Draft.AccessType","name":"accessType","type":"uint8"},{"internalType":"address","name":"specificAddress","type":"address"}],"name":"manageAccessControl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address[]","name":"collaboratorAddresses","type":"address[]"},{"internalType":"bool[]","name":"collaboratorAddressAccess","type":"bool[]"}],"name":"manageCollaborators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"address","name":"value","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"prepareMessageToPresignAddressAttribute","outputs":[{"internalType":"bytes32","name":"message","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"bool","name":"value","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"prepareMessageToPresignBoolAttribute","outputs":[{"internalType":"bytes32","name":"message","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"prepareMessageToPresignBytesAttribute","outputs":[{"internalType":"bytes32","name":"message","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"prepareMessageToPresignStringAttribute","outputs":[{"internalType":"bytes32","name":"message","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"prepareMessageToPresignUintAttribute","outputs":[{"internalType":"bytes32","name":"message","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"setter","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"address","name":"value","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"presignedSetAddressAttribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"setter","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"bool","name":"value","type":"bool"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"presignedSetBoolAttribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"setter","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"presignedSetBytesAttribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"setter","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"presignedSetStringAttribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"setter","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"presignedSetUintAttribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"issuer","type":"address"},{"internalType":"bool","name":"useOwnable","type":"bool"}],"name":"registerAccessControl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"address","name":"value","type":"address"}],"name":"setAddressAttribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"address","name":"value","type":"address"}],"internalType":"struct IERC7508Draft.AddressAttribute[]","name":"attributes","type":"tuple[]"}],"name":"setAddressAttributes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"internalType":"struct IERC7508Draft.StringAttribute[]","name":"stringAttributes","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IERC7508Draft.UintAttribute[]","name":"uintAttributes","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bool","name":"value","type":"bool"}],"internalType":"struct IERC7508Draft.BoolAttribute[]","name":"boolAttributes","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"address","name":"value","type":"address"}],"internalType":"struct IERC7508Draft.AddressAttribute[]","name":"addressAttributes","type":"tuple[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"}],"internalType":"struct IERC7508Draft.BytesAttribute[]","name":"bytesAttributes","type":"tuple[]"}],"name":"setAttributes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"string","name":"attributesMetadataURI","type":"string"}],"name":"setAttributesMetadataURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setBoolAttribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bool","name":"value","type":"bool"}],"internalType":"struct IERC7508Draft.BoolAttribute[]","name":"attributes","type":"tuple[]"}],"name":"setBoolAttributes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"}],"name":"setBytesAttribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"}],"internalType":"struct IERC7508Draft.BytesAttribute[]","name":"attributes","type":"tuple[]"}],"name":"setBytesAttributes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setStringAttribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"internalType":"struct IERC7508Draft.StringAttribute[]","name":"attributes","type":"tuple[]"}],"name":"setStringAttributes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"key","type":"string"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setUintAttribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"collections","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"components":[{"internalType":"string","name":"key","type":"string"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IERC7508Draft.UintAttribute[]","name":"attributes","type":"tuple[]"}],"name":"setUintAttributes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608061016081815260336101e0527f4552432d373530383a205075626c6963204f6e2d436861696e204e4654204174610200527f7472696275746573205265706f7369746f7279000000000000000000000000006102205260e0610180819052600161024052603160f81b61026052466101a052306101c052610120610140819052610280604052918290209092527f20772140fdb3d071eaa7b3c498d767632d85382eadebf1c930637df53bdb772f60a0527f62f1fea563417698e0150e612482a1413def1f1206fd1c85981ff0bd9ffb5f8860c0527fb44b995c45c2bef12a1ba33bc54e45cbbdd566df618a1d8d769adc7f902121149091527f8d7561f54c33dc0cf43c405f24523cfbf86f6c991e371994b70c7f65bf87406e610100527fb6d8284afd9120a0a19f8dd4bb0119595e5fb90b1c0a48c239b3e001105fdf4b905234801561014e57600080fd5b5060805160a05160c05160e05161010051610120516149d761022a6000396000818161056201528181611ab40152611f3c015260008181610515015281816119440152611edd0152600081816106ba01528181611c1501526124cf01526000818161059c01528181610c1d01526112b90152600081816106e1015281816119fc0152611e7e0152600081816103ec01528181610bfc0152818161129801528181611923015281816119db01528181611a9301528181611bf401528181611e5d01528181611ebc01528181611f1b01526124ae01526149d76000f3fe608060405234801561001057600080fd5b50600436106102895760003560e01c806369a2b5f11161015c578063bf65cf66116100ce578063dacdb1a211610087578063dacdb1a21461068f578063e3698a9c146106a2578063e482c4a2146106b5578063e7bc7454146106dc578063ed20867214610703578063efd1f2e21461071657600080fd5b8063bf65cf661461061d578063c034868c14610630578063c58281bc14610643578063cc9cc37214610656578063cedb3f8914610669578063cf59a0311461067c57600080fd5b806399d58b181161012057806399d58b18146105975780639ccf774f146105be578063acb80ac8146105d1578063ad965b35146105e4578063b43c50e2146105f7578063bcbf00261461060a57600080fd5b806369a2b5f1146105105780636a97da2b14610537578063700a9fe21461054a578063890d6d5d1461055d57806399ce1b6a1461058457600080fd5b8063323ebf301161020057806358d7ac36116101b957806358d7ac36146104845780635d1d61b6146104975780635e63d019146104b7578063622a61e1146104ca578063649dde6a146104dd5780636592caf6146104f057600080fd5b8063323ebf30146103c75780633644e515146103e75780633806d3841461040e5780633b4afbe5146104215780634a70d1091461045e57806350fc17281461047157600080fd5b80630c7af259116102525780630c7af2591461032357806314ac5b391461034e5780631785d5151461036e57806319c4fb5d1461038e5780631b8bfea3146103a15780632d793515146103b457600080fd5b806274b0571461028e57806301ffc9a7146102a357806305c55942146102cb578063062d49aa146102de57806308cca828146102ff575b600080fd5b6102a161029c366004613181565b610729565b005b6102b66102b13660046131f9565b610934565b60405190151581526020015b60405180910390f35b6102a16102d93660046132d1565b61096b565b6102f16102ec3660046133a3565b610bf8565b6040519081526020016102c2565b61031261030d3660046134a9565b610c78565b6040516102c29594939291906136df565b61033661033136600461374c565b610d78565b6040516001600160a01b0390911681526020016102c2565b61036161035c3660046137ff565b610ddf565b6040516102c2919061387c565b61038161037c3660046137ff565b610f3a565b6040516102c2919061388f565b6102a161039c3660046138a2565b611084565b6102f16103af36600461374c565b611097565b6102a16103c236600461390b565b6110f4565b6103da6103d536600461396b565b611101565b6040516102c29190613988565b6102f17f000000000000000000000000000000000000000000000000000000000000000081565b6103da61041c36600461374c565b6111ad565b6102b661042f36600461399b565b6001600160a01b0390811660009081526003602090815260408083209490931682529290925290205460ff1690565b6102a161046c3660046139e5565b611294565b6102a161047f366004613b63565b611358565b6103da61049236600461374c565b611464565b6104aa6104a53660046137ff565b61149c565b6040516102c29190613be0565b6102b66104c5366004613bf3565b6115f3565b6102b66104d836600461374c565b611668565b6102a16104eb366004613d0b565b6116c9565b6105036104fe3660046137ff565b6117cb565b6040516102c29190613d88565b6102f17f000000000000000000000000000000000000000000000000000000000000000081565b6102a16105453660046139e5565b61191f565b6102a1610558366004613d9b565b6119d7565b6102f17f000000000000000000000000000000000000000000000000000000000000000081565b6102f1610592366004613e20565b611a8f565b6102f17f000000000000000000000000000000000000000000000000000000000000000081565b6102a16105cc366004613f71565b611aee565b6102a16105df366004613fee565b611bf0565b6102a16105f236600461407a565b611ca8565b6102f16106053660046140c1565b611e59565b6102f16106183660046133a3565b611eb8565b6102a161062b36600461412b565b611f17565b61050361063e3660046137ff565b611fcf565b6102a16106513660046141a4565b612123565b6102a16106643660046142eb565b612130565b6102a16106773660046141a4565b612232565b6102a161068a366004614368565b61223f565b6102a161069d366004613f71565b6123a8565b6102f16106b03660046143b7565b6124aa565b6102f17f000000000000000000000000000000000000000000000000000000000000000081565b6102f17f000000000000000000000000000000000000000000000000000000000000000081565b6102a1610711366004614417565b612509565b6102a1610724366004614477565b612516565b6001600160a01b038416600090815260026020526040902054849060ff1661076457604051632a5cc95960e21b815260040160405180910390fd5b6001600160a01b0385166000908152600260205260409020548590610100900460ff161561082457336001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f89190614553565b6001600160a01b03161461081f576040516373fe3ec360e11b815260040160405180910390fd5b610864565b6001600160a01b03818116600090815260026020526040902054620100009004163314610864576040516373fe3ec360e11b815260040160405180910390fd5b600061086f866126f5565b6001600160a01b03881660009081526020818152604080832084845290915290208054919250869160ff191660018360048111156108af576108af614570565b02179055506001600160a01b0387811660008181526001602090815260408083208684529091529081902080546001600160a01b0319169388169390931790925590517f97d2a2ba740da24a4e4a4e94fd62999fa5917e0df31c996b0305550a292673a99061092390899089908990614586565b60405180910390a250505050505050565b60006001600160e01b03198216633177473d60e11b148061096557506001600160e01b031982166301ffc9a760e01b145b92915050565b6001600160a01b038316600090815260026020526040902054839060ff166109a657604051632a5cc95960e21b815260040160405180910390fd5b6001600160a01b0384166000908152600260205260409020548490610100900460ff1615610a6657336001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3a9190614553565b6001600160a01b031614610a61576040516373fe3ec360e11b815260040160405180910390fd5b610aa6565b6001600160a01b03818116600090815260026020526040902054620100009004163314610aa6576040516373fe3ec360e11b815260040160405180910390fd5b835183518114610ac957604051630b13873760e01b815260040160405180910390fd5b60005b81811015610bef57848181518110610ae657610ae66145d8565b602002602001015160036000896001600160a01b03166001600160a01b031681526020019081526020016000206000888481518110610b2757610b276145d8565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550858181518110610b7857610b786145d8565b60200260200101516001600160a01b0316876001600160a01b03167f5ce2cdea67a188cbf267b966a3a0d897f902c098d0b718269e43dd3cd618761a878481518110610bc657610bc66145d8565b6020026020010151604051610bdf911515815260200190565b60405180910390a3600101610acc565b50505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008787878787604051602001610c5797969594939291906145ee565b60405160208183030381529060405280519060200120905095945050505050565b60608080808060006001604051908082528060200260200182016040528015610cab578160200160208202803683370190505b5060408051600180825281830190925291925060009190602080830190803683370190505090508d82600081518110610ce657610ce66145d8565b60200260200101906001600160a01b031690816001600160a01b0316815250508c81600081518110610d1a57610d1a6145d8565b602002602001018181525050610d3182828e6117cb565b9650610d3e82828d610f3a565b9550610d4b82828c610ddf565b9450610d5882828b61149c565b9350610d6582828a611fcf565b9250505097509750975097509792505050565b6001600160a01b038316600090815260076020908152604080832085845290915280822090518290600490610dae908690614648565b90815260408051602092819003830190205483529082019290925201600020546001600160a01b0316949350505050565b6060600080600080610df388888851612785565b9350935093509350806001600160401b03811115610e1357610e136130a4565b604051908082528060200260200182016040528015610e3c578160200160208202803683370190505b50945060005b81811015610f2e57610f0485610e725789600081518110610e6557610e656145d8565b6020026020010151610e8d565b898281518110610e8457610e846145d8565b60200260200101515b85610eb25789600081518110610ea557610ea56145d8565b6020026020010151610ecd565b898381518110610ec457610ec46145d8565b60200260200101515b85610ef25789600081518110610ee557610ee56145d8565b6020026020010151611668565b898481518110610ee557610ee56145d8565b868281518110610f1657610f166145d8565b91151560209283029190910190910152600101610e42565b50505050509392505050565b6060600080600080610f4e88888851612785565b9350935093509350806001600160401b03811115610f6e57610f6e6130a4565b604051908082528060200260200182016040528015610f97578160200160208202803683370190505b50945060005b81811015610f2e5761105f85610fcd5789600081518110610fc057610fc06145d8565b6020026020010151610fe8565b898281518110610fdf57610fdf6145d8565b60200260200101515b8561100d5789600081518110611000576110006145d8565b6020026020010151611028565b89838151811061101f5761101f6145d8565b60200260200101515b8561104d5789600081518110611040576110406145d8565b6020026020010151611097565b898481518110611040576110406145d8565b868281518110611071576110716145d8565b6020908102919091010152600101610f9d565b6110913385858585612834565b50505050565b6001600160a01b0383166000908152600960209081526040808320858452909152808220905182906004906110cd908690614648565b90815260200160405180910390205481526020019081526020016000205490509392505050565b61109133858585856128de565b6001600160a01b038116600090815260066020526040902080546060919061112890614664565b80601f016020809104026020016040519081016040528092919081815260200182805461115490614664565b80156111a15780601f10611176576101008083540402835291602001916111a1565b820191906000526020600020905b81548152906001019060200180831161118457829003601f168201915b50505050509050919050565b6001600160a01b03831660009081526008602090815260408083208584529091528082209051606092906004906111e5908690614648565b9081526020016040518091039020548152602001908152602001600020805461120d90614664565b80601f016020809104026020016040519081016040528092919081815260200182805461123990614664565b80156112865780601f1061125b57610100808354040283529160200191611286565b820191906000526020600020905b81548152906001019060200180831161126957829003601f168201915b505050505090509392505050565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008a8a8a8a8a6040516020016112f397969594939291906145ee565b60405160208183030381529060405280519060200120604051602001611319919061469e565b60405160208183030381529060405280519060200120905061133f8a8683878787612979565b61134c8a8a8a8a8a612a2c565b50505050505050505050565b60008060008061136a87878751612785565b935093509350935060005b8181101561145a576000836113a45786600081518110611397576113976145d8565b60200260200101516113bf565b8682815181106113b6576113b66145d8565b60200260200101515b905061145133876113ea578a6000815181106113dd576113dd6145d8565b6020026020010151611405565b8a84815181106113fc576113fc6145d8565b60200260200101515b8761142a578a60008151811061141d5761141d6145d8565b6020026020010151611445565b8a858151811061143c5761143c6145d8565b60200260200101515b84516020860151612abd565b50600101611375565b5050505050505050565b6001600160a01b0383166000908152600b602090815260408083208584529091528082209051606092906004906111e5908690614648565b60606000806000806114b088888851612785565b9350935093509350806001600160401b038111156114d0576114d06130a4565b6040519080825280602002602001820160405280156114f9578160200160208202803683370190505b50945060005b81811015610f2e576115c18561152f5789600081518110611522576115226145d8565b602002602001015161154a565b898281518110611541576115416145d8565b60200260200101515b8561156f5789600081518110611562576115626145d8565b602002602001015161158a565b898381518110611581576115816145d8565b60200260200101515b856115af57896000815181106115a2576115a26145d8565b6020026020010151610d78565b8984815181106115a2576115a26145d8565b8682815181106115d3576115d36145d8565b6001600160a01b03909216602092830291909101909101526001016114ff565b6000836001600160a01b031660016000856001600160a01b03166001600160a01b0316815260200190815260200160002060006004856040516116369190614648565b90815260408051602092819003830190205483529082019290925201600020546001600160a01b031614949350505050565b6001600160a01b0383166000908152600a602090815260408083208584529091528082209051829060049061169e908690614648565b908152604080516020928190038301902054835290820192909252016000205460ff16949350505050565b6000806000806116db87878751612785565b935093509350935060005b8181101561145a576000836117155786600081518110611708576117086145d8565b6020026020010151611730565b868281518110611727576117276145d8565b60200260200101515b90506117c2338761175b578a60008151811061174e5761174e6145d8565b6020026020010151611776565b8a848151811061176d5761176d6145d8565b60200260200101515b8761179b578a60008151811061178e5761178e6145d8565b60200260200101516117b6565b8a85815181106117ad576117ad6145d8565b60200260200101515b845160208601516128de565b506001016116e6565b60606000806000806117df88888851612785565b9350935093509350806001600160401b038111156117ff576117ff6130a4565b60405190808252806020026020018201604052801561183257816020015b606081526020019060019003908161181d5790505b50945060005b81811015610f2e576118fa85611868578960008151811061185b5761185b6145d8565b6020026020010151611883565b89828151811061187a5761187a6145d8565b60200260200101515b856118a8578960008151811061189b5761189b6145d8565b60200260200101516118c3565b8983815181106118ba576118ba6145d8565b60200260200101515b856118e857896000815181106118db576118db6145d8565b6020026020010151611464565b8984815181106118db576118db6145d8565b86828151811061190c5761190c6145d8565b6020908102919091010152600101611838565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008a8a8a8a8a60405160200161197e97969594939291906145ee565b604051602081830303815290604052805190602001206040516020016119a4919061469e565b6040516020818303038152906040528051906020012090506119ca8a8683878787612979565b61134c8a8a8a8a8a612b45565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008a8a8a8a8a604051602001611a3697969594939291906146cf565b60405160208183030381529060405280519060200120604051602001611a5c919061469e565b604051602081830303815290604052805190602001209050611a828a8683878787612979565b61134c8a8a8a8a8a612abd565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008787878787604051602001610c579796959493929190614718565b600080600080611b0087878751612785565b935093509350935060005b8181101561145a57600083611b3a5786600081518110611b2d57611b2d6145d8565b6020026020010151611b55565b868281518110611b4c57611b4c6145d8565b60200260200101515b9050611be73387611b80578a600081518110611b7357611b736145d8565b6020026020010151611b9b565b8a8481518110611b9257611b926145d8565b60200260200101515b87611bc0578a600081518110611bb357611bb36145d8565b6020026020010151611bdb565b8a8581518110611bd257611bd26145d8565b60200260200101515b84516020860151612b45565b50600101611b0b565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008a8a8a8a8a604051602001611c4f9796959493929190614761565b60405160208183030381529060405280519060200120604051602001611c75919061469e565b604051602081830303815290604052805190602001209050611c9b8a8683878787612979565b61134c8a8a8a8a8a612834565b60408051600481526024810182526020810180516001600160e01b0316638da5cb5b60e01b179052905160009182916001600160a01b03871691611ceb91614648565b6000604051808303816000865af19150503d8060008114611d28576040519150601f19603f3d011682016040523d82523d6000602084013e611d2d565b606091505b5090925090506000611d3e826147aa565b6001600160a01b031603611d6557604051632384b66d60e01b815260040160405180910390fd5b818015611d83575033611d77826147aa565b6001600160a01b031614155b15611da1576040516373fe3ec360e11b815260040160405180910390fd5b604080516060810182526001815284151560208083018281526001600160a01b038981168587018181528c83166000818152600287528990209751885495519251909416620100000262010000600160b01b03199215156101000261ff00199515159590951661ffff19909616959095179390931716929092179094559351918252339392917f961c9ccd18ff75f83e58597107ced585c08a0514de45947c8aa7a0d5fdf67d18910160405180910390a45050505050565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008787878787604051602001610c5797969594939291906146cf565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008787878787604051602001610c5797969594939291906145ee565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008a8a8a8a8a604051602001611f769796959493929190614718565b60405160208183030381529060405280519060200120604051602001611f9c919061469e565b604051602081830303815290604052805190602001209050611fc28a8683878787612979565b61134c8a8a8a8a8a6128de565b6060600080600080611fe388888851612785565b9350935093509350806001600160401b03811115612003576120036130a4565b60405190808252806020026020018201604052801561203657816020015b60608152602001906001900390816120215790505b50945060005b81811015610f2e576120fe8561206c578960008151811061205f5761205f6145d8565b6020026020010151612087565b89828151811061207e5761207e6145d8565b60200260200101515b856120ac578960008151811061209f5761209f6145d8565b60200260200101516120c7565b8983815181106120be576120be6145d8565b60200260200101515b856120ec57896000815181106120df576120df6145d8565b60200260200101516111ad565b8984815181106120df576120df6145d8565b868281518110612110576121106145d8565b602090810291909101015260010161203c565b6110913385858585612b45565b60008060008061214287878751612785565b935093509350935060005b8181101561145a5760008361217c578660008151811061216f5761216f6145d8565b6020026020010151612197565b86828151811061218e5761218e6145d8565b60200260200101515b905061222933876121c2578a6000815181106121b5576121b56145d8565b60200260200101516121dd565b8a84815181106121d4576121d46145d8565b60200260200101515b87612202578a6000815181106121f5576121f56145d8565b602002602001015161221d565b8a8581518110612214576122146145d8565b60200260200101515b84516020860151612834565b5060010161214d565b6110913385858585612a2c565b6001600160a01b0382166000908152600260205260409020548290610100900460ff16156122ff57336001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d39190614553565b6001600160a01b0316146122fa576040516373fe3ec360e11b815260040160405180910390fd5b61233f565b6001600160a01b0381811660009081526002602052604090205462010000900416331461233f576040516373fe3ec360e11b815260040160405180910390fd5b6001600160a01b0383166000908152600660205260409020612361838261481d565b50826001600160a01b03167f1b460238cb695fc31c141a22bca8cea3e92a6fa4ded4ccee2a33f9972f2eece08360405161239b9190613988565b60405180910390a2505050565b6000806000806123ba87878751612785565b935093509350935060005b8181101561145a576000836123f457866000815181106123e7576123e76145d8565b602002602001015161240f565b868281518110612406576124066145d8565b60200260200101515b90506124a1338761243a578a60008151811061242d5761242d6145d8565b6020026020010151612455565b8a848151811061244c5761244c6145d8565b60200260200101515b8761247a578a60008151811061246d5761246d6145d8565b6020026020010151612495565b8a858151811061248c5761248c6145d8565b60200260200101515b84516020860151612a2c565b506001016123c5565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008787878787604051602001610c579796959493929190614761565b6110913385858585612abd565b845160005b818110156125725761256a338a8a8a858151811061253b5761253b6145d8565b6020026020010151600001518b8681518110612559576125596145d8565b602002602001015160200151612a2c565b60010161251b565b5050835160005b818110156125d0576125c8338a8a898581518110612599576125996145d8565b6020026020010151600001518a86815181106125b7576125b76145d8565b602002602001015160200151612abd565b600101612579565b5050825160005b8181101561262e57612626338a8a8885815181106125f7576125f76145d8565b602002602001015160000151898681518110612615576126156145d8565b602002602001015160200151612834565b6001016125d7565b5050815160005b8181101561268c57612684338a8a878581518110612655576126556145d8565b602002602001015160000151888681518110612673576126736145d8565b6020026020010151602001516128de565b600101612635565b5050805160005b818110156126ea576126e2338a8a8685815181106126b3576126b36145d8565b6020026020010151600001518786815181106126d1576126d16145d8565b602002602001015160200151612b45565b600101612693565b505050505050505050565b60006004826040516127079190614648565b90815260200160405180910390205460000361275e576005805490600061272d836148dc565b91905055506005546004836040516127459190614648565b9081526040519081900360200190205550600554919050565b60048260405161276e9190614648565b90815260200160405180910390205490505b919050565b82518251600191821480159291821415918414159060009084906127a65750815b80156127b3575084875114155b806127d057508280156127c35750815b80156127d0575084865114155b806127ee57508380156127e05750825b80156127ee57508551875114155b1561280c5760405163586cb9e160e01b815260040160405180910390fd5b831561281a5750855161282b565b82156128285750845161282b565b50835b93509350935093565b61284085858486612bd6565b6001600160a01b0384166000908152600a602090815260408083208684529091528120829161286e856126f5565b815260200190815260200160002060006101000a81548160ff02191690831515021790555082846001600160a01b03167ffc6eac6df20a61ff9d8ec7453e452ca73931f2cb16944e9dc884b4a8d642391484846040516128cf929190614903565b60405180910390a35050505050565b6128ea85858486612bd6565b6001600160a01b038416600090815260076020908152604080832086845290915281208291612918856126f5565b81526020810191909152604090810160002080546001600160a01b0319166001600160a01b039384161790555184918616907f78ab16f2d097b9728046fb602022fccefef4ec306810b9e8b6fd618e91c12214906128cf9086908690614927565b8442111561299a5760405163f87d927160e01b815260040160405180910390fd5b6040805160008082526020820180845287905260ff861692820192909252606081018490526080810183905260019060a0016020604051602081039080840390855afa1580156129ee573d6000803e3d6000fd5b505050602060405103519050866001600160a01b0316816001600160a01b031614610bef57604051638baa579f60e01b815260040160405180910390fd5b612a3885858486612bd6565b6001600160a01b0384166000908152600b6020908152604080832086845290915281208291612a66856126f5565b81526020019081526020016000209081612a80919061481d565b5082846001600160a01b03167f11e1b2f69159e4bf02488e2c90bf30e6075a4bf57a39ce63ba83d10a96777c0384846040516128cf929190614951565b612ac985858486612bd6565b6001600160a01b038416600090815260096020908152604080832086845290915281208291612af7856126f5565b81526020019081526020016000208190555082846001600160a01b03167f2b529d8c80cbea7dc71690ffd099111430f1e30963439b4659e9a1ec3fba578584846040516128cf92919061497f565b612b5185858486612bd6565b6001600160a01b038416600090815260086020908152604080832086845290915281208291612b7f856126f5565b81526020019081526020016000209081612b99919061481d565b5082846001600160a01b03167f3e7f7fe71b156da17053b2814558642d261b19433ae77e083aac01f074124f3784846040516128cf929190614951565b6001600160a01b03831660009081526020819052604080822090518290600490612c01908790614648565b9081526040805160209281900383019020548352908201929092520160009081205460ff169150816004811115612c3a57612c3a614570565b148015612d3957506001600160a01b038416600090815260026020526040902054610100900460ff168015612ce25750846001600160a01b0316846001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd69190614553565b6001600160a01b031614155b80612d3957506001600160a01b038416600090815260026020526040902054610100900460ff16158015612d3957506001600160a01b03848116600090815260026020526040902054620100009004811690861614155b15612d57576040516373fe3ec360e11b815260040160405180910390fd5b6001816004811115612d6b57612d6b614570565b148015612d9e57506001600160a01b0380851660009081526003602090815260408083209389168352929052205460ff16155b15612dbc57604051637dc99f8960e11b815260040160405180910390fd5b6002816004811115612dd057612dd0614570565b148015612ecf57506001600160a01b038416600090815260026020526040902054610100900460ff168015612e785750846001600160a01b0316846001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6c9190614553565b6001600160a01b031614155b80612ecf57506001600160a01b038416600090815260026020526040902054610100900460ff16158015612ecf57506001600160a01b03848116600090815260026020526040902054620100009004811690861614155b8015612f0157506001600160a01b0380851660009081526003602090815260408083209389168352929052205460ff16155b15612f1f576040516369fb20b560e01b815260040160405180910390fd5b6003816004811115612f3357612f33614570565b148015612fb557506040516331a9108f60e11b8152600481018390526001600160a01b038087169190861690636352211e90602401602060405180830381865afa158015612f85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fa99190614553565b6001600160a01b031614155b15612fd3576040516359dc379f60e01b815260040160405180910390fd5b6004816004811115612fe757612fe7614570565b14801561305c5750846001600160a01b031660016000866001600160a01b03166001600160a01b0316815260200190815260200160002060006004866040516130309190614648565b90815260408051602092819003830190205483529082019290925201600020546001600160a01b031614155b1561307a576040516370e2142360e11b815260040160405180910390fd5b5050505050565b6001600160a01b038116811461309657600080fd5b50565b803561278081613081565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156130dc576130dc6130a4565b60405290565b604051601f8201601f191681016001600160401b038111828210171561310a5761310a6130a4565b604052919050565b600082601f83011261312357600080fd5b81356001600160401b0381111561313c5761313c6130a4565b61314f601f8201601f19166020016130e2565b81815284602083860101111561316457600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561319757600080fd5b84356131a281613081565b935060208501356001600160401b038111156131bd57600080fd5b6131c987828801613112565b9350506040850135600581106131de57600080fd5b915060608501356131ee81613081565b939692955090935050565b60006020828403121561320b57600080fd5b81356001600160e01b03198116811461322357600080fd5b9392505050565b60006001600160401b03821115613243576132436130a4565b5060051b60200190565b600082601f83011261325e57600080fd5b8135602061327361326e8361322a565b6130e2565b82815260059290921b8401810191818101908684111561329257600080fd5b8286015b848110156132b65780356132a981613081565b8352918301918301613296565b509695505050505050565b8035801515811461278057600080fd5b6000806000606084860312156132e657600080fd5b83356132f181613081565b92506020848101356001600160401b038082111561330e57600080fd5b61331a8883890161324d565b9450604087013591508082111561333057600080fd5b508501601f8101871361334257600080fd5b803561335061326e8261322a565b81815260059190911b8201830190838101908983111561336f57600080fd5b928401925b8284101561339457613385846132c1565b82529284019290840190613374565b80955050505050509250925092565b600080600080600060a086880312156133bb57600080fd5b85356133c681613081565b94506020860135935060408601356001600160401b03808211156133e957600080fd5b6133f589838a01613112565b9450606088013591508082111561340b57600080fd5b5061341888828901613112565b95989497509295608001359392505050565b600082601f83011261343b57600080fd5b8135602061344b61326e8361322a565b82815260059290921b8401810191818101908684111561346a57600080fd5b8286015b848110156132b65780356001600160401b0381111561348d5760008081fd5b61349b8986838b0101613112565b84525091830191830161346e565b600080600080600080600060e0888a0312156134c457600080fd5b6134cd88613099565b96506020880135955060408801356001600160401b03808211156134f057600080fd5b6134fc8b838c0161342a565b965060608a013591508082111561351257600080fd5b61351e8b838c0161342a565b955060808a013591508082111561353457600080fd5b6135408b838c0161342a565b945060a08a013591508082111561355657600080fd5b6135628b838c0161342a565b935060c08a013591508082111561357857600080fd5b506135858a828b0161342a565b91505092959891949750929550565b60005b838110156135af578181015183820152602001613597565b50506000910152565b600081518084526135d0816020860160208601613594565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b8581101561362c57828403895261361a8483516135b8565b98850198935090840190600101613602565b5091979650505050505050565b600081518084526020808501945080840160005b838110156136695781518752958201959082019060010161364d565b509495945050505050565b600081518084526020808501945080840160005b83811015613669578151151587529582019590820190600101613688565b600081518084526020808501945080840160005b838110156136695781516001600160a01b0316875295820195908201906001016136ba565b60a0815260006136f260a08301886135e4565b82810360208401526137048188613639565b905082810360408401526137188187613674565b9050828103606084015261372c81866136a6565b9050828103608084015261374081856135e4565b98975050505050505050565b60008060006060848603121561376157600080fd5b833561376c81613081565b92506020840135915060408401356001600160401b0381111561378e57600080fd5b61379a86828701613112565b9150509250925092565b600082601f8301126137b557600080fd5b813560206137c561326e8361322a565b82815260059290921b840181019181810190868411156137e457600080fd5b8286015b848110156132b657803583529183019183016137e8565b60008060006060848603121561381457600080fd5b83356001600160401b038082111561382b57600080fd5b6138378783880161324d565b9450602086013591508082111561384d57600080fd5b613859878388016137a4565b9350604086013591508082111561386f57600080fd5b5061379a8682870161342a565b6020815260006132236020830184613674565b6020815260006132236020830184613639565b600080600080608085870312156138b857600080fd5b84356138c381613081565b93506020850135925060408501356001600160401b038111156138e557600080fd5b6138f187828801613112565b925050613900606086016132c1565b905092959194509250565b6000806000806080858703121561392157600080fd5b843561392c81613081565b93506020850135925060408501356001600160401b0381111561394e57600080fd5b61395a87828801613112565b92505060608501356131ee81613081565b60006020828403121561397d57600080fd5b813561322381613081565b60208152600061322360208301846135b8565b600080604083850312156139ae57600080fd5b82356139b981613081565b915060208301356139c981613081565b809150509250929050565b803560ff8116811461278057600080fd5b60008060008060008060008060006101208a8c031215613a0457600080fd5b8935613a0f81613081565b985060208a0135613a1f81613081565b975060408a0135965060608a01356001600160401b0380821115613a4257600080fd5b613a4e8d838e01613112565b975060808c0135915080821115613a6457600080fd5b50613a718c828d01613112565b95505060a08a01359350613a8760c08b016139d4565b925060e08a013591506101008a013590509295985092959850929598565b600082601f830112613ab657600080fd5b81356020613ac661326e8361322a565b82815260059290921b84018101918181019086841115613ae557600080fd5b8286015b848110156132b65780356001600160401b0380821115613b095760008081fd5b908801906040828b03601f1901811315613b235760008081fd5b613b2b6130ba565b8784013583811115613b3d5760008081fd5b613b4b8d8a83880101613112565b82525092013586830152508352918301918301613ae9565b600080600060608486031215613b7857600080fd5b83356001600160401b0380821115613b8f57600080fd5b613b9b8783880161324d565b94506020860135915080821115613bb157600080fd5b613bbd878388016137a4565b93506040860135915080821115613bd357600080fd5b5061379a86828701613aa5565b60208152600061322360208301846136a6565b600080600060608486031215613c0857600080fd5b8335613c1381613081565b92506020840135613c2381613081565b915060408401356001600160401b0381111561378e57600080fd5b600082601f830112613c4f57600080fd5b81356020613c5f61326e8361322a565b82815260059290921b84018101918181019086841115613c7e57600080fd5b8286015b848110156132b65780356001600160401b0380821115613ca25760008081fd5b908801906040828b03601f1901811315613cbc5760008081fd5b613cc46130ba565b8784013583811115613cd65760008081fd5b613ce48d8a83880101613112565b8252509281013592613cf584613081565b8088019390935250508352918301918301613c82565b600080600060608486031215613d2057600080fd5b83356001600160401b0380821115613d3757600080fd5b613d438783880161324d565b94506020860135915080821115613d5957600080fd5b613d65878388016137a4565b93506040860135915080821115613d7b57600080fd5b5061379a86828701613c3e565b60208152600061322360208301846135e4565b60008060008060008060008060006101208a8c031215613dba57600080fd5b8935613dc581613081565b985060208a0135613dd581613081565b975060408a0135965060608a01356001600160401b03811115613df757600080fd5b613e038c828d01613112565b96505060808a0135945060a08a01359350613a8760c08b016139d4565b600080600080600060a08688031215613e3857600080fd5b8535613e4381613081565b94506020860135935060408601356001600160401b03811115613e6557600080fd5b613e7188828901613112565b9350506060860135613e8281613081565b949793965091946080013592915050565b600082601f830112613ea457600080fd5b81356020613eb461326e8361322a565b82815260059290921b84018101918181019086841115613ed357600080fd5b8286015b848110156132b65780356001600160401b0380821115613ef75760008081fd5b908801906040828b03601f1901811315613f115760008081fd5b613f196130ba565b8784013583811115613f2b5760008081fd5b613f398d8a83880101613112565b825250908301359082821115613f4f5760008081fd5b613f5d8c8984870101613112565b818901528652505050918301918301613ed7565b600080600060608486031215613f8657600080fd5b83356001600160401b0380821115613f9d57600080fd5b613fa98783880161324d565b94506020860135915080821115613fbf57600080fd5b613fcb878388016137a4565b93506040860135915080821115613fe157600080fd5b5061379a86828701613e93565b60008060008060008060008060006101208a8c03121561400d57600080fd5b893561401881613081565b985060208a013561402881613081565b975060408a0135965060608a01356001600160401b0381111561404a57600080fd5b6140568c828d01613112565b96505061406560808b016132c1565b945060a08a01359350613a8760c08b016139d4565b60008060006060848603121561408f57600080fd5b833561409a81613081565b925060208401356140aa81613081565b91506140b8604085016132c1565b90509250925092565b600080600080600060a086880312156140d957600080fd5b85356140e481613081565b94506020860135935060408601356001600160401b0381111561410657600080fd5b61411288828901613112565b9598949750949560608101359550608001359392505050565b60008060008060008060008060006101208a8c03121561414a57600080fd5b893561415581613081565b985060208a013561416581613081565b975060408a0135965060608a01356001600160401b0381111561418757600080fd5b6141938c828d01613112565b96505060808a013561406581613081565b600080600080608085870312156141ba57600080fd5b84356141c581613081565b93506020850135925060408501356001600160401b03808211156141e857600080fd5b6141f488838901613112565b9350606087013591508082111561420a57600080fd5b5061421787828801613112565b91505092959194509250565b600082601f83011261423457600080fd5b8135602061424461326e8361322a565b82815260059290921b8401810191818101908684111561426357600080fd5b8286015b848110156132b65780356001600160401b03808211156142875760008081fd5b908801906040828b03601f19018113156142a15760008081fd5b6142a96130ba565b87840135838111156142bb5760008081fd5b6142c98d8a83880101613112565b8252506142d78285016132c1565b818901528652505050918301918301614267565b60008060006060848603121561430057600080fd5b83356001600160401b038082111561431757600080fd5b6143238783880161324d565b9450602086013591508082111561433957600080fd5b614345878388016137a4565b9350604086013591508082111561435b57600080fd5b5061379a86828701614223565b6000806040838503121561437b57600080fd5b823561438681613081565b915060208301356001600160401b038111156143a157600080fd5b6143ad85828601613112565b9150509250929050565b600080600080600060a086880312156143cf57600080fd5b85356143da81613081565b94506020860135935060408601356001600160401b038111156143fc57600080fd5b61440888828901613112565b935050613e82606087016132c1565b6000806000806080858703121561442d57600080fd5b843561443881613081565b93506020850135925060408501356001600160401b0381111561445a57600080fd5b61446687828801613112565b949793965093946060013593505050565b600080600080600080600060e0888a03121561449257600080fd5b61449b88613099565b96506020880135955060408801356001600160401b03808211156144be57600080fd5b6144ca8b838c01613e93565b965060608a01359150808211156144e057600080fd5b6144ec8b838c01613aa5565b955060808a013591508082111561450257600080fd5b61450e8b838c01614223565b945060a08a013591508082111561452457600080fd5b6145308b838c01613c3e565b935060c08a013591508082111561454657600080fd5b506135858a828b01613e93565b60006020828403121561456557600080fd5b815161322381613081565b634e487b7160e01b600052602160045260246000fd5b60608152600061459960608301866135b8565b9050600584106145b957634e487b7160e01b600052602160045260246000fd5b60208201939093526001600160a01b0391909116604090910152919050565b634e487b7160e01b600052603260045260246000fd5b87815286602082015260018060a01b038616604082015284606082015260e06080820152600061462160e08301866135b8565b82810360a084015261463381866135b8565b9150508260c083015298975050505050505050565b6000825161465a818460208701613594565b9190910192915050565b600181811c9082168061467857607f821691505b60208210810361469857634e487b7160e01b600052602260045260246000fd5b50919050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b87815286602082015260018060a01b038616604082015284606082015260e06080820152600061470260e08301866135b8565b60a08301949094525060c0015295945050505050565b878152866020820152600060018060a01b03808816604084015286606084015260e0608084015261474c60e08401876135b8565b941660a08301525060c0015295945050505050565b87815286602082015260018060a01b038616604082015284606082015260e06080820152600061479460e08301866135b8565b93151560a08301525060c0015295945050505050565b805160208083015191908110156146985760001960209190910360031b1b16919050565b601f82111561481857600081815260208120601f850160051c810160208610156147f55750805b601f850160051c820191505b8181101561481457828155600101614801565b5050505b505050565b81516001600160401b03811115614836576148366130a4565b61484a816148448454614664565b846147ce565b602080601f83116001811461487f57600084156148675750858301515b600019600386901b1c1916600185901b178555614814565b600085815260208120601f198616915b828110156148ae5788860151825594840194600190910190840161488f565b50858210156148cc5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000600182016148fc57634e487b7160e01b600052601160045260246000fd5b5060010190565b60408152600061491660408301856135b8565b905082151560208301529392505050565b60408152600061493a60408301856135b8565b905060018060a01b03831660208301529392505050565b60408152600061496460408301856135b8565b828103602084015261497681856135b8565b95945050505050565b60408152600061499260408301856135b8565b9050826020830152939250505056fea2646970667358221220ea06907bb934af84aa38e1ede82b212855aa51f7b1ffc16c736ed769264eb00564736f6c63430008150033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102895760003560e01c806369a2b5f11161015c578063bf65cf66116100ce578063dacdb1a211610087578063dacdb1a21461068f578063e3698a9c146106a2578063e482c4a2146106b5578063e7bc7454146106dc578063ed20867214610703578063efd1f2e21461071657600080fd5b8063bf65cf661461061d578063c034868c14610630578063c58281bc14610643578063cc9cc37214610656578063cedb3f8914610669578063cf59a0311461067c57600080fd5b806399d58b181161012057806399d58b18146105975780639ccf774f146105be578063acb80ac8146105d1578063ad965b35146105e4578063b43c50e2146105f7578063bcbf00261461060a57600080fd5b806369a2b5f1146105105780636a97da2b14610537578063700a9fe21461054a578063890d6d5d1461055d57806399ce1b6a1461058457600080fd5b8063323ebf301161020057806358d7ac36116101b957806358d7ac36146104845780635d1d61b6146104975780635e63d019146104b7578063622a61e1146104ca578063649dde6a146104dd5780636592caf6146104f057600080fd5b8063323ebf30146103c75780633644e515146103e75780633806d3841461040e5780633b4afbe5146104215780634a70d1091461045e57806350fc17281461047157600080fd5b80630c7af259116102525780630c7af2591461032357806314ac5b391461034e5780631785d5151461036e57806319c4fb5d1461038e5780631b8bfea3146103a15780632d793515146103b457600080fd5b806274b0571461028e57806301ffc9a7146102a357806305c55942146102cb578063062d49aa146102de57806308cca828146102ff575b600080fd5b6102a161029c366004613181565b610729565b005b6102b66102b13660046131f9565b610934565b60405190151581526020015b60405180910390f35b6102a16102d93660046132d1565b61096b565b6102f16102ec3660046133a3565b610bf8565b6040519081526020016102c2565b61031261030d3660046134a9565b610c78565b6040516102c29594939291906136df565b61033661033136600461374c565b610d78565b6040516001600160a01b0390911681526020016102c2565b61036161035c3660046137ff565b610ddf565b6040516102c2919061387c565b61038161037c3660046137ff565b610f3a565b6040516102c2919061388f565b6102a161039c3660046138a2565b611084565b6102f16103af36600461374c565b611097565b6102a16103c236600461390b565b6110f4565b6103da6103d536600461396b565b611101565b6040516102c29190613988565b6102f17f9f3c1709ee31fe1cae732286b4075668113234ff5507605a3cf6d4af994d9a9881565b6103da61041c36600461374c565b6111ad565b6102b661042f36600461399b565b6001600160a01b0390811660009081526003602090815260408083209490931682529290925290205460ff1690565b6102a161046c3660046139e5565b611294565b6102a161047f366004613b63565b611358565b6103da61049236600461374c565b611464565b6104aa6104a53660046137ff565b61149c565b6040516102c29190613be0565b6102b66104c5366004613bf3565b6115f3565b6102b66104d836600461374c565b611668565b6102a16104eb366004613d0b565b6116c9565b6105036104fe3660046137ff565b6117cb565b6040516102c29190613d88565b6102f17f8d7561f54c33dc0cf43c405f24523cfbf86f6c991e371994b70c7f65bf87406e81565b6102a16105453660046139e5565b61191f565b6102a1610558366004613d9b565b6119d7565b6102f17fb6d8284afd9120a0a19f8dd4bb0119595e5fb90b1c0a48c239b3e001105fdf4b81565b6102f1610592366004613e20565b611a8f565b6102f17f62f1fea563417698e0150e612482a1413def1f1206fd1c85981ff0bd9ffb5f8881565b6102a16105cc366004613f71565b611aee565b6102a16105df366004613fee565b611bf0565b6102a16105f236600461407a565b611ca8565b6102f16106053660046140c1565b611e59565b6102f16106183660046133a3565b611eb8565b6102a161062b36600461412b565b611f17565b61050361063e3660046137ff565b611fcf565b6102a16106513660046141a4565b612123565b6102a16106643660046142eb565b612130565b6102a16106773660046141a4565b612232565b6102a161068a366004614368565b61223f565b6102a161069d366004613f71565b6123a8565b6102f16106b03660046143b7565b6124aa565b6102f17fb44b995c45c2bef12a1ba33bc54e45cbbdd566df618a1d8d769adc7f9021211481565b6102f17f20772140fdb3d071eaa7b3c498d767632d85382eadebf1c930637df53bdb772f81565b6102a1610711366004614417565b612509565b6102a1610724366004614477565b612516565b6001600160a01b038416600090815260026020526040902054849060ff1661076457604051632a5cc95960e21b815260040160405180910390fd5b6001600160a01b0385166000908152600260205260409020548590610100900460ff161561082457336001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f89190614553565b6001600160a01b03161461081f576040516373fe3ec360e11b815260040160405180910390fd5b610864565b6001600160a01b03818116600090815260026020526040902054620100009004163314610864576040516373fe3ec360e11b815260040160405180910390fd5b600061086f866126f5565b6001600160a01b03881660009081526020818152604080832084845290915290208054919250869160ff191660018360048111156108af576108af614570565b02179055506001600160a01b0387811660008181526001602090815260408083208684529091529081902080546001600160a01b0319169388169390931790925590517f97d2a2ba740da24a4e4a4e94fd62999fa5917e0df31c996b0305550a292673a99061092390899089908990614586565b60405180910390a250505050505050565b60006001600160e01b03198216633177473d60e11b148061096557506001600160e01b031982166301ffc9a760e01b145b92915050565b6001600160a01b038316600090815260026020526040902054839060ff166109a657604051632a5cc95960e21b815260040160405180910390fd5b6001600160a01b0384166000908152600260205260409020548490610100900460ff1615610a6657336001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3a9190614553565b6001600160a01b031614610a61576040516373fe3ec360e11b815260040160405180910390fd5b610aa6565b6001600160a01b03818116600090815260026020526040902054620100009004163314610aa6576040516373fe3ec360e11b815260040160405180910390fd5b835183518114610ac957604051630b13873760e01b815260040160405180910390fd5b60005b81811015610bef57848181518110610ae657610ae66145d8565b602002602001015160036000896001600160a01b03166001600160a01b031681526020019081526020016000206000888481518110610b2757610b276145d8565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550858181518110610b7857610b786145d8565b60200260200101516001600160a01b0316876001600160a01b03167f5ce2cdea67a188cbf267b966a3a0d897f902c098d0b718269e43dd3cd618761a878481518110610bc657610bc66145d8565b6020026020010151604051610bdf911515815260200190565b60405180910390a3600101610acc565b50505050505050565b60007f9f3c1709ee31fe1cae732286b4075668113234ff5507605a3cf6d4af994d9a987f62f1fea563417698e0150e612482a1413def1f1206fd1c85981ff0bd9ffb5f888787878787604051602001610c5797969594939291906145ee565b60405160208183030381529060405280519060200120905095945050505050565b60608080808060006001604051908082528060200260200182016040528015610cab578160200160208202803683370190505b5060408051600180825281830190925291925060009190602080830190803683370190505090508d82600081518110610ce657610ce66145d8565b60200260200101906001600160a01b031690816001600160a01b0316815250508c81600081518110610d1a57610d1a6145d8565b602002602001018181525050610d3182828e6117cb565b9650610d3e82828d610f3a565b9550610d4b82828c610ddf565b9450610d5882828b61149c565b9350610d6582828a611fcf565b9250505097509750975097509792505050565b6001600160a01b038316600090815260076020908152604080832085845290915280822090518290600490610dae908690614648565b90815260408051602092819003830190205483529082019290925201600020546001600160a01b0316949350505050565b6060600080600080610df388888851612785565b9350935093509350806001600160401b03811115610e1357610e136130a4565b604051908082528060200260200182016040528015610e3c578160200160208202803683370190505b50945060005b81811015610f2e57610f0485610e725789600081518110610e6557610e656145d8565b6020026020010151610e8d565b898281518110610e8457610e846145d8565b60200260200101515b85610eb25789600081518110610ea557610ea56145d8565b6020026020010151610ecd565b898381518110610ec457610ec46145d8565b60200260200101515b85610ef25789600081518110610ee557610ee56145d8565b6020026020010151611668565b898481518110610ee557610ee56145d8565b868281518110610f1657610f166145d8565b91151560209283029190910190910152600101610e42565b50505050509392505050565b6060600080600080610f4e88888851612785565b9350935093509350806001600160401b03811115610f6e57610f6e6130a4565b604051908082528060200260200182016040528015610f97578160200160208202803683370190505b50945060005b81811015610f2e5761105f85610fcd5789600081518110610fc057610fc06145d8565b6020026020010151610fe8565b898281518110610fdf57610fdf6145d8565b60200260200101515b8561100d5789600081518110611000576110006145d8565b6020026020010151611028565b89838151811061101f5761101f6145d8565b60200260200101515b8561104d5789600081518110611040576110406145d8565b6020026020010151611097565b898481518110611040576110406145d8565b868281518110611071576110716145d8565b6020908102919091010152600101610f9d565b6110913385858585612834565b50505050565b6001600160a01b0383166000908152600960209081526040808320858452909152808220905182906004906110cd908690614648565b90815260200160405180910390205481526020019081526020016000205490509392505050565b61109133858585856128de565b6001600160a01b038116600090815260066020526040902080546060919061112890614664565b80601f016020809104026020016040519081016040528092919081815260200182805461115490614664565b80156111a15780601f10611176576101008083540402835291602001916111a1565b820191906000526020600020905b81548152906001019060200180831161118457829003601f168201915b50505050509050919050565b6001600160a01b03831660009081526008602090815260408083208584529091528082209051606092906004906111e5908690614648565b9081526020016040518091039020548152602001908152602001600020805461120d90614664565b80601f016020809104026020016040519081016040528092919081815260200182805461123990614664565b80156112865780601f1061125b57610100808354040283529160200191611286565b820191906000526020600020905b81548152906001019060200180831161126957829003601f168201915b505050505090509392505050565b60007f9f3c1709ee31fe1cae732286b4075668113234ff5507605a3cf6d4af994d9a987f62f1fea563417698e0150e612482a1413def1f1206fd1c85981ff0bd9ffb5f888a8a8a8a8a6040516020016112f397969594939291906145ee565b60405160208183030381529060405280519060200120604051602001611319919061469e565b60405160208183030381529060405280519060200120905061133f8a8683878787612979565b61134c8a8a8a8a8a612a2c565b50505050505050505050565b60008060008061136a87878751612785565b935093509350935060005b8181101561145a576000836113a45786600081518110611397576113976145d8565b60200260200101516113bf565b8682815181106113b6576113b66145d8565b60200260200101515b905061145133876113ea578a6000815181106113dd576113dd6145d8565b6020026020010151611405565b8a84815181106113fc576113fc6145d8565b60200260200101515b8761142a578a60008151811061141d5761141d6145d8565b6020026020010151611445565b8a858151811061143c5761143c6145d8565b60200260200101515b84516020860151612abd565b50600101611375565b5050505050505050565b6001600160a01b0383166000908152600b602090815260408083208584529091528082209051606092906004906111e5908690614648565b60606000806000806114b088888851612785565b9350935093509350806001600160401b038111156114d0576114d06130a4565b6040519080825280602002602001820160405280156114f9578160200160208202803683370190505b50945060005b81811015610f2e576115c18561152f5789600081518110611522576115226145d8565b602002602001015161154a565b898281518110611541576115416145d8565b60200260200101515b8561156f5789600081518110611562576115626145d8565b602002602001015161158a565b898381518110611581576115816145d8565b60200260200101515b856115af57896000815181106115a2576115a26145d8565b6020026020010151610d78565b8984815181106115a2576115a26145d8565b8682815181106115d3576115d36145d8565b6001600160a01b03909216602092830291909101909101526001016114ff565b6000836001600160a01b031660016000856001600160a01b03166001600160a01b0316815260200190815260200160002060006004856040516116369190614648565b90815260408051602092819003830190205483529082019290925201600020546001600160a01b031614949350505050565b6001600160a01b0383166000908152600a602090815260408083208584529091528082209051829060049061169e908690614648565b908152604080516020928190038301902054835290820192909252016000205460ff16949350505050565b6000806000806116db87878751612785565b935093509350935060005b8181101561145a576000836117155786600081518110611708576117086145d8565b6020026020010151611730565b868281518110611727576117276145d8565b60200260200101515b90506117c2338761175b578a60008151811061174e5761174e6145d8565b6020026020010151611776565b8a848151811061176d5761176d6145d8565b60200260200101515b8761179b578a60008151811061178e5761178e6145d8565b60200260200101516117b6565b8a85815181106117ad576117ad6145d8565b60200260200101515b845160208601516128de565b506001016116e6565b60606000806000806117df88888851612785565b9350935093509350806001600160401b038111156117ff576117ff6130a4565b60405190808252806020026020018201604052801561183257816020015b606081526020019060019003908161181d5790505b50945060005b81811015610f2e576118fa85611868578960008151811061185b5761185b6145d8565b6020026020010151611883565b89828151811061187a5761187a6145d8565b60200260200101515b856118a8578960008151811061189b5761189b6145d8565b60200260200101516118c3565b8983815181106118ba576118ba6145d8565b60200260200101515b856118e857896000815181106118db576118db6145d8565b6020026020010151611464565b8984815181106118db576118db6145d8565b86828151811061190c5761190c6145d8565b6020908102919091010152600101611838565b60007f9f3c1709ee31fe1cae732286b4075668113234ff5507605a3cf6d4af994d9a987f8d7561f54c33dc0cf43c405f24523cfbf86f6c991e371994b70c7f65bf87406e8a8a8a8a8a60405160200161197e97969594939291906145ee565b604051602081830303815290604052805190602001206040516020016119a4919061469e565b6040516020818303038152906040528051906020012090506119ca8a8683878787612979565b61134c8a8a8a8a8a612b45565b60007f9f3c1709ee31fe1cae732286b4075668113234ff5507605a3cf6d4af994d9a987f20772140fdb3d071eaa7b3c498d767632d85382eadebf1c930637df53bdb772f8a8a8a8a8a604051602001611a3697969594939291906146cf565b60405160208183030381529060405280519060200120604051602001611a5c919061469e565b604051602081830303815290604052805190602001209050611a828a8683878787612979565b61134c8a8a8a8a8a612abd565b60007f9f3c1709ee31fe1cae732286b4075668113234ff5507605a3cf6d4af994d9a987fb6d8284afd9120a0a19f8dd4bb0119595e5fb90b1c0a48c239b3e001105fdf4b8787878787604051602001610c579796959493929190614718565b600080600080611b0087878751612785565b935093509350935060005b8181101561145a57600083611b3a5786600081518110611b2d57611b2d6145d8565b6020026020010151611b55565b868281518110611b4c57611b4c6145d8565b60200260200101515b9050611be73387611b80578a600081518110611b7357611b736145d8565b6020026020010151611b9b565b8a8481518110611b9257611b926145d8565b60200260200101515b87611bc0578a600081518110611bb357611bb36145d8565b6020026020010151611bdb565b8a8581518110611bd257611bd26145d8565b60200260200101515b84516020860151612b45565b50600101611b0b565b60007f9f3c1709ee31fe1cae732286b4075668113234ff5507605a3cf6d4af994d9a987fb44b995c45c2bef12a1ba33bc54e45cbbdd566df618a1d8d769adc7f902121148a8a8a8a8a604051602001611c4f9796959493929190614761565b60405160208183030381529060405280519060200120604051602001611c75919061469e565b604051602081830303815290604052805190602001209050611c9b8a8683878787612979565b61134c8a8a8a8a8a612834565b60408051600481526024810182526020810180516001600160e01b0316638da5cb5b60e01b179052905160009182916001600160a01b03871691611ceb91614648565b6000604051808303816000865af19150503d8060008114611d28576040519150601f19603f3d011682016040523d82523d6000602084013e611d2d565b606091505b5090925090506000611d3e826147aa565b6001600160a01b031603611d6557604051632384b66d60e01b815260040160405180910390fd5b818015611d83575033611d77826147aa565b6001600160a01b031614155b15611da1576040516373fe3ec360e11b815260040160405180910390fd5b604080516060810182526001815284151560208083018281526001600160a01b038981168587018181528c83166000818152600287528990209751885495519251909416620100000262010000600160b01b03199215156101000261ff00199515159590951661ffff19909616959095179390931716929092179094559351918252339392917f961c9ccd18ff75f83e58597107ced585c08a0514de45947c8aa7a0d5fdf67d18910160405180910390a45050505050565b60007f9f3c1709ee31fe1cae732286b4075668113234ff5507605a3cf6d4af994d9a987f20772140fdb3d071eaa7b3c498d767632d85382eadebf1c930637df53bdb772f8787878787604051602001610c5797969594939291906146cf565b60007f9f3c1709ee31fe1cae732286b4075668113234ff5507605a3cf6d4af994d9a987f8d7561f54c33dc0cf43c405f24523cfbf86f6c991e371994b70c7f65bf87406e8787878787604051602001610c5797969594939291906145ee565b60007f9f3c1709ee31fe1cae732286b4075668113234ff5507605a3cf6d4af994d9a987fb6d8284afd9120a0a19f8dd4bb0119595e5fb90b1c0a48c239b3e001105fdf4b8a8a8a8a8a604051602001611f769796959493929190614718565b60405160208183030381529060405280519060200120604051602001611f9c919061469e565b604051602081830303815290604052805190602001209050611fc28a8683878787612979565b61134c8a8a8a8a8a6128de565b6060600080600080611fe388888851612785565b9350935093509350806001600160401b03811115612003576120036130a4565b60405190808252806020026020018201604052801561203657816020015b60608152602001906001900390816120215790505b50945060005b81811015610f2e576120fe8561206c578960008151811061205f5761205f6145d8565b6020026020010151612087565b89828151811061207e5761207e6145d8565b60200260200101515b856120ac578960008151811061209f5761209f6145d8565b60200260200101516120c7565b8983815181106120be576120be6145d8565b60200260200101515b856120ec57896000815181106120df576120df6145d8565b60200260200101516111ad565b8984815181106120df576120df6145d8565b868281518110612110576121106145d8565b602090810291909101015260010161203c565b6110913385858585612b45565b60008060008061214287878751612785565b935093509350935060005b8181101561145a5760008361217c578660008151811061216f5761216f6145d8565b6020026020010151612197565b86828151811061218e5761218e6145d8565b60200260200101515b905061222933876121c2578a6000815181106121b5576121b56145d8565b60200260200101516121dd565b8a84815181106121d4576121d46145d8565b60200260200101515b87612202578a6000815181106121f5576121f56145d8565b602002602001015161221d565b8a8581518110612214576122146145d8565b60200260200101515b84516020860151612834565b5060010161214d565b6110913385858585612a2c565b6001600160a01b0382166000908152600260205260409020548290610100900460ff16156122ff57336001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d39190614553565b6001600160a01b0316146122fa576040516373fe3ec360e11b815260040160405180910390fd5b61233f565b6001600160a01b0381811660009081526002602052604090205462010000900416331461233f576040516373fe3ec360e11b815260040160405180910390fd5b6001600160a01b0383166000908152600660205260409020612361838261481d565b50826001600160a01b03167f1b460238cb695fc31c141a22bca8cea3e92a6fa4ded4ccee2a33f9972f2eece08360405161239b9190613988565b60405180910390a2505050565b6000806000806123ba87878751612785565b935093509350935060005b8181101561145a576000836123f457866000815181106123e7576123e76145d8565b602002602001015161240f565b868281518110612406576124066145d8565b60200260200101515b90506124a1338761243a578a60008151811061242d5761242d6145d8565b6020026020010151612455565b8a848151811061244c5761244c6145d8565b60200260200101515b8761247a578a60008151811061246d5761246d6145d8565b6020026020010151612495565b8a858151811061248c5761248c6145d8565b60200260200101515b84516020860151612a2c565b506001016123c5565b60007f9f3c1709ee31fe1cae732286b4075668113234ff5507605a3cf6d4af994d9a987fb44b995c45c2bef12a1ba33bc54e45cbbdd566df618a1d8d769adc7f902121148787878787604051602001610c579796959493929190614761565b6110913385858585612abd565b845160005b818110156125725761256a338a8a8a858151811061253b5761253b6145d8565b6020026020010151600001518b8681518110612559576125596145d8565b602002602001015160200151612a2c565b60010161251b565b5050835160005b818110156125d0576125c8338a8a898581518110612599576125996145d8565b6020026020010151600001518a86815181106125b7576125b76145d8565b602002602001015160200151612abd565b600101612579565b5050825160005b8181101561262e57612626338a8a8885815181106125f7576125f76145d8565b602002602001015160000151898681518110612615576126156145d8565b602002602001015160200151612834565b6001016125d7565b5050815160005b8181101561268c57612684338a8a878581518110612655576126556145d8565b602002602001015160000151888681518110612673576126736145d8565b6020026020010151602001516128de565b600101612635565b5050805160005b818110156126ea576126e2338a8a8685815181106126b3576126b36145d8565b6020026020010151600001518786815181106126d1576126d16145d8565b602002602001015160200151612b45565b600101612693565b505050505050505050565b60006004826040516127079190614648565b90815260200160405180910390205460000361275e576005805490600061272d836148dc565b91905055506005546004836040516127459190614648565b9081526040519081900360200190205550600554919050565b60048260405161276e9190614648565b90815260200160405180910390205490505b919050565b82518251600191821480159291821415918414159060009084906127a65750815b80156127b3575084875114155b806127d057508280156127c35750815b80156127d0575084865114155b806127ee57508380156127e05750825b80156127ee57508551875114155b1561280c5760405163586cb9e160e01b815260040160405180910390fd5b831561281a5750855161282b565b82156128285750845161282b565b50835b93509350935093565b61284085858486612bd6565b6001600160a01b0384166000908152600a602090815260408083208684529091528120829161286e856126f5565b815260200190815260200160002060006101000a81548160ff02191690831515021790555082846001600160a01b03167ffc6eac6df20a61ff9d8ec7453e452ca73931f2cb16944e9dc884b4a8d642391484846040516128cf929190614903565b60405180910390a35050505050565b6128ea85858486612bd6565b6001600160a01b038416600090815260076020908152604080832086845290915281208291612918856126f5565b81526020810191909152604090810160002080546001600160a01b0319166001600160a01b039384161790555184918616907f78ab16f2d097b9728046fb602022fccefef4ec306810b9e8b6fd618e91c12214906128cf9086908690614927565b8442111561299a5760405163f87d927160e01b815260040160405180910390fd5b6040805160008082526020820180845287905260ff861692820192909252606081018490526080810183905260019060a0016020604051602081039080840390855afa1580156129ee573d6000803e3d6000fd5b505050602060405103519050866001600160a01b0316816001600160a01b031614610bef57604051638baa579f60e01b815260040160405180910390fd5b612a3885858486612bd6565b6001600160a01b0384166000908152600b6020908152604080832086845290915281208291612a66856126f5565b81526020019081526020016000209081612a80919061481d565b5082846001600160a01b03167f11e1b2f69159e4bf02488e2c90bf30e6075a4bf57a39ce63ba83d10a96777c0384846040516128cf929190614951565b612ac985858486612bd6565b6001600160a01b038416600090815260096020908152604080832086845290915281208291612af7856126f5565b81526020019081526020016000208190555082846001600160a01b03167f2b529d8c80cbea7dc71690ffd099111430f1e30963439b4659e9a1ec3fba578584846040516128cf92919061497f565b612b5185858486612bd6565b6001600160a01b038416600090815260086020908152604080832086845290915281208291612b7f856126f5565b81526020019081526020016000209081612b99919061481d565b5082846001600160a01b03167f3e7f7fe71b156da17053b2814558642d261b19433ae77e083aac01f074124f3784846040516128cf929190614951565b6001600160a01b03831660009081526020819052604080822090518290600490612c01908790614648565b9081526040805160209281900383019020548352908201929092520160009081205460ff169150816004811115612c3a57612c3a614570565b148015612d3957506001600160a01b038416600090815260026020526040902054610100900460ff168015612ce25750846001600160a01b0316846001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd69190614553565b6001600160a01b031614155b80612d3957506001600160a01b038416600090815260026020526040902054610100900460ff16158015612d3957506001600160a01b03848116600090815260026020526040902054620100009004811690861614155b15612d57576040516373fe3ec360e11b815260040160405180910390fd5b6001816004811115612d6b57612d6b614570565b148015612d9e57506001600160a01b0380851660009081526003602090815260408083209389168352929052205460ff16155b15612dbc57604051637dc99f8960e11b815260040160405180910390fd5b6002816004811115612dd057612dd0614570565b148015612ecf57506001600160a01b038416600090815260026020526040902054610100900460ff168015612e785750846001600160a01b0316846001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6c9190614553565b6001600160a01b031614155b80612ecf57506001600160a01b038416600090815260026020526040902054610100900460ff16158015612ecf57506001600160a01b03848116600090815260026020526040902054620100009004811690861614155b8015612f0157506001600160a01b0380851660009081526003602090815260408083209389168352929052205460ff16155b15612f1f576040516369fb20b560e01b815260040160405180910390fd5b6003816004811115612f3357612f33614570565b148015612fb557506040516331a9108f60e11b8152600481018390526001600160a01b038087169190861690636352211e90602401602060405180830381865afa158015612f85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fa99190614553565b6001600160a01b031614155b15612fd3576040516359dc379f60e01b815260040160405180910390fd5b6004816004811115612fe757612fe7614570565b14801561305c5750846001600160a01b031660016000866001600160a01b03166001600160a01b0316815260200190815260200160002060006004866040516130309190614648565b90815260408051602092819003830190205483529082019290925201600020546001600160a01b031614155b1561307a576040516370e2142360e11b815260040160405180910390fd5b5050505050565b6001600160a01b038116811461309657600080fd5b50565b803561278081613081565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156130dc576130dc6130a4565b60405290565b604051601f8201601f191681016001600160401b038111828210171561310a5761310a6130a4565b604052919050565b600082601f83011261312357600080fd5b81356001600160401b0381111561313c5761313c6130a4565b61314f601f8201601f19166020016130e2565b81815284602083860101111561316457600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561319757600080fd5b84356131a281613081565b935060208501356001600160401b038111156131bd57600080fd5b6131c987828801613112565b9350506040850135600581106131de57600080fd5b915060608501356131ee81613081565b939692955090935050565b60006020828403121561320b57600080fd5b81356001600160e01b03198116811461322357600080fd5b9392505050565b60006001600160401b03821115613243576132436130a4565b5060051b60200190565b600082601f83011261325e57600080fd5b8135602061327361326e8361322a565b6130e2565b82815260059290921b8401810191818101908684111561329257600080fd5b8286015b848110156132b65780356132a981613081565b8352918301918301613296565b509695505050505050565b8035801515811461278057600080fd5b6000806000606084860312156132e657600080fd5b83356132f181613081565b92506020848101356001600160401b038082111561330e57600080fd5b61331a8883890161324d565b9450604087013591508082111561333057600080fd5b508501601f8101871361334257600080fd5b803561335061326e8261322a565b81815260059190911b8201830190838101908983111561336f57600080fd5b928401925b8284101561339457613385846132c1565b82529284019290840190613374565b80955050505050509250925092565b600080600080600060a086880312156133bb57600080fd5b85356133c681613081565b94506020860135935060408601356001600160401b03808211156133e957600080fd5b6133f589838a01613112565b9450606088013591508082111561340b57600080fd5b5061341888828901613112565b95989497509295608001359392505050565b600082601f83011261343b57600080fd5b8135602061344b61326e8361322a565b82815260059290921b8401810191818101908684111561346a57600080fd5b8286015b848110156132b65780356001600160401b0381111561348d5760008081fd5b61349b8986838b0101613112565b84525091830191830161346e565b600080600080600080600060e0888a0312156134c457600080fd5b6134cd88613099565b96506020880135955060408801356001600160401b03808211156134f057600080fd5b6134fc8b838c0161342a565b965060608a013591508082111561351257600080fd5b61351e8b838c0161342a565b955060808a013591508082111561353457600080fd5b6135408b838c0161342a565b945060a08a013591508082111561355657600080fd5b6135628b838c0161342a565b935060c08a013591508082111561357857600080fd5b506135858a828b0161342a565b91505092959891949750929550565b60005b838110156135af578181015183820152602001613597565b50506000910152565b600081518084526135d0816020860160208601613594565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b8581101561362c57828403895261361a8483516135b8565b98850198935090840190600101613602565b5091979650505050505050565b600081518084526020808501945080840160005b838110156136695781518752958201959082019060010161364d565b509495945050505050565b600081518084526020808501945080840160005b83811015613669578151151587529582019590820190600101613688565b600081518084526020808501945080840160005b838110156136695781516001600160a01b0316875295820195908201906001016136ba565b60a0815260006136f260a08301886135e4565b82810360208401526137048188613639565b905082810360408401526137188187613674565b9050828103606084015261372c81866136a6565b9050828103608084015261374081856135e4565b98975050505050505050565b60008060006060848603121561376157600080fd5b833561376c81613081565b92506020840135915060408401356001600160401b0381111561378e57600080fd5b61379a86828701613112565b9150509250925092565b600082601f8301126137b557600080fd5b813560206137c561326e8361322a565b82815260059290921b840181019181810190868411156137e457600080fd5b8286015b848110156132b657803583529183019183016137e8565b60008060006060848603121561381457600080fd5b83356001600160401b038082111561382b57600080fd5b6138378783880161324d565b9450602086013591508082111561384d57600080fd5b613859878388016137a4565b9350604086013591508082111561386f57600080fd5b5061379a8682870161342a565b6020815260006132236020830184613674565b6020815260006132236020830184613639565b600080600080608085870312156138b857600080fd5b84356138c381613081565b93506020850135925060408501356001600160401b038111156138e557600080fd5b6138f187828801613112565b925050613900606086016132c1565b905092959194509250565b6000806000806080858703121561392157600080fd5b843561392c81613081565b93506020850135925060408501356001600160401b0381111561394e57600080fd5b61395a87828801613112565b92505060608501356131ee81613081565b60006020828403121561397d57600080fd5b813561322381613081565b60208152600061322360208301846135b8565b600080604083850312156139ae57600080fd5b82356139b981613081565b915060208301356139c981613081565b809150509250929050565b803560ff8116811461278057600080fd5b60008060008060008060008060006101208a8c031215613a0457600080fd5b8935613a0f81613081565b985060208a0135613a1f81613081565b975060408a0135965060608a01356001600160401b0380821115613a4257600080fd5b613a4e8d838e01613112565b975060808c0135915080821115613a6457600080fd5b50613a718c828d01613112565b95505060a08a01359350613a8760c08b016139d4565b925060e08a013591506101008a013590509295985092959850929598565b600082601f830112613ab657600080fd5b81356020613ac661326e8361322a565b82815260059290921b84018101918181019086841115613ae557600080fd5b8286015b848110156132b65780356001600160401b0380821115613b095760008081fd5b908801906040828b03601f1901811315613b235760008081fd5b613b2b6130ba565b8784013583811115613b3d5760008081fd5b613b4b8d8a83880101613112565b82525092013586830152508352918301918301613ae9565b600080600060608486031215613b7857600080fd5b83356001600160401b0380821115613b8f57600080fd5b613b9b8783880161324d565b94506020860135915080821115613bb157600080fd5b613bbd878388016137a4565b93506040860135915080821115613bd357600080fd5b5061379a86828701613aa5565b60208152600061322360208301846136a6565b600080600060608486031215613c0857600080fd5b8335613c1381613081565b92506020840135613c2381613081565b915060408401356001600160401b0381111561378e57600080fd5b600082601f830112613c4f57600080fd5b81356020613c5f61326e8361322a565b82815260059290921b84018101918181019086841115613c7e57600080fd5b8286015b848110156132b65780356001600160401b0380821115613ca25760008081fd5b908801906040828b03601f1901811315613cbc5760008081fd5b613cc46130ba565b8784013583811115613cd65760008081fd5b613ce48d8a83880101613112565b8252509281013592613cf584613081565b8088019390935250508352918301918301613c82565b600080600060608486031215613d2057600080fd5b83356001600160401b0380821115613d3757600080fd5b613d438783880161324d565b94506020860135915080821115613d5957600080fd5b613d65878388016137a4565b93506040860135915080821115613d7b57600080fd5b5061379a86828701613c3e565b60208152600061322360208301846135e4565b60008060008060008060008060006101208a8c031215613dba57600080fd5b8935613dc581613081565b985060208a0135613dd581613081565b975060408a0135965060608a01356001600160401b03811115613df757600080fd5b613e038c828d01613112565b96505060808a0135945060a08a01359350613a8760c08b016139d4565b600080600080600060a08688031215613e3857600080fd5b8535613e4381613081565b94506020860135935060408601356001600160401b03811115613e6557600080fd5b613e7188828901613112565b9350506060860135613e8281613081565b949793965091946080013592915050565b600082601f830112613ea457600080fd5b81356020613eb461326e8361322a565b82815260059290921b84018101918181019086841115613ed357600080fd5b8286015b848110156132b65780356001600160401b0380821115613ef75760008081fd5b908801906040828b03601f1901811315613f115760008081fd5b613f196130ba565b8784013583811115613f2b5760008081fd5b613f398d8a83880101613112565b825250908301359082821115613f4f5760008081fd5b613f5d8c8984870101613112565b818901528652505050918301918301613ed7565b600080600060608486031215613f8657600080fd5b83356001600160401b0380821115613f9d57600080fd5b613fa98783880161324d565b94506020860135915080821115613fbf57600080fd5b613fcb878388016137a4565b93506040860135915080821115613fe157600080fd5b5061379a86828701613e93565b60008060008060008060008060006101208a8c03121561400d57600080fd5b893561401881613081565b985060208a013561402881613081565b975060408a0135965060608a01356001600160401b0381111561404a57600080fd5b6140568c828d01613112565b96505061406560808b016132c1565b945060a08a01359350613a8760c08b016139d4565b60008060006060848603121561408f57600080fd5b833561409a81613081565b925060208401356140aa81613081565b91506140b8604085016132c1565b90509250925092565b600080600080600060a086880312156140d957600080fd5b85356140e481613081565b94506020860135935060408601356001600160401b0381111561410657600080fd5b61411288828901613112565b9598949750949560608101359550608001359392505050565b60008060008060008060008060006101208a8c03121561414a57600080fd5b893561415581613081565b985060208a013561416581613081565b975060408a0135965060608a01356001600160401b0381111561418757600080fd5b6141938c828d01613112565b96505060808a013561406581613081565b600080600080608085870312156141ba57600080fd5b84356141c581613081565b93506020850135925060408501356001600160401b03808211156141e857600080fd5b6141f488838901613112565b9350606087013591508082111561420a57600080fd5b5061421787828801613112565b91505092959194509250565b600082601f83011261423457600080fd5b8135602061424461326e8361322a565b82815260059290921b8401810191818101908684111561426357600080fd5b8286015b848110156132b65780356001600160401b03808211156142875760008081fd5b908801906040828b03601f19018113156142a15760008081fd5b6142a96130ba565b87840135838111156142bb5760008081fd5b6142c98d8a83880101613112565b8252506142d78285016132c1565b818901528652505050918301918301614267565b60008060006060848603121561430057600080fd5b83356001600160401b038082111561431757600080fd5b6143238783880161324d565b9450602086013591508082111561433957600080fd5b614345878388016137a4565b9350604086013591508082111561435b57600080fd5b5061379a86828701614223565b6000806040838503121561437b57600080fd5b823561438681613081565b915060208301356001600160401b038111156143a157600080fd5b6143ad85828601613112565b9150509250929050565b600080600080600060a086880312156143cf57600080fd5b85356143da81613081565b94506020860135935060408601356001600160401b038111156143fc57600080fd5b61440888828901613112565b935050613e82606087016132c1565b6000806000806080858703121561442d57600080fd5b843561443881613081565b93506020850135925060408501356001600160401b0381111561445a57600080fd5b61446687828801613112565b949793965093946060013593505050565b600080600080600080600060e0888a03121561449257600080fd5b61449b88613099565b96506020880135955060408801356001600160401b03808211156144be57600080fd5b6144ca8b838c01613e93565b965060608a01359150808211156144e057600080fd5b6144ec8b838c01613aa5565b955060808a013591508082111561450257600080fd5b61450e8b838c01614223565b945060a08a013591508082111561452457600080fd5b6145308b838c01613c3e565b935060c08a013591508082111561454657600080fd5b506135858a828b01613e93565b60006020828403121561456557600080fd5b815161322381613081565b634e487b7160e01b600052602160045260246000fd5b60608152600061459960608301866135b8565b9050600584106145b957634e487b7160e01b600052602160045260246000fd5b60208201939093526001600160a01b0391909116604090910152919050565b634e487b7160e01b600052603260045260246000fd5b87815286602082015260018060a01b038616604082015284606082015260e06080820152600061462160e08301866135b8565b82810360a084015261463381866135b8565b9150508260c083015298975050505050505050565b6000825161465a818460208701613594565b9190910192915050565b600181811c9082168061467857607f821691505b60208210810361469857634e487b7160e01b600052602260045260246000fd5b50919050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b87815286602082015260018060a01b038616604082015284606082015260e06080820152600061470260e08301866135b8565b60a08301949094525060c0015295945050505050565b878152866020820152600060018060a01b03808816604084015286606084015260e0608084015261474c60e08401876135b8565b941660a08301525060c0015295945050505050565b87815286602082015260018060a01b038616604082015284606082015260e06080820152600061479460e08301866135b8565b93151560a08301525060c0015295945050505050565b805160208083015191908110156146985760001960209190910360031b1b16919050565b601f82111561481857600081815260208120601f850160051c810160208610156147f55750805b601f850160051c820191505b8181101561481457828155600101614801565b5050505b505050565b81516001600160401b03811115614836576148366130a4565b61484a816148448454614664565b846147ce565b602080601f83116001811461487f57600084156148675750858301515b600019600386901b1c1916600185901b178555614814565b600085815260208120601f198616915b828110156148ae5788860151825594840194600190910190840161488f565b50858210156148cc5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000600182016148fc57634e487b7160e01b600052601160045260246000fd5b5060010190565b60408152600061491660408301856135b8565b905082151560208301529392505050565b60408152600061493a60408301856135b8565b905060018060a01b03831660208301529392505050565b60408152600061496460408301856135b8565b828103602084015261497681856135b8565b95945050505050565b60408152600061499260408301856135b8565b9050826020830152939250505056fea2646970667358221220ea06907bb934af84aa38e1ede82b212855aa51f7b1ffc16c736ed769264eb00564736f6c63430008150033
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
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.