Source Code
Overview
FRAX Balance
0 FRAX
More Info
ContractCreator
Multichain Info
N/A
Loading...
Loading
Contract Name:
L1BlockCGT
Compiler Version
v0.8.15+commit.e14f2714
Contract Source Code (Solidity)
/** *Submitted for verification at holesky.fraxscan.com on 2025-03-26 */ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; // lib/optimism/packages/contracts-bedrock/lib/solady/src/utils/LibString.sol /// @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) /// /// 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(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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 { mstore(0x00, 0x2194895a) // `HexLengthInsufficient()`. 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 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) // Write 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)) // Write 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)) // Write 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) // 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 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) // 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, 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) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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. // Allocate the memory. mstore(0x40, add(result, add(resultLength, 0x20))) } } } /// @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) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(result, and(add(resultLength, 0x3f), 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, 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) // 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, 0x1f), w)) } } /// @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) let o := add(result, 0x20) mstore(o, s) mstore(add(o, n), 0) mstore(0x40, add(result, 0x40)) } } /// @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 { // 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 behavior 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) } } } // lib/optimism/packages/contracts-bedrock/src/L1/interfaces/IResourceMetering.sol interface IResourceMetering { struct ResourceParams { uint128 prevBaseFee; uint64 prevBoughtGas; uint64 prevBlockNum; } struct ResourceConfig { uint32 maxResourceLimit; uint8 elasticityMultiplier; uint8 baseFeeMaxChangeDenominator; uint32 minimumBaseFee; uint32 systemTxMaxGas; uint128 maximumBaseFee; } error OutOfGas(); event Initialized(uint8 version); function params() external view returns (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum); // nosemgrep function __constructor__() external; } // lib/optimism/packages/contracts-bedrock/src/libraries/L1BlockErrors.sol /// @notice Error returns when a non-depositor account tries to set L1 block values. error NotDepositor(); /// @notice Error when a non-cross L2 Inbox sender tries to call the `isDeposit()` method. error NotCrossL2Inbox(); /// @notice Error when a chain ID is not in the interop dependency set. error NotDependency(); /// @notice Error when the interop dependency set size is too large. error DependencySetSizeTooLarge(); /// @notice Error when a chain ID already in the interop dependency set is attempted to be added. error AlreadyDependency(); /// @notice Error when the chain's chain ID is attempted to be removed from the interop dependency set. error CantRemovedDependency(); // lib/optimism/packages/contracts-bedrock/src/libraries/Storage.sol /// @title Storage /// @notice Storage handles reading and writing to arbitary storage locations library Storage { /// @notice Returns an address stored in an arbitrary storage slot. /// These storage slots decouple the storage layout from /// solc's automation. /// @param _slot The storage slot to retrieve the address from. function getAddress(bytes32 _slot) internal view returns (address addr_) { assembly { addr_ := sload(_slot) } } /// @notice Stores an address in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the address in. /// @param _address The protocol version to store /// @dev WARNING! This function must be used cautiously, as it allows for overwriting addresses /// in arbitrary storage slots. function setAddress(bytes32 _slot, address _address) internal { assembly { sstore(_slot, _address) } } /// @notice Returns a uint256 stored in an arbitrary storage slot. /// These storage slots decouple the storage layout from /// solc's automation. /// @param _slot The storage slot to retrieve the address from. function getUint(bytes32 _slot) internal view returns (uint256 value_) { assembly { value_ := sload(_slot) } } /// @notice Stores a value in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the address in. /// @param _value The protocol version to store /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values /// in arbitrary storage slots. function setUint(bytes32 _slot, uint256 _value) internal { assembly { sstore(_slot, _value) } } /// @notice Returns a bytes32 stored in an arbitrary storage slot. /// These storage slots decouple the storage layout from /// solc's automation. /// @param _slot The storage slot to retrieve the address from. function getBytes32(bytes32 _slot) internal view returns (bytes32 value_) { assembly { value_ := sload(_slot) } } /// @notice Stores a bytes32 value in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the address in. /// @param _value The bytes32 value to store. /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values /// in arbitrary storage slots. function setBytes32(bytes32 _slot, bytes32 _value) internal { assembly { sstore(_slot, _value) } } /// @notice Stores a bool value in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the bool in. /// @param _value The bool value to store /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values /// in arbitrary storage slots. function setBool(bytes32 _slot, bool _value) internal { assembly { sstore(_slot, _value) } } /// @notice Returns a bool stored in an arbitrary storage slot. /// @param _slot The storage slot to retrieve the bool from. function getBool(bytes32 _slot) internal view returns (bool value_) { assembly { value_ := sload(_slot) } } } // lib/optimism/packages/contracts-bedrock/src/universal/interfaces/ISemver.sol /// @title ISemver /// @notice ISemver is a simple contract for ensuring that contracts are /// versioned using semantic versioning. interface ISemver { /// @notice Getter for the semantic version of the contract. This is not /// meant to be used onchain but instead meant to be used by offchain /// tooling. /// @return Semver contract version as a string. function version() external view returns (string memory); } // lib/optimism/packages/contracts-bedrock/src/libraries/Constants.sol /// @title Constants /// @notice Constants is a library for storing constants. Simple! Don't put everything in here, just /// the stuff used in multiple contracts. Constants that only apply to a single contract /// should be defined in that contract instead. library Constants { /// @notice Special address to be used as the tx origin for gas estimation calls in the /// OptimismPortal and CrossDomainMessenger calls. You only need to use this address if /// the minimum gas limit specified by the user is not actually enough to execute the /// given message and you're attempting to estimate the actual necessary gas limit. We /// use address(1) because it's the ecrecover precompile and therefore guaranteed to /// never have any code on any EVM chain. address internal constant ESTIMATION_ADDRESS = address(1); /// @notice Value used for the L2 sender storage slot in both the OptimismPortal and the /// CrossDomainMessenger contracts before an actual sender is set. This value is /// non-zero to reduce the gas cost of message passing transactions. address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; /// @notice The storage slot that holds the address of a proxy implementation. /// @dev `bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)` bytes32 internal constant PROXY_IMPLEMENTATION_ADDRESS = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /// @notice The storage slot that holds the address of the owner. /// @dev `bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)` bytes32 internal constant PROXY_OWNER_ADDRESS = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /// @notice The address that represents ether when dealing with ERC20 token addresses. address internal constant ETHER = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /// @notice The address that represents the system caller responsible for L1 attributes /// transactions. address internal constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; /// @notice Returns the default values for the ResourceConfig. These are the recommended values /// for a production network. function DEFAULT_RESOURCE_CONFIG() internal pure returns (IResourceMetering.ResourceConfig memory) { IResourceMetering.ResourceConfig memory config = IResourceMetering.ResourceConfig({ maxResourceLimit: 20_000_000, elasticityMultiplier: 10, baseFeeMaxChangeDenominator: 8, minimumBaseFee: 1 gwei, systemTxMaxGas: 1_000_000, maximumBaseFee: type(uint128).max }); return config; } } // lib/optimism/packages/contracts-bedrock/src/libraries/GasPayingToken.sol /// @title IGasToken /// @notice Implemented by contracts that are aware of the custom gas token used /// by the L2 network. interface IGasToken { /// @notice Getter for the ERC20 token address that is used to pay for gas and its decimals. function gasPayingToken() external view returns (address, uint8); /// @notice Returns the gas token name. function gasPayingTokenName() external view returns (string memory); /// @notice Returns the gas token symbol. function gasPayingTokenSymbol() external view returns (string memory); /// @notice Returns true if the network uses a custom gas token. function isCustomGasToken() external view returns (bool); } /// @title GasPayingToken /// @notice Handles reading and writing the custom gas token to storage. /// To be used in any place where gas token information is read or /// written to state. If multiple contracts use this library, the /// values in storage should be kept in sync between them. library GasPayingToken { /// @notice The storage slot that contains the address and decimals of the gas paying token bytes32 internal constant GAS_PAYING_TOKEN_SLOT = bytes32(uint256(keccak256("opstack.gaspayingtoken")) - 1); /// @notice The storage slot that contains the ERC20 `name()` of the gas paying token bytes32 internal constant GAS_PAYING_TOKEN_NAME_SLOT = bytes32(uint256(keccak256("opstack.gaspayingtokenname")) - 1); /// @notice the storage slot that contains the ERC20 `symbol()` of the gas paying token bytes32 internal constant GAS_PAYING_TOKEN_SYMBOL_SLOT = bytes32(uint256(keccak256("opstack.gaspayingtokensymbol")) - 1); /// @notice Reads the gas paying token and its decimals from the magic /// storage slot. If nothing is set in storage, then the ether /// address is returned instead. function getToken() internal view returns (address addr_, uint8 decimals_) { bytes32 slot = Storage.getBytes32(GAS_PAYING_TOKEN_SLOT); addr_ = address(uint160(uint256(slot) & uint256(type(uint160).max))); if (addr_ == address(0)) { addr_ = Constants.ETHER; decimals_ = 18; } else { decimals_ = uint8(uint256(slot) >> 160); } } /// @notice Reads the gas paying token's name from the magic storage slot. /// If nothing is set in storage, then the ether name, 'Ether', is returned instead. function getName() internal view returns (string memory name_) { (address addr,) = getToken(); if (addr == Constants.ETHER) { name_ = "Ether"; } else { name_ = LibString.fromSmallString(Storage.getBytes32(GAS_PAYING_TOKEN_NAME_SLOT)); } } /// @notice Reads the gas paying token's symbol from the magic storage slot. /// If nothing is set in storage, then the ether symbol, 'ETH', is returned instead. function getSymbol() internal view returns (string memory symbol_) { (address addr,) = getToken(); if (addr == Constants.ETHER) { symbol_ = "ETH"; } else { symbol_ = LibString.fromSmallString(Storage.getBytes32(GAS_PAYING_TOKEN_SYMBOL_SLOT)); } } /// @notice Writes the gas paying token, its decimals, name and symbol to the magic storage slot. function set(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) internal { Storage.setBytes32(GAS_PAYING_TOKEN_SLOT, bytes32(uint256(_decimals) << 160 | uint256(uint160(_token)))); Storage.setBytes32(GAS_PAYING_TOKEN_NAME_SLOT, _name); Storage.setBytes32(GAS_PAYING_TOKEN_SYMBOL_SLOT, _symbol); } /// @notice Maps a string to a normalized null-terminated small string. function sanitize(string memory _str) internal pure returns (bytes32) { require(bytes(_str).length <= 32, "GasPayingToken: string cannot be greater than 32 bytes"); return LibString.toSmallString(_str); } } // src/contracts/Fraxtal/L2/L1BlockCGT.sol /// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000015 /// @title L1Block /// @notice The L1Block predeploy gives users access to information about the last known L1 block. /// Values within this contract are updated once per epoch (every L1 block) and can only be /// set by the "depositor" account, a special system address. Depositor account transactions /// are created by the protocol whenever we move to a new epoch. contract L1BlockCGT is ISemver, IGasToken { /// @notice Event emitted when the gas paying token is set. event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol); /// @notice Address of the special depositor account. function DEPOSITOR_ACCOUNT() public pure returns (address addr_) { addr_ = Constants.DEPOSITOR_ACCOUNT; } /// @notice The latest L1 block number known by the L2 system. uint64 public number; /// @notice The latest L1 timestamp known by the L2 system. uint64 public timestamp; /// @notice The latest L1 base fee. uint256 public basefee; /// @notice The latest L1 blockhash. bytes32 public hash; /// @notice The number of L2 blocks in the same epoch. uint64 public sequenceNumber; /// @notice The scalar value applied to the L1 blob base fee portion of the blob-capable L1 cost func. uint32 public blobBaseFeeScalar; /// @notice The scalar value applied to the L1 base fee portion of the blob-capable L1 cost func. uint32 public baseFeeScalar; /// @notice The versioned hash to authenticate the batcher by. bytes32 public batcherHash; /// @notice The overhead value applied to the L1 portion of the transaction fee. /// @custom:legacy uint256 public l1FeeOverhead; /// @notice The scalar value applied to the L1 portion of the transaction fee. /// @custom:legacy uint256 public l1FeeScalar; /// @notice The latest L1 blob base fee. uint256 public blobBaseFee; /// @custom:semver 1.5.1-beta.3 string public constant version = "1.5.1-beta.3"; /// @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades of the L1Block contract. /// @dev Added by Frax Finance uint256[42] private __gap; /// @notice Mapping from blockHash to bool that it written after a block hash is received from L1 /// @dev Added by Frax Finance mapping(bytes32 => bool) public storedBlockHashes; /// @notice The ```BlockHashReceived``` event is emitted when a block hash is received /// @dev Added by Frax Finance /// @param blockHash A block hash of a L1 block event BlockHashReceived(bytes32 blockHash); /// @notice Returns the gas paying token, its decimals, name and symbol. /// If nothing is set in state, then it means ether is used. function gasPayingToken() public view returns (address addr_, uint8 decimals_) { (addr_, decimals_) = GasPayingToken.getToken(); } /// @notice Returns the gas paying token name. /// If nothing is set in state, then it means ether is used. function gasPayingTokenName() public view returns (string memory name_) { name_ = GasPayingToken.getName(); } /// @notice Returns the gas paying token symbol. /// If nothing is set in state, then it means ether is used. function gasPayingTokenSymbol() public view returns (string memory symbol_) { symbol_ = GasPayingToken.getSymbol(); } /// @notice Getter for custom gas token paying networks. Returns true if the /// network uses a custom gas token. function isCustomGasToken() public view returns (bool) { (address token, ) = gasPayingToken(); return token != Constants.ETHER; } /// @custom:legacy /// @notice Updates the L1 block values. /// @param _number L1 blocknumber. /// @param _timestamp L1 timestamp. /// @param _basefee L1 basefee. /// @param _hash L1 blockhash. /// @param _sequenceNumber Number of L2 blocks since epoch start. /// @param _batcherHash Versioned hash to authenticate batcher by. /// @param _l1FeeOverhead L1 fee overhead. /// @param _l1FeeScalar L1 fee scalar. function setL1BlockValues( uint64 _number, uint64 _timestamp, uint256 _basefee, bytes32 _hash, uint64 _sequenceNumber, bytes32 _batcherHash, uint256 _l1FeeOverhead, uint256 _l1FeeScalar ) external { require(msg.sender == DEPOSITOR_ACCOUNT(), "L1Block: only the depositor account can set L1 block values"); number = _number; timestamp = _timestamp; basefee = _basefee; hash = _hash; sequenceNumber = _sequenceNumber; batcherHash = _batcherHash; l1FeeOverhead = _l1FeeOverhead; l1FeeScalar = _l1FeeScalar; // Don't write state or emit event again if we already stored this hash /// @dev Added by Frax Finance if (!storedBlockHashes[_hash]) { storedBlockHashes[_hash] = true; emit BlockHashReceived(_hash); } } /// @notice The ```blockHashStored``` function returns if the _blockHash is stored or not /// @param _blockHash The block hash /// @return _result A bool representing if the _blockHash is stored or not function blockHashStored(bytes32 _blockHash) external view returns (bool _result) { _result = storedBlockHashes[_blockHash]; } /// @notice Updates the L1 block values for an Ecotone upgraded chain. /// Params are packed and passed in as raw msg.data instead of ABI to reduce calldata size. /// Params are expected to be in the following order: /// 1. _baseFeeScalar L1 base fee scalar /// 2. _blobBaseFeeScalar L1 blob base fee scalar /// 3. _sequenceNumber Number of L2 blocks since epoch start. /// 4. _timestamp L1 timestamp. /// 5. _number L1 blocknumber. /// 6. _basefee L1 base fee. /// 7. _blobBaseFee L1 blob base fee. /// 8. _hash L1 blockhash. /// 9. _batcherHash Versioned hash to authenticate batcher by. function setL1BlockValuesEcotone() public { _setL1BlockValuesEcotone(); } /// @notice Updates the L1 block values for an Ecotone upgraded chain. /// Params are packed and passed in as raw msg.data instead of ABI to reduce calldata size. /// Params are expected to be in the following order: /// 1. _baseFeeScalar L1 base fee scalar /// 2. _blobBaseFeeScalar L1 blob base fee scalar /// 3. _sequenceNumber Number of L2 blocks since epoch start. /// 4. _timestamp L1 timestamp. /// 5. _number L1 blocknumber. /// 6. _basefee L1 base fee. /// 7. _blobBaseFee L1 blob base fee. /// 8. _hash L1 blockhash. /// 9. _batcherHash Versioned hash to authenticate batcher by. function _setL1BlockValuesEcotone() internal { bytes32 eventHash = bytes32(keccak256("BlockHashReceived(bytes32)")); // Added by Frax Finance address depositor = DEPOSITOR_ACCOUNT(); assembly { // Revert if the caller is not the depositor account. if xor(caller(), depositor) { mstore(0x00, 0x3cc50b45) // 0x3cc50b45 is the 4-byte selector of "NotDepositor()" revert(0x1C, 0x04) // returns the stored 4-byte selector from above } // Added by Frax Finance // sequencenum (uint64), blobBaseFeeScalar (uint32), baseFeeScalar (uint32) sstore(sequenceNumber.slot, shr(128, calldataload(4))) // number (uint64) and timestamp (uint64) sstore(number.slot, shr(128, calldataload(20))) sstore(basefee.slot, calldataload(36)) // uint256 sstore(blobBaseFee.slot, calldataload(68)) // uint256 sstore(hash.slot, calldataload(100)) // bytes32 sstore(batcherHash.slot, calldataload(132)) // bytes32 // Added by Frax Finance /// @dev Added by Frax Finance // load the L1 blockhash to memory mstore(0, calldataload(100)) // bytes32 // load the storage slot of storedBlockHashes to memory mstore(32, 50) // for clarity - same as storedBlackHashes.slot // Get the hash of the memory for the mapping key let key := keccak256(0, 64) // Update mapping only if the mapping has not yet been updated if eq(sload(key), false) { // Set the mapping to true sstore(key, true) // Emit the event of the blockhash from memory log1(0, 32, eventHash) } } } /// @notice Sets the gas paying token for the L2 system. Can only be called by the special /// depositor account. This function is not called on every L2 block but instead /// only called by specially crafted L1 deposit transactions. function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external { if (msg.sender != DEPOSITOR_ACCOUNT()) revert NotDepositor(); GasPayingToken.set({ _token: _token, _decimals: _decimals, _name: _name, _symbol: _symbol }); emit GasPayingTokenSet({ token: _token, decimals: _decimals, name: _name, symbol: _symbol }); } }
Contract ABI
API[{"inputs":[],"name":"NotDepositor","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"blockHash","type":"bytes32"}],"name":"BlockHashReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint8","name":"decimals","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"symbol","type":"bytes32"}],"name":"GasPayingTokenSet","type":"event"},{"inputs":[],"name":"DEPOSITOR_ACCOUNT","outputs":[{"internalType":"address","name":"addr_","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"baseFeeScalar","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"basefee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"batcherHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blobBaseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blobBaseFeeScalar","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_blockHash","type":"bytes32"}],"name":"blockHashStored","outputs":[{"internalType":"bool","name":"_result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasPayingToken","outputs":[{"internalType":"address","name":"addr_","type":"address"},{"internalType":"uint8","name":"decimals_","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasPayingTokenName","outputs":[{"internalType":"string","name":"name_","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasPayingTokenSymbol","outputs":[{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isCustomGasToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l1FeeOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l1FeeScalar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"number","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sequenceNumber","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"bytes32","name":"_name","type":"bytes32"},{"internalType":"bytes32","name":"_symbol","type":"bytes32"}],"name":"setGasPayingToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_number","type":"uint64"},{"internalType":"uint64","name":"_timestamp","type":"uint64"},{"internalType":"uint256","name":"_basefee","type":"uint256"},{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"uint64","name":"_sequenceNumber","type":"uint64"},{"internalType":"bytes32","name":"_batcherHash","type":"bytes32"},{"internalType":"uint256","name":"_l1FeeOverhead","type":"uint256"},{"internalType":"uint256","name":"_l1FeeScalar","type":"uint256"}],"name":"setL1BlockValues","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setL1BlockValuesEcotone","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"storedBlockHashes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timestamp","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50610c44806100206000396000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c80638178856b116100d8578063c59859181161008c578063e81b2c6d11610066578063e81b2c6d1461038c578063ebe86a5514610395578063f8206140146103b857600080fd5b8063c598591814610342578063d844471514610362578063e591b2821461036a57600080fd5b80638b239f73116100bd5780638b239f73146103105780639e8c496614610319578063b80777ea1461032257600080fd5b80638178856b146102d95780638381f58a146102fc57600080fd5b806354fd4d501161013a57806364ca23ef1161011457806364ca23ef1461026857806368d5dca61461029557806371cfaa3f146102c657600080fd5b806354fd4d501461020e578063550fcdc9146102575780635cf249691461025f57600080fd5b8063213268491161016b57806321326849146101b85780634397dfef146101d0578063440a5e201461020657600080fd5b8063015d8eb91461018757806309bd5a601461019c575b600080fd5b61019a610195366004610a6d565b6103c1565b005b6101a560025481565b6040519081526020015b60405180910390f35b6101c0610589565b60405190151581526020016101af565b6101d86105c8565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016101af565b61019a6105dc565b61024a6040518060400160405280600c81526020017f312e352e312d626574612e33000000000000000000000000000000000000000081525081565b6040516101af9190610adf565b61024a6105e6565b6101a560015481565b60035461027c9067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101af565b6003546102b19068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016101af565b61019a6102d4366004610b52565b6105f5565b6101c06102e7366004610bb7565b60326020526000908152604090205460ff1681565b60005461027c9067ffffffffffffffff1681565b6101a560055481565b6101a560065481565b60005461027c9068010000000000000000900467ffffffffffffffff1681565b6003546102b1906c01000000000000000000000000900463ffffffff1681565b61024a6106aa565b60405173deaddeaddeaddeaddeaddeaddeaddeaddead000181526020016101af565b6101a560045481565b6101c06103a3366004610bb7565b60009081526032602052604090205460ff1690565b6101a560075481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610468576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff8a81167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117680100000000000000008a83160217825560018890556002879055600380547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169187169190911790556004849055600583905560068290558581526032602052604090205460ff1661057f576000858152603260205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f12cb9a47c977b6cbe82b9e495407e99a32a54bca6b26f1e4d497a3a42dccb914906105769087815260200190565b60405180910390a15b5050505050505050565b6000806105946105c8565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b6000806105d36106b4565b90939092509050565b6105e4610735565b565b60606105f06107d3565b905090565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610642576040517f3cc50b4500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61064e84848484610894565b604080518381526020810183905260ff85169173ffffffffffffffffffffffffffffffffffffffff8716917f10e43c4d58f3ef4edae7c1ca2e7f02d46b2cadbcc046737038527ed8486ffeb0910160405180910390a350505050565b60606105f0610966565b600080806106ea6106e660017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec610bd0565b5490565b73ffffffffffffffffffffffffffffffffffffffff81169350905082610729575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b7f12cb9a47c977b6cbe82b9e495407e99a32a54bca6b26f1e4d497a3a42dccb91473deaddeaddeaddeaddeaddeaddeaddeaddead000133811461078057633cc50b456000526004601cfd5b60043560801c60035560143560801c6000556024356001556044356007556064356002556084356004556064356000526032602052604060002060008154036107ce57600181558260206000a15b505050565b606060006107df6106b4565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161085857505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61088e6108896106e660017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd05764610bd0565b610a1c565b91505090565b6108fa6108c260017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec610bd0565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61092d61092860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d610bd0565b839055565b61096061095b60017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd05764610bd0565b829055565b50505050565b606060006109726106b4565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016109eb57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61088e6108896106e660017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d610bd0565b60405160005b82811a15610a3257600101610a22565b80825260208201838152600082820152505060408101604052919050565b803567ffffffffffffffff81168114610a6857600080fd5b919050565b600080600080600080600080610100898b031215610a8a57600080fd5b610a9389610a50565b9750610aa160208a01610a50565b96506040890135955060608901359450610abd60808a01610a50565b979a969950949793969560a0850135955060c08501359460e001359350915050565b600060208083528351808285015260005b81811015610b0c57858101830151858201604001528201610af0565b81811115610b1e576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008060008060808587031215610b6857600080fd5b843573ffffffffffffffffffffffffffffffffffffffff81168114610b8c57600080fd5b9350602085013560ff81168114610ba257600080fd5b93969395505050506040820135916060013590565b600060208284031215610bc957600080fd5b5035919050565b600082821015610c09577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea2646970667358221220a4b6ebb429b77a4a657330536ffd3215f7c620ebadbe69b9159d567733fe3a0764736f6c634300080f0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101825760003560e01c80638178856b116100d8578063c59859181161008c578063e81b2c6d11610066578063e81b2c6d1461038c578063ebe86a5514610395578063f8206140146103b857600080fd5b8063c598591814610342578063d844471514610362578063e591b2821461036a57600080fd5b80638b239f73116100bd5780638b239f73146103105780639e8c496614610319578063b80777ea1461032257600080fd5b80638178856b146102d95780638381f58a146102fc57600080fd5b806354fd4d501161013a57806364ca23ef1161011457806364ca23ef1461026857806368d5dca61461029557806371cfaa3f146102c657600080fd5b806354fd4d501461020e578063550fcdc9146102575780635cf249691461025f57600080fd5b8063213268491161016b57806321326849146101b85780634397dfef146101d0578063440a5e201461020657600080fd5b8063015d8eb91461018757806309bd5a601461019c575b600080fd5b61019a610195366004610a6d565b6103c1565b005b6101a560025481565b6040519081526020015b60405180910390f35b6101c0610589565b60405190151581526020016101af565b6101d86105c8565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016101af565b61019a6105dc565b61024a6040518060400160405280600c81526020017f312e352e312d626574612e33000000000000000000000000000000000000000081525081565b6040516101af9190610adf565b61024a6105e6565b6101a560015481565b60035461027c9067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101af565b6003546102b19068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016101af565b61019a6102d4366004610b52565b6105f5565b6101c06102e7366004610bb7565b60326020526000908152604090205460ff1681565b60005461027c9067ffffffffffffffff1681565b6101a560055481565b6101a560065481565b60005461027c9068010000000000000000900467ffffffffffffffff1681565b6003546102b1906c01000000000000000000000000900463ffffffff1681565b61024a6106aa565b60405173deaddeaddeaddeaddeaddeaddeaddeaddead000181526020016101af565b6101a560045481565b6101c06103a3366004610bb7565b60009081526032602052604090205460ff1690565b6101a560075481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610468576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff8a81167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117680100000000000000008a83160217825560018890556002879055600380547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169187169190911790556004849055600583905560068290558581526032602052604090205460ff1661057f576000858152603260205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f12cb9a47c977b6cbe82b9e495407e99a32a54bca6b26f1e4d497a3a42dccb914906105769087815260200190565b60405180910390a15b5050505050505050565b6000806105946105c8565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b6000806105d36106b4565b90939092509050565b6105e4610735565b565b60606105f06107d3565b905090565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610642576040517f3cc50b4500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61064e84848484610894565b604080518381526020810183905260ff85169173ffffffffffffffffffffffffffffffffffffffff8716917f10e43c4d58f3ef4edae7c1ca2e7f02d46b2cadbcc046737038527ed8486ffeb0910160405180910390a350505050565b60606105f0610966565b600080806106ea6106e660017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec610bd0565b5490565b73ffffffffffffffffffffffffffffffffffffffff81169350905082610729575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b7f12cb9a47c977b6cbe82b9e495407e99a32a54bca6b26f1e4d497a3a42dccb91473deaddeaddeaddeaddeaddeaddeaddeaddead000133811461078057633cc50b456000526004601cfd5b60043560801c60035560143560801c6000556024356001556044356007556064356002556084356004556064356000526032602052604060002060008154036107ce57600181558260206000a15b505050565b606060006107df6106b4565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161085857505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61088e6108896106e660017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd05764610bd0565b610a1c565b91505090565b6108fa6108c260017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec610bd0565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61092d61092860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d610bd0565b839055565b61096061095b60017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd05764610bd0565b829055565b50505050565b606060006109726106b4565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016109eb57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61088e6108896106e660017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d610bd0565b60405160005b82811a15610a3257600101610a22565b80825260208201838152600082820152505060408101604052919050565b803567ffffffffffffffff81168114610a6857600080fd5b919050565b600080600080600080600080610100898b031215610a8a57600080fd5b610a9389610a50565b9750610aa160208a01610a50565b96506040890135955060608901359450610abd60808a01610a50565b979a969950949793969560a0850135955060c08501359460e001359350915050565b600060208083528351808285015260005b81811015610b0c57858101830151858201604001528201610af0565b81811115610b1e576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008060008060808587031215610b6857600080fd5b843573ffffffffffffffffffffffffffffffffffffffff81168114610b8c57600080fd5b9350602085013560ff81168114610ba257600080fd5b93969395505050506040820135916060013590565b600060208284031215610bc957600080fd5b5035919050565b600082821015610c09577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea2646970667358221220a4b6ebb429b77a4a657330536ffd3215f7c620ebadbe69b9159d567733fe3a0764736f6c634300080f0033
Deployed Bytecode Sourcemap
66547:9345:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70481:936;;;;;;:::i;:::-;;:::i;:::-;;67264:19;;;;;;;;;1014:25:1;;;1002:2;987:18;67264:19:0;;;;;;;;69825:152;;;:::i;:::-;;;1215:14:1;;1208:22;1190:41;;1178:2;1163:18;69825:152:0;1050:187:1;69017:144:0;;;:::i;:::-;;;;1442:42:1;1430:55;;;1412:74;;1534:4;1522:17;;;1517:2;1502:18;;1495:45;1385:18;69017:144:0;1242:304:1;72528:87:0;;;:::i;68187:47::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;69554:131::-;;;:::i;67191:22::-;;;;;;67352:28;;;;;;;;;;;;2568:18:1;2556:31;;;2538:50;;2526:2;2511:18;67352:28:0;2394:200:1;67497:31:0;;;;;;;;;;;;;;;2773:10:1;2761:23;;;2743:42;;2731:2;2716:18;67497:31:0;2599:192:1;75499:390:0;;;;;;:::i;:::-;;:::i;68575:49::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;67024:20;;;;;;;;;67889:28;;;;;;68034:26;;;;;;67118:23;;;;;;;;;;;;67640:27;;;;;;;;;;;;69295:123;;;:::i;66829:119::-;;;61146:42;3743:74:1;;3731:2;3716:18;66829:119:0;3597:226:1;67744:26:0;;;;;;71642:140;;;;;;:::i;:::-;71710:12;71745:29;;;:17;:29;;;;;;;;;71642:140;68115:26;;;;;;70481:936;70774:10;61146:42;70774:33;70766:105;;;;;;;4030:2:1;70766:105:0;;;4012:21:1;4069:2;4049:18;;;4042:30;4108:34;4088:18;;;4081:62;4179:29;4159:18;;;4152:57;4226:19;;70766:105:0;;;;;;;;70884:6;:16;;;;;;70911:22;;;;;;;;;;;;;;;;-1:-1:-1;70944:18:0;;;70973:4;:12;;;70996:14;:32;;70884:16;70996:32;;;;;;;;;;71039:11;:26;;;71076:13;:30;;;71117:11;:26;;;71282:24;;;:17;:24;;;;;;;;71277:133;;71323:24;;;;:17;:24;;;;;;;:31;;;;71350:4;71323:31;;;71374:24;;;;;71341:5;1014:25:1;;1002:2;987:18;;868:177;71374:24:0;;;;;;;;71277:133;70481:936;;;;;;;;:::o;69825:152::-;69874:4;69892:13;69911:16;:14;:16::i;:::-;-1:-1:-1;69945:24:0;;60925:42;69945:24;;;69825:152;-1:-1:-1;;69825:152:0:o;69017:144::-;69064:13;69079:15;69128:25;:23;:25::i;:::-;69107:46;;;;-1:-1:-1;69017:144:0;-1:-1:-1;69017:144:0:o;72528:87::-;72581:26;:24;:26::i;:::-;72528:87::o;69554:131::-;69607:21;69651:26;:24;:26::i;:::-;69641:36;;69554:131;:::o;75499:390::-;75615:10;61146:42;75615:33;75611:60;;75657:14;;;;;;;;;;;;;;75611:60;75684:92;75713:6;75732:9;75750:5;75766:7;75684:18;:92::i;:::-;75794:87;;;4430:25:1;;;4486:2;4471:18;;4464:34;;;75794:87:0;;;;;;;;;;4403:18:1;75794:87:0;;;;;;;75499:390;;;;:::o;69295:123::-;69346:19;69386:24;:22;:24::i;63831:415::-;63874:13;;;63932:41;63128:48;63175:1;63136:35;63128:48;:::i;:::-;57056:12;;56937:149;63932:41;64032:17;64008:42;;;-1:-1:-1;63917:56:0;-1:-1:-1;64008:42:0;64063:176;;-1:-1:-1;60925:42:0;;64153:2;;-1:-1:-1;63831:415:0;-1:-1:-1;63831:415:0:o;64063:176::-;64223:3;64206:20;;;;-1:-1:-1;63906:340:0;63831:415;;:::o;73361:1865::-;73445:39;61146:42;73669:8;73662:228;;;;73722:10;73716:4;73709:24;73821:4;73815;73808:18;73662:228;74081:1;74068:15;74063:3;74059:25;74038:19;74031:54;74196:2;74183:16;74178:3;74174:26;74161:11;74154:47;74249:2;74236:16;74222:12;74215:38;74316:2;74303:16;74285;74278:42;74376:3;74363:17;74352:9;74345:36;74444:3;74431:17;74413:16;74406:43;74629:3;74616:17;74613:1;74606:28;74739:2;74735;74728:14;74891:2;74888:1;74878:16;75002:5;74996:3;74990:10;74987:21;74984:224;;75084:4;75079:3;75072:17;75183:9;75179:2;75176:1;75171:22;74984:224;;73580:1639;;73361:1865::o;64925:313::-;64969:21;65004:12;65021:10;:8;:10::i;:::-;-1:-1:-1;65003:28:0;-1:-1:-1;65046:23:0;;;;;65042:189;;-1:-1:-1;;65086:15:0;;;;;;;;;;;;;;;;;;64925:313::o;65042:189::-;65144:75;65170:48;63569:54;63622:1;63577:41;63569:54;:::i;65170:48::-;65144:25;:75::i;:::-;65134:85;;64992:246;64925:313;:::o;65349:342::-;65447:104;63128:48;63175:1;63136:35;63128:48;:::i;:::-;65497:25;65519:3;65497:25;;;;65525:24;;;65497:52;57523:21;;57428:134;65447:104;65562:53;63340:52;63391:1;63348:39;63340:52;:::i;:::-;65609:5;57523:21;;57428:134;65562:53;65626:57;63569:54;63622:1;63577:41;63569:54;:::i;:::-;65675:7;57523:21;;57428:134;65626:57;65349:342;;;;:::o;64432:305::-;64474:19;64507:12;64524:10;:8;:10::i;:::-;-1:-1:-1;64506:28:0;-1:-1:-1;64549:23:0;;;;;64545:185;;-1:-1:-1;;64589:15:0;;;;;;;;;;;;;;;;;;64925:313::o;64545:185::-;64645:73;64671:46;63340:52;63391:1;63348:39;63340:52;:::i;41033:470::-;41209:4;41203:11;41237:1;41252:39;41267:1;41264;41259:10;41252:39;;;41284:1;41277:9;41252:39;;;41338:1;41330:6;41323:17;41375:4;41367:6;41363:17;41404:1;41401;41394:12;41438:1;41434;41431;41427:9;41420:20;;;41479:4;41471:6;41467:17;41461:4;41454:31;41033:470;;;:::o;14:171:1:-;81:20;;141:18;130:30;;120:41;;110:69;;175:1;172;165:12;110:69;14:171;;;:::o;190:673::-;309:6;317;325;333;341;349;357;365;418:3;406:9;397:7;393:23;389:33;386:53;;;435:1;432;425:12;386:53;458:28;476:9;458:28;:::i;:::-;448:38;;505:37;538:2;527:9;523:18;505:37;:::i;:::-;495:47;;589:2;578:9;574:18;561:32;551:42;;640:2;629:9;625:18;612:32;602:42;;663:38;696:3;685:9;681:19;663:38;:::i;:::-;190:673;;;;-1:-1:-1;190:673:1;;;;653:48;748:3;733:19;;720:33;;-1:-1:-1;800:3:1;785:19;;772:33;;852:3;837:19;824:33;;-1:-1:-1;190:673:1;-1:-1:-1;;190:673:1:o;1551:656::-;1663:4;1692:2;1721;1710:9;1703:21;1753:6;1747:13;1796:6;1791:2;1780:9;1776:18;1769:34;1821:1;1831:140;1845:6;1842:1;1839:13;1831:140;;;1940:14;;;1936:23;;1930:30;1906:17;;;1925:2;1902:26;1895:66;1860:10;;1831:140;;;1989:6;1986:1;1983:13;1980:91;;;2059:1;2054:2;2045:6;2034:9;2030:22;2026:31;2019:42;1980:91;-1:-1:-1;2123:2:1;2111:15;2128:66;2107:88;2092:104;;;;2198:2;2088:113;;1551:656;-1:-1:-1;;;1551:656:1:o;2796:611::-;2880:6;2888;2896;2904;2957:3;2945:9;2936:7;2932:23;2928:33;2925:53;;;2974:1;2971;2964:12;2925:53;3013:9;3000:23;3063:42;3056:5;3052:54;3045:5;3042:65;3032:93;;3121:1;3118;3111:12;3032:93;3144:5;-1:-1:-1;3201:2:1;3186:18;;3173:32;3249:4;3236:18;;3224:31;;3214:59;;3269:1;3266;3259:12;3214:59;2796:611;;3292:7;;-1:-1:-1;;;;3346:2:1;3331:18;;3318:32;;3397:2;3382:18;3369:32;;2796:611::o;3412:180::-;3471:6;3524:2;3512:9;3503:7;3499:23;3495:32;3492:52;;;3540:1;3537;3530:12;3492:52;-1:-1:-1;3563:23:1;;3412:180;-1:-1:-1;3412:180:1:o;4509:279::-;4549:4;4577:1;4574;4571:8;4568:188;;;4612:77;4609:1;4602:88;4713:4;4710:1;4703:15;4741:4;4738:1;4731:15;4568:188;-1:-1:-1;4773:9:1;;4509:279::o
Swarm Source
ipfs://a4b6ebb429b77a4a657330536ffd3215f7c620ebadbe69b9159d567733fe3a07
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.