synapsecns/sanguine

View on GitHub
agents/contracts/test/gasdata/gasdataharness.contractinfo.json

Summary

Maintainability
Test Coverage
{"solidity/GasDataHarness.t.sol:GasDataHarness":{"code":"0x608060405234801561001057600080fd5b50610634806100206000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c806376fb64391161008c578063b75c78b311610066578063b75c78b314610217578063e0fdbe0c14610225578063e47805cd14610238578063f26b89891461024b57600080fd5b806376fb6439146101de578063a1a8a01c146101f1578063a1ae8d431461020457600080fd5b8063405f3dfa116100bd578063405f3dfa1461017357806356ce0ac4146101865780635f331a83146101b657600080fd5b8063092d72d1146100e457806313092f821461010f57806334ec6ed414610143575b600080fd5b6100f76100f23660046103bc565b61026c565b60405161ffff90911681526020015b60405180910390f35b61012261011d3660046103de565b610280565b6040516fffffffffffffffffffffffffffffffff9091168152602001610106565b6101226101513660046103f7565b63ffffffff1660209190911b6fffffffffffffffffffffffff00000000161790565b6100f76101813660046103bc565b610288565b610199610194366004610457565b61029e565b6040516bffffffffffffffffffffffff9091168152602001610106565b6101c96101c4366004610457565b6102b8565b60405163ffffffff9091168152602001610106565b6100f76101ec3660046103bc565b6102d2565b6100f76101ff3660046103bc565b6102ea565b6100f76102123660046103bc565b610300565b61019961011d3660046103de565b610199610233366004610484565b610314565b6100f76102463660046103bc565b610379565b61025e610259366004610527565b610389565b604051908152602001610106565b6000604082901c63ffffffff165b92915050565b60008161027a565b60006bffffffffffffffffffffffff821661027a565b6000602082901c6bffffffffffffffffffffffff1661027a565b60006fffffffffffffffffffffffffffffffff821661027a565b6000601082901c69ffffffffffffffffffff1661027a565b6000602082901c67ffffffffffffffff1661027a565b6000603082901c65ffffffffffff1661027a565b60008061ffff8316601085901b63ffff000016602087901b65ffff0000000016603089901b67ffff0000000000001660408b901b69ffff00000000000000001660508d901b6bffff000000000000000000001617171717175b98975050505050505050565b6000605082901c61ffff1661027a565b805160051b602082012060009061027a565b80356bffffffffffffffffffffffff811681146103b757600080fd5b919050565b6000602082840312156103ce57600080fd5b6103d78261039b565b9392505050565b6000602082840312156103f057600080fd5b5035919050565b6000806040838503121561040a57600080fd5b6104138361039b565b9150602083013563ffffffff8116811461042c57600080fd5b809150509250929050565b80356fffffffffffffffffffffffffffffffff811681146103b757600080fd5b60006020828403121561046957600080fd5b6103d782610437565b803561ffff811681146103b757600080fd5b60008060008060008060c0878903121561049d57600080fd5b6104a687610472565b95506104b460208801610472565b94506104c260408801610472565b93506104d060608801610472565b92506104de60808801610472565b91506104ec60a08801610472565b90509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602080838503121561053a57600080fd5b823567ffffffffffffffff8082111561055257600080fd5b818501915085601f83011261056657600080fd5b813581811115610578576105786104f8565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811085821117156105bb576105bb6104f8565b6040529182528482019250838101850191888311156105d957600080fd5b938501935b8285101561036d576105ef85610437565b845293850193928501926105de56fea26469706673582212205b3c138bc3b2fe660091143b1c98a3c07ab8690d4a1c7f35c2e7bc47264b0dcd64736f6c63430008110033","runtime-code":"0x608060405234801561001057600080fd5b50600436106100df5760003560e01c806376fb64391161008c578063b75c78b311610066578063b75c78b314610217578063e0fdbe0c14610225578063e47805cd14610238578063f26b89891461024b57600080fd5b806376fb6439146101de578063a1a8a01c146101f1578063a1ae8d431461020457600080fd5b8063405f3dfa116100bd578063405f3dfa1461017357806356ce0ac4146101865780635f331a83146101b657600080fd5b8063092d72d1146100e457806313092f821461010f57806334ec6ed414610143575b600080fd5b6100f76100f23660046103bc565b61026c565b60405161ffff90911681526020015b60405180910390f35b61012261011d3660046103de565b610280565b6040516fffffffffffffffffffffffffffffffff9091168152602001610106565b6101226101513660046103f7565b63ffffffff1660209190911b6fffffffffffffffffffffffff00000000161790565b6100f76101813660046103bc565b610288565b610199610194366004610457565b61029e565b6040516bffffffffffffffffffffffff9091168152602001610106565b6101c96101c4366004610457565b6102b8565b60405163ffffffff9091168152602001610106565b6100f76101ec3660046103bc565b6102d2565b6100f76101ff3660046103bc565b6102ea565b6100f76102123660046103bc565b610300565b61019961011d3660046103de565b610199610233366004610484565b610314565b6100f76102463660046103bc565b610379565b61025e610259366004610527565b610389565b604051908152602001610106565b6000604082901c63ffffffff165b92915050565b60008161027a565b60006bffffffffffffffffffffffff821661027a565b6000602082901c6bffffffffffffffffffffffff1661027a565b60006fffffffffffffffffffffffffffffffff821661027a565b6000601082901c69ffffffffffffffffffff1661027a565b6000602082901c67ffffffffffffffff1661027a565b6000603082901c65ffffffffffff1661027a565b60008061ffff8316601085901b63ffff000016602087901b65ffff0000000016603089901b67ffff0000000000001660408b901b69ffff00000000000000001660508d901b6bffff000000000000000000001617171717175b98975050505050505050565b6000605082901c61ffff1661027a565b805160051b602082012060009061027a565b80356bffffffffffffffffffffffff811681146103b757600080fd5b919050565b6000602082840312156103ce57600080fd5b6103d78261039b565b9392505050565b6000602082840312156103f057600080fd5b5035919050565b6000806040838503121561040a57600080fd5b6104138361039b565b9150602083013563ffffffff8116811461042c57600080fd5b809150509250929050565b80356fffffffffffffffffffffffffffffffff811681146103b757600080fd5b60006020828403121561046957600080fd5b6103d782610437565b803561ffff811681146103b757600080fd5b60008060008060008060c0878903121561049d57600080fd5b6104a687610472565b95506104b460208801610472565b94506104c260408801610472565b93506104d060608801610472565b92506104de60808801610472565b91506104ec60a08801610472565b90509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602080838503121561053a57600080fd5b823567ffffffffffffffff8082111561055257600080fd5b818501915085601f83011261056657600080fd5b813581811115610578576105786104f8565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811085821117156105bb576105bb6104f8565b6040529182528482019250838101850191888311156105d957600080fd5b938501935b8285101561036d576105ef85610437565b845293850193928501926105de56fea26469706673582212205b3c138bc3b2fe660091143b1c98a3c07ab8690d4a1c7f35c2e7bc47264b0dcd64736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17;\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// test/harnesses/libs/stack/GasDataHarness.t.sol\n\ncontract GasDataHarness {\n    // Note: we don't add an empty test() function here, as it currently leads\n    // to zero coverage on the corresponding library.\n\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) public pure returns (GasData) {\n        GasData result =\n            GasDataLib.encodeGasData(gasPrice_, dataPrice_, execBuffer_, amortAttCost_, etherPrice_, markup_);\n        return result;\n    }\n\n    function wrapGasData(uint256 paddedGasData) public pure returns (GasData) {\n        return GasDataLib.wrapGasData(paddedGasData);\n    }\n\n    function encodeChainGas(GasData gasData_, uint32 domain_) public pure returns (ChainGas) {\n        ChainGas result = GasDataLib.encodeChainGas(gasData_, domain_);\n        return result;\n    }\n\n    function wrapChainGas(uint256 paddedChainGas) public pure returns (ChainGas) {\n        return GasDataLib.wrapChainGas(paddedChainGas);\n    }\n\n    function gasPrice(GasData gasData_) public pure returns (Number) {\n        return gasData_.gasPrice();\n    }\n\n    function dataPrice(GasData gasData_) public pure returns (Number) {\n        return gasData_.dataPrice();\n    }\n\n    function execBuffer(GasData gasData_) public pure returns (Number) {\n        return gasData_.execBuffer();\n    }\n\n    function amortAttCost(GasData gasData_) public pure returns (Number) {\n        return gasData_.amortAttCost();\n    }\n\n    function etherPrice(GasData gasData_) public pure returns (Number) {\n        return gasData_.etherPrice();\n    }\n\n    function markup(GasData gasData_) public pure returns (Number) {\n        return gasData_.markup();\n    }\n\n    function domain(ChainGas chainData_) public pure returns (uint32) {\n        return chainData_.domain();\n    }\n\n    function gasData(ChainGas chainData_) public pure returns (GasData) {\n        return chainData_.gasData();\n    }\n\n    function snapGasHash(ChainGas[] memory snapGas) public pure returns (bytes32) {\n        return GasDataLib.snapGasHash(snapGas);\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"15518:2108:0:-:0;;;;;;;;;;;;;;;;;;;","srcMapRuntime":"15518:2108:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16674:110;;;;;;:::i;:::-;;:::i;:::-;;;658:6:1;646:19;;;628:38;;616:2;601:18;16674:110:0;;;;;;;;16414:140;;;;;;:::i;:::-;;:::i;:::-;;;1066:34:1;1054:47;;;1036:66;;1024:2;1009:18;16414:140:0;862:246:1;16217:191:0;;;;;;:::i;:::-;13556:16;;8925:5;13502:51;;;;;;:70;;16217:191;17148:104;;;;;;:::i;:::-;;:::i;17373:112::-;;;;;;:::i;:::-;;:::i;:::-;;;2174:26:1;2162:39;;;2144:58;;2132:2;2117:18;17373:112:0;1972:236:1;17258:109:0;;;;;;:::i;:::-;;:::i;:::-;;;2387:10:1;2375:23;;;2357:42;;2345:2;2330:18;17258:109:0;2213:192:1;17030:112:0;;;;;;:::i;:::-;;:::i;16908:116::-;;;;;;:::i;:::-;;:::i;16790:112::-;;;;;;:::i;:::-;;:::i;16076:135::-;;;;;;:::i;15682:388::-;;;;;;:::i;:::-;;:::i;16560:108::-;;;;;;:::i;:::-;;:::i;17491:133::-;;;;;;:::i;:::-;;:::i;:::-;;;4993:25:1;;;4981:2;4966:18;17491:133:0;4847:177:1;16674:110:0;16732:6;8476:5;11471:40;;;;;16757:20;16750:27;16674:110;-1:-1:-1;;16674:110:0:o;16414:140::-;16481:8;16532:14;16508:39;13651:233;17148:104;17203:6;17228:15;;;:17;13651:233;17373:112;17432:7;8925:5;14128:39;;;;;17458:20;13936:240;17258:109;17316:6;17341:17;;;:19;13651:233;17030:112;17089:6;8817:5;12472:41;;;;;17114:21;12280:242;16908:116;16969:6;8705:5;12127:44;;;;;16994:23;11933:247;16790:112;16849:6;8588:5;11798:41;;;;;16874:21;11606:242;15682:388;15895:7;;10555:30;;;8817:5;10485:55;;;;;8705:5;10410:60;;;;;8588:5;10340:55;;;;;8476:5;10272:53;;;;;8365:6;10206:51;;;;;:119;:189;:264;:334;:379;15943:97;15914:126;15682:388;-1:-1:-1;;;;;;;;15682:388:0:o;16560:108::-;16617:6;8365;11154:39;;;;;16642:19;10964:238;17491:133;15337:14;;15334:1;15330:22;15138:4;15125:18;;15428:19;17560:7;;17586:31;14505:958;14:201:1;103:20;;163:26;152:38;;142:49;;132:77;;205:1;202;195:12;132:77;14:201;;;:::o;220:234::-;306:6;359:2;347:9;338:7;334:23;330:32;327:52;;;375:1;372;365:12;327:52;398:50;438:9;398:50;:::i;:::-;388:60;220:234;-1:-1:-1;;;220:234:1:o;677:180::-;736:6;789:2;777:9;768:7;764:23;760:32;757:52;;;805:1;802;795:12;757:52;-1:-1:-1;828:23:1;;677:180;-1:-1:-1;677:180:1:o;1113:398::-;1207:6;1215;1268:2;1256:9;1247:7;1243:23;1239:32;1236:52;;;1284:1;1281;1274:12;1236:52;1307:50;1347:9;1307:50;:::i;:::-;1297:60;;1407:2;1396:9;1392:18;1379:32;1451:10;1444:5;1440:22;1433:5;1430:33;1420:61;;1477:1;1474;1467:12;1420:61;1500:5;1490:15;;;1113:398;;;;;:::o;1516:210::-;1606:20;;1666:34;1655:46;;1645:57;;1635:85;;1716:1;1713;1706:12;1731:236;1818:6;1871:2;1859:9;1850:7;1846:23;1842:32;1839:52;;;1887:1;1884;1877:12;1839:52;1910:51;1951:9;1910:51;:::i;2410:180::-;2498:20;;2558:6;2547:18;;2537:29;;2527:57;;2580:1;2577;2570:12;2595:823;2843:6;2851;2859;2867;2875;2883;2936:3;2924:9;2915:7;2911:23;2907:33;2904:53;;;2953:1;2950;2943:12;2904:53;2976:49;3015:9;2976:49;:::i;:::-;2966:59;;3044:58;3098:2;3087:9;3083:18;3044:58;:::i;:::-;3034:68;;3121:58;3175:2;3164:9;3160:18;3121:58;:::i;:::-;3111:68;;3198:58;3252:2;3241:9;3237:18;3198:58;:::i;:::-;3188:68;;3275:59;3329:3;3318:9;3314:19;3275:59;:::i;:::-;3265:69;;3353:59;3407:3;3396:9;3392:19;3353:59;:::i;:::-;3343:69;;2595:823;;;;;;;;:::o;3423:184::-;3475:77;3472:1;3465:88;3572:4;3569:1;3562:15;3596:4;3593:1;3586:15;3612:1230;3724:6;3755:2;3798;3786:9;3777:7;3773:23;3769:32;3766:52;;;3814:1;3811;3804:12;3766:52;3854:9;3841:23;3883:18;3924:2;3916:6;3913:14;3910:34;;;3940:1;3937;3930:12;3910:34;3978:6;3967:9;3963:22;3953:32;;4023:7;4016:4;4012:2;4008:13;4004:27;3994:55;;4045:1;4042;4035:12;3994:55;4081:2;4068:16;4103:2;4099;4096:10;4093:36;;;4109:18;;:::i;:::-;4155:2;4152:1;4148:10;4187:2;4181:9;4246:66;4241:2;4237;4233:11;4229:84;4221:6;4217:97;4364:6;4352:10;4349:22;4344:2;4332:10;4329:18;4326:46;4323:72;;;4375:18;;:::i;:::-;4411:2;4404:22;4461:18;;;4495:15;;;;-1:-1:-1;4537:11:1;;;4533:20;;;4565:19;;;4562:39;;;4597:1;4594;4587:12;4562:39;4621:11;;;;4641:170;4657:6;4652:3;4649:15;4641:170;;;4723:45;4764:3;4723:45;:::i;:::-;4711:58;;4674:12;;;;4789;;;;4641:170;","abiDefinition":[{"inputs":[{"internalType":"GasData","name":"gasData_","type":"uint96"}],"name":"amortAttCost","outputs":[{"internalType":"Number","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"GasData","name":"gasData_","type":"uint96"}],"name":"dataPrice","outputs":[{"internalType":"Number","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"ChainGas","name":"chainData_","type":"uint128"}],"name":"domain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"GasData","name":"gasData_","type":"uint96"},{"internalType":"uint32","name":"domain_","type":"uint32"}],"name":"encodeChainGas","outputs":[{"internalType":"ChainGas","name":"","type":"uint128"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"Number","name":"gasPrice_","type":"uint16"},{"internalType":"Number","name":"dataPrice_","type":"uint16"},{"internalType":"Number","name":"execBuffer_","type":"uint16"},{"internalType":"Number","name":"amortAttCost_","type":"uint16"},{"internalType":"Number","name":"etherPrice_","type":"uint16"},{"internalType":"Number","name":"markup_","type":"uint16"}],"name":"encodeGasData","outputs":[{"internalType":"GasData","name":"","type":"uint96"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"GasData","name":"gasData_","type":"uint96"}],"name":"etherPrice","outputs":[{"internalType":"Number","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"GasData","name":"gasData_","type":"uint96"}],"name":"execBuffer","outputs":[{"internalType":"Number","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"ChainGas","name":"chainData_","type":"uint128"}],"name":"gasData","outputs":[{"internalType":"GasData","name":"","type":"uint96"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"GasData","name":"gasData_","type":"uint96"}],"name":"gasPrice","outputs":[{"internalType":"Number","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"GasData","name":"gasData_","type":"uint96"}],"name":"markup","outputs":[{"internalType":"Number","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"ChainGas[]","name":"snapGas","type":"uint128[]"}],"name":"snapGasHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"paddedChainGas","type":"uint256"}],"name":"wrapChainGas","outputs":[{"internalType":"ChainGas","name":"","type":"uint128"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"paddedGasData","type":"uint256"}],"name":"wrapGasData","outputs":[{"internalType":"GasData","name":"","type":"uint96"}],"stateMutability":"pure","type":"function"}],"userDoc":{"kind":"user","methods":{},"version":1},"developerDoc":{"kind":"dev","methods":{},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"GasData\",\"name\":\"gasData_\",\"type\":\"uint96\"}],\"name\":\"amortAttCost\",\"outputs\":[{\"internalType\":\"Number\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GasData\",\"name\":\"gasData_\",\"type\":\"uint96\"}],\"name\":\"dataPrice\",\"outputs\":[{\"internalType\":\"Number\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"ChainGas\",\"name\":\"chainData_\",\"type\":\"uint128\"}],\"name\":\"domain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GasData\",\"name\":\"gasData_\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"domain_\",\"type\":\"uint32\"}],\"name\":\"encodeChainGas\",\"outputs\":[{\"internalType\":\"ChainGas\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"Number\",\"name\":\"gasPrice_\",\"type\":\"uint16\"},{\"internalType\":\"Number\",\"name\":\"dataPrice_\",\"type\":\"uint16\"},{\"internalType\":\"Number\",\"name\":\"execBuffer_\",\"type\":\"uint16\"},{\"internalType\":\"Number\",\"name\":\"amortAttCost_\",\"type\":\"uint16\"},{\"internalType\":\"Number\",\"name\":\"etherPrice_\",\"type\":\"uint16\"},{\"internalType\":\"Number\",\"name\":\"markup_\",\"type\":\"uint16\"}],\"name\":\"encodeGasData\",\"outputs\":[{\"internalType\":\"GasData\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GasData\",\"name\":\"gasData_\",\"type\":\"uint96\"}],\"name\":\"etherPrice\",\"outputs\":[{\"internalType\":\"Number\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GasData\",\"name\":\"gasData_\",\"type\":\"uint96\"}],\"name\":\"execBuffer\",\"outputs\":[{\"internalType\":\"Number\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"ChainGas\",\"name\":\"chainData_\",\"type\":\"uint128\"}],\"name\":\"gasData\",\"outputs\":[{\"internalType\":\"GasData\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GasData\",\"name\":\"gasData_\",\"type\":\"uint96\"}],\"name\":\"gasPrice\",\"outputs\":[{\"internalType\":\"Number\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GasData\",\"name\":\"gasData_\",\"type\":\"uint96\"}],\"name\":\"markup\",\"outputs\":[{\"internalType\":\"Number\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"ChainGas[]\",\"name\":\"snapGas\",\"type\":\"uint128[]\"}],\"name\":\"snapGasHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"paddedChainGas\",\"type\":\"uint256\"}],\"name\":\"wrapChainGas\",\"outputs\":[{\"internalType\":\"ChainGas\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"paddedGasData\",\"type\":\"uint256\"}],\"name\":\"wrapGasData\",\"outputs\":[{\"internalType\":\"GasData\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/GasDataHarness.t.sol\":\"GasDataHarness\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/GasDataHarness.t.sol\":{\"keccak256\":\"0x1cd9c72cedd3ab19117b6f606bce2effeb9ca4bf2b21e247368699dfbeb52fcf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://929f486975e66ccc27e9138fa8382bfc07f603708a47276beb427c12ff583d9a\",\"dweb:/ipfs/QmYM8Pqv64PvcGE4v8S4YZZSdTtsUCjqxiJ3KsPRZyY5Rr\"]}},\"version\":1}"},"hashes":{"amortAttCost(uint96)":"a1a8a01c","dataPrice(uint96)":"092d72d1","domain(uint128)":"5f331a83","encodeChainGas(uint96,uint32)":"34ec6ed4","encodeGasData(uint16,uint16,uint16,uint16,uint16,uint16)":"e0fdbe0c","etherPrice(uint96)":"76fb6439","execBuffer(uint96)":"a1ae8d43","gasData(uint128)":"56ce0ac4","gasPrice(uint96)":"e47805cd","markup(uint96)":"405f3dfa","snapGasHash(uint128[])":"f26b8989","wrapChainGas(uint256)":"13092f82","wrapGasData(uint256)":"b75c78b3"}},"solidity/GasDataHarness.t.sol:GasDataLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c1f14549a7e5169a415c94bfe0be5e66d517ece7b76c723181e5a27d4f2db38864736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c1f14549a7e5169a415c94bfe0be5e66d517ece7b76c723181e5a27d4f2db38864736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17;\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// test/harnesses/libs/stack/GasDataHarness.t.sol\n\ncontract GasDataHarness {\n    // Note: we don't add an empty test() function here, as it currently leads\n    // to zero coverage on the corresponding library.\n\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) public pure returns (GasData) {\n        GasData result =\n            GasDataLib.encodeGasData(gasPrice_, dataPrice_, execBuffer_, amortAttCost_, etherPrice_, markup_);\n        return result;\n    }\n\n    function wrapGasData(uint256 paddedGasData) public pure returns (GasData) {\n        return GasDataLib.wrapGasData(paddedGasData);\n    }\n\n    function encodeChainGas(GasData gasData_, uint32 domain_) public pure returns (ChainGas) {\n        ChainGas result = GasDataLib.encodeChainGas(gasData_, domain_);\n        return result;\n    }\n\n    function wrapChainGas(uint256 paddedChainGas) public pure returns (ChainGas) {\n        return GasDataLib.wrapChainGas(paddedChainGas);\n    }\n\n    function gasPrice(GasData gasData_) public pure returns (Number) {\n        return gasData_.gasPrice();\n    }\n\n    function dataPrice(GasData gasData_) public pure returns (Number) {\n        return gasData_.dataPrice();\n    }\n\n    function execBuffer(GasData gasData_) public pure returns (Number) {\n        return gasData_.execBuffer();\n    }\n\n    function amortAttCost(GasData gasData_) public pure returns (Number) {\n        return gasData_.amortAttCost();\n    }\n\n    function etherPrice(GasData gasData_) public pure returns (Number) {\n        return gasData_.etherPrice();\n    }\n\n    function markup(GasData gasData_) public pure returns (Number) {\n        return gasData_.markup();\n    }\n\n    function domain(ChainGas chainData_) public pure returns (uint32) {\n        return chainData_.domain();\n    }\n\n    function gasData(ChainGas chainData_) public pure returns (GasData) {\n        return chainData_.gasData();\n    }\n\n    function snapGasHash(ChainGas[] memory snapGas) public pure returns (bytes32) {\n        return GasDataLib.snapGasHash(snapGas);\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"8243:7222:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;8243:7222:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"8243:7222:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"Library for encoding and decoding GasData and ChainGas structs. # GasData `GasData` is a struct to store the \"basic information about gas prices\", that could be later used to approximate the cost of a message execution, and thus derive the minimal tip values for sending a message to the chain. \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the \u003e approximates instead of the exact values, and thus save on storage costs. \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an \u003e 0.4% error on the approximates would be acceptable. `GasData` is supposed to be included in the Origin's state, which are synced across chains using Agent-signed snapshots and attestations. ## GasData stack layout (from highest bits to lowest) | Position   | Field        | Type   | Bytes | Description                                         | | ---------- | ------------ | ------ | ----- | --------------------------------------------------- | | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       | | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         | | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) | | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  | | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) | | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          | \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math. ## ChainGas stack layout (from highest bits to lowest) | Position   | Field   | Type   | Bytes | Description      | | ---------- | ------- | ------ | ----- | ---------------- | | (016..004] | gasData | uint96 | 12    | Chain's gas data | | (004..000] | domain  | uint32 | 4     | Chain's domain   |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"SHIFT_AMORT_ATT_COST":{"details":"Amount of bits to shift to amortAttCost field"},"SHIFT_DATA_PRICE":{"details":"Amount of bits to shift to dataPrice field"},"SHIFT_ETHER_PRICE":{"details":"Amount of bits to shift to etherPrice field"},"SHIFT_EXEC_BUFFER":{"details":"Amount of bits to shift to execBuffer field"},"SHIFT_GAS_DATA":{"details":"Amount of bits to shift to gasData field"},"SHIFT_GAS_PRICE":{"details":"Amount of bits to shift to gasPrice field"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"SHIFT_AMORT_ATT_COST\":{\"details\":\"Amount of bits to shift to amortAttCost field\"},\"SHIFT_DATA_PRICE\":{\"details\":\"Amount of bits to shift to dataPrice field\"},\"SHIFT_ETHER_PRICE\":{\"details\":\"Amount of bits to shift to etherPrice field\"},\"SHIFT_EXEC_BUFFER\":{\"details\":\"Amount of bits to shift to execBuffer field\"},\"SHIFT_GAS_DATA\":{\"details\":\"Amount of bits to shift to gasData field\"},\"SHIFT_GAS_PRICE\":{\"details\":\"Amount of bits to shift to gasPrice field\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Library for encoding and decoding GasData and ChainGas structs. # GasData `GasData` is a struct to store the \\\"basic information about gas prices\\\", that could be later used to approximate the cost of a message execution, and thus derive the minimal tip values for sending a message to the chain. \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the \u003e approximates instead of the exact values, and thus save on storage costs. \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an \u003e 0.4% error on the approximates would be acceptable. `GasData` is supposed to be included in the Origin's state, which are synced across chains using Agent-signed snapshots and attestations. ## GasData stack layout (from highest bits to lowest) | Position   | Field        | Type   | Bytes | Description                                         | | ---------- | ------------ | ------ | ----- | --------------------------------------------------- | | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       | | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         | | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) | | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  | | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) | | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          | \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math. ## ChainGas stack layout (from highest bits to lowest) | Position   | Field   | Type   | Bytes | Description      | | ---------- | ------- | ------ | ----- | ---------------- | | (016..004] | gasData | uint96 | 12    | Chain's gas data | | (004..000] | domain  | uint32 | 4     | Chain's domain   |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/GasDataHarness.t.sol\":\"GasDataLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/GasDataHarness.t.sol\":{\"keccak256\":\"0x1cd9c72cedd3ab19117b6f606bce2effeb9ca4bf2b21e247368699dfbeb52fcf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://929f486975e66ccc27e9138fa8382bfc07f603708a47276beb427c12ff583d9a\",\"dweb:/ipfs/QmYM8Pqv64PvcGE4v8S4YZZSdTtsUCjqxiJ3KsPRZyY5Rr\"]}},\"version\":1}"},"hashes":{}},"solidity/GasDataHarness.t.sol:NumberLib":{"code":"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212204e1bb6760b397fabd9933c93d87c178fd961d3161fa6d5a63af4cbcf719fa82564736f6c63430008110033","runtime-code":"0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212204e1bb6760b397fabd9933c93d87c178fd961d3161fa6d5a63af4cbcf719fa82564736f6c63430008110033","info":{"source":"// SPDX-License-Identifier: MIT\npragma solidity =0.8.17;\n\n// contracts/libs/stack/Number.sol\n\n/// Number is a compact representation of uint256, that is fit into 16 bits\n/// with the maximum relative error under 0.4%.\ntype Number is uint16;\n\nusing NumberLib for Number global;\n\n/// # Number\n/// Library for compact representation of uint256 numbers.\n/// - Number is stored using mantissa and exponent, each occupying 8 bits.\n/// - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`.\n/// - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent`\n/// \u003e - `0 \u003c= mantissa \u003c 256`\n/// \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256)\n/// # Number stack layout (from highest bits to lowest)\n///\n/// | Position   | Field    | Type  | Bytes |\n/// | ---------- | -------- | ----- | ----- |\n/// | (002..001] | mantissa | uint8 | 1     |\n/// | (001..000] | exponent | uint8 | 1     |\n\nlibrary NumberLib {\n    /// @dev Amount of bits to shift to mantissa field\n    uint16 private constant SHIFT_MANTISSA = 8;\n\n    /// @notice For bwad math (binary wad) we use 2**64 as \"wad\" unit.\n    /// @dev We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\n    uint256 internal constant BWAD_SHIFT = 64;\n    uint256 internal constant BWAD = 1 \u003c\u003c BWAD_SHIFT;\n    /// @notice ~0.1% in bwad units.\n    uint256 internal constant PER_MILLE_SHIFT = BWAD_SHIFT - 10;\n    uint256 internal constant PER_MILLE = 1 \u003c\u003c PER_MILLE_SHIFT;\n\n    /// @notice Compresses uint256 number into 16 bits.\n    function compress(uint256 value) internal pure returns (Number) {\n        // Find `msb` such as `2**msb \u003c= value \u003c 2**(msb + 1)`\n        uint256 msb = mostSignificantBit(value);\n        // We want to preserve 9 bits of precision.\n        // The highest bit is always 1, so we can skip it.\n        // The remaining 8 highest bits are stored as mantissa.\n        if (msb \u003c 8) {\n            // Value is less than 2**8, so we can use value as mantissa with \"-1\" exponent.\n            return _encode(uint8(value), 0xFF);\n        } else {\n            // We use `msb - 8` as exponent otherwise. Note that `exponent \u003e= 0`.\n            unchecked {\n                uint256 exponent = msb - 8;\n                // Shifting right by `msb-8` bits will shift the \"remaining 8 highest bits\" into the 8 lowest bits.\n                // uint8() will truncate the highest bit.\n                return _encode(uint8(value \u003e\u003e exponent), uint8(exponent));\n            }\n        }\n    }\n\n    /// @notice Decompresses 16 bits number into uint256.\n    /// @dev The outcome is an approximation of the original number: `(value - value / 256) \u003c number \u003c= value`.\n    function decompress(Number number) internal pure returns (uint256 value) {\n        // Isolate 8 highest bits as the mantissa.\n        uint256 mantissa = Number.unwrap(number) \u003e\u003e SHIFT_MANTISSA;\n        // This will truncate the highest bits, leaving only the exponent.\n        uint256 exponent = uint8(Number.unwrap(number));\n        if (exponent == 0xFF) {\n            return mantissa;\n        } else {\n            unchecked {\n                return (256 + mantissa) \u003c\u003c (exponent);\n            }\n        }\n    }\n\n    /// @dev Returns the most significant bit of `x`\n    /// https://solidity-by-example.org/bitwise/\n    function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\n        // To find `msb` we determine it bit by bit, starting from the highest one.\n        // `0 \u003c= msb \u003c= 255`, so we start from the highest bit, 1\u003c\u003c7 == 128.\n        // If `x` is at least 2**128, then the highest bit of `x` is at least 128.\n        // solhint-disable no-inline-assembly\n        assembly {\n            // `f` is set to 1\u003c\u003c7 if `x \u003e= 2**128` and to 0 otherwise.\n            let f := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n            // If `x \u003e= 2**128` then set `msb` highest bit to 1 and shift `x` right by 128.\n            // Otherwise, `msb` remains 0 and `x` remains unchanged.\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        // `x` is now at most 2**128 - 1. Continue the same way, the next highest bit is 1\u003c\u003c6 == 64.\n        assembly {\n            // `f` is set to 1\u003c\u003c6 if `x \u003e= 2**64` and to 0 otherwise.\n            let f := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c5 if `x \u003e= 2**32` and to 0 otherwise.\n            let f := shl(5, gt(x, 0xFFFFFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c4 if `x \u003e= 2**16` and to 0 otherwise.\n            let f := shl(4, gt(x, 0xFFFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c3 if `x \u003e= 2**8` and to 0 otherwise.\n            let f := shl(3, gt(x, 0xFF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c2 if `x \u003e= 2**4` and to 0 otherwise.\n            let f := shl(2, gt(x, 0xF))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1\u003c\u003c1 if `x \u003e= 2**2` and to 0 otherwise.\n            let f := shl(1, gt(x, 0x3))\n            x := shr(f, x)\n            msb := or(msb, f)\n        }\n        assembly {\n            // `f` is set to 1 if `x \u003e= 2**1` and to 0 otherwise.\n            let f := gt(x, 0x1)\n            msb := or(msb, f)\n        }\n    }\n\n    /// @dev Wraps (mantissa, exponent) pair into Number.\n    function _encode(uint8 mantissa, uint8 exponent) private pure returns (Number) {\n        // Casts below are upcasts, so they are safe.\n        return Number.wrap(uint16(mantissa) \u003c\u003c SHIFT_MANTISSA | uint16(exponent));\n    }\n}\n\n// contracts/libs/stack/GasData.sol\n\n/// GasData in encoded data with \"basic information about gas prices\" for some chain.\ntype GasData is uint96;\n\nusing GasDataLib for GasData global;\n\n/// ChainGas is encoded data with given chain's \"basic information about gas prices\".\ntype ChainGas is uint128;\n\nusing GasDataLib for ChainGas global;\n\n/// Library for encoding and decoding GasData and ChainGas structs.\n/// # GasData\n/// `GasData` is a struct to store the \"basic information about gas prices\", that could\n/// be later used to approximate the cost of a message execution, and thus derive the\n/// minimal tip values for sending a message to the chain.\n/// \u003e - `GasData` is supposed to be cached by `GasOracle` contract, allowing to store the\n/// \u003e approximates instead of the exact values, and thus save on storage costs.\n/// \u003e - For instance, if `GasOracle` only updates the values on +- 10% change, having an\n/// \u003e 0.4% error on the approximates would be acceptable.\n/// `GasData` is supposed to be included in the Origin's state, which are synced across\n/// chains using Agent-signed snapshots and attestations.\n/// ## GasData stack layout (from highest bits to lowest)\n///\n/// | Position   | Field        | Type   | Bytes | Description                                         |\n/// | ---------- | ------------ | ------ | ----- | --------------------------------------------------- |\n/// | (012..010] | gasPrice     | uint16 | 2     | Gas price for the chain (in Wei per gas unit)       |\n/// | (010..008] | dataPrice    | uint16 | 2     | Calldata price (in Wei per byte of content)         |\n/// | (008..006] | execBuffer   | uint16 | 2     | Tx fee safety buffer for message execution (in Wei) |\n/// | (006..004] | amortAttCost | uint16 | 2     | Amortized cost for attestation submission (in Wei)  |\n/// | (004..002] | etherPrice   | uint16 | 2     | Chain's Ether Price / Mainnet Ether Price (in BWAD) |\n/// | (002..000] | markup       | uint16 | 2     | Markup for the message execution (in BWAD)          |\n/// \u003e See Number.sol for more details on `Number` type and BWAD (binary WAD) math.\n///\n/// ## ChainGas stack layout (from highest bits to lowest)\n///\n/// | Position   | Field   | Type   | Bytes | Description      |\n/// | ---------- | ------- | ------ | ----- | ---------------- |\n/// | (016..004] | gasData | uint96 | 12    | Chain's gas data |\n/// | (004..000] | domain  | uint32 | 4     | Chain's domain   |\nlibrary GasDataLib {\n    /// @dev Amount of bits to shift to gasPrice field\n    uint96 private constant SHIFT_GAS_PRICE = 10 * 8;\n    /// @dev Amount of bits to shift to dataPrice field\n    uint96 private constant SHIFT_DATA_PRICE = 8 * 8;\n    /// @dev Amount of bits to shift to execBuffer field\n    uint96 private constant SHIFT_EXEC_BUFFER = 6 * 8;\n    /// @dev Amount of bits to shift to amortAttCost field\n    uint96 private constant SHIFT_AMORT_ATT_COST = 4 * 8;\n    /// @dev Amount of bits to shift to etherPrice field\n    uint96 private constant SHIFT_ETHER_PRICE = 2 * 8;\n\n    /// @dev Amount of bits to shift to gasData field\n    uint128 private constant SHIFT_GAS_DATA = 4 * 8;\n\n    // ═════════════════════════════════════════════════ GAS DATA ══════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded GasData struct with the given fields.\n    /// @param gasPrice_        Gas price for the chain (in Wei per gas unit)\n    /// @param dataPrice_       Calldata price (in Wei per byte of content)\n    /// @param execBuffer_      Tx fee safety buffer for message execution (in Wei)\n    /// @param amortAttCost_    Amortized cost for attestation submission (in Wei)\n    /// @param etherPrice_      Ratio of Chain's Ether Price / Mainnet Ether Price (in BWAD)\n    /// @param markup_          Markup for the message execution (in BWAD)\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) internal pure returns (GasData) {\n        // Number type wraps uint16, so could safely be casted to uint96\n        // forgefmt: disable-next-item\n        return GasData.wrap(\n            uint96(Number.unwrap(gasPrice_)) \u003c\u003c SHIFT_GAS_PRICE |\n            uint96(Number.unwrap(dataPrice_)) \u003c\u003c SHIFT_DATA_PRICE |\n            uint96(Number.unwrap(execBuffer_)) \u003c\u003c SHIFT_EXEC_BUFFER |\n            uint96(Number.unwrap(amortAttCost_)) \u003c\u003c SHIFT_AMORT_ATT_COST |\n            uint96(Number.unwrap(etherPrice_)) \u003c\u003c SHIFT_ETHER_PRICE |\n            uint96(Number.unwrap(markup_))\n        );\n    }\n\n    /// @notice Wraps padded uint256 value into GasData struct.\n    function wrapGasData(uint256 paddedGasData) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(paddedGasData));\n    }\n\n    /// @notice Returns the gas price, in Wei per gas unit.\n    function gasPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_GAS_PRICE));\n    }\n\n    /// @notice Returns the calldata price, in Wei per byte of content.\n    function dataPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_DATA_PRICE));\n    }\n\n    /// @notice Returns the tx fee safety buffer for message execution, in Wei.\n    function execBuffer(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_EXEC_BUFFER));\n    }\n\n    /// @notice Returns the amortized cost for attestation submission, in Wei.\n    function amortAttCost(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_AMORT_ATT_COST));\n    }\n\n    /// @notice Returns the ratio of Chain's Ether Price / Mainnet Ether Price, in BWAD math.\n    function etherPrice(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data) \u003e\u003e SHIFT_ETHER_PRICE));\n    }\n\n    /// @notice Returns the markup for the message execution, in BWAD math.\n    function markup(GasData data) internal pure returns (Number) {\n        // Casting to uint16 will truncate the highest bits, which is the behavior we want\n        return Number.wrap(uint16(GasData.unwrap(data)));\n    }\n\n    // ════════════════════════════════════════════════ CHAIN DATA ═════════════════════════════════════════════════════\n\n    /// @notice Returns an encoded ChainGas struct with the given fields.\n    /// @param gasData_ Chain's gas data\n    /// @param domain_  Chain's domain\n    function encodeChainGas(GasData gasData_, uint32 domain_) internal pure returns (ChainGas) {\n        // GasData type wraps uint96, so could safely be casted to uint128\n        return ChainGas.wrap(uint128(GasData.unwrap(gasData_)) \u003c\u003c SHIFT_GAS_DATA | uint128(domain_));\n    }\n\n    /// @notice Wraps padded uint256 value into ChainGas struct.\n    function wrapChainGas(uint256 paddedChainGas) internal pure returns (ChainGas) {\n        // Casting to uint128 will truncate the highest bits, which is the behavior we want\n        return ChainGas.wrap(uint128(paddedChainGas));\n    }\n\n    /// @notice Returns the chain's gas data.\n    function gasData(ChainGas data) internal pure returns (GasData) {\n        // Casting to uint96 will truncate the highest bits, which is the behavior we want\n        return GasData.wrap(uint96(ChainGas.unwrap(data) \u003e\u003e SHIFT_GAS_DATA));\n    }\n\n    /// @notice Returns the chain's domain.\n    function domain(ChainGas data) internal pure returns (uint32) {\n        // Casting to uint32 will truncate the highest bits, which is the behavior we want\n        return uint32(ChainGas.unwrap(data));\n    }\n\n    /// @notice Returns the hash for the list of ChainGas structs.\n    function snapGasHash(ChainGas[] memory snapGas) internal pure returns (bytes32 snapGasHash_) {\n        // Use assembly to calculate the hash of the array without copying it\n        // ChainGas takes a single word of storage, thus ChainGas[] is stored in the following way:\n        // 0x00: length of the array, in words\n        // 0x20: first ChainGas struct\n        // 0x40: second ChainGas struct\n        // And so on...\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Find the location where the array data starts, we add 0x20 to skip the length field\n            let loc := add(snapGas, 0x20)\n            // Load the length of the array (in words).\n            // Shifting left 5 bits is equivalent to multiplying by 32: this converts from words to bytes.\n            let len := shl(5, mload(snapGas))\n            // Calculate the hash of the array\n            snapGasHash_ := keccak256(loc, len)\n        }\n    }\n}\n\n// test/harnesses/libs/stack/GasDataHarness.t.sol\n\ncontract GasDataHarness {\n    // Note: we don't add an empty test() function here, as it currently leads\n    // to zero coverage on the corresponding library.\n\n    function encodeGasData(\n        Number gasPrice_,\n        Number dataPrice_,\n        Number execBuffer_,\n        Number amortAttCost_,\n        Number etherPrice_,\n        Number markup_\n    ) public pure returns (GasData) {\n        GasData result =\n            GasDataLib.encodeGasData(gasPrice_, dataPrice_, execBuffer_, amortAttCost_, etherPrice_, markup_);\n        return result;\n    }\n\n    function wrapGasData(uint256 paddedGasData) public pure returns (GasData) {\n        return GasDataLib.wrapGasData(paddedGasData);\n    }\n\n    function encodeChainGas(GasData gasData_, uint32 domain_) public pure returns (ChainGas) {\n        ChainGas result = GasDataLib.encodeChainGas(gasData_, domain_);\n        return result;\n    }\n\n    function wrapChainGas(uint256 paddedChainGas) public pure returns (ChainGas) {\n        return GasDataLib.wrapChainGas(paddedChainGas);\n    }\n\n    function gasPrice(GasData gasData_) public pure returns (Number) {\n        return gasData_.gasPrice();\n    }\n\n    function dataPrice(GasData gasData_) public pure returns (Number) {\n        return gasData_.dataPrice();\n    }\n\n    function execBuffer(GasData gasData_) public pure returns (Number) {\n        return gasData_.execBuffer();\n    }\n\n    function amortAttCost(GasData gasData_) public pure returns (Number) {\n        return gasData_.amortAttCost();\n    }\n\n    function etherPrice(GasData gasData_) public pure returns (Number) {\n        return gasData_.etherPrice();\n    }\n\n    function markup(GasData gasData_) public pure returns (Number) {\n        return gasData_.markup();\n    }\n\n    function domain(ChainGas chainData_) public pure returns (uint32) {\n        return chainData_.domain();\n    }\n\n    function gasData(ChainGas chainData_) public pure returns (GasData) {\n        return chainData_.gasData();\n    }\n\n    function snapGasHash(ChainGas[] memory snapGas) public pure returns (bytes32) {\n        return GasDataLib.snapGasHash(snapGas);\n    }\n}\n","language":"Solidity","languageVersion":"0.8.17","compilerVersion":"0.8.17","compilerOptions":"--combined-json bin,bin-runtime,srcmap,srcmap-runtime,abi,userdoc,devdoc,metadata,hashes --optimize --optimize-runs 10000 --allow-paths ., ./, ../","srcMap":"926:4887:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;926:4887:0;;;;;;;;;;;;;;;;;","srcMapRuntime":"926:4887:0:-:0;;;;;;;;","abiDefinition":[],"userDoc":{"kind":"user","methods":{},"notice":"# Number Library for compact representation of uint256 numbers. - Number is stored using mantissa and exponent, each occupying 8 bits. - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`. - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent` \u003e - `0 \u003c= mantissa \u003c 256` \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256) # Number stack layout (from highest bits to lowest) | Position   | Field    | Type  | Bytes | | ---------- | -------- | ----- | ----- | | (002..001] | mantissa | uint8 | 1     | | (001..000] | exponent | uint8 | 1     |","version":1},"developerDoc":{"kind":"dev","methods":{},"stateVariables":{"BWAD_SHIFT":{"details":"We are using not using 10**18 as wad, because it is not stored precisely in NumberLib."},"SHIFT_MANTISSA":{"details":"Amount of bits to shift to mantissa field"}},"version":1},"metadata":"{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"stateVariables\":{\"BWAD_SHIFT\":{\"details\":\"We are using not using 10**18 as wad, because it is not stored precisely in NumberLib.\"},\"SHIFT_MANTISSA\":{\"details\":\"Amount of bits to shift to mantissa field\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"# Number Library for compact representation of uint256 numbers. - Number is stored using mantissa and exponent, each occupying 8 bits. - Numbers under 2**8 are stored as `mantissa` with `exponent = 0xFF`. - Numbers at least 2**8 are approximated as `(256 + mantissa) \u003c\u003c exponent` \u003e - `0 \u003c= mantissa \u003c 256` \u003e - `0 \u003c= exponent \u003c= 247` (`256 * 2**248` doesn't fit into uint256) # Number stack layout (from highest bits to lowest) | Position   | Field    | Type  | Bytes | | ---------- | -------- | ----- | ----- | | (002..001] | mantissa | uint8 | 1     | | (001..000] | exponent | uint8 | 1     |\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"solidity/GasDataHarness.t.sol\":\"NumberLib\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"solidity/GasDataHarness.t.sol\":{\"keccak256\":\"0x1cd9c72cedd3ab19117b6f606bce2effeb9ca4bf2b21e247368699dfbeb52fcf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://929f486975e66ccc27e9138fa8382bfc07f603708a47276beb427c12ff583d9a\",\"dweb:/ipfs/QmYM8Pqv64PvcGE4v8S4YZZSdTtsUCjqxiJ3KsPRZyY5Rr\"]}},\"version\":1}"},"hashes":{}}}