Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 21 from a total of 21 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Approval For... | 1536549 | 10 hrs ago | IN | 0 ETH | 0.00000484 | ||||
Safe Transfer Fr... | 1536442 | 10 hrs ago | IN | 0 ETH | 0.00000569 | ||||
Set Approval For... | 1535215 | 10 hrs ago | IN | 0 ETH | 0.00000394 | ||||
Set Approval For... | 1535166 | 10 hrs ago | IN | 0 ETH | 0.00000421 | ||||
Set Approval For... | 1533632 | 11 hrs ago | IN | 0 ETH | 0.00000485 | ||||
Set Approval For... | 1533366 | 11 hrs ago | IN | 0 ETH | 0.00000484 | ||||
Set Approval For... | 1530509 | 11 hrs ago | IN | 0 ETH | 0.00000516 | ||||
Set Approval For... | 1529008 | 12 hrs ago | IN | 0 ETH | 0.00000422 | ||||
Set Approval For... | 1528349 | 12 hrs ago | IN | 0 ETH | 0.000004 | ||||
Set Approval For... | 1528284 | 12 hrs ago | IN | 0 ETH | 0.00000381 | ||||
Set Approval For... | 1528250 | 12 hrs ago | IN | 0 ETH | 0.00000511 | ||||
Set Approval For... | 1528158 | 12 hrs ago | IN | 0 ETH | 0.0000041 | ||||
Set Approval For... | 1528077 | 12 hrs ago | IN | 0 ETH | 0.00000423 | ||||
Safe Transfer Fr... | 1520660 | 14 hrs ago | IN | 0 ETH | 0.00000598 | ||||
Safe Transfer Fr... | 1515644 | 16 hrs ago | IN | 0 ETH | 0.0000068 | ||||
Set Approval For... | 1515292 | 16 hrs ago | IN | 0 ETH | 0.00000776 | ||||
Set Approval For... | 1509069 | 18 hrs ago | IN | 0 ETH | 0.00000545 | ||||
Safe Transfer Fr... | 1508575 | 18 hrs ago | IN | 0 ETH | 0.00000598 | ||||
Set Approval For... | 1501780 | 20 hrs ago | IN | 0 ETH | 0.00000534 | ||||
Set Approval For... | 1460366 | 32 hrs ago | IN | 0 ETH | 0.00000491 | ||||
Set Gacha Machin... | 1106092 | 5 days ago | IN | 0 ETH | 0.00000434 |
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
1105489 | 5 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
SofamonWearable
Compiler Version
v0.8.25+commit.b61c2a91
ZkSolc Version
v1.5.11
Optimization Enabled:
Yes with Mode 3
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
/// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import { Owned } from "lib/solmate/src/auth/Owned.sol"; import { ERC1155 } from "lib/solmate/src/tokens/ERC1155.sol"; import { LibString } from "lib/solady/src/utils/LibString.sol"; import { ISofamonGachaMachine } from "src/interfaces/ISofamonGachaMachine.sol"; /// @author CopyPaste /// @title SofamonWearable, A Wearable NFT for your Sofamon! contract SofamonWearable is ERC1155, Owned(msg.sender) { /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ error NotMachine(); error AddressBlacklisted(); /// @param _baseURI The base URI for all Sofamon Weawrable Metadata constructor(string memory _baseURI) ERC1155() { baseURI = _baseURI; } /*////////////////////////////////////////////////////////////// STORAGE //////////////////////////////////////////////////////////////*/ /// @dev MakerDAO Constant for 1e18 Scaling uint256 constant WAD = 1e18; /// @dev The SofamonGachaMachine address address public machine; /// @dev Mapping tracks whether or not an address is blacklisted to interact with Sofamon mapping(address addr => bool auth) public blacklisted; /// @param newMachine The new address of the Sofamon Gacha Machien function setGachaMachine(address newMachine) public onlyOwner { machine = newMachine; } /// @param user The user to determine the status of /// @param status Whether or not the user is blacklisted function setBlacklist(address user, bool status) external onlyOwner { blacklisted[user] = status; } /// @param newURI The new base ERC1155 URI function setURI(string memory newURI) external onlyOwner { baseURI = newURI; } /// @param person The address to check is not blacklisted modifier NoBlacklist(address person) { if (blacklisted[person]) { revert AddressBlacklisted(); } _; } /*////////////////////////////////////////////////////////////// ERC1155 BLACKLIST OVERRIDES //////////////////////////////////////////////////////////////*/ function setApprovalForAll(address operator, bool approved) public override { super.setApprovalForAll(operator, approved); } function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public override NoBlacklist(to) NoBlacklist(from) NoBlacklist(msg.sender) { super.safeTransferFrom(from, to, id, amount, data); } function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public override NoBlacklist(to) NoBlacklist(from) NoBlacklist(msg.sender) { super.safeBatchTransferFrom(from, to, ids, amounts, data); } /*////////////////////////////////////////////////////////////// ERC1155 METADATA //////////////////////////////////////////////////////////////*/ /// @dev The baseURI for the Sofamon Wearable Metadata string internal baseURI; /// @dev Returns the Uniform Resource Identifier (URI) for token `id`. function uri(uint256 id) public view override returns (string memory) { return string(abi.encodePacked(baseURI, LibString.toString(id))); } /*////////////////////////////////////////////////////////////// ERC1155 EXTENSION n/////////////////////////////////////////////////////////////*/ /// @param to The address to mint the NFT to /// @param wearable The WearableId to mint function mint(address to, uint256 wearable) external { if (msg.sender != machine) { revert NotMachine(); } _mint(to, wearable, 1, ""); } /// @notice Irreversibly Burns a Sofamon Wearable, should only be called /// if you know what you are doing /// @param wearable The WearableId to burn /// @param amount The amount of wearables to burn function burn(uint256 wearable, uint256 amount) external { _burn(msg.sender, wearable, amount); } /*////////////////////////////////////////////////////////////// ERC2981 //////////////////////////////////////////////////////////////*/ /// @dev The royalty fee to take from sales out of 1e18 uint256 public royaltyFee; event NewRoyaltyFee(uint256 newFee); /// @param newRoyaltyFee The new fee out of 1e18 to set for royalties function updateRoyaltyFee(uint256 newRoyaltyFee) public onlyOwner { royaltyFee = newRoyaltyFee; emit NewRoyaltyFee(newRoyaltyFee); } /// @param _salePrice The sale price of the NFT /// /// @return receiver The address to send the royalty fee to /// @return royaltyAmount The amount which should be paid as a royalty function royaltyInfo(uint256, uint256 _salePrice) external view returns (address receiver, uint256 royaltyAmount) { receiver = ISofamonGachaMachine(machine).protocolFeeTo(); royaltyAmount = _salePrice * royaltyFee / WAD; } /*////////////////////////////////////////////////////////////// ERC165 //////////////////////////////////////////////////////////////*/ /// @param interfaceId The interfaceId, or 4byte signature of the interface /// @return supported Whether or not the interface is supported function supportsInterface(bytes4 interfaceId) public pure override returns (bool supported) { supported = interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165 || interfaceId == 0xd9b67a26 // ERC165 Interface ID for ERC1155 || interfaceId == 0x2a55205a; // ERC165 Interface ID for ERC2981 } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) abstract contract Owned { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OwnershipTransferred(address indexed user, address indexed newOwner); /*////////////////////////////////////////////////////////////// OWNERSHIP STORAGE //////////////////////////////////////////////////////////////*/ address public owner; modifier onlyOwner() virtual { require(msg.sender == owner, "UNAUTHORIZED"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address _owner) { owner = _owner; emit OwnershipTransferred(address(0), _owner); } /*////////////////////////////////////////////////////////////// OWNERSHIP LOGIC //////////////////////////////////////////////////////////////*/ function transferOwnership(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Minimalist and gas efficient standard ERC1155 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount ); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event URI(string value, uint256 indexed id); /*////////////////////////////////////////////////////////////// ERC1155 STORAGE //////////////////////////////////////////////////////////////*/ mapping(address => mapping(uint256 => uint256)) public balanceOf; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// METADATA LOGIC //////////////////////////////////////////////////////////////*/ function uri(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC1155 LOGIC //////////////////////////////////////////////////////////////*/ function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); balanceOf[from][id] -= amount; balanceOf[to][id] += amount; emit TransferSingle(msg.sender, from, to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { require(ids.length == amounts.length, "LENGTH_MISMATCH"); require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); // Storing these outside the loop saves ~15 gas per iteration. uint256 id; uint256 amount; for (uint256 i = 0; i < ids.length; ) { id = ids[i]; amount = amounts[i]; balanceOf[from][id] -= amount; balanceOf[to][id] += amount; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) public view virtual returns (uint256[] memory balances) { require(owners.length == ids.length, "LENGTH_MISMATCH"); balances = new uint256[](owners.length); // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < owners.length; ++i) { balances[i] = balanceOf[owners[i]][ids[i]]; } } } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { balanceOf[to][id] += amount; emit TransferSingle(msg.sender, address(0), to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function _batchMint( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[to][ids[i]] += amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, address(0), to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function _batchBurn( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[from][ids[i]] -= amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, address(0), ids, amounts); } function _burn( address from, uint256 id, uint256 amount ) internal virtual { balanceOf[from][id] -= amount; emit TransferSingle(msg.sender, from, address(0), id, amount); } } /// @notice A generic interface for a contract which properly accepts ERC1155 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155TokenReceiver { function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for converting numbers into strings and other string operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) /// /// @dev Note: /// For performance and bytecode compactness, most of the string operations are restricted to /// byte strings (7-bit ASCII), except where otherwise specified. /// Usage of byte string operations on charsets with runes spanning two or more bytes /// can lead to undefined behavior. library LibString { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The length of the output is too small to contain all the hex digits. error HexLengthInsufficient(); /// @dev The length of the string is more than 32 bytes. error TooBigForSmallString(); /// @dev The input string must be a 7-bit ASCII. error StringNot7BitASCII(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The constant returned when the `search` is not found in the string. uint256 internal constant NOT_FOUND = type(uint256).max; /// @dev Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'. uint128 internal constant ALPHANUMERIC_7_BIT_ASCII = 0x7fffffe07fffffe03ff000000000000; /// @dev Lookup for 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'. uint128 internal constant LETTERS_7_BIT_ASCII = 0x7fffffe07fffffe0000000000000000; /// @dev Lookup for 'abcdefghijklmnopqrstuvwxyz'. uint128 internal constant LOWERCASE_7_BIT_ASCII = 0x7fffffe000000000000000000000000; /// @dev Lookup for 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. uint128 internal constant UPPERCASE_7_BIT_ASCII = 0x7fffffe0000000000000000; /// @dev Lookup for '0123456789'. uint128 internal constant DIGITS_7_BIT_ASCII = 0x3ff000000000000; /// @dev Lookup for '0123456789abcdefABCDEF'. uint128 internal constant HEXDIGITS_7_BIT_ASCII = 0x7e0000007e03ff000000000000; /// @dev Lookup for '01234567'. uint128 internal constant OCTDIGITS_7_BIT_ASCII = 0xff000000000000; /// @dev Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'. uint128 internal constant PRINTABLE_7_BIT_ASCII = 0x7fffffffffffffffffffffff00003e00; /// @dev Lookup for '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'. uint128 internal constant PUNCTUATION_7_BIT_ASCII = 0x78000001f8000001fc00fffe00000000; /// @dev Lookup for ' \t\n\r\x0b\x0c'. uint128 internal constant WHITESPACE_7_BIT_ASCII = 0x100003e00; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* DECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the base 10 decimal representation of `value`. function toString(uint256 value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. str := add(mload(0x40), 0x80) mstore(0x40, add(str, 0x20)) // Allocate the memory. mstore(str, 0) // Zeroize the slot after the string. let end := str // Cache the end of the memory to calculate the length later. let w := not(0) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { str := add(str, w) // `sub(str, 1)`. // Store the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) temp := div(temp, 10) // Keep dividing `temp` until zero. if iszero(temp) { break } } let length := sub(end, str) str := sub(str, 0x20) // Move the pointer 32 bytes back to make room for the length. mstore(str, length) // Store the length. } } /// @dev Returns the base 10 decimal representation of `value`. function toString(int256 value) internal pure returns (string memory str) { if (value >= 0) return toString(uint256(value)); unchecked { str = toString(~uint256(value) + 1); } /// @solidity memory-safe-assembly assembly { // We still have some spare memory space on the left, // as we have allocated 3 words (96 bytes) for up to 78 digits. let length := mload(str) // Load the string length. mstore(str, 0x2d) // Store the '-' character. str := sub(str, 1) // Move back the string pointer by a byte. mstore(str, add(length, 1)) // Update the string length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HEXADECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `length` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `length * 2 + 2` bytes. /// Reverts if `length` is too small for the output to contain all the digits. function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) { str = toHexStringNoPrefix(value, length); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Store the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `length` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `length * 2` bytes. /// Reverts if `length` is too small for the output to contain all the digits. function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length. // We add 0x20 to the total and round down to a multiple of 0x20. // (0x20 + 0x20 + 0x02 + 0x20) = 0x62. str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f))) mstore(0x40, add(str, 0x20)) // Allocate the memory. mstore(str, 0) // Zeroize the slot after the string. let end := str // Cache the end to calculate the length later. // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let start := sub(str, add(length, length)) let w := not(1) // Tsk. let temp := value // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for {} 1 {} { str := add(str, w) // `sub(str, 2)`. mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(xor(str, start)) { break } } if temp { mstore(0x00, 0x2194895a) // `HexLengthInsufficient()`. revert(0x1c, 0x04) } let strLength := sub(end, str) str := sub(str, 0x20) mstore(str, strLength) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2 + 2` bytes. function toHexString(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Store the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x". /// The output excludes leading "0" from the `toHexString` output. /// `0x00: "0x0", 0x01: "0x1", 0x12: "0x12", 0x123: "0x123"`. function toMinimalHexString(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present. let strLength := add(mload(str), 2) // Compute the length. mstore(add(str, o), 0x3078) // Store the "0x" prefix, accounting for leading zero. str := sub(add(str, o), 2) // Move the pointer, accounting for leading zero. mstore(str, sub(strLength, o)) // Store the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output excludes leading "0" from the `toHexStringNoPrefix` output. /// `0x00: "0", 0x01: "1", 0x12: "12", 0x123: "123"`. function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present. let strLength := mload(str) // Get the length. str := add(str, o) // Move the pointer, accounting for leading zero. mstore(str, sub(strLength, o)) // Store the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2` bytes. function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x40 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0. str := add(mload(0x40), 0x80) mstore(0x40, add(str, 0x20)) // Allocate the memory. mstore(str, 0) // Zeroize the slot after the string. let end := str // Cache the end to calculate the length later. mstore(0x0f, 0x30313233343536373839616263646566) // Store the "0123456789abcdef" lookup. let w := not(1) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { str := add(str, w) // `sub(str, 2)`. mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(temp) { break } } let strLength := sub(end, str) str := sub(str, 0x20) mstore(str, strLength) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte, /// and the alphabets are capitalized conditionally according to /// https://eips.ethereum.org/EIPS/eip-55 function toHexStringChecksummed(address value) internal pure returns (string memory str) { str = toHexString(value); /// @solidity memory-safe-assembly assembly { let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...` let o := add(str, 0x22) let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... ` let t := shl(240, 136) // `0b10001000 << 240` for { let i := 0 } 1 {} { mstore(add(i, i), mul(t, byte(i, hashed))) i := add(i, 1) if eq(i, 20) { break } } mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask))))) o := add(o, 0x20) mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask))))) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. function toHexString(address value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Store the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(address value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { str := mload(0x40) // Allocate the memory. // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x28 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80. mstore(0x40, add(str, 0x80)) mstore(0x0f, 0x30313233343536373839616263646566) // Store the "0123456789abcdef" lookup. str := add(str, 2) mstore(str, 40) // Store the length. let o := add(str, 0x20) mstore(add(o, 40), 0) // Zeroize the slot after the string. value := shl(96, value) // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let i := 0 } 1 {} { let p := add(o, add(i, i)) let temp := byte(i, value) mstore8(add(p, 1), mload(and(temp, 15))) mstore8(p, mload(shr(4, temp))) i := add(i, 1) if eq(i, 20) { break } } } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexString(bytes memory raw) internal pure returns (string memory str) { str = toHexStringNoPrefix(raw); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Store the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Store the length. } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { let length := mload(raw) str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix. mstore(str, add(length, length)) // Store the length of the output. mstore(0x0f, 0x30313233343536373839616263646566) // Store the "0123456789abcdef" lookup. let o := add(str, 0x20) let end := add(raw, length) for {} iszero(eq(raw, end)) {} { raw := add(raw, 1) mstore8(add(o, 1), mload(and(mload(raw), 15))) mstore8(o, mload(and(shr(4, mload(raw)), 15))) o := add(o, 2) } mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate the memory. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RUNE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the number of UTF characters in the string. function runeCount(string memory s) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { if mload(s) { mstore(0x00, div(not(0), 255)) mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506) let o := add(s, 0x20) let end := add(o, mload(s)) for { result := 1 } 1 { result := add(result, 1) } { o := add(o, byte(0, mload(shr(250, mload(o))))) if iszero(lt(o, end)) { break } } } } } /// @dev Returns if this string is a 7-bit ASCII string. /// (i.e. all characters codes are in [0..127]) function is7BitASCII(string memory s) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let mask := shl(7, div(not(0), 255)) result := 1 let n := mload(s) if n { let o := add(s, 0x20) let end := add(o, n) let last := mload(end) mstore(end, 0) for {} 1 {} { if and(mask, mload(o)) { result := 0 break } o := add(o, 0x20) if iszero(lt(o, end)) { break } } mstore(end, last) } } } /// @dev Returns if this string is a 7-bit ASCII string, /// AND all characters are in the `allowed` lookup. /// Note: If `s` is empty, returns true regardless of `allowed`. function is7BitASCII(string memory s, uint128 allowed) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := 1 if mload(s) { let allowed_ := shr(128, shl(128, allowed)) let o := add(s, 0x20) let end := add(o, mload(s)) for {} 1 {} { result := and(result, shr(byte(0, mload(o)), allowed_)) o := add(o, 1) if iszero(and(result, lt(o, end))) { break } } } } } /// @dev Converts the bytes in the 7-bit ASCII string `s` to /// an allowed lookup for use in `is7BitASCII(s, allowed)`. /// To save runtime gas, you can cache the result in an immutable variable. function to7BitASCIIAllowedLookup(string memory s) internal pure returns (uint128 result) { /// @solidity memory-safe-assembly assembly { if mload(s) { let o := add(s, 0x20) let end := add(o, mload(s)) for {} 1 {} { result := or(result, shl(byte(0, mload(o)), 1)) o := add(o, 1) if iszero(lt(o, end)) { break } } if shr(128, result) { mstore(0x00, 0xc9807e0d) // `StringNot7BitASCII()`. revert(0x1c, 0x04) } } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // For performance and bytecode compactness, byte string operations are restricted // to 7-bit ASCII strings. All offsets are byte offsets, not UTF character offsets. // Usage of byte string operations on charsets with runes spanning two or more bytes // can lead to undefined behavior. /// @dev Returns `subject` all occurrences of `search` replaced with `replacement`. function replace(string memory subject, string memory search, string memory replacement) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) let searchLength := mload(search) let replacementLength := mload(replacement) subject := add(subject, 0x20) search := add(search, 0x20) replacement := add(replacement, 0x20) result := add(mload(0x40), 0x20) let subjectEnd := add(subject, subjectLength) if iszero(gt(searchLength, subjectLength)) { let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1) let h := 0 if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) } let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(search) for {} 1 {} { let t := mload(subject) // Whether the first `searchLength % 32` bytes of // `subject` and `search` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(subject, searchLength), h)) { mstore(result, t) result := add(result, 1) subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } continue } } // Copy the `replacement` one word at a time. for { let o := 0 } 1 {} { mstore(add(result, o), mload(add(replacement, o))) o := add(o, 0x20) if iszero(lt(o, replacementLength)) { break } } result := add(result, replacementLength) subject := add(subject, searchLength) if searchLength { if iszero(lt(subject, subjectSearchEnd)) { break } continue } } mstore(result, t) result := add(result, 1) subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } } } let resultRemainder := result result := add(mload(0x40), 0x20) let k := add(sub(resultRemainder, result), sub(subjectEnd, subject)) // Copy the rest of the string one word at a time. for {} lt(subject, subjectEnd) {} { mstore(resultRemainder, mload(subject)) resultRemainder := add(resultRemainder, 0x20) subject := add(subject, 0x20) } result := sub(result, 0x20) let last := add(add(result, 0x20), k) // Zeroize the slot after the string. mstore(last, 0) mstore(0x40, add(last, 0x20)) // Allocate the memory. mstore(result, k) // Store the length. } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from left to right, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function indexOf(string memory subject, string memory search, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for { let subjectLength := mload(subject) } 1 {} { if iszero(mload(search)) { if iszero(gt(from, subjectLength)) { result := from break } result := subjectLength break } let searchLength := mload(search) let subjectStart := add(subject, 0x20) result := not(0) // Initialize to `NOT_FOUND`. subject := add(subjectStart, from) let end := add(sub(add(subjectStart, subjectLength), searchLength), 1) let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(add(search, 0x20)) if iszero(and(lt(subject, end), lt(from, subjectLength))) { break } if iszero(lt(searchLength, 0x20)) { for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} { if iszero(shr(m, xor(mload(subject), s))) { if eq(keccak256(subject, searchLength), h) { result := sub(subject, subjectStart) break } } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } for {} 1 {} { if iszero(shr(m, xor(mload(subject), s))) { result := sub(subject, subjectStart) break } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from left to right. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function indexOf(string memory subject, string memory search) internal pure returns (uint256 result) { result = indexOf(subject, search, 0); } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from right to left, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function lastIndexOf(string memory subject, string memory search, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for {} 1 {} { result := not(0) // Initialize to `NOT_FOUND`. let searchLength := mload(search) if gt(searchLength, mload(subject)) { break } let w := result let fromMax := sub(mload(subject), searchLength) if iszero(gt(fromMax, from)) { from := fromMax } let end := add(add(subject, 0x20), w) subject := add(add(subject, 0x20), from) if iszero(gt(subject, end)) { break } // As this function is not too often used, // we shall simply use keccak256 for smaller bytecode size. for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} { if eq(keccak256(subject, searchLength), h) { result := sub(subject, add(end, 1)) break } subject := add(subject, w) // `sub(subject, 1)`. if iszero(gt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from right to left. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function lastIndexOf(string memory subject, string memory search) internal pure returns (uint256 result) { result = lastIndexOf(subject, search, uint256(int256(-1))); } /// @dev Returns true if `search` is found in `subject`, false otherwise. function contains(string memory subject, string memory search) internal pure returns (bool) { return indexOf(subject, search) != NOT_FOUND; } /// @dev Returns whether `subject` starts with `search`. function startsWith(string memory subject, string memory search) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let searchLength := mload(search) // Just using keccak256 directly is actually cheaper. // forgefmt: disable-next-item result := and( iszero(gt(searchLength, mload(subject))), eq( keccak256(add(subject, 0x20), searchLength), keccak256(add(search, 0x20), searchLength) ) ) } } /// @dev Returns whether `subject` ends with `search`. function endsWith(string memory subject, string memory search) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let searchLength := mload(search) let subjectLength := mload(subject) // Whether `search` is not longer than `subject`. let withinRange := iszero(gt(searchLength, subjectLength)) // Just using keccak256 directly is actually cheaper. // forgefmt: disable-next-item result := and( withinRange, eq( keccak256( // `subject + 0x20 + max(subjectLength - searchLength, 0)`. add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))), searchLength ), keccak256(add(search, 0x20), searchLength) ) ) } } /// @dev Returns `subject` repeated `times`. function repeat(string memory subject, uint256 times) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) if iszero(or(iszero(times), iszero(subjectLength))) { subject := add(subject, 0x20) result := mload(0x40) let output := add(result, 0x20) for {} 1 {} { // Copy the `subject` one word at a time. for { let o := 0 } 1 {} { mstore(add(output, o), mload(add(subject, o))) o := add(o, 0x20) if iszero(lt(o, subjectLength)) { break } } output := add(output, subjectLength) times := sub(times, 1) if iszero(times) { break } } mstore(output, 0) // Zeroize the slot after the string. let resultLength := sub(output, add(result, 0x20)) mstore(result, resultLength) // Store the length. mstore(0x40, add(result, add(resultLength, 0x40))) // Allocate the memory. } } } /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive). /// `start` and `end` are byte offsets. function slice(string memory subject, uint256 start, uint256 end) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) if iszero(gt(subjectLength, end)) { end := subjectLength } if iszero(gt(subjectLength, start)) { start := subjectLength } if lt(start, end) { result := mload(0x40) let resultLength := sub(end, start) mstore(result, resultLength) subject := add(subject, start) let w := not(0x1f) // Copy the `subject` one word at a time, backwards. for { let o := and(add(resultLength, 0x1f), w) } 1 {} { mstore(add(result, o), mload(add(subject, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } // Zeroize the slot after the string. mstore(add(add(result, 0x20), resultLength), 0) mstore(0x40, add(result, add(resultLength, 0x40))) // Allocate the memory. } } } /// @dev Returns a copy of `subject` sliced from `start` to the end of the string. /// `start` is a byte offset. function slice(string memory subject, uint256 start) internal pure returns (string memory result) { result = slice(subject, start, uint256(int256(-1))); } /// @dev Returns all the indices of `search` in `subject`. /// The indices are byte offsets. function indicesOf(string memory subject, string memory search) internal pure returns (uint256[] memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) let searchLength := mload(search) if iszero(gt(searchLength, subjectLength)) { subject := add(subject, 0x20) search := add(search, 0x20) result := add(mload(0x40), 0x20) let subjectStart := subject let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1) let h := 0 if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) } let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(search) for {} 1 {} { let t := mload(subject) // Whether the first `searchLength % 32` bytes of // `subject` and `search` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(subject, searchLength), h)) { subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } continue } } // Append to `result`. mstore(result, sub(subject, subjectStart)) result := add(result, 0x20) // Advance `subject` by `searchLength`. subject := add(subject, searchLength) if searchLength { if iszero(lt(subject, subjectSearchEnd)) { break } continue } } subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } } let resultEnd := result // Assign `result` to the free memory pointer. result := mload(0x40) // Store the length of `result`. mstore(result, shr(5, sub(resultEnd, add(result, 0x20)))) // Allocate memory for result. // We allocate one more word, so this array can be recycled for {split}. mstore(0x40, add(resultEnd, 0x20)) } } } /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string. function split(string memory subject, string memory delimiter) internal pure returns (string[] memory result) { uint256[] memory indices = indicesOf(subject, delimiter); /// @solidity memory-safe-assembly assembly { let w := not(0x1f) let indexPtr := add(indices, 0x20) let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1))) mstore(add(indicesEnd, w), mload(subject)) mstore(indices, add(mload(indices), 1)) let prevIndex := 0 for {} 1 {} { let index := mload(indexPtr) mstore(indexPtr, 0x60) if iszero(eq(index, prevIndex)) { let element := mload(0x40) let elementLength := sub(index, prevIndex) mstore(element, elementLength) // Copy the `subject` one word at a time, backwards. for { let o := and(add(elementLength, 0x1f), w) } 1 {} { mstore(add(element, o), mload(add(add(subject, prevIndex), o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } // Zeroize the slot after the string. mstore(add(add(element, 0x20), elementLength), 0) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(element, and(add(elementLength, 0x3f), w))) // Store the `element` into the array. mstore(indexPtr, element) } prevIndex := add(index, mload(delimiter)) indexPtr := add(indexPtr, 0x20) if iszero(lt(indexPtr, indicesEnd)) { break } } result := indices if iszero(mload(delimiter)) { result := add(indices, 0x20) mstore(result, sub(mload(indices), 2)) } } } /// @dev Returns a concatenated string of `a` and `b`. /// Cheaper than `string.concat()` and does not de-align the free memory pointer. function concat(string memory a, string memory b) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let w := not(0x1f) result := mload(0x40) let aLength := mload(a) // Copy `a` one word at a time, backwards. for { let o := and(add(aLength, 0x20), w) } 1 {} { mstore(add(result, o), mload(add(a, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let bLength := mload(b) let output := add(result, aLength) // Copy `b` one word at a time, backwards. for { let o := and(add(bLength, 0x20), w) } 1 {} { mstore(add(output, o), mload(add(b, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let totalLength := add(aLength, bLength) let last := add(add(result, 0x20), totalLength) mstore(last, 0) // Zeroize the slot after the string. mstore(result, totalLength) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } /// @dev Returns a copy of the string in either lowercase or UPPERCASE. /// WARNING! This function is only compatible with 7-bit ASCII strings. function toCase(string memory subject, bool toUpper) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let length := mload(subject) if length { result := add(mload(0x40), 0x20) subject := add(subject, 1) let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff) let w := not(0) for { let o := length } 1 {} { o := add(o, w) let b := and(0xff, mload(add(subject, o))) mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20))) if iszero(o) { break } } result := mload(0x40) mstore(result, length) // Store the length. let last := add(add(result, 0x20), length) mstore(last, 0) // Zeroize the slot after the string. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } } /// @dev Returns a string from a small bytes32 string. /// `s` must be null-terminated, or behavior will be undefined. function fromSmallString(bytes32 s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let n := 0 for {} byte(n, s) { n := add(n, 1) } {} // Scan for '\0'. mstore(result, n) // Store the length. let o := add(result, 0x20) mstore(o, s) // Store the bytes of the string. mstore(add(o, n), 0) // Zeroize the slot after the string. mstore(0x40, add(result, 0x40)) // Allocate the memory. } } /// @dev Returns the small string, with all bytes after the first null byte zeroized. function normalizeSmallString(bytes32 s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { for {} byte(result, s) { result := add(result, 1) } {} // Scan for '\0'. mstore(0x00, s) mstore(result, 0x00) result := mload(0x00) } } /// @dev Returns the string as a normalized null-terminated small string. function toSmallString(string memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { result := mload(s) if iszero(lt(result, 33)) { mstore(0x00, 0xec92f9a3) // `TooBigForSmallString()`. revert(0x1c, 0x04) } result := shl(shl(3, sub(32, result)), mload(add(s, result))) } } /// @dev Returns a lowercased copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function lower(string memory subject) internal pure returns (string memory result) { result = toCase(subject, false); } /// @dev Returns an UPPERCASED copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function upper(string memory subject) internal pure returns (string memory result) { result = toCase(subject, true); } /// @dev Escapes the string to be used within HTML tags. function escapeHTML(string memory s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let end := add(s, mload(s)) result := add(mload(0x40), 0x20) // Store the bytes of the packed offsets and strides into the scratch space. // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6. mstore(0x1f, 0x900094) mstore(0x08, 0xc0000000a6ab) // Store ""&'<>" into the scratch space. mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b)) for {} iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) // Not in `["\"","'","&","<",">"]`. if iszero(and(shl(c, 1), 0x500000c400000000)) { mstore8(result, c) result := add(result, 1) continue } let t := shr(248, mload(c)) mstore(result, mload(and(t, 0x1f))) result := add(result, shr(5, t)) } let last := result mstore(last, 0) // Zeroize the slot after the string. result := mload(0x40) mstore(result, sub(last, add(result, 0x20))) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. /// If `addDoubleQuotes` is true, the result will be enclosed in double-quotes. function escapeJSON(string memory s, bool addDoubleQuotes) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let end := add(s, mload(s)) result := add(mload(0x40), 0x20) if addDoubleQuotes { mstore8(result, 34) result := add(1, result) } // Store "\\u0000" in scratch space. // Store "0123456789abcdef" in scratch space. // Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`. // into the scratch space. mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672) // Bitmask for detecting `["\"","\\"]`. let e := or(shl(0x22, 1), shl(0x5c, 1)) for {} iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) if iszero(lt(c, 0x20)) { if iszero(and(shl(c, 1), e)) { // Not in `["\"","\\"]`. mstore8(result, c) result := add(result, 1) continue } mstore8(result, 0x5c) // "\\". mstore8(add(result, 1), c) result := add(result, 2) continue } if iszero(and(shl(c, 1), 0x3700)) { // Not in `["\b","\t","\n","\f","\d"]`. mstore8(0x1d, mload(shr(4, c))) // Hex value. mstore8(0x1e, mload(and(c, 15))) // Hex value. mstore(result, mload(0x19)) // "\\u00XX". result := add(result, 6) continue } mstore8(result, 0x5c) // "\\". mstore8(add(result, 1), mload(add(c, 8))) result := add(result, 2) } if addDoubleQuotes { mstore8(result, 34) result := add(1, result) } let last := result mstore(last, 0) // Zeroize the slot after the string. result := mload(0x40) mstore(result, sub(last, add(result, 0x20))) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. function escapeJSON(string memory s) internal pure returns (string memory result) { result = escapeJSON(s, false); } /// @dev Returns whether `a` equals `b`. function eq(string memory a, string memory b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b))) } } /// @dev Returns whether `a` equals `b`, where `b` is a null-terminated small string. function eqs(string memory a, bytes32 b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { // These should be evaluated on compile time, as far as possible. let m := not(shl(7, div(not(iszero(b)), 255))) // `0x7f7f ...`. let x := not(or(m, or(b, add(m, and(b, m))))) let r := shl(7, iszero(iszero(shr(128, x)))) r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x)))))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item result := gt(eq(mload(a), add(iszero(x), xor(31, shr(3, r)))), xor(shr(add(8, r), b), shr(add(8, r), mload(add(a, 0x20))))) } } /// @dev Packs a single string with its length into a single word. /// Returns `bytes32(0)` if the length is zero or greater than 31. function packOne(string memory a) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { // We don't need to zero right pad the string, // since this is our own custom non-standard packing scheme. result := mul( // Load the length and the bytes. mload(add(a, 0x1f)), // `length != 0 && length < 32`. Abuses underflow. // Assumes that the length is valid and within the block gas limit. lt(sub(mload(a), 1), 0x1f) ) } } /// @dev Unpacks a string packed using {packOne}. /// Returns the empty string if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packOne}, the output behavior is undefined. function unpackOne(bytes32 packed) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) // Grab the free memory pointer. mstore(0x40, add(result, 0x40)) // Allocate 2 words (1 for the length, 1 for the bytes). mstore(result, 0) // Zeroize the length slot. mstore(add(result, 0x1f), packed) // Store the length and bytes. mstore(add(add(result, 0x20), mload(result)), 0) // Right pad with zeroes. } } /// @dev Packs two strings with their lengths into a single word. /// Returns `bytes32(0)` if combined length is zero or greater than 30. function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let aLength := mload(a) // We don't need to zero right pad the strings, // since this is our own custom non-standard packing scheme. result := mul( or( // Load the length and the bytes of `a` and `b`. shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))), mload(sub(add(b, 0x1e), aLength)) ), // `totalLength != 0 && totalLength < 31`. Abuses underflow. // Assumes that the lengths are valid and within the block gas limit. lt(sub(add(aLength, mload(b)), 1), 0x1e) ) } } /// @dev Unpacks strings packed using {packTwo}. /// Returns the empty strings if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packTwo}, the output behavior is undefined. function unpackTwo(bytes32 packed) internal pure returns (string memory resultA, string memory resultB) { /// @solidity memory-safe-assembly assembly { resultA := mload(0x40) // Grab the free memory pointer. resultB := add(resultA, 0x40) // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words. mstore(0x40, add(resultB, 0x40)) // Zeroize the length slots. mstore(resultA, 0) mstore(resultB, 0) // Store the lengths and bytes. mstore(add(resultA, 0x1f), packed) mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA)))) // Right pad with zeroes. mstore(add(add(resultA, 0x20), mload(resultA)), 0) mstore(add(add(resultB, 0x20), mload(resultB)), 0) } } /// @dev Directly returns `a` without copying. function directReturn(string memory a) internal pure { assembly { // Assumes that the string does not start from the scratch space. let retStart := sub(a, 0x20) let retUnpaddedSize := add(mload(a), 0x40) // Right pad with zeroes. Just in case the string is produced // by a method that doesn't zero right pad. mstore(add(retStart, retUnpaddedSize), 0) mstore(retStart, 0x20) // Store the return offset. // End the transaction, returning the string. return(retStart, and(not(0x1f), add(0x1f, retUnpaddedSize))) } } }
/// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; interface ISofamonGachaMachine { function protocolFeeTo() external view returns (address); }
{ "viaIR": true, "codegen": "yul", "remappings": [ "@pythnetwork/entropy-sdk-solidity/=node_modules/@pythnetwork/entropy-sdk-solidity/", "@manifoldxyz/=lib/lssvm2/lib/", "@openzeppelin/contracts-upgradeable/=lib/lssvm2/lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/lssvm2/lib/openzeppelin-contracts/contracts/", "@prb/math/=lib/lssvm2/lib/prb-math/src/", "chainlink/=lib/chainlink/", "clones-with-immutable-args/=lib/lssvm2/lib/clones-with-immutable-args/src/", "create2-helpers/=lib/lssvm2/lib/royalty-registry-solidity/lib/create2-helpers/", "create3-factory/=lib/lssvm2/lib/create3-factory/", "ds-test/=lib/solmate/lib/ds-test/src/", "erc4626-tests/=lib/lssvm2/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "foundry-huff/=lib/lssvm2/lib/foundry-huff/src/", "huffmate/=lib/lssvm2/lib/huffmate/src/", "libraries-solidity/=lib/lssvm2/lib/libraries-solidity/contracts/", "lssvm2/=lib/lssvm2/src/", "manifoldxyz/=lib/lssvm2/lib/royalty-registry-solidity/contracts/", "openzeppelin-contracts-upgradeable/=lib/lssvm2/lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/lssvm2/lib/openzeppelin-contracts/", "prb-math/=lib/lssvm2/lib/prb-math/src/", "prb-test/=lib/lssvm2/lib/prb-math/lib/prb-test/src/", "royalty-registry-solidity/=lib/lssvm2/lib/royalty-registry-solidity/", "solady/=lib/solady/src/", "solmate/=lib/solmate/src/", "stringutils/=lib/lssvm2/lib/foundry-huff/lib/solidity-stringutils/", "vrf-contracts/=lib/vrf-contracts/contracts/" ], "evmVersion": "cancun", "outputSelection": { "*": { "*": [ "abi" ] } }, "optimizer": { "enabled": true, "mode": "3", "fallback_to_optimizing_for_size": false, "disable_system_request_memoization": true }, "metadata": {}, "libraries": {}, "enableEraVMExtensions": false, "forceEVMLA": false }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressBlacklisted","type":"error"},{"inputs":[],"name":"NotMachine","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"NewRoyaltyFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"blacklisted","outputs":[{"internalType":"bool","name":"auth","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"wearable","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"machine","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"wearable","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMachine","type":"address"}],"name":"setGachaMachine","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newURI","type":"string"}],"name":"setURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"supported","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRoyaltyFee","type":"uint256"}],"name":"updateRoyaltyFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
9c4d535b0000000000000000000000000000000000000000000000000000000000000000010002c751a1e684bb6c9f983fc1d987326adf9623ace8668c66ee9f09b2ad67000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6465762d6170692e736f66616d6f6e2e78797a2f7765617261626c65732f0000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x0001000000000002000e000000000002000000000801034f00000000000103550000008003000039000000400030043f000000600110027000000271011001970000000100200190000000370000c13d000000040010008c000000560000413d000000000208043b000000e0022002700000027b0020009c000000580000213d000002890020009c000000800000213d000002900020009c000000ef0000a13d000002910020009c0000028d0000613d000002920020009c000002f30000613d000002930020009c000000560000c13d0000000002000416000000000002004b000000560000c13d09c009690000040f0000000203000039000000000303041a00000296033001970000000004000411000000000034004b00000000030000390000000103006039000d00000001001d000e00000002001d000000000103001909c0097c0000040f0000000d010000290000029601100197000000000010043f0000000401000039000000200010043f000000400100003909c009a50000040f000000000301041a000002c1023001970000000e0000006b000000010220c1bf000000000021041b0000000001000019000009c10001042e0000000002000416000000000002004b000000560000c13d0000001f0210003900000272022001970000008002200039000000400020043f0000001f0410018f00000273051001980000008002500039000000470000613d000000000608034f000000006706043c0000000003730436000000000023004b000000430000c13d000000000004004b000000540000613d000000000358034f0000000304400210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000200010008c000000670000813d0000000001000019000009c2000104300000027c0020009c000000a10000213d000002830020009c000001060000a13d000002840020009c000003280000613d000002850020009c0000036b0000613d000002860020009c000000560000c13d0000000001000416000000000001004b000000560000c13d0000000601000039000005610000013d000000800300043d000002740030009c000000560000213d0000001f02300039000000000012004b000000000400001900000275040080410000027502200197000000000002004b00000000050000190000027505004041000002750020009c000000000504c019000000000005004b000000560000c13d00000080023000390000000002020433000002740020009c000000c40000a13d000002aa01000041000000000010043f0000004101000039000000040010043f000002ab01000041000009c2000104300000028a0020009c0000010f0000a13d0000028b0020009c000003ae0000613d0000028c0020009c000004120000613d0000028d0020009c000000560000c13d000000240010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000000201000039000000000101041a00000296011001970000000002000411000000000012004b000005d10000c13d0000000401800370000000000101043b0000000602000039000000000012041b000000800010043f0000000001000414000002710010009c0000027101008041000000c001100210000002a5011001c70000800d020000390000000103000039000002a604000041000003a90000013d0000027d0020009c0000027d0000a13d0000027e0020009c0000046a0000613d0000027f0020009c000004890000613d000002800020009c000000560000c13d000000240010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000000401800370000000000601043b000002960060009c000000560000213d0000000201000039000000000201041a00000296032001970000000005000411000000000035004b000005d10000c13d0000027602200197000000000262019f000000000021041b0000000001000414000002710010009c0000027101008041000000c00110021000000277011001c70000800d0200003900000003030000390000027804000041000003a90000013d0000001f04200039000002c2044001970000003f04400039000002c204400197000000400600043d0000000004460019000000000064004b00000000050000390000000105004039000002740040009c0000007a0000213d00000001005001900000007a0000c13d0000008005100039000000400040043f000d00000006001d0000000001260436000e00000001001d000000a0013000390000000003120019000000000053004b000000560000213d000002c2042001970000001f0320018f0000000e09000029000000000091004b000005db0000813d000000000004004b000000eb0000613d00000000063100190000000005390019000000200550008a000000200660008a0000000007450019000000000846001900000000080804330000000000870435000000200440008c000000e50000c13d000000000003004b000005f10000613d0000000005090019000005e70000013d000002940020009c0000054c0000613d000002950020009c000000560000c13d000000240010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000000401800370000000000201043b0000029e00200198000000560000c13d0000000101000039000002be0020009c0000056b0000613d000002bf0020009c0000056b0000613d000002c00020009c000000000100c019000000800010043f000002a001000041000009c10001042e000002870020009c000005650000613d000002880020009c000000560000c13d0000000001000416000000000001004b000000560000c13d0000000201000039000005690000013d0000028e0020009c0000056e0000613d0000028f0020009c000000560000c13d000000a40010008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000402800370000000000202043b000e00000002001d000002960020009c000000560000213d0000002402800370000000000202043b000d00000002001d000002960020009c000000560000213d0000004402800370000000000202043b000002740020009c000000560000213d0000002303200039000000000013004b000000560000813d000600040020003d0000000603800360000000000303043b000a00000003001d000002740030009c000000560000213d00000024032000390000000a020000290000000502200210000500000002001d000800000003001d0000000002320019000000000012004b000000560000213d0000006402800370000000000202043b000002740020009c000000560000213d0000002303200039000000000013004b000000560000813d000400040020003d0000000403800360000000000303043b000c00000003001d000002740030009c000000560000213d00000024032000390000000c020000290000000502200210000300000002001d000700000003001d0000000002320019000000000012004b000000560000213d0000008402800370000000000202043b000002740020009c000000560000213d0000002303200039000000000013004b000000560000813d0000000403200039000000000338034f000000000303043b000200000003001d000002740030009c000000560000213d0000002403200039000100000003001d0000000202300029000000000012004b000000560000213d0000000d01000029000000000010043f0000000401000039000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000006f30000c13d0000000e01000029000000000010043f0000000401000039000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000006f30000c13d0000000001000411000000000010043f0000000401000039000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000006f30000c13d0000000c020000290000000a0020006b0000081d0000c13d00000000020004110000000e0020006c000008240000c13d0000000a0000006b000008430000c13d000000400100043d0000004002000039000000000221043600000040031000390000000a040000290000000000430435000002b20040009c000000560000213d0000000506000029000c001f006001930000000603000029000900200030003d000000000300036700000060051000390000000004650019000000000006004b000001af0000613d0000000906300360000000006706043c0000000005750436000000000045004b000001ab0000c13d0000000c0000006b000000000514004900000000005204350000000a0200002900000000022404360000000304000029000b001f004001930000000405000029000800200050003d000000000004004b000001c10000613d000000080330036000000003042000290000000005020019000000003603043c0000000005650436000000000045004b000001bd0000c13d0000000b0000006b00000003031000690000000002230019000002710020009c00000271020080410000006002200210000002710010009c00000271010080410000004001100210000000000112019f0000000002000414000002710020009c0000027102008041000000c002200210000000000112019f00000277011001c70000800d020000390000000403000039000002b30400004100000000050004110000000e060000290000000d0700002909c009b60000040f0000000100200190000000560000613d000002990100004100000000001004430000000d0100002900000004001004430000000001000414000002710010009c0000027101008041000000c0011002100000029a011001c7000080020200003909c009bb0000040f0000000100200190000006fb0000613d000000000101043b000000000001004b0000054a0000613d000000400300043d000000a4013000390000000a0200002900000000002104350000004401300039000000a002000039000000000021043500000024013000390000000e020000290000000000210435000002b4010000410000000000130435000000040130003900000000020004110000000000210435000700000003001d000000c40330003900000005023000290000000001000367000000050000006b000002040000613d0000000904100360000000004504043c0000000003530436000000000023004b000002000000c13d0000000c0000006b000000070300002900000064033000390000000504000029000000c00440003900000000004304350000000a0300002900000000033204360000000302300029000000030000006b000002140000613d0000000804100360000000004504043c0000000003530436000000000023004b000002100000c13d0000000b0000006b00000007040000290000000003420049000000040330008a00000084044000390000000000340435000000010410036000000002030000290000000001320436000002c2053001980000001f0630018f0000000003510019000002270000613d000000000704034f0000000008010019000000007907043c0000000008980436000000000038004b000002230000c13d000000000006004b000002340000613d000000000454034f0000000305600210000000000603043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f000000000043043500000002040000290000001f03400039000002c20230019700000000034100190000000000030435000000070300002900000000023200490000000001120019000002710010009c00000271010080410000006001100210000002710030009c000002710200004100000000020340190000004002200210000000000121019f0000000002000414000002710020009c0000027102008041000000c002200210000000000112019f0000000d0200002909c009b60000040f00000060031002700000027103300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000007057000290000025a0000613d000000000801034f0000000709000029000000008a08043c0000000009a90436000000000059004b000002560000c13d000000000006004b000002670000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000009190000613d0000001f01400039000000600210018f0000000701200029000000000021004b00000000020000390000000102004039000002740010009c0000007a0000213d00000001002001900000007a0000c13d000000400010043f000000200030008c000000560000413d000000070100002900000000010104330000029e00100198000000560000c13d0000029f01100197000002b40010009c000007e30000013d000002810020009c000005b80000613d000002820020009c000000560000c13d000000240010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000000401800370000000000101043b000002960010009c000000560000213d000000000010043f00000004010000390000047f0000013d000000240010008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000402800370000000000402043b000002740040009c000000560000213d0000002302400039000000000012004b000000560000813d0000000405400039000000000258034f000000000202043b000002740020009c0000007a0000213d0000001f06200039000002c2066001970000003f06600039000002c206600197000002a90060009c0000007a0000213d0000008006600039000000400060043f000000800020043f00000000042400190000002404400039000000000014004b000000560000213d0000002001500039000000000418034f000002c2052001980000001f0620018f000000a001500039000002b70000613d000000a007000039000000000804034f000000008908043c0000000007970436000000000017004b000002b30000c13d000000000006004b000002c40000613d000000000454034f0000000305600210000000000601043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000410435000000a00120003900000000000104350000000201000039000000000101041a00000296011001970000000002000411000000000012004b000006c10000c13d000000800200043d000002740020009c0000007a0000213d0000000501000039000000000501041a000000010050019000000001045002700000007f0440618f0000001f0040008c00000000060000390000000106002039000000000565013f0000000100500190000006130000c13d000000200040008c000002eb0000413d000000000010043f0000001f052000390000000505500270000002bc0550009a000000200020008c000002bb050040410000001f044000390000000504400270000002bc0440009a000000000045004b000002eb0000813d000000000005041b0000000105500039000000000045004b000002e70000413d0000001f0020008c000007060000a13d000000000010043f000002c2042001980000073a0000c13d000000a005000039000002bb03000041000007480000013d000000240010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000012001000039000000400010043f000001000a000039000001000000043f0000000402800370000000000202043b00000000030a0019000000090020008c0000000a1220011a000000f804100210000000010aa0008a00000000050a0433000002b905500197000000000445019f000002ba044001c700000000004a0435000002fe0000213d0000010102300089000000210330008a00000000002304350000000506000039000000000506041a000000010750019000000001025002700000007f0220618f0000001f0020008c00000000040000390000000104002039000000000445013f0000000100400190000006130000c13d000000400100043d0000002004100039000000000007004b000006370000613d000000000060043f000000000002004b000006390000613d000002bb0500004100000000060000190000000007460019000000000805041a000000000087043500000001055000390000002006600039000000000026004b000003200000413d000006390000013d000000440010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000000401800370000000000101043b000e00000001001d000002960010009c000000560000213d0000002401800370000000000201043b000000000002004b0000000001000039000000010100c039000d00000002001d000000000012004b000000560000c13d0000000001000411000000000010043f0000000101000039000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b0000000e02000029000000000020043f000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000201041a000002c1022001970000000d03000029000000000232019f000000000021041b000000400100043d0000000000310435000002710010009c000002710100804100000040011002100000000002000414000002710020009c0000027102008041000000c002200210000000000112019f00000279011001c70000800d020000390000000303000039000002a10400004100000000050004110000000e06000029000003a90000013d000000440010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000002401800370000000000101043b000d00000001001d0000000401800370000000000101043b000e00000001001d0000000001000411000000000010043f000000200000043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b0000000e02000029000000000020043f000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000201041a0000000d03000029000000000232004b000008910000413d000000000021041b000000400100043d000000200210003900000000003204350000000e020000290000000000210435000002710010009c000002710100804100000040011002100000000002000414000002710020009c0000027102008041000000c002200210000000000112019f00000297011001c70000800d020000390000000403000039000002980400004100000000050004110000000006050019000000000700001909c009b60000040f0000000100200190000000560000613d0000000001000019000009c10001042e000000440010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000000401800370000000000101043b000e00000001001d000002960010009c000000560000213d0000002401800370000000000201043b0000000301000039000000000101041a00000296011001970000000003000411000000000013004b0000064f0000c13d000d00000002001d000000a001000039000000400010043f000000800000043f0000000e01000029000000000010043f000000200000043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b0000000d02000029000000000020043f000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000201041a000000010220003a000008910000613d000000000021041b000000400100043d0000002002100039000000010300003900000000003204350000000d020000290000000000210435000002710010009c000002710100804100000040011002100000000002000414000002710020009c0000027102008041000000c002200210000000000112019f00000297011001c70000800d0200003900000004030000390000029804000041000000000500041100000000060000190000000e0700002909c009b60000040f0000000100200190000000560000613d000002990100004100000000001004430000000e0100002900000004001004430000000001000414000002710010009c0000027101008041000000c0011002100000029a011001c7000080020200003909c009bb0000040f0000000100200190000006fb0000613d000000000101043b000000000001004b000007100000c13d0000000e01000029000000000001004b0000000001000039000000010100c039000000010110018f09c009900000040f0000000001000019000009c10001042e000000440010008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000402800370000000000202043b000002740020009c000000560000213d0000002303200039000000000013004b000000560000813d0000000403200039000000000338034f000000000303043b000c00000003001d000002740030009c000000560000213d000b00240020003d0000000c0200002900000005022002100000000b03200029000000000013004b000000560000213d0000002403800370000000000303043b000002740030009c000000560000213d0000002304300039000000000014004b000000560000813d0000000404300039000000000448034f000000000404043b000002740040009c000000560000213d000a00240030003d00000005034002100000000a03300029000000000013004b000000560000213d0000000c0040006b000006fc0000c13d0000003f03200039000002a803300197000002a90030009c0000007a0000213d0000008003300039000000400030043f0000000c03000029000000800030043f0000001f0320018f000000000002004b0000044f0000613d000000000118034f000000a002200039000000a004000039000000001501043c0000000004540436000000000024004b0000044b0000c13d000000000003004b0000000c0000006b000007570000c13d000000400100043d00000020020000390000000002210436000000800300043d00000000003204350000004002100039000000000003004b000004610000613d000000a0040000390000000005000019000000004604043400000000026204360000000105500039000000000035004b0000045c0000413d0000000002120049000002710020009c00000271020080410000006002200210000002710010009c00000271010080410000004001100210000000000112019f000009c10001042e000000440010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000000401800370000000000101043b000002960010009c000000560000213d0000002402800370000000000202043b000e00000002001d000002960020009c000000560000213d000000000010043f0000000101000039000000200010043f000000400100003909c009a50000040f0000000e02000029000000000020043f000000200010043f000000400100003909c009a50000040f000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f000002a001000041000009c10001042e000000a40010008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000402800370000000000202043b000e00000002001d000002960020009c000000560000213d0000002402800370000000000202043b000d00000002001d000002960020009c000000560000213d0000006402800370000000000202043b000b00000002001d0000004402800370000000000202043b000c00000002001d0000008402800370000000000202043b000002740020009c000000560000213d0000002303200039000000000013004b000000560000813d000900040020003d0000000903800360000000000303043b000a00000003001d000002740030009c000000560000213d0000000a022000290000002402200039000000000012004b000000560000213d0000000d01000029000000000010043f0000000401000039000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000006f30000c13d0000000e01000029000000000010043f0000000401000039000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000006f30000c13d0000000001000411000000000010043f0000000401000039000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000006f30000c13d00000000020004110000000e0020006c000007f80000c13d0000000e01000029000000000010043f000000200000043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b0000000c02000029000000000020043f000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000201041a0000000b0220006c000008910000413d000000000021041b0000000d01000029000000000010043f000000200000043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b0000000c02000029000000000020043f000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000201041a0000000b0020002a000008910000413d0000000b030000290000000002320019000000000021041b000000400100043d000000200210003900000000003204350000000c020000290000000000210435000002710010009c000002710100804100000040011002100000000002000414000002710020009c0000027102008041000000c002200210000000000112019f00000297011001c70000800d020000390000000403000039000002980400004100000000050004110000000e060000290000000d0700002909c009b60000040f0000000100200190000000560000613d000002990100004100000000001004430000000d0100002900000004001004430000000001000414000002710010009c0000027101008041000000c0011002100000029a011001c7000080020200003909c009bb0000040f0000000100200190000006fb0000613d000000000101043b000000000001004b000008970000c13d0000000d010000290000040b0000013d000000440010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000000401800370000000000101043b000002960010009c000000560000213d000000000010043f000000200000043f0000004001000039000e00000008035309c009a50000040f0000000e0200035f0000002402200370000000000202043b000000000020043f000000200010043f000000400100003909c009a50000040f000000000101041a000000800010043f000002a001000041000009c10001042e0000000001000416000000000001004b000000560000c13d0000000301000039000000000101041a0000029601100197000000800010043f000002a001000041000009c10001042e000000440010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000002401800370000000000101043b000e00000001001d0000000301000039000000000101041a000002b502000041000000800020043f00000000030004140000029602100197000002710030009c0000027103008041000000c001300210000002ad011001c709c009bb0000040f00000060031002700000027103300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000005900000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b0000058c0000c13d000000000006004b0000059d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000006190000613d0000001f01400039000000600210018f00000080012001bf000000400010043f000000200030008c000000560000413d000000800300043d000002b60030009c000000560000813d0000000604000039000000000504041a0000000e0600002900000000046500a9000000000006004b000005b10000613d00000000066400d9000000000065004b000008910000c13d0000000000310435000002b70340012a000000a00220003900000000003204350000004001100210000002b8011001c7000009c10001042e000000240010008c000000560000413d0000000001000416000000000001004b000000560000c13d0000000401800370000000000101043b000e00000001001d000002960010009c000000560000213d0000000201000039000000000101041a00000296011001970000000002000411000000000012004b0000000001000039000000010100603909c0097c0000040f0000000301000039000000000201041a00000276022001970000000e022001af000000000021041b0000000001000019000009c10001042e000002a201000041000000800010043f0000002001000039000000840010043f0000000c01000039000000a40010043f000002a301000041000000c40010043f000002a401000041000009c2000104300000000005490019000000000004004b000005e40000613d0000000006010019000000000709001900000000680604340000000007870436000000000057004b000005e00000c13d000000000003004b000005f10000613d00000000014100190000000303300210000000000405043300000000043401cf000000000434022f00000000010104330000010003300089000000000131022f00000000013101cf000000000141019f0000000000150435000000000129001900000000000104350000000201000039000000000201041a00000276022001970000000006000411000000000262019f000000000021041b0000000001000414000002710010009c0000027101008041000000c00110021000000277011001c70000800d0200003900000003030000390000027804000041000000000500001909c009b60000040f0000000100200190000000560000613d0000000d010000290000000005010433000002740050009c0000007a0000213d0000000504000039000000000104041a000000010210019000000001031002700000007f0330618f0000001f0030008c00000000010000390000000101002039000000000012004b000006800000613d000002aa01000041000000000010043f0000002201000039000000040010043f000002ab01000041000009c2000104300000001f0530018f0000027306300198000000400200043d0000000004620019000006240000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006200000c13d000000000005004b000006310000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000002710020009c00000271020080410000004002200210000000000112019f000009c200010430000002c105500197000000000054043500000000022400190000000003030433000002c2053001970000001f0430018f00000000002a004b000006530000813d000000000005004b0000064b0000613d00000000074a00190000000006420019000000200660008a000000200770008a0000000008560019000000000957001900000000090904330000000000980435000000200550008c000006450000c13d000000000004004b000006690000613d00000000060200190000065f0000013d000002ac01000041000000800010043f000002ad01000041000009c2000104300000000006520019000000000005004b0000065c0000613d00000000070a0019000000000802001900000000790704340000000008980436000000000068004b000006580000c13d000000000004004b000006690000613d000000000a5a00190000000304400210000000000506043300000000054501cf000000000545022f00000000070a04330000010004400089000000000747022f00000000044701cf000000000454019f0000000000460435000000000223001900000000000204350000000002120049000000200320008a0000000000310435000e00000001001d09c009250000040f0000002001000039000000400200043d000d00000002001d00000000021204360000000e0100002909c009370000040f0000000d020000290000000001210049000002710010009c00000271010080410000006001100210000002710020009c00000271020080410000004002200210000000000121019f000009c10001042e000000200030008c000006a00000413d000b00000003001d000c00000005001d000000000040043f0000000001000414000002710010009c0000027101008041000000c00110021000000279011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d0000000c050000290000001f025000390000000502200270000000200050008c0000000002004019000000000301043b0000000b010000290000001f01100039000000050110027000000000011300190000000002230019000000000012004b0000000504000039000006a00000813d000000000002041b0000000102200039000000000012004b0000069c0000413d0000001f0050008c0000002008000039000006b60000a13d000c00000005001d000000000040043f0000000001000414000002710010009c0000027101008041000000c00110021000000279011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d0000000c07000029000002c202700198000000000101043b000006d20000c13d000000200800003900000000030800190000000d06000029000006e00000013d000000000005004b0000000001000019000006bb0000613d0000000e0100002900000000010104330000000302500210000002c30220027f000002c302200167000000000221016f0000000101500210000006ed0000013d000000400100043d0000004402100039000002a303000041000000000032043500000024021000390000000c030000390000000000320435000002a2020000410000000000210435000000040210003900000020030000390000000000320435000002710010009c00000271010080410000004001100210000002b0011001c7000009c200010430000000010320008a00000005033002700000000004310019000000200300003900000001044000390000000d06000029000000200800003900000000056300190000000005050433000000000051041b00000020033000390000000101100039000000000041004b000006d90000c13d000000000072004b000006ea0000813d0000000302700210000000f80220018f000002c30220027f000002c30220016700000000036300190000000003030433000000000223016f000000000021041b000000010100003900000001027002100000000504000039000000000112019f000000000014041b000001000080044300000120000004430000027a01000041000009c10001042e000000400100043d000002ae020000410000000000210435000002710010009c00000271010080410000004001100210000002af011001c7000009c200010430000000000001042f000002a201000041000000800010043f0000002001000039000000840010043f0000000f01000039000000a40010043f000002a701000041000000c40010043f000002a401000041000009c200010430000000000002004b00000000030000190000070a0000613d000000a00300043d0000000304200210000002c30440027f000002c304400167000000000443016f0000000103200210000007530000013d000000400300043d0000008401300039000000a002000039000000000021043500000064013000390000000102000039000000000021043500000044013000390000000d0200002900000000002104350000029b01000041000000000013043500000004013000390000000002000411000000000021043500000024013000390000000000010435000000a402300039000000800100043d0000000000120435000002c2051001970000001f0410018f000c00000003001d000000c403300039000000a10030008c000007880000413d000000000005004b000007350000613d000000000743001900000080064001bf000000200770008a0000000008570019000000000956001900000000090904330000000000980435000000200550008c0000072f0000c13d000000000004004b0000079e0000613d000000a0050000390000000006030019000007940000013d000002bb030000410000002006000039000000010540008a0000000505500270000002bd0550009a000000000706001900000080066000390000000006060433000000000063041b00000020067000390000000103300039000000000053004b0000073f0000c13d000000a005700039000000000024004b000007510000813d0000000304200210000000f80440018f000002c30440027f000002c3044001670000000005050433000000000445016f000000000043041b00000001030000390000000104200210000000000234019f000000000021041b0000000001000019000009c10001042e0000000003000019000d00000003001d0000000502300210000e00000002001d0000000b012000290000000001100367000000000101043b000002960010009c000000560000213d000000000010043f000000200000043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d0000000e030000290000000a023000290000000002200367000000000202043b000000000101043b000000000020043f000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000800200043d0000000d03000029000000000023004b000007f20000813d000000000101043b000000000101041a0000000e02000029000000a002200039000000000012043500000001033000390000000c0030006c000007580000413d000004520000013d0000000006530019000000000005004b000000a009000039000007910000613d000000000703001900000000980904340000000007870436000000000067004b0000078d0000c13d000000000004004b0000079e0000613d000000a0055000390000000304400210000000000706043300000000074701cf000000000747022f00000000050504330000010004400089000000000545022f00000000044501cf000000000474019f00000000004604350000001f04100039000002c20240019700000000013100190000000000010435000000c401200039000002710010009c000002710100804100000060011002100000000c02000029000002710020009c00000271020080410000004002200210000000000121019f0000000002000414000002710020009c0000027102008041000000c002200210000000000121019f0000000e0200002909c009b60000040f00000060031002700000027103300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000c05700029000007c10000613d000000000801034f0000000c09000029000000008a08043c0000000009a90436000000000059004b000007bd0000c13d000000000006004b000007ce0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000007e60000613d0000001f01400039000000600210018f0000000c01200029000000000021004b00000000020000390000000102004039000002740010009c0000007a0000213d00000001002001900000007a0000c13d000000400010043f000000200030008c000000560000413d0000000c0100002900000000010104330000029e00100198000000560000c13d0000029f011001970000029b0010009c000000000100003900000001010060390000040e0000013d0000001f0530018f0000027306300198000000400200043d0000000004620019000006240000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000007ed0000c13d000006240000013d000002aa01000041000000000010043f0000003201000039000000040010043f000002ab01000041000009c2000104300000000e01000029000000000010043f0000000101000039000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b0000000002000411000000000020043f000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000004e50000c13d000000400100043d0000004402100039000002b103000041000000000032043500000024021000390000000e03000039000006c70000013d000000400100043d0000004402100039000002a703000041000000000032043500000024021000390000000f03000039000006c70000013d0000000e01000029000000000010043f0000000101000039000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b0000000002000411000000000020043f000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000001970000c13d000008160000013d0000000002000019000900000002001d00000005012002100000000702100029000000080110002900000000011003670000000002200367000000000202043b000b00000002001d000000000101043b000c00000001001d0000000e01000029000000000010043f000000200000043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b0000000c02000029000000000020043f000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000201041a0000000b0220006c000008910000413d000000000021041b0000000d01000029000000000010043f000000200000043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b0000000c02000029000000000020043f000000200010043f0000000001000414000002710010009c0000027101008041000000c00110021000000297011001c7000080100200003909c009bb0000040f0000000100200190000000560000613d000000000101043b000000000201041a0000000b03000029000000000032001a000008910000413d0000000002320019000000000021041b000000090200002900000001022000390000000a0020006c000008440000413d000001990000013d000002aa01000041000000000010043f0000001101000039000000040010043f000002ab01000041000009c200010430000000400300043d0000008401300039000000a002000039000000000021043500000064013000390000000b02000029000000000021043500000044013000390000000c02000029000000000021043500000024013000390000000e0200002900000000002104350000029b010000410000000000130435000000040130003900000000020004110000000000210435000000a4013000390000000a020000290000000000210435000002c2042001980000001f0520018f000800000003001d000000c4023000390000000003420019000000090600002900000020066000390000000006600367000008bb0000613d000000000706034f0000000008020019000000007907043c0000000008980436000000000038004b000008b70000c13d000000000005004b000008c80000613d000000000446034f0000000305500210000000000603043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f00000000004304350000000a03000029000000000232001900000000000204350000001f02300039000002c2012001970000029c0010009c0000029c0100804100000060011002100000000802000029000002710020009c00000271020080410000004002200210000000000121019f0000000002000414000002710020009c0000027102008041000000c002200210000000000121019f0000029d0110009a0000000d0200002909c009b60000040f00000060031002700000027103300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000805700029000008ec0000613d000000000801034f0000000809000029000000008a08043c0000000009a90436000000000059004b000008e80000c13d000000000006004b000008f90000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f000000000065043500000001002001900000090d0000613d0000001f01400039000000600210018f0000000801200029000000000021004b00000000020000390000000102004039000002740010009c0000007a0000213d00000001002001900000007a0000c13d000000400010043f000000200030008c000000560000413d000000080100002900000000010104330000029e00100198000000560000c13d000007e10000013d0000001f0530018f0000027306300198000000400200043d0000000004620019000006240000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009140000c13d000006240000013d0000001f0530018f0000027306300198000000400200043d0000000004620019000006240000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009200000c13d000006240000013d0000001f02200039000002c2022001970000000001120019000000000021004b00000000020000390000000102004039000002740010009c000009310000213d0000000100200190000009310000c13d000000400010043f000000000001042d000002aa01000041000000000010043f0000004101000039000000040010043f000002ab01000041000009c20001043000000000430104340000000001320436000002c2063001970000001f0530018f000000000014004b0000094d0000813d000000000006004b000009490000613d00000000085400190000000007510019000000200770008a000000200880008a0000000009670019000000000a680019000000000a0a04330000000000a90435000000200660008c000009430000c13d000000000005004b000009630000613d0000000007010019000009590000013d0000000007610019000000000006004b000009560000613d00000000080400190000000009010019000000008a0804340000000009a90436000000000079004b000009520000c13d000000000005004b000009630000613d00000000046400190000000305500210000000000607043300000000065601cf000000000656022f00000000040404330000010005500089000000000454022f00000000045401cf000000000464019f0000000000470435000000000431001900000000000404350000001f03300039000002c2023001970000000001210019000000000001042d000002c40010009c0000097a0000213d000000430010008c0000097a0000a13d00000000020003670000000401200370000000000101043b000002960010009c0000097a0000213d0000002402200370000000000202043b000000000002004b0000000003000039000000010300c039000000000032004b0000097a0000c13d000000000001042d0000000001000019000009c200010430000000000001004b0000097f0000613d000000000001042d000000400100043d0000004402100039000002a303000041000000000032043500000024021000390000000c030000390000000000320435000002a2020000410000000000210435000000040210003900000020030000390000000000320435000002710010009c00000271010080410000004001100210000002b0011001c7000009c200010430000000000001004b000009930000613d000000000001042d000000400100043d0000004402100039000002c5030000410000000000320435000000240210003900000010030000390000000000320435000002a2020000410000000000210435000000040210003900000020030000390000000000320435000002710010009c00000271010080410000004001100210000002b0011001c7000009c200010430000000000001042f000002710010009c000002710100804100000060011002100000000002000414000002710020009c0000027102008041000000c002200210000000000112019f00000277011001c7000080100200003909c009bb0000040f0000000100200190000009b40000613d000000000101043b000000000001042d0000000001000019000009c200010430000009b9002104210000000102000039000000000001042d0000000002000019000000000001042d000009be002104230000000102000039000000000001042d0000000002000019000000000001042d000009c000000432000009c10001042e000009c200010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000000ffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0020000000000000000000000000000000000002000000000000000000000000000000002000000000000000000000000000000400000010000000000000000000000000000000000000000000000000000000000000000000000000075c6022400000000000000000000000000000000000000000000000000000000d1a448c800000000000000000000000000000000000000000000000000000000e985e9c400000000000000000000000000000000000000000000000000000000e985e9c500000000000000000000000000000000000000000000000000000000f242432a00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000d1a448c900000000000000000000000000000000000000000000000000000000dbac26e900000000000000000000000000000000000000000000000000000000a22cb46400000000000000000000000000000000000000000000000000000000a22cb46500000000000000000000000000000000000000000000000000000000b390c0ab00000000000000000000000000000000000000000000000000000000b8997a970000000000000000000000000000000000000000000000000000000075c60225000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000002a5520590000000000000000000000000000000000000000000000000000000040c10f180000000000000000000000000000000000000000000000000000000040c10f19000000000000000000000000000000000000000000000000000000004e1273f4000000000000000000000000000000000000000000000000000000004e83be47000000000000000000000000000000000000000000000000000000002a55205a000000000000000000000000000000000000000000000000000000002eb2c2d60000000000000000000000000000000000000000000000000000000002fe53040000000000000000000000000000000000000000000000000000000002fe5305000000000000000000000000000000000000000000000000000000000e89341c00000000000000000000000000000000000000000000000000000000153b0d1e0000000000000000000000000000000000000000000000000000000000fdd58e0000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0200000000000000000000000000000000000040000000000000000000000000c3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f621806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000f23a6e610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffff3bffffffffffffffffffffffffffffffffffffff3c00000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000080000000000000000017307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3108c379a000000000000000000000000000000000000000000000000000000000554e415554484f52495a454400000000000000000000000000000000000000000000000000000000000000000000000000000064000000800000000000000000020000000000000000000000000000000000002000000080000000000000000061ed6a11a3344a6beb955961a0bdb0520b226cc2eae238f5784b751bd82fb5284c454e4754485f4d49534d4154434800000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000ffffffffffffff7f4e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000091c1cca70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000008000000000000000001f7b776b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000640000000000000000000000004e4f545f415554484f52495a454400000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fbbc197c8100000000000000000000000000000000000000000000000000000000ef3692520000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000004000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3000000000000000000000000000000000000000000000000000000000000000036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0fc949c7b4a13586e39d89eead2f38644f9fb3efb5a0490b14f8fc0ceab44c250fc949c7b4a13586e39d89eead2f38644f9fb3efb5a0490b14f8fc0ceab44c24f01ffc9a7000000000000000000000000000000000000000000000000000000002a55205a00000000000000000000000000000000000000000000000000000000d9b67a2600000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff554e534146455f524543495049454e5400000000000000000000000000000000785b97758beaf9b5d9304d98167a331de9ed0b66e7e117d5c62ff18d04abd962
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6465762d6170692e736f66616d6f6e2e78797a2f7765617261626c65732f0000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _baseURI (string): https://dev-api.sofamon.xyz/wearables/
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000026
Arg [2] : 68747470733a2f2f6465762d6170692e736f66616d6f6e2e78797a2f77656172
Arg [3] : 61626c65732f0000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.