ERC-721
Overview
Max Total Supply
0 SCR
Holders
5
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 SCRLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
Scrabble
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library to encode strings in Base64. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Base64.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Base64.sol) /// @author Modified from (https://github.com/Brechtpd/base64/blob/main/base64.sol) by Brecht Devos - <[email protected]>. library Base64 { /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// See: https://datatracker.ietf.org/doc/html/rfc4648 /// @param fileSafe Whether to replace '+' with '-' and '/' with '_'. /// @param noPadding Whether to strip away the padding. function encode(bytes memory data, bool fileSafe, bool noPadding) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let dataLength := mload(data) if dataLength { // Multiply by 4/3 rounded up. // The `shl(2, ...)` is equivalent to multiplying by 4. let encodedLength := shl(2, div(add(dataLength, 2), 3)) // Set `result` to point to the start of the free memory. result := mload(0x40) // Store the table into the scratch space. // Offsetted by -1 byte so that the `mload` will load the character. // We will rewrite the free memory pointer at `0x40` later with // the allocated size. // The magic constant 0x0230 will translate "-_" + "+/". mstore(0x1f, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef") mstore(0x3f, sub("ghijklmnopqrstuvwxyz0123456789-_", mul(iszero(fileSafe), 0x0230))) // Skip the first slot, which stores the length. let ptr := add(result, 0x20) let end := add(ptr, encodedLength) // Run over the input, 3 bytes at a time. for {} 1 {} { data := add(data, 3) // Advance 3 bytes. let input := mload(data) // Write 4 bytes. Optimized for fewer stack operations. mstore8(0, mload(and(shr(18, input), 0x3F))) mstore8(1, mload(and(shr(12, input), 0x3F))) mstore8(2, mload(and(shr(6, input), 0x3F))) mstore8(3, mload(and(input, 0x3F))) mstore(ptr, mload(0x00)) ptr := add(ptr, 4) // Advance 4 bytes. if iszero(lt(ptr, end)) { break } } // Allocate the memory for the string. // Add 31 and mask with `not(31)` to round the // free memory pointer up the next multiple of 32. mstore(0x40, and(add(end, 31), not(31))) // Equivalent to `o = [0, 2, 1][dataLength % 3]`. let o := div(2, mod(dataLength, 3)) // Offset `ptr` and pad with '='. We can simply write over the end. mstore(sub(ptr, o), shl(240, 0x3d3d)) // Set `o` to zero if there is padding. o := mul(iszero(iszero(noPadding)), o) // Zeroize the slot after the string. mstore(sub(ptr, o), 0) // Write the length of the string. mstore(result, sub(encodedLength, o)) } } } /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// Equivalent to `encode(data, false, false)`. function encode(bytes memory data) internal pure returns (string memory result) { result = encode(data, false, false); } /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// Equivalent to `encode(data, fileSafe, false)`. function encode(bytes memory data, bool fileSafe) internal pure returns (string memory result) { result = encode(data, fileSafe, false); } /// @dev Encodes base64 encoded `data`. /// /// Supports: /// - RFC 4648 (both standard and file-safe mode). /// - RFC 3501 (63: ','). /// /// Does not support: /// - Line breaks. /// /// Note: For performance reasons, /// this function will NOT revert on invalid `data` inputs. /// Outputs for invalid inputs will simply be undefined behaviour. /// It is the user's responsibility to ensure that the `data` /// is a valid base64 encoded string. function decode(string memory data) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { let dataLength := mload(data) if dataLength { let decodedLength := mul(shr(2, dataLength), 3) for {} 1 {} { // If padded. if iszero(and(dataLength, 3)) { let t := xor(mload(add(data, dataLength)), 0x3d3d) // forgefmt: disable-next-item decodedLength := sub( decodedLength, add(iszero(byte(30, t)), iszero(byte(31, t))) ) break } // If non-padded. decodedLength := add(decodedLength, sub(and(dataLength, 3), 1)) break } result := mload(0x40) // Write the length of the bytes. mstore(result, decodedLength) // Skip the first slot, which stores the length. let ptr := add(result, 0x20) let end := add(ptr, decodedLength) // Load the table into the scratch space. // Constants are optimized for smaller bytecode with zero gas overhead. // `m` also doubles as the mask of the upper 6 bits. let m := 0xfc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc mstore(0x5b, m) mstore(0x3b, 0x04080c1014181c2024282c3034383c4044484c5054585c6064) mstore(0x1a, 0xf8fcf800fcd0d4d8dce0e4e8ecf0f4) for {} 1 {} { // Read 4 bytes. data := add(data, 4) let input := mload(data) // Write 3 bytes. // forgefmt: disable-next-item mstore(ptr, or( and(m, mload(byte(28, input))), shr(6, or( and(m, mload(byte(29, input))), shr(6, or( and(m, mload(byte(30, input))), shr(6, mload(byte(31, input))) )) )) )) ptr := add(ptr, 3) if iszero(lt(ptr, end)) { break } } // Allocate the memory for the string. // Add 31 and mask with `not(31)` to round the // free memory pointer up the next multiple of 32. mstore(0x40, and(add(end, 31), not(31))) // Zeroize the slot after the bytes. mstore(end, 0) // Restore the zero slot. mstore(0x60, 0) } } } }
// 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) library LibString { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The `length` of the output is too small to contain all the hex digits. error HexLengthInsufficient(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The constant returned when the `search` is not found in the string. uint256 internal constant NOT_FOUND = type(uint256).max; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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) // Update the free memory pointer to allocate. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str 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)`. // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, 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)); } /// @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) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write 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))) // Allocate the memory. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // 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 { // Store the function selector of `HexLengthInsufficient()`. mstore(0x00, 0x2194895a) // Revert with (offset, size). revert(0x1c, 0x04) } // Compute the string's length. let strLength := sub(end, str) // Move the pointer and write the length. str := sub(str, 0x20) mstore(str, strLength) } } /// @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) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @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) // Allocate the memory. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) 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 } } // Compute the string's length. let strLength := sub(end, str) // Move the pointer and write the length. str := sub(str, 0x20) mstore(str, strLength) } } /// @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 toHexStringChecksumed(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) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write 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)) // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) str := add(str, 2) mstore(str, 40) let o := add(str, 0x20) mstore(add(o, 40), 0) 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) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write 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. // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) 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, and(add(o, 31), not(31))) // 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 } } } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // For performance and bytecode compactness, all indices of the following operations // are byte (ASCII) offsets, not UTF character offsets. /// @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, 32)) { h := keccak256(search, searchLength) } let m := shl(3, sub(32, and(searchLength, 31))) 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) // Zeroize the slot after the string. let last := add(add(result, 0x20), k) mstore(last, 0) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, and(add(last, 31), not(31))) // Store the length of the result. mstore(result, k) } } /// @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(32, and(searchLength, 31))) let s := mload(add(search, 0x20)) if iszero(and(lt(subject, end), lt(from, subjectLength))) { break } if iszero(lt(searchLength, 32)) { 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 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 } } // Zeroize the slot after the string. mstore(output, 0) // Store the length. let resultLength := sub(output, add(result, 0x20)) mstore(result, resultLength) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(result, and(add(resultLength, 63), not(31)))) } } } /// @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(31) // Copy the `subject` one word at a time, backwards. for { let o := and(add(resultLength, 31), 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) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(result, and(add(resultLength, 63), w))) } } } /// @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, 32)) { h := keccak256(search, searchLength) } let m := shl(3, sub(32, and(searchLength, 31))) 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(31) 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, 31), 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, 63), 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(31) result := mload(0x40) let aLength := mload(a) // Copy `a` one word at a time, backwards. for { let o := and(add(mload(a), 32), 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, mload(a)) // Copy `b` one word at a time, backwards. for { let o := and(add(bLength, 32), 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) // Zeroize the slot after the string. mstore(last, 0) // Stores the length. mstore(result, totalLength) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, and(add(last, 31), w)) } } /// @dev Returns a copy of the string in either lowercase or UPPERCASE. 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)), 67108863) 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 } } // Restore the result. result := mload(0x40) // Stores the string length. mstore(result, length) // Zeroize the slot after the string. let last := add(add(result, 0x20), length) mstore(last, 0) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, and(add(last, 31), not(31))) } } } /// @dev Returns a lowercased copy of the string. function lower(string memory subject) internal pure returns (string memory result) { result = toCase(subject, false); } /// @dev Returns an UPPERCASED copy of the string. 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 { for { 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)) } 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, 31))) result := add(result, shr(5, t)) } let last := result // Zeroize the slot after the string. mstore(last, 0) // Restore the result to the start of the free memory. result := mload(0x40) // Store the length of the result. mstore(result, sub(last, add(result, 0x20))) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, and(add(last, 31), not(31))) } } /// @dev Escapes the string to be used within double-quotes in a JSON. function escapeJSON(string memory s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { for { let end := add(s, mload(s)) result := add(mload(0x40), 0x20) // 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)) } 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) } let last := result // Zeroize the slot after the string. mstore(last, 0) // Restore the result to the start of the free memory. result := mload(0x40) // Store the length of the result. mstore(result, sub(last, add(result, 0x20))) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, and(add(last, 31), not(31))) } } /// @dev Returns whether `a` equals `b`. function eq(string memory a, string memory b) internal pure returns (bool result) { assembly { result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b))) } } /// @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 behaviour is undefined. function unpackOne(bytes32 packed) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. result := mload(0x40) // Allocate 2 words (1 for the length, 1 for the bytes). mstore(0x40, add(result, 0x40)) // Zeroize the length slot. mstore(result, 0) // Store the length and bytes. mstore(add(result, 0x1f), packed) // Right pad with zeroes. mstore(add(add(result, 0x20), mload(result)), 0) } } /// @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( // Load the length and the bytes of `a` and `b`. or( 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 behaviour is undefined. function unpackTwo(bytes32 packed) internal pure returns (string memory resultA, string memory resultB) { /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. resultA := mload(0x40) 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 retSize := 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, retSize), 0) // Store the return offset. mstore(retStart, 0x20) // End the transaction, returning the string. return(retStart, retSize) } } }
// 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 Modern, minimalist, and gas efficient ERC-721 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _ownerOf; mapping(address => uint256) internal _balanceOf; function ownerOf(uint256 id) public view virtual returns (address owner) { require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); } function balanceOf(address owner) public view virtual returns (uint256) { require(owner != address(0), "ZERO_ADDRESS"); return _balanceOf[owner]; } /*////////////////////////////////////////////////////////////// ERC721 APPROVAL STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner = _ownerOf[id]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[from]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(_ownerOf[id] == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. unchecked { _balanceOf[to]++; } _ownerOf[id] = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner = _ownerOf[id]; require(owner != address(0), "NOT_MINTED"); // Ownership check above ensures no underflow. unchecked { _balanceOf[owner]--; } delete _ownerOf[id]; delete getApproved[id]; emit Transfer(owner, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint( address to, uint256 id, bytes memory data ) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } } /// @notice A generic interface for a contract which properly accepts ERC721 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721TokenReceiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; import "solmate/tokens/ERC721.sol"; import "solmate/auth/Owned.sol"; import "solady/utils/Base64.sol"; import "solady/utils/LibString.sol"; /// @title Scrabble /// @author M1LL1P3D3 contract Scrabble is ERC721, Owned { using LibString for string; string[] public pieces = [ "A:1", "A:1", "A:1", "A:1", "A:1", "A:1", "A:1", "A:1", "A:1", "B:3", "B:3", "C:3", "C:3", "D:2", "D:2", "D:2", "D:2", "E:1", "E:1", "E:1", "E:1", "E:1", "E:1", "E:1", "E:1", "E:1", "E:1", "E:1", "E:1", "F:4", "F:4", "G:2", "G:2", "G:2", "H:4", "H:4", "I:1", "I:1", "I:1", "I:1", "I:1", "I:1", "I:1", "I:1", "I:1", "J:8", "K:5", "L:1", "L:1", "L:1", "L:1", "M:3", "M:3", "N:1", "N:1", "N:1", "N:1", "N:1", "N:1", "O:1", "O:1", "O:1", "O:1", "O:1", "O:1", "O:1", "O:1", "P:3", "P:3", "Q:10", "R:1", "R:1", "R:1", "R:1", "R:1", "R:1", "S:1", "S:1", "S:1", "S:1", "T:1", "T:1", "T:1", "T:1", "T:1", "T:1", "U:1", "U:1", "U:1", "U:1", "V:4", "V:4", "W:4", "W:4", "X:8", "Y:4", "Y:4", "Z:10" ]; uint256 public constant MAX_SUPPLY = 98; uint256 public mintCostEther = 0.1 ether; uint256 public mintCounter; constructor() ERC721("Scrabble", "SCR") Owned(msg.sender) {} receive() external payable { uint256 amount = msg.value / mintCostEther; require(amount * mintCostEther == msg.value, "Invalid amount of ether sent"); mint(amount); } // @notice Mints a piece // @param amount The amount of pieces to mint function mint(uint256 amount) public payable { require(mintCounter + amount <= MAX_SUPPLY, "Max supply reached"); require(msg.value == mintCostEther * amount, "Not enough ether sent"); for (uint256 i = 0; i < amount; i++) { _mint(msg.sender, mintCounter); mintCounter++; } } // @notice Returns the URI for a given token ID // @param tokenId The token ID to return the URI for function tokenURI(uint256 tokenId) public view override returns (string memory) { string[8] memory svgParts; svgParts[0] = '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 700 700"><style>.base { fill: white; font-family: serif; font-size: 300px; }</style><rect width="100%" height="100%" fill="#000000" /><text x="50%" y="50%" class="base" dominant-baseline="middle" text-anchor="middle">'; svgParts[1] = pieces[tokenId]; svgParts[2] = "</text></svg>"; string memory output = string(abi.encodePacked(svgParts[0], svgParts[1], svgParts[2])); string memory json = Base64.encode( bytes( string( abi.encodePacked( '{"name": "Piece: ', pieces[tokenId], '", "description": "On-chain Scrabble by Omakasea", "image": "data:image/svg+xml;base64,', Base64.encode(bytes(output)), '"}' ) ) ) ); output = string(abi.encodePacked("data:application/json;base64,", json)); return output; } // @notice Updates the cost of minting a piece // @param newCost The new cost of minting a piece function updateMintCost(uint256 newCost) public onlyOwner { mintCostEther = newCost; } // @notice Withdraws all funds from the contract to the owner function withdraw() public onlyOwner { payable(msg.sender).transfer(address(this).balance); } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "solady/=lib/solady/src/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintCostEther","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pieces","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","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":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"updateMintCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6003610cc081815262413a3160e81b610ce08190526080918252610d00838152610d2082905260a052610d40838152610d6082905260c052610d80838152610da082905260e052610dc0838152610de082905261010052610e00838152610e2082905261012052610e40838152610e6082905261014052610e80838152610ea082905261016052610ec0838152610ee09190915261018052610f0082815262423a3360e81b610f208190526101a091909152610f40838152610f60919091526101c052610f8082815262433a3360e81b610fa08190526101e091909152610fc0838152610fe0919091526102005261100082815262221d1960e91b61102081905261022091909152611040838152611060829052610240526110808381526110a0829052610260526110c08381526110e0919091526102805261110082815262453a3160e81b6111208190526102a0919091526111408381526111608290526102c0526111808381526111a08290526102e0526111c08381526111e08290526103005261120083815261122082905261032052611240838152611260829052610340526112808381526112a0829052610360526112c08381526112e0829052610380526113008381526113208290526103a0526113408381526113608290526103c0526113808381526113a08290526103e0526113c08381526113e0919091526104005261140082815262118e8d60ea1b61142081905261042091909152611440838152611460919091526104405261148082815262239d1960e91b6114a0819052610460919091526114c08381526114e082905261048052611500838152611520919091526104a05261154082815262120e8d60ea1b6115608190526104c0919091526115808381526115a0919091526104e0526115c082815262493a3160e81b6115e08190526105009190915261160083815261162082905261052052611640838152611660829052610540526116808381526116a0829052610560526116c08381526116e0829052610580526117008381526117208290526105a0526117408381526117608290526105c0526117808381526117a08290526105e0526117c08381526117e091909152610600526118008281526209474760eb1b6118205261062052611840828152624b3a3560e81b6118605261064052611880828152624c3a3160e81b6118a0819052610660919091526118c08381526118e0829052610680526119008381526119208290526106a052611940838152611960919091526106c052611980828152624d3a3360e81b6119a08190526106e0919091526119c08381526119e09190915261070052611a00828152624e3a3160e81b611a2081905261072091909152611a40838152611a6082905261074052611a80838152611aa082905261076052611ac0838152611ae082905261078052611b00838152611b208290526107a052611b40838152611b60919091526107c052611b80828152624f3a3160e81b611ba08190526107e091909152611bc0838152611be082905261080052611c00838152611c2082905261082052611c40838152611c6082905261084052611c80838152611ca082905261086052611cc0838152611ce082905261088052611d00838152611d208290526108a052611d40838152611d60919091526108c052611d8082815262503a3360e81b611da08190526108e091909152611dc0838152611de091909152610900526004611e00818152630513a31360e41b611e205261092052611e4083815262523a3160e81b611e6081905261094091909152611e80848152611ea082905261096052611ec0848152611ee082905261098052611f00848152611f208290526109a052611f40848152611f608290526109c052611f80848152611fa0919091526109e052611fc083815262533a3160e81b611fe0819052610a0091909152612000848152612020829052610a2052612040848152612060829052610a40526120808481526120a091909152610a60526120c083815262543a3160e81b6120e0819052610a8091909152612100848152612120829052610aa052612140848152612160829052610ac0526121808481526121a0829052610ae0526121c08481526121e0829052610b005261220084815261222091909152610b205261224083815262553a3160e81b612260819052610b40919091526122808481526122a0829052610b60526122c08481526122e0829052610b805261230084815261232091909152610ba05261234083815262158e8d60ea1b612360819052610bc0919091526123808481526123a091909152610be0526123c08381526215ce8d60ea1b6123e0819052610c009190915261240084815261242091909152610c2052612440838152620b074760eb1b61246052610c405261248083815262164e8d60ea1b6124a0819052610c60919091526124c09384526124e052610c80929092526125406040526125009182526305a3a31360e41b61252052610ca0919091526200073990600790606262000807565b5067016345785d8a00006008553480156200075357600080fd5b5033604051806040016040528060088152602001675363726162626c6560c01b8152506040518060400160405280600381526020016229a1a960e91b8152508160009081620007a3919062000983565b506001620007b2828262000983565b5050600680546001600160a01b0319166001600160a01b0384169081179091556040519091506000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35062000a4f565b82805482825590600052602060002090810192821562000852579160200282015b8281111562000852578251829062000841908262000983565b509160200191906001019062000828565b506200086092915062000864565b5090565b80821115620008605760006200087b828262000885565b5060010162000864565b5080546200089390620008f4565b6000825580601f10620008a4575050565b601f016020900490600052602060002090810190620008c49190620008c7565b50565b5b80821115620008605760008155600101620008c8565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200090957607f821691505b6020821081036200092a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200097e57600081815260208120601f850160051c81016020861015620009595750805b601f850160051c820191505b818110156200097a5782815560010162000965565b5050505b505050565b81516001600160401b038111156200099f576200099f620008de565b620009b781620009b08454620008f4565b8462000930565b602080601f831160018114620009ef5760008415620009d65750858301515b600019600386901b1c1916600185901b1785556200097a565b600085815260208120601f198616915b8281101562000a2057888601518255948401946001909101908401620009ff565b508582101562000a3f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61186e8062000a5f6000396000f3fe6080604052600436106101395760003560e01c806370a08231116100ab578063a22cb4651161006f578063a22cb465146103dc578063b88d4fde146103fc578063c4c7bca01461041c578063c87b56dd14610432578063e985e9c514610452578063f2fde38b1461048d57600080fd5b806370a08231146103545780638da5cb5b146103745780638f64be301461039457806395d89b41146103b4578063a0712d68146103c957600080fd5b806328d911fb116100fd57806328d911fb146102a657806332cb6b0c146102c65780633ccfd60b146102e957806342842e0e146102fe57806346aa52ce1461031e5780636352211e1461033457600080fd5b806301ffc9a7146101c157806306fdde03146101f6578063081812fc14610218578063095ea7b31461026657806323b872dd1461028657600080fd5b366101bc5760006008543461014e919061117a565b9050346008548261015f919061119c565b146101b15760405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420616d6f756e74206f662065746865722073656e740000000060448201526064015b60405180910390fd5b6101ba816104ad565b005b600080fd5b3480156101cd57600080fd5b506101e16101dc3660046111c9565b610597565b60405190151581526020015b60405180910390f35b34801561020257600080fd5b5061020b6105e9565b6040516101ed9190611211565b34801561022457600080fd5b5061024e610233366004611244565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016101ed565b34801561027257600080fd5b506101ba610281366004611274565b610677565b34801561029257600080fd5b506101ba6102a136600461129e565b610759565b3480156102b257600080fd5b506101ba6102c1366004611244565b610920565b3480156102d257600080fd5b506102db606281565b6040519081526020016101ed565b3480156102f557600080fd5b506101ba61094f565b34801561030a57600080fd5b506101ba61031936600461129e565b6109a8565b34801561032a57600080fd5b506102db60095481565b34801561034057600080fd5b5061024e61034f366004611244565b610aa0565b34801561036057600080fd5b506102db61036f3660046112da565b610af7565b34801561038057600080fd5b5060065461024e906001600160a01b031681565b3480156103a057600080fd5b5061020b6103af366004611244565b610b5a565b3480156103c057600080fd5b5061020b610b85565b6101ba6103d7366004611244565b6104ad565b3480156103e857600080fd5b506101ba6103f73660046112f5565b610b92565b34801561040857600080fd5b506101ba610417366004611331565b610bfe565b34801561042857600080fd5b506102db60085481565b34801561043e57600080fd5b5061020b61044d366004611244565b610ce6565b34801561045e57600080fd5b506101e161046d3660046113cc565b600560209081526000928352604080842090915290825290205460ff1681565b34801561049957600080fd5b506101ba6104a83660046112da565b610ec6565b6062816009546104bd91906113ff565b11156105005760405162461bcd60e51b815260206004820152601260248201527113585e081cdd5c1c1b1e481c995858da195960721b60448201526064016101a8565b8060085461050e919061119c565b34146105545760405162461bcd60e51b8152602060048201526015602482015274139bdd08195b9bdd59da08195d1a195c881cd95b9d605a1b60448201526064016101a8565b60005b818110156105935761056b33600954610f3c565b6009805490600061057b83611412565b9190505550808061058b90611412565b915050610557565b5050565b60006301ffc9a760e01b6001600160e01b0319831614806105c857506380ac58cd60e01b6001600160e01b03198316145b806105e35750635b5e139f60e01b6001600160e01b03198316145b92915050565b600080546105f69061142b565b80601f01602080910402602001604051908101604052809291908181526020018280546106229061142b565b801561066f5780601f106106445761010080835404028352916020019161066f565b820191906000526020600020905b81548152906001019060200180831161065257829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b0316338114806106c057506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6106fd5760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016101a8565b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000818152600260205260409020546001600160a01b038481169116146107af5760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016101a8565b6001600160a01b0382166107f95760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064016101a8565b336001600160a01b038416148061083357506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b8061085457506000818152600460205260409020546001600160a01b031633145b6108915760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016101a8565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6006546001600160a01b0316331461094a5760405162461bcd60e51b81526004016101a890611465565b600855565b6006546001600160a01b031633146109795760405162461bcd60e51b81526004016101a890611465565b60405133904780156108fc02916000818181858888f193505050501580156109a5573d6000803e3d6000fd5b50565b6109b3838383610759565b6001600160a01b0382163b1580610a5c5750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610a2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a50919061148b565b6001600160e01b031916145b610a9b5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016101a8565b505050565b6000818152600260205260409020546001600160a01b031680610af25760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b60448201526064016101a8565b919050565b60006001600160a01b038216610b3e5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b60448201526064016101a8565b506001600160a01b031660009081526003602052604090205490565b60078181548110610b6a57600080fd5b9060005260206000200160009150905080546105f69061142b565b600180546105f69061142b565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610c09858585610759565b6001600160a01b0384163b1580610ca05750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290610c519033908a908990899089906004016114a8565b6020604051808303816000875af1158015610c70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c94919061148b565b6001600160e01b031916145b610cdf5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016101a8565b5050505050565b6060610cf061113c565b6040518061016001604052806101328152602001611707610132913981526007805484908110610d2257610d226114fc565b906000526020600020018054610d379061142b565b80601f0160208091040260200160405190810160405280929190818152602001828054610d639061142b565b8015610db05780601f10610d8557610100808354040283529160200191610db0565b820191906000526020600020905b815481529060010190602001808311610d9357829003601f168201915b505050505081600160088110610dc857610dc86114fc565b60200201819052506040518060400160405280600d81526020016c1e17ba32bc3a1f1e17b9bb339f60991b81525081600260088110610e0957610e096114fc565b602002015260008181602002015182600160200201518360026020020151604051602001610e399392919061152e565b60405160208183030381529060405290506000610e9a60078681548110610e6257610e626114fc565b90600052602060002001610e7584611047565b604051602001610e86929190611571565b604051602081830303815290604052611047565b905080604051602001610ead91906116c1565b60408051601f1981840301815291905295945050505050565b6006546001600160a01b03163314610ef05760405162461bcd60e51b81526004016101a890611465565b600680546001600160a01b0319166001600160a01b03831690811790915560405133907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b6001600160a01b038216610f865760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064016101a8565b6000818152600260205260409020546001600160a01b031615610fdc5760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b60448201526064016101a8565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60606105e382600080606083518015611134576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526102308515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f03603f52602083018181015b6003880197508751603f8160121c1651600053603f81600c1c1651600153603f8160061c1651600253603f8116516003535060005182526004820191508082106110c057601f01601f1916604052613d3d60f01b600384066002048083039190915260008615159091029182900352900382525b509392505050565b6040518061010001604052806008905b606081526020019060019003908161114c5790505090565b634e487b7160e01b600052601160045260246000fd5b60008261119757634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176105e3576105e3611164565b6001600160e01b0319811681146109a557600080fd5b6000602082840312156111db57600080fd5b81356111e6816111b3565b9392505050565b60005b838110156112085781810151838201526020016111f0565b50506000910152565b60208152600082518060208401526112308160408501602087016111ed565b601f01601f19169190910160400192915050565b60006020828403121561125657600080fd5b5035919050565b80356001600160a01b0381168114610af257600080fd5b6000806040838503121561128757600080fd5b6112908361125d565b946020939093013593505050565b6000806000606084860312156112b357600080fd5b6112bc8461125d565b92506112ca6020850161125d565b9150604084013590509250925092565b6000602082840312156112ec57600080fd5b6111e68261125d565b6000806040838503121561130857600080fd5b6113118361125d565b91506020830135801515811461132657600080fd5b809150509250929050565b60008060008060006080868803121561134957600080fd5b6113528661125d565b94506113606020870161125d565b935060408601359250606086013567ffffffffffffffff8082111561138457600080fd5b818801915088601f83011261139857600080fd5b8135818111156113a757600080fd5b8960208285010111156113b957600080fd5b9699959850939650602001949392505050565b600080604083850312156113df57600080fd5b6113e88361125d565b91506113f66020840161125d565b90509250929050565b808201808211156105e3576105e3611164565b60006001820161142457611424611164565b5060010190565b600181811c9082168061143f57607f821691505b60208210810361145f57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b60006020828403121561149d57600080fd5b81516111e6816111b3565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b634e487b7160e01b600052603260045260246000fd5b600081516115248185602086016111ed565b9290920192915050565b600084516115408184602089016111ed565b8451908301906115548183602089016111ed565b84519101906115678183602088016111ed565b0195945050505050565b7003d913730b6b2911d10112834b2b1b29d1607d1b815282546000906011908290600181811c90808316806115a757607f831692505b602080841082036115c657634e487b7160e01b86526022600452602486fd5b8180156115da57600181146115f357611624565b60ff1986168a89015284151585028a0188019650611624565b60008c81526020902060005b8681101561161a5781548c82018b01529085019083016115ff565b505087858b010196505b50507f222c20226465736372697074696f6e223a20224f6e2d636861696e2053637261855250507f62626c65206279204f6d616b61736561222c2022696d616765223a2022646174602084015250507f613a696d6167652f7376672b786d6c3b6261736536342c00000000000000000060408201526116b76116a96057830187611512565b61227d60f01b815260020190565b9695505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516116f981601d8501602087016111ed565b91909101601d019291505056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302037303020373030223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a2033303070783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d222330303030303022202f3e3c7465787420783d223530252220793d223530252220636c6173733d22626173652220646f6d696e616e742d626173656c696e653d226d6964646c652220746578742d616e63686f723d226d6964646c65223ea26469706673582212205070edc3b0bf4f239cdf0839550a305448817f1ba98a86b4289eee2873a02c4264736f6c63430008130033
Deployed Bytecode
0x6080604052600436106101395760003560e01c806370a08231116100ab578063a22cb4651161006f578063a22cb465146103dc578063b88d4fde146103fc578063c4c7bca01461041c578063c87b56dd14610432578063e985e9c514610452578063f2fde38b1461048d57600080fd5b806370a08231146103545780638da5cb5b146103745780638f64be301461039457806395d89b41146103b4578063a0712d68146103c957600080fd5b806328d911fb116100fd57806328d911fb146102a657806332cb6b0c146102c65780633ccfd60b146102e957806342842e0e146102fe57806346aa52ce1461031e5780636352211e1461033457600080fd5b806301ffc9a7146101c157806306fdde03146101f6578063081812fc14610218578063095ea7b31461026657806323b872dd1461028657600080fd5b366101bc5760006008543461014e919061117a565b9050346008548261015f919061119c565b146101b15760405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420616d6f756e74206f662065746865722073656e740000000060448201526064015b60405180910390fd5b6101ba816104ad565b005b600080fd5b3480156101cd57600080fd5b506101e16101dc3660046111c9565b610597565b60405190151581526020015b60405180910390f35b34801561020257600080fd5b5061020b6105e9565b6040516101ed9190611211565b34801561022457600080fd5b5061024e610233366004611244565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016101ed565b34801561027257600080fd5b506101ba610281366004611274565b610677565b34801561029257600080fd5b506101ba6102a136600461129e565b610759565b3480156102b257600080fd5b506101ba6102c1366004611244565b610920565b3480156102d257600080fd5b506102db606281565b6040519081526020016101ed565b3480156102f557600080fd5b506101ba61094f565b34801561030a57600080fd5b506101ba61031936600461129e565b6109a8565b34801561032a57600080fd5b506102db60095481565b34801561034057600080fd5b5061024e61034f366004611244565b610aa0565b34801561036057600080fd5b506102db61036f3660046112da565b610af7565b34801561038057600080fd5b5060065461024e906001600160a01b031681565b3480156103a057600080fd5b5061020b6103af366004611244565b610b5a565b3480156103c057600080fd5b5061020b610b85565b6101ba6103d7366004611244565b6104ad565b3480156103e857600080fd5b506101ba6103f73660046112f5565b610b92565b34801561040857600080fd5b506101ba610417366004611331565b610bfe565b34801561042857600080fd5b506102db60085481565b34801561043e57600080fd5b5061020b61044d366004611244565b610ce6565b34801561045e57600080fd5b506101e161046d3660046113cc565b600560209081526000928352604080842090915290825290205460ff1681565b34801561049957600080fd5b506101ba6104a83660046112da565b610ec6565b6062816009546104bd91906113ff565b11156105005760405162461bcd60e51b815260206004820152601260248201527113585e081cdd5c1c1b1e481c995858da195960721b60448201526064016101a8565b8060085461050e919061119c565b34146105545760405162461bcd60e51b8152602060048201526015602482015274139bdd08195b9bdd59da08195d1a195c881cd95b9d605a1b60448201526064016101a8565b60005b818110156105935761056b33600954610f3c565b6009805490600061057b83611412565b9190505550808061058b90611412565b915050610557565b5050565b60006301ffc9a760e01b6001600160e01b0319831614806105c857506380ac58cd60e01b6001600160e01b03198316145b806105e35750635b5e139f60e01b6001600160e01b03198316145b92915050565b600080546105f69061142b565b80601f01602080910402602001604051908101604052809291908181526020018280546106229061142b565b801561066f5780601f106106445761010080835404028352916020019161066f565b820191906000526020600020905b81548152906001019060200180831161065257829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b0316338114806106c057506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6106fd5760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016101a8565b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000818152600260205260409020546001600160a01b038481169116146107af5760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016101a8565b6001600160a01b0382166107f95760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064016101a8565b336001600160a01b038416148061083357506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b8061085457506000818152600460205260409020546001600160a01b031633145b6108915760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016101a8565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6006546001600160a01b0316331461094a5760405162461bcd60e51b81526004016101a890611465565b600855565b6006546001600160a01b031633146109795760405162461bcd60e51b81526004016101a890611465565b60405133904780156108fc02916000818181858888f193505050501580156109a5573d6000803e3d6000fd5b50565b6109b3838383610759565b6001600160a01b0382163b1580610a5c5750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610a2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a50919061148b565b6001600160e01b031916145b610a9b5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016101a8565b505050565b6000818152600260205260409020546001600160a01b031680610af25760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b60448201526064016101a8565b919050565b60006001600160a01b038216610b3e5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b60448201526064016101a8565b506001600160a01b031660009081526003602052604090205490565b60078181548110610b6a57600080fd5b9060005260206000200160009150905080546105f69061142b565b600180546105f69061142b565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610c09858585610759565b6001600160a01b0384163b1580610ca05750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290610c519033908a908990899089906004016114a8565b6020604051808303816000875af1158015610c70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c94919061148b565b6001600160e01b031916145b610cdf5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016101a8565b5050505050565b6060610cf061113c565b6040518061016001604052806101328152602001611707610132913981526007805484908110610d2257610d226114fc565b906000526020600020018054610d379061142b565b80601f0160208091040260200160405190810160405280929190818152602001828054610d639061142b565b8015610db05780601f10610d8557610100808354040283529160200191610db0565b820191906000526020600020905b815481529060010190602001808311610d9357829003601f168201915b505050505081600160088110610dc857610dc86114fc565b60200201819052506040518060400160405280600d81526020016c1e17ba32bc3a1f1e17b9bb339f60991b81525081600260088110610e0957610e096114fc565b602002015260008181602002015182600160200201518360026020020151604051602001610e399392919061152e565b60405160208183030381529060405290506000610e9a60078681548110610e6257610e626114fc565b90600052602060002001610e7584611047565b604051602001610e86929190611571565b604051602081830303815290604052611047565b905080604051602001610ead91906116c1565b60408051601f1981840301815291905295945050505050565b6006546001600160a01b03163314610ef05760405162461bcd60e51b81526004016101a890611465565b600680546001600160a01b0319166001600160a01b03831690811790915560405133907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b6001600160a01b038216610f865760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064016101a8565b6000818152600260205260409020546001600160a01b031615610fdc5760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b60448201526064016101a8565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60606105e382600080606083518015611134576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526102308515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f03603f52602083018181015b6003880197508751603f8160121c1651600053603f81600c1c1651600153603f8160061c1651600253603f8116516003535060005182526004820191508082106110c057601f01601f1916604052613d3d60f01b600384066002048083039190915260008615159091029182900352900382525b509392505050565b6040518061010001604052806008905b606081526020019060019003908161114c5790505090565b634e487b7160e01b600052601160045260246000fd5b60008261119757634e487b7160e01b600052601260045260246000fd5b500490565b80820281158282048414176105e3576105e3611164565b6001600160e01b0319811681146109a557600080fd5b6000602082840312156111db57600080fd5b81356111e6816111b3565b9392505050565b60005b838110156112085781810151838201526020016111f0565b50506000910152565b60208152600082518060208401526112308160408501602087016111ed565b601f01601f19169190910160400192915050565b60006020828403121561125657600080fd5b5035919050565b80356001600160a01b0381168114610af257600080fd5b6000806040838503121561128757600080fd5b6112908361125d565b946020939093013593505050565b6000806000606084860312156112b357600080fd5b6112bc8461125d565b92506112ca6020850161125d565b9150604084013590509250925092565b6000602082840312156112ec57600080fd5b6111e68261125d565b6000806040838503121561130857600080fd5b6113118361125d565b91506020830135801515811461132657600080fd5b809150509250929050565b60008060008060006080868803121561134957600080fd5b6113528661125d565b94506113606020870161125d565b935060408601359250606086013567ffffffffffffffff8082111561138457600080fd5b818801915088601f83011261139857600080fd5b8135818111156113a757600080fd5b8960208285010111156113b957600080fd5b9699959850939650602001949392505050565b600080604083850312156113df57600080fd5b6113e88361125d565b91506113f66020840161125d565b90509250929050565b808201808211156105e3576105e3611164565b60006001820161142457611424611164565b5060010190565b600181811c9082168061143f57607f821691505b60208210810361145f57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b60006020828403121561149d57600080fd5b81516111e6816111b3565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b634e487b7160e01b600052603260045260246000fd5b600081516115248185602086016111ed565b9290920192915050565b600084516115408184602089016111ed565b8451908301906115548183602089016111ed565b84519101906115678183602088016111ed565b0195945050505050565b7003d913730b6b2911d10112834b2b1b29d1607d1b815282546000906011908290600181811c90808316806115a757607f831692505b602080841082036115c657634e487b7160e01b86526022600452602486fd5b8180156115da57600181146115f357611624565b60ff1986168a89015284151585028a0188019650611624565b60008c81526020902060005b8681101561161a5781548c82018b01529085019083016115ff565b505087858b010196505b50507f222c20226465736372697074696f6e223a20224f6e2d636861696e2053637261855250507f62626c65206279204f6d616b61736561222c2022696d616765223a2022646174602084015250507f613a696d6167652f7376672b786d6c3b6261736536342c00000000000000000060408201526116b76116a96057830187611512565b61227d60f01b815260020190565b9695505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516116f981601d8501602087016111ed565b91909101601d019291505056fe3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207072657365727665417370656374526174696f3d22784d696e594d696e206d656574222076696577426f783d223020302037303020373030223e3c7374796c653e2e62617365207b2066696c6c3a2077686974653b20666f6e742d66616d696c793a2073657269663b20666f6e742d73697a653a2033303070783b207d3c2f7374796c653e3c726563742077696474683d223130302522206865696768743d2231303025222066696c6c3d222330303030303022202f3e3c7465787420783d223530252220793d223530252220636c6173733d22626173652220646f6d696e616e742d626173656c696e653d226d6964646c652220746578742d616e63686f723d226d6964646c65223ea26469706673582212205070edc3b0bf4f239cdf0839550a305448817f1ba98a86b4289eee2873a02c4264736f6c63430008130033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.