Contract 0x8Eb76679F7eD2a2Ec0145A87fE35d67ff6e19aa6 15

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x402e97fb6cc5e0aef6d5c9b01db70bdd8656320e91eccf3ea2c60eedb3c48276Settle Maker Ord...1983164702024-04-06 21:38:536 days 2 hrs ago0xbb150d0358c85efaf0dd302156c6520454aae4e7 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00000123 0.01
0xbdc8e3e06d87688fe767b8fd3c053bd102529a6112584b99604e0b38d6e272aaSettle Maker Ord...1983163942024-04-06 21:38:346 days 2 hrs ago0xbb150d0358c85efaf0dd302156c6520454aae4e7 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00000126 0.01
0xb6a5b468d8ce6b81303b964e93f7452d3b72e5991cb603cc3179ee71094c46a1Settle Maker Ord...1972291032024-04-03 17:45:569 days 6 hrs ago0x070df62e2a9d0f2e1ef3a209cf16088657e352fa IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00000683 0.01
0x89d829082dea01a8228e8afe62491782b0c5f0991ac2b75939ac48c317bd8e48Settle Maker Ord...1967295792024-04-02 6:50:0910 days 16 hrs ago0x15cab3a9981b2c68fab38b227b86dd8bb01d9cf6 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00000871 0.01
0x3ff1bbc93e28f11508b444977b2d708a66e65a2c1b9e74904e3471f196acf6a3Settle Maker Ord...1950247682024-03-28 7:51:5315 days 15 hrs ago0xb4cb11e7a73ae3c3e1d666be2ec12a2c1e941fe8 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00000505 0.01
0xaa7b9d3452ada4b42c1b72a00b2e48ac30a1018590a8d8939381851f99c0d352Settle Maker Ord...1950238272024-03-28 7:47:5815 days 15 hrs ago0xb4cb11e7a73ae3c3e1d666be2ec12a2c1e941fe8 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00000388 0.01
0x8c98dba1d24e40cf6593757be098edd0e6ae71829f0778a887f1d22c91a5c74bSettle Maker Ord...1946881682024-03-27 8:23:3916 days 15 hrs ago0x0002bc17448382e180dd1085e696d541d3766000 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.0000039 0.01
0x851c49c43531f325da746128fbcac6dfe9fb1d5ae7f24f4a046d16555c2f9f03Settle Maker Ord...1940975912024-03-25 15:19:0418 days 8 hrs ago0x7b44bee4224b1f5f0e6a70ae868167df7653ee3b IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.000002 0.01
0x5baff7b4f7aa730759fd79033dcad2548d7163819ad08871aacc1e8ad3c2b6daSettle Maker Ord...1940971132024-03-25 15:17:0418 days 8 hrs ago0xd2f90018bb19e615a810bcdd592ff5c34b808217 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00000194 0.01
0x579391e546820804581967158d7f28540d96a112fb18566fb08952feab64c586Settle Maker Ord...1921753152024-03-20 1:24:0923 days 22 hrs ago0xbad142c1342529ccaa3794547766637f65f452a4 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.000002 0.011506
0x50f48ea783c91dfb58c9e2dbeaca9e43c645252734245c74d4caa19be64bb7adSettle Maker Ord...1905626232024-03-15 8:01:1428 days 15 hrs ago0xf1cf8a7d8750b71167b21f24d85fbeaf654daaaa IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00001696 0.1
0xa9064edc09ec82680bf0379e14f75850abbb3046943eb542ad14785c4ebe50dcSettle Maker Ord...1905096372024-03-15 4:18:5028 days 19 hrs ago0x98ce0777f2dcd0b82942200a1145100f9797b009 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00001734 0.1
0x04f922aaae5f38fb3ec8fa809ecd33dd141ea6238855f0fafc85f2c3f649303eSettle Maker Ord...1905095412024-03-15 4:18:2628 days 19 hrs ago0x98ce0777f2dcd0b82942200a1145100f9797b009 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00002095 0.1
0x400710d951538c2c1e29fe445e0fc32a3a37d2aac08454f153808968958f9c21Settle Maker Ord...1905083902024-03-15 4:13:3628 days 19 hrs ago0x940ede0c11a6080b47f05d27eb02ddb91f8646fc IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00001582 0.1
0xc5939daca96061e37b448a6fe7cf3764e8200dff7b3a5b113dcbe0a526d2c6c3Settle Maker Ord...1905083002024-03-15 4:13:1328 days 19 hrs ago0x940ede0c11a6080b47f05d27eb02ddb91f8646fc IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00001584 0.1
0x1b4eec315cde352745c0e278420f5a2d511a032231f95f292a3c497b442fb383Settle Maker Ord...1901912582024-03-14 5:57:3629 days 17 hrs ago0xf1cf8a7d8750b71167b21f24d85fbeaf654daaaa IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00012425 0.1
0xcf162970912614ce85f5c2eb1370890406d27225e7a0faac654f206dc84f9dbdSettle Maker Ord...1879316582024-03-07 7:46:3136 days 15 hrs ago0xe4f35de87af47b5738f011a9e7f9ee56dd3dbbcf IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00011976 0.1
0x07050b8f666747f004e1736e582ac83a824dc35114b8df7447c3246a89e983bcSettle Maker Ord...1871893162024-03-05 2:01:4038 days 21 hrs ago0xbad142c1342529ccaa3794547766637f65f452a4 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00018106 0.1
0xcb01e8f111e7a4eaf42621e00a791ce11d6c34a7223ccf7d0be8c3be68d8864fSettle Maker Ord...1870473262024-03-04 15:27:2239 days 8 hrs ago0x1073d928ea11901fea2d185dae71c9cf6c1c69ee IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.000311 0.1
0xfdc6921b5352f091f1ad61c1bd9ac2c5e41af0a53452609e443a2d3150f8e58aSettle Maker Ord...1858965352024-03-01 4:15:5442 days 19 hrs ago0xdfa35a2ebcf4bad6b0d02ae45c8d8a097a28896f IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.000118210.1
0x99828df5ed40ded94b6ba82d490cf7f2248cd9bf1eeea0247ec585da27c2c793Settle Maker Ord...1856705002024-02-29 12:10:0843 days 11 hrs ago0xe4f35de87af47b5738f011a9e7f9ee56dd3dbbcf IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00020169 0.1
0xfe383074e68e1e5124c68708e4e42034f14ad7eaf3fd3d11eafbb2f10d2816a8Settle Maker Ord...1856053122024-02-29 7:34:2843 days 16 hrs ago0xc781ca55dd74c2c035bb56db9d093070271d78d1 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.000157140.1
0x300d60b4e18a4fc8134379bbb5bb1fa2458b64d3e346a6c66a9204499aa93983Settle Maker Ord...1843414292024-02-25 13:40:2247 days 10 hrs ago0x98ce0777f2dcd0b82942200a1145100f9797b009 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.0000871 0.1
0x420af98b0249b9a6675b0f5e22d8709edf1119ac377280614f81085e94a3b5beSettle Maker Ord...1834041652024-02-22 17:15:5550 days 6 hrs ago0x7d295fe2882cc130713f51512bf04f84ca2386c6 IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00015696 0.1
0x065d1221ace68b38191200905494b4a6b2e515c00b6bee6b5ff875c8cb0d00aaSettle Maker Ord...1832365242024-02-22 5:23:2850 days 18 hrs ago0x29a30424cad0797899b22d242fade9d4559c79db IN  0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60 ETH0.00013541 0.1
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x402e97fb6cc5e0aef6d5c9b01db70bdd8656320e91eccf3ea2c60eedb3c482761983164702024-04-06 21:38:536 days 2 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60xbb150d0358c85efaf0dd302156c6520454aae4e70.002 ETH
0x402e97fb6cc5e0aef6d5c9b01db70bdd8656320e91eccf3ea2c60eedb3c482761983164702024-04-06 21:38:536 days 2 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.002 ETH
0xbdc8e3e06d87688fe767b8fd3c053bd102529a6112584b99604e0b38d6e272aa1983163942024-04-06 21:38:346 days 2 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60xbb150d0358c85efaf0dd302156c6520454aae4e70.002 ETH
0xbdc8e3e06d87688fe767b8fd3c053bd102529a6112584b99604e0b38d6e272aa1983163942024-04-06 21:38:346 days 2 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.002 ETH
0xb6a5b468d8ce6b81303b964e93f7452d3b72e5991cb603cc3179ee71094c46a11972291032024-04-03 17:45:569 days 6 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60x070df62e2a9d0f2e1ef3a209cf16088657e352fa0.000002119128730712 ETH
0xb6a5b468d8ce6b81303b964e93f7452d3b72e5991cb603cc3179ee71094c46a11972291032024-04-03 17:45:569 days 6 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.000002119128730712 ETH
0x04f922aaae5f38fb3ec8fa809ecd33dd141ea6238855f0fafc85f2c3f649303e1905095412024-03-15 4:18:2628 days 19 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60x98ce0777f2dcd0b82942200a1145100f9797b0090.070786432 ETH
0x04f922aaae5f38fb3ec8fa809ecd33dd141ea6238855f0fafc85f2c3f649303e1905095412024-03-15 4:18:2628 days 19 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.070786432 ETH
0xcf162970912614ce85f5c2eb1370890406d27225e7a0faac654f206dc84f9dbd1879316582024-03-07 7:46:3136 days 15 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60xe4f35de87af47b5738f011a9e7f9ee56dd3dbbcf0.157 ETH
0xcf162970912614ce85f5c2eb1370890406d27225e7a0faac654f206dc84f9dbd1879316582024-03-07 7:46:3136 days 15 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.157 ETH
0xfdc6921b5352f091f1ad61c1bd9ac2c5e41af0a53452609e443a2d3150f8e58a1858965352024-03-01 4:15:5442 days 19 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60xdfa35a2ebcf4bad6b0d02ae45c8d8a097a28896f0.015 ETH
0xfdc6921b5352f091f1ad61c1bd9ac2c5e41af0a53452609e443a2d3150f8e58a1858965352024-03-01 4:15:5442 days 19 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.015 ETH
0x99828df5ed40ded94b6ba82d490cf7f2248cd9bf1eeea0247ec585da27c2c7931856705002024-02-29 12:10:0843 days 11 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60xe4f35de87af47b5738f011a9e7f9ee56dd3dbbcf0.157 ETH
0x99828df5ed40ded94b6ba82d490cf7f2248cd9bf1eeea0247ec585da27c2c7931856705002024-02-29 12:10:0843 days 11 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.157 ETH
0xfe383074e68e1e5124c68708e4e42034f14ad7eaf3fd3d11eafbb2f10d2816a81856053122024-02-29 7:34:2843 days 16 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60xc781ca55dd74c2c035bb56db9d093070271d78d10.019 ETH
0xfe383074e68e1e5124c68708e4e42034f14ad7eaf3fd3d11eafbb2f10d2816a81856053122024-02-29 7:34:2843 days 16 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.019 ETH
0xe20e92ea3c80049192083fd5e27a9fcbd0b377857424d13aa116642f2202c9a61825756112024-02-20 5:59:5352 days 17 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60x6bbb446669bcd060b01896361b6329bc763035c80.02 ETH
0xe20e92ea3c80049192083fd5e27a9fcbd0b377857424d13aa116642f2202c9a61825756112024-02-20 5:59:5352 days 17 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.02 ETH
0x4af1f0c25353c0b5347d1366e415c8336b271b43d40571d9b83d6d14a9f258461819412782024-02-18 8:32:4154 days 15 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60x6271811ca4c2bd0ef8716e51ecb9e6d22fe9fd830.000001441209915015 ETH
0x4af1f0c25353c0b5347d1366e415c8336b271b43d40571d9b83d6d14a9f258461819412782024-02-18 8:32:4154 days 15 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.000001441209915015 ETH
0xf2eb2b9ad966bdfa34c029622379c3fef7516fd94b5efc123276fb61915e50761816756992024-02-17 13:05:3455 days 10 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60xdfa35a2ebcf4bad6b0d02ae45c8d8a097a28896f0.015 ETH
0xf2eb2b9ad966bdfa34c029622379c3fef7516fd94b5efc123276fb61915e50761816756992024-02-17 13:05:3455 days 10 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.015 ETH
0xd23b3adee34212d7d74f286207d98ace909eaab36cc1598ec389d491cc000b0f1810134022024-02-15 13:25:0457 days 10 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60x6bbb446669bcd060b01896361b6329bc763035c80.028 ETH
0xd23b3adee34212d7d74f286207d98ace909eaab36cc1598ec389d491cc000b0f1810134022024-02-15 13:25:0457 days 10 hrs ago Wrapped Ether 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60.028 ETH
0xbb14dbddb9525f689d2960795588e3dd28779e2d2d6dece8765c345dc5898a031799890442024-02-12 12:19:5960 days 11 hrs ago 0x8eb76679f7ed2a2ec0145a87fe35d67ff6e19aa60x6bbb446669bcd060b01896361b6329bc763035c80.028155462686441255 ETH
[ Download CSV Export 
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0xda57aaf912619bf10e8e585e932e20d941269733
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
Grid

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 8500 runs

Other Settings:
default evmVersion
File 1 of 28 : Grid.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.9;
pragma abicoder v2;

import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./interfaces/IGrid.sol";
import "./interfaces/IWETHMinimum.sol";
import "./interfaces/callback/IGridSwapCallback.sol";
import "./interfaces/callback/IGridPlaceMakerOrderCallback.sol";
import "./interfaces/callback/IGridFlashCallback.sol";
import "./interfaces/IGridEvents.sol";
import "./interfaces/IGridStructs.sol";
import "./interfaces/IGridParameters.sol";
import "./interfaces/IGridDeployer.sol";
import "./interfaces/IPriceOracle.sol";
import "./libraries/BoundaryMath.sol";
import "./libraries/BoundaryBitmap.sol";
import "./libraries/BundleMath.sol";
import "./libraries/Uint128Math.sol";
import "./libraries/Uint160Math.sol";
import "./libraries/SwapMath.sol";

/// @title The implementation of a Gridex grid
contract Grid is IGrid, IGridStructs, IGridEvents, IGridParameters, Context {
    using SafeCast for uint256;
    using BoundaryBitmap for mapping(int16 => uint256);
    using BundleMath for Bundle;

    address public immutable override token0;
    address public immutable override token1;
    int24 public immutable override resolution;

    address private immutable weth9;
    address private immutable priceOracle;

    int24 public immutable takerFee;

    Slot0 public override slot0;

    mapping(int24 => Boundary) public override boundaries0;
    mapping(int24 => Boundary) public override boundaries1;
    mapping(int16 => uint256) public override boundaryBitmaps0;
    mapping(int16 => uint256) public override boundaryBitmaps1;

    uint256 private _orderId;
    mapping(uint256 => Order) public override orders;

    uint64 private _bundleId;
    mapping(uint64 => Bundle) public override bundles;

    mapping(address => TokensOwed) public override tokensOweds;

    /// @dev Used to receive Ether when settling and collecting orders
    receive() external payable {}

    constructor() {
        (token0, token1, resolution, takerFee, priceOracle, weth9) = IGridDeployer(_msgSender()).parameters();
    }

    modifier lock() {
        // G_PL: Grid locked
        require(slot0.unlocked, "G_GL");
        slot0.unlocked = false;
        _;
        slot0.unlocked = true;
    }

    /// @inheritdoc IGrid
    function initialize(
        InitializeParameters memory parameters,
        bytes calldata data
    ) external override returns (uint256[] memory orderIds0, uint256[] memory orderIds1) {
        // G_GAI: grid already initialized
        require(slot0.priceX96 == 0, "G_GAI");
        // G_POR: price out of range
        require(BoundaryMath.isPriceX96InRange(parameters.priceX96), "G_POR");
        // G_T0OE: token0 orders must be non-empty
        require(parameters.orders0.length > 0, "G_ONE");
        // G_T1OE: token1 orders must be non-empty
        require(parameters.orders1.length > 0, "G_ONE");

        IPriceOracle(priceOracle).register(token0, token1, resolution);

        int24 boundary = BoundaryMath.getBoundaryAtPriceX96(parameters.priceX96);
        slot0 = Slot0({
            priceX96: parameters.priceX96,
            boundary: boundary,
            blockTimestamp: uint32(block.timestamp),
            unlocked: false // still keep the grid locked to prevent reentrancy
        });
        // emits an Initialize event before placing orders
        emit Initialize(parameters.priceX96, boundary);

        // places orders for token0 and token1
        uint256 amount0Total;
        (orderIds0, amount0Total) = _placeMakerOrderInBatch(parameters.recipient, true, parameters.orders0);
        uint256 amount1Total;
        (orderIds1, amount1Total) = _placeMakerOrderInBatch(parameters.recipient, false, parameters.orders1);
        (uint256 balance0Before, uint256 balance1Before) = (_balance0(), _balance1());

        IGridPlaceMakerOrderCallback(_msgSender()).gridexPlaceMakerOrderCallback(amount0Total, amount1Total, data);

        (uint256 balance0After, uint256 balance1After) = (_balance0(), _balance1());
        // G_TPF: token pay failed
        require(
            balance0After - balance0Before >= amount0Total && balance1After - balance1Before >= amount1Total,
            "G_TPF"
        );

        slot0.unlocked = true;
    }

    /// @inheritdoc IGrid
    function placeMakerOrder(
        PlaceOrderParameters memory parameters,
        bytes calldata data
    ) external override lock returns (uint256 orderId) {
        orderId = _nextOrderId();

        _processPlaceOrder(orderId, parameters.recipient, parameters.zero, parameters.boundaryLower, parameters.amount);

        _processPlaceOrderReceiveAndCallback(parameters.zero, parameters.amount, data);
    }

    /// @inheritdoc IGrid
    function placeMakerOrderInBatch(
        PlaceOrderInBatchParameters memory parameters,
        bytes calldata data
    ) external override lock returns (uint256[] memory orderIds) {
        uint256 amountTotal;
        (orderIds, amountTotal) = _placeMakerOrderInBatch(parameters.recipient, parameters.zero, parameters.orders);
        _processPlaceOrderReceiveAndCallback(parameters.zero, amountTotal, data);
    }

    function _placeMakerOrderInBatch(
        address recipient,
        bool zero,
        BoundaryLowerWithAmountParameters[] memory parameters
    ) private returns (uint256[] memory orderIds, uint256 amountTotal) {
        orderIds = new uint256[](parameters.length);
        uint256 orderId = _nextOrderIdInBatch(parameters.length);

        for (uint256 i = 0; i < parameters.length; ) {
            BoundaryLowerWithAmountParameters memory each = parameters[i];

            _processPlaceOrder(orderId, recipient, zero, each.boundaryLower, each.amount);
            orderIds[i] = orderId;

            unchecked {
                // next order id
                orderId++;
                i++;
            }

            amountTotal += each.amount;
        }
    }

    function _processPlaceOrder(
        uint256 orderId,
        address recipient,
        bool zero,
        int24 boundaryLower,
        uint128 amount
    ) private {
        // G_OAZ: order amount is zero
        require(amount > 0, "G_OAZ");
        // G_IBL: invalid boundary lower
        require(
            boundaryLower >= BoundaryMath.MIN_BOUNDARY &&
                boundaryLower + resolution <= BoundaryMath.MAX_BOUNDARY &&
                BoundaryMath.isValidBoundary(boundaryLower, resolution),
            "G_IBL"
        );

        // updates the boundary
        Boundary storage boundary = _boundaryAt(boundaryLower, zero);
        Bundle storage bundle;
        uint64 bundleId = boundary.bundle1Id;
        // 1. If bundle1 has been initialized, add the order to bundle1 directly
        // 2. If bundle0 is not initialized, add the order to bundle0 after initialization
        // 3. If bundle0 has been initialized, and bundle0 has been used,
        //    then bundle1 is initialized and the order is added to bundle1, otherwise, it is added to bundle0
        if (bundleId > 0) {
            bundle = bundles[bundleId];
            bundle.addLiquidity(amount);
        } else {
            uint64 bundle0Id = boundary.bundle0Id;
            if (bundle0Id == 0) {
                // initializes new bundle
                (bundleId, bundle) = _nextBundle(boundaryLower, zero);
                boundary.bundle0Id = bundleId;

                bundle.makerAmountTotal = amount;
                bundle.makerAmountRemaining = amount;
            } else {
                bundleId = bundle0Id;
                bundle = bundles[bundleId];

                uint128 makerAmountTotal = bundle.makerAmountTotal;
                uint128 makerAmountRemaining = bundle.makerAmountRemaining;

                if (makerAmountRemaining < makerAmountTotal) {
                    // initializes new bundle
                    (bundleId, bundle) = _nextBundle(boundaryLower, zero);
                    boundary.bundle1Id = bundleId;

                    bundle.makerAmountTotal = amount;
                    bundle.makerAmountRemaining = amount;
                } else {
                    bundle.addLiquidityWithAmount(makerAmountTotal, makerAmountRemaining, amount);
                }
            }
        }

        // saves order
        orders[orderId] = Order({owner: recipient, bundleId: bundleId, amount: amount});
        emit PlaceMakerOrder(orderId, recipient, bundleId, zero, boundaryLower, amount);

        // If the current boundary has no liquidity, it must be flipped
        uint128 makerAmountRemainingForBoundary = boundary.makerAmountRemaining;

        if (makerAmountRemainingForBoundary == 0) _flipBoundary(boundaryLower, zero);

        boundary.makerAmountRemaining = makerAmountRemainingForBoundary + amount;
    }

    function _processPlaceOrderReceiveAndCallback(bool zero, uint256 amount, bytes calldata data) private {
        // tokens to be received
        (address tokenToReceive, uint256 amount0, uint256 amount1) = zero
            ? (token0, amount, uint256(0))
            : (token1, uint256(0), amount);
        uint256 balanceBefore = IERC20(tokenToReceive).balanceOf(address(this));
        IGridPlaceMakerOrderCallback(_msgSender()).gridexPlaceMakerOrderCallback(amount0, amount1, data);
        uint256 balanceAfter = IERC20(tokenToReceive).balanceOf(address(this));
        // G_TPF: token pay failed
        require(balanceAfter - balanceBefore >= amount, "G_TPF");
    }

    /// @inheritdoc IGrid
    function swap(
        address recipient,
        bool zeroForOne,
        int256 amountSpecified,
        uint160 priceLimitX96,
        bytes calldata data
    ) external override returns (int256 amount0, int256 amount1) {
        // G_ASZ: amount specified cannot be zero
        require(amountSpecified != 0, "G_ASZ");

        Slot0 memory slot0Cache = slot0;
        // G_PL: Grid locked
        require(slot0Cache.unlocked, "G_GL");
        // G_PLO: price limit over range
        require(zeroForOne ? priceLimitX96 < slot0Cache.priceX96 : priceLimitX96 > slot0Cache.priceX96, "G_PLO");

        // we lock the grid before swap
        slot0.unlocked = false;

        SwapState memory state = SwapState({
            zeroForOne: zeroForOne,
            amountSpecifiedRemaining: amountSpecified,
            amountInputCalculated: 0,
            feeAmountInputCalculated: 0,
            amountOutputCalculated: 0,
            priceX96: slot0Cache.priceX96,
            priceLimitX96: priceLimitX96,
            boundary: slot0Cache.boundary,
            boundaryLower: BoundaryMath.getBoundaryLowerAtBoundary(slot0Cache.boundary, resolution),
            initializedBoundaryLowerPriceX96: 0,
            initializedBoundaryUpperPriceX96: 0,
            stopSwap: false
        });

        mapping(int16 => uint256) storage counterBoundaryBitmap = _boundaryBitmaps(!zeroForOne);
        mapping(int24 => Boundary) storage counterBoundaries = _boundaries(!zeroForOne);
        while (state.amountSpecifiedRemaining != 0 && !state.stopSwap) {
            int24 boundaryNext;
            bool initialized;
            (
                boundaryNext,
                initialized,
                state.initializedBoundaryLowerPriceX96,
                state.initializedBoundaryUpperPriceX96
            ) = counterBoundaryBitmap.nextInitializedBoundary(
                state.boundary,
                state.priceX96,
                counterBoundaries[state.boundaryLower].makerAmountRemaining > 0,
                resolution,
                state.boundaryLower,
                state.zeroForOne
            );
            if (!initialized) break;

            // swap for boundary
            state.stopSwap = _processSwapForBoundary(counterBoundaryBitmap, counterBoundaries, boundaryNext, state);
        }

        // updates slot0
        if (state.priceX96 != slot0Cache.priceX96) {
            state.boundary = BoundaryMath.getBoundaryAtPriceX96(state.priceX96);
            uint32 blockTimestamp;
            // We only update the oracle in the first transaction of each block, using only the boundary
            // before the update to improve the security of the oracle
            if (
                slot0Cache.boundary != state.boundary &&
                slot0Cache.blockTimestamp != (blockTimestamp = uint32(block.timestamp))
            ) {
                IPriceOracle(priceOracle).update(slot0Cache.boundary, blockTimestamp);
                slot0.blockTimestamp = blockTimestamp;
            }

            (slot0.priceX96, slot0.boundary) = (state.priceX96, state.boundary);
        }

        (amount0, amount1) = _processTransferForSwap(state, recipient, data);
        emit Swap(_msgSender(), recipient, amount0, amount1, state.priceX96, state.boundary);

        // we unlock the grid after swap
        slot0.unlocked = true;
    }

    /// @dev Process swap for a given boundary
    /// @param counterBoundaryBitmap The boundary bitmap of the opposite side. When zeroForOne is true,
    /// it is the boundary bitmap of token1, otherwise it is the boundary bitmap of token0
    /// @param counterBoundaries The boundary of the opposite side. When zeroForOne is true,
    /// it is the boundary of token1, otherwise it is the boundary of token0
    /// @param boundaryNext The next boundary where liquidity exists
    /// @param state The state of the swap
    /// @return stopSwap stopSwap = true if the amount of swapped out is 0,
    /// or when the specified price limit is reached
    function _processSwapForBoundary(
        mapping(int16 => uint256) storage counterBoundaryBitmap,
        mapping(int24 => Boundary) storage counterBoundaries,
        int24 boundaryNext,
        SwapState memory state
    ) private returns (bool stopSwap) {
        SwapForBoundaryState memory swapForBoundaryState = SwapForBoundaryState({
            boundaryLowerPriceX96: state.initializedBoundaryLowerPriceX96,
            boundaryUpperPriceX96: state.initializedBoundaryUpperPriceX96,
            boundaryPriceX96: 0,
            priceX96: 0
        });
        // resets the current priceX96 to the price range
        (swapForBoundaryState.boundaryPriceX96, swapForBoundaryState.priceX96) = state.zeroForOne
            ? (
                swapForBoundaryState.boundaryLowerPriceX96,
                Uint160Math.minUint160(swapForBoundaryState.boundaryUpperPriceX96, state.priceX96)
            )
            : (
                swapForBoundaryState.boundaryUpperPriceX96,
                Uint160Math.maxUint160(swapForBoundaryState.boundaryLowerPriceX96, state.priceX96)
            );

        // when the price has reached the specified price limit, swapping stops
        if (
            (state.zeroForOne && swapForBoundaryState.priceX96 <= state.priceLimitX96) ||
            (!state.zeroForOne && swapForBoundaryState.priceX96 >= state.priceLimitX96)
        ) {
            return true;
        }

        Boundary storage boundary = counterBoundaries[boundaryNext];
        SwapMath.ComputeSwapStep memory step = SwapMath.computeSwapStep(
            swapForBoundaryState.priceX96,
            swapForBoundaryState.boundaryPriceX96,
            state.priceLimitX96,
            state.amountSpecifiedRemaining,
            boundary.makerAmountRemaining,
            takerFee
        );
        // when the amount of swapped out tokens is 0, swapping stops
        if (step.amountOut == 0) return true;

        // updates taker amount input and fee amount input
        state.amountInputCalculated = state.amountInputCalculated + step.amountIn;
        state.feeAmountInputCalculated = state.feeAmountInputCalculated + step.feeAmount;
        state.amountOutputCalculated = state.amountOutputCalculated + step.amountOut;
        state.amountSpecifiedRemaining = state.amountSpecifiedRemaining < 0
            ? state.amountSpecifiedRemaining + int256(uint256(step.amountOut))
            : state.amountSpecifiedRemaining - step.amountIn.toInt256() - int256(uint256(step.feeAmount));

        {
            Bundle storage bundle0 = bundles[boundary.bundle0Id];
            UpdateBundleForTakerParameters memory parameters = bundle0.updateForTaker(
                step.amountIn,
                step.amountOut,
                step.feeAmount
            );
            emit ChangeBundleForSwap(
                boundary.bundle0Id,
                -int256(uint256(parameters.amountOutUsed)),
                parameters.amountInUsed,
                parameters.takerFeeForMakerAmountUsed
            );

            // bundle0 has been fully filled
            if (bundle0.makerAmountRemaining == 0) {
                _activateBundle1(boundary);

                if (parameters.amountOutRemaining > 0) {
                    Bundle storage bundle1 = bundles[boundary.bundle0Id];
                    parameters = bundle1.updateForTaker(
                        parameters.amountInRemaining,
                        parameters.amountOutRemaining,
                        parameters.takerFeeForMakerAmountRemaining
                    );
                    emit ChangeBundleForSwap(
                        boundary.bundle0Id,
                        -int256(uint256(parameters.amountOutUsed)),
                        parameters.amountInUsed,
                        parameters.takerFeeForMakerAmountUsed
                    );
                    // bundle1 has been fully filled
                    if (bundle1.makerAmountRemaining == 0) {
                        _activateBundle1(boundary);
                    }
                }
            }
        }

        // updates remaining maker amount
        uint128 makerAmountRemaining;
        unchecked {
            makerAmountRemaining = boundary.makerAmountRemaining - step.amountOut;
        }
        boundary.makerAmountRemaining = makerAmountRemaining;
        // this boundary has been fully filled
        if (makerAmountRemaining == 0) counterBoundaryBitmap.flipBoundary(boundaryNext, resolution);

        state.priceX96 = step.priceNextX96;
        // when the price has reached the specified lower price, the boundary should equal to boundaryNext,
        // otherwise swapping stops and the boundary is recomputed
        state.boundary = boundaryNext;
        state.boundaryLower = boundaryNext;

        return false;
    }

    function _processTransferForSwap(
        SwapState memory state,
        address recipient,
        bytes calldata data
    ) private returns (int256 amount0, int256 amount1) {
        uint256 amountInputTotal = state.amountInputCalculated + state.feeAmountInputCalculated;
        uint256 amountOutputTotal = state.amountOutputCalculated;
        address tokenToPay;
        address tokenToReceive;
        (tokenToPay, tokenToReceive, amount0, amount1) = state.zeroForOne
            ? (token1, token0, SafeCast.toInt256(amountInputTotal), -SafeCast.toInt256(amountOutputTotal))
            : (token0, token1, -SafeCast.toInt256(amountOutputTotal), SafeCast.toInt256(amountInputTotal));

        // pays token to recipient
        SafeERC20.safeTransfer(IERC20(tokenToPay), recipient, amountOutputTotal);

        uint256 balanceBefore = IERC20(tokenToReceive).balanceOf(address(this));
        // receives token
        IGridSwapCallback(_msgSender()).gridexSwapCallback(amount0, amount1, data);
        uint256 balanceAfter = IERC20(tokenToReceive).balanceOf(address(this));
        // G_TRF: token to receive failed
        require(balanceAfter - balanceBefore >= amountInputTotal, "G_TRF");
    }

    /// @inheritdoc IGrid
    function settleMakerOrder(uint256 orderId) external override lock returns (uint128 amount0, uint128 amount1) {
        (amount0, amount1) = _settleMakerOrder(orderId);

        TokensOwed storage tokensOwed = tokensOweds[_msgSender()];
        if (amount0 > 0) tokensOwed.token0 = tokensOwed.token0 + amount0;
        if (amount1 > 0) tokensOwed.token1 = tokensOwed.token1 + amount1;
    }

    function _settleMakerOrder(uint256 orderId) private returns (uint128 amount0, uint128 amount1) {
        (bool zero, uint128 makerAmountOut, uint128 takerAmountOut, uint128 takerFeeAmountOut) = _processSettleOrder(
            orderId
        );
        (amount0, amount1) = zero
            ? (makerAmountOut, takerAmountOut + takerFeeAmountOut)
            : (takerAmountOut + takerFeeAmountOut, makerAmountOut);
    }

    /// @inheritdoc IGrid
    function settleMakerOrderAndCollect(
        address recipient,
        uint256 orderId,
        bool unwrapWETH9
    ) external override lock returns (uint128 amount0, uint128 amount1) {
        (amount0, amount1) = _settleMakerOrder(orderId);

        _collect(recipient, amount0, amount1, unwrapWETH9);
    }

    /// @inheritdoc IGrid
    function settleMakerOrderAndCollectInBatch(
        address recipient,
        uint256[] memory orderIds,
        bool unwrapWETH9
    ) external override lock returns (uint128 amount0Total, uint128 amount1Total) {
        (amount0Total, amount1Total) = _settleMakerOrderInBatch(orderIds);

        _collect(recipient, amount0Total, amount1Total, unwrapWETH9);
    }

    function _settleMakerOrderInBatch(
        uint256[] memory orderIds
    ) private returns (uint128 amount0Total, uint128 amount1Total) {
        for (uint256 i = 0; i < orderIds.length; i++) {
            (
                bool zero,
                uint128 makerAmountOut,
                uint128 takerAmountOut,
                uint128 takerFeeAmountOut
            ) = _processSettleOrder(orderIds[i]);
            (amount0Total, amount1Total) = zero
                ? (amount0Total + makerAmountOut, amount1Total + takerAmountOut + takerFeeAmountOut)
                : (amount0Total + takerAmountOut + takerFeeAmountOut, amount1Total + makerAmountOut);
        }
    }

    function _processSettleOrder(
        uint256 orderId
    ) private returns (bool zero, uint128 makerAmountOut, uint128 takerAmountOut, uint128 takerFeeAmountOut) {
        Order memory order = orders[orderId];
        // G_COO: caller is not the order owner
        require(order.owner == _msgSender(), "G_COO");

        // deletes order from storage
        delete orders[orderId];

        Bundle storage bundle = bundles[order.bundleId];
        zero = bundle.zero;

        uint128 makerAmountTotalNew;
        (makerAmountOut, takerAmountOut, takerFeeAmountOut, makerAmountTotalNew) = bundle.removeLiquidity(order.amount);

        emit ChangeBundleForSettleOrder(
            order.bundleId,
            -int256(uint256(order.amount)),
            -int256(uint256(makerAmountOut))
        );

        // removes liquidity from boundary
        Boundary storage boundary = _boundaryAt(bundle.boundaryLower, zero);
        uint64 bundle0Id = boundary.bundle0Id;
        if (bundle0Id == order.bundleId || boundary.bundle1Id == order.bundleId) {
            uint128 makerAmountRemaining = boundary.makerAmountRemaining - makerAmountOut;
            boundary.makerAmountRemaining = makerAmountRemaining;
            // all bundle liquidity is removed
            if (makerAmountTotalNew == 0) {
                // when the liquidity of bundle0 is fully removed:
                // 1. Activate directly when bundle1 has been initialized
                // 2. Reuse bundle0 to save gas
                if (bundle0Id == order.bundleId && boundary.bundle1Id > 0) _activateBundle1(boundary);
                if (makerAmountRemaining == 0) _flipBoundary(bundle.boundaryLower, zero);
            }
        }

        emit SettleMakerOrder(orderId, makerAmountOut, takerAmountOut, takerFeeAmountOut);
    }

    function _collect(address recipient, uint128 amount0, uint128 amount1, bool unwrapWETH9) private {
        if (amount0 > 0) {
            _collectSingle(recipient, token0, amount0, unwrapWETH9);
        }
        if (amount1 > 0) {
            _collectSingle(recipient, token1, amount1, unwrapWETH9);
        }
        emit Collect(_msgSender(), recipient, amount0, amount1);
    }

    function _collectSingle(address recipient, address token, uint128 amount, bool unwrapWETH9) private {
        if (unwrapWETH9 && token == weth9) {
            IWETHMinimum(token).withdraw(amount);
            Address.sendValue(payable(recipient), amount);
        } else {
            SafeERC20.safeTransfer(IERC20(token), recipient, amount);
        }
    }

    /// @inheritdoc IGrid
    function flash(address recipient, uint256 amount0, uint256 amount1, bytes calldata data) external override lock {
        uint256 balance0Before;
        uint256 balance1Before;

        if (amount0 > 0) {
            balance0Before = _balance0();
            SafeERC20.safeTransfer(IERC20(token0), recipient, amount0);
        }
        if (amount1 > 0) {
            balance1Before = _balance1();
            SafeERC20.safeTransfer(IERC20(token1), recipient, amount1);
        }

        IGridFlashCallback(_msgSender()).gridexFlashCallback(data);

        uint128 paid0;
        uint128 paid1;
        if (amount0 > 0) {
            uint256 balance0After = _balance0();
            paid0 = (balance0After - balance0Before).toUint128();
        }
        if (amount1 > 0) {
            uint256 balance1After = _balance1();
            paid1 = (balance1After - balance1Before).toUint128();
        }

        emit Flash(_msgSender(), recipient, amount0, amount1, paid0, paid1);
    }

    /// @inheritdoc IGrid
    function collect(
        address recipient,
        uint128 amount0Requested,
        uint128 amount1Requested
    ) external override lock returns (uint128 amount0, uint128 amount1) {
        (amount0, amount1) = _collectOwed(tokensOweds[_msgSender()], recipient, amount0Requested, amount1Requested);

        emit Collect(_msgSender(), recipient, amount0, amount1);
    }

    function _collectOwed(
        TokensOwed storage tokensOwed,
        address recipient,
        uint128 amount0Requested,
        uint128 amount1Requested
    ) private returns (uint128 amount0, uint128 amount1) {
        if (amount0Requested > 0) {
            amount0 = Uint128Math.minUint128(amount0Requested, tokensOwed.token0);
            unchecked {
                tokensOwed.token0 = tokensOwed.token0 - amount0;
            }

            SafeERC20.safeTransfer(IERC20(token0), recipient, amount0);
        }
        if (amount1Requested > 0) {
            amount1 = Uint128Math.minUint128(amount1Requested, tokensOwed.token1);
            unchecked {
                tokensOwed.token1 = tokensOwed.token1 - amount1;
            }
            SafeERC20.safeTransfer(IERC20(token1), recipient, amount1);
        }
    }

    function _balance0() private view returns (uint256) {
        return IERC20(token0).balanceOf(address(this));
    }

    function _balance1() private view returns (uint256) {
        return IERC20(token1).balanceOf(address(this));
    }

    /// @dev Returns the next order id
    function _nextOrderId() private returns (uint256 orderId) {
        orderId = ++_orderId;
    }

    /// @dev Returns the next order id in a given batch
    function _nextOrderIdInBatch(uint256 batch) private returns (uint256 orderId) {
        orderId = _orderId;
        _orderId = orderId + batch;
        unchecked {
            return orderId + 1;
        }
    }

    /// @dev Returns the next bundle id
    function _nextBundleId() private returns (uint64 bundleId) {
        bundleId = ++_bundleId;
    }

    /// @dev Creates and returns the next bundle and its corresponding id
    function _nextBundle(int24 boundaryLower, bool zero) private returns (uint64 bundleId, Bundle storage bundle) {
        bundleId = _nextBundleId();
        bundle = bundles[bundleId];
        bundle.boundaryLower = boundaryLower;
        bundle.zero = zero;
    }

    /// @dev Returns a mapping of the boundaries of either token0 or token1
    function _boundaries(bool zero) private view returns (mapping(int24 => Boundary) storage) {
        return zero ? boundaries0 : boundaries1;
    }

    /// @dev Returns the boundary of token0 or token1
    function _boundaryAt(int24 boundary, bool zero) private view returns (Boundary storage) {
        return zero ? boundaries0[boundary] : boundaries1[boundary];
    }

    /// @dev Flip the boundary of token0 or token1
    function _flipBoundary(int24 boundary, bool zero) private {
        _boundaryBitmaps(zero).flipBoundary(boundary, resolution);
    }

    /// @dev Returns the boundary bitmap of token0 or token1
    function _boundaryBitmaps(bool zero) private view returns (mapping(int16 => uint256) storage) {
        return zero ? boundaryBitmaps0 : boundaryBitmaps1;
    }

    /// @dev Closes bundle0 and activates bundle1
    function _activateBundle1(Boundary storage self) internal {
        self.bundle0Id = self.bundle1Id;
        self.bundle1Id = 0;
    }
}

File 2 of 28 : IGrid.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import "./IGridStructs.sol";
import "./IGridParameters.sol";

/// @title The interface for Gridex grid
interface IGrid {
    ///==================================== Grid States  ====================================

    /// @notice The first token in the grid, after sorting by address
    function token0() external view returns (address);

    /// @notice The second token in the grid, after sorting by address
    function token1() external view returns (address);

    /// @notice The step size in initialized boundaries for a grid created with a given fee
    function resolution() external view returns (int24);

    /// @notice The fee paid to the grid denominated in hundredths of a bip, i.e. 1e-6
    function takerFee() external view returns (int24);

    /// @notice The 0th slot of the grid holds a lot of values that can be gas-efficiently accessed
    /// externally as a single method
    /// @return priceX96 The current price of the grid, as a Q64.96
    /// @return boundary The current boundary of the grid
    /// @return blockTimestamp The time the oracle was last updated
    /// @return unlocked Whether the grid is unlocked or not
    function slot0() external view returns (uint160 priceX96, int24 boundary, uint32 blockTimestamp, bool unlocked);

    /// @notice Returns the boundary information of token0
    /// @param boundary The boundary of the grid
    /// @return bundle0Id The unique identifier of bundle0
    /// @return bundle1Id The unique identifier of bundle1
    /// @return makerAmountRemaining The remaining amount of token0 that can be swapped out,
    /// which is the sum of bundle0 and bundle1
    function boundaries0(
        int24 boundary
    ) external view returns (uint64 bundle0Id, uint64 bundle1Id, uint128 makerAmountRemaining);

    /// @notice Returns the boundary information of token1
    /// @param boundary The boundary of the grid
    /// @return bundle0Id The unique identifier of bundle0
    /// @return bundle1Id The unique identifier of bundle1
    /// @return makerAmountRemaining The remaining amount of token1 that can be swapped out,
    /// which is the sum of bundle0 and bundle1
    function boundaries1(
        int24 boundary
    ) external view returns (uint64 bundle0Id, uint64 bundle1Id, uint128 makerAmountRemaining);

    /// @notice Returns 256 packed boundary initialized boolean values for token0
    function boundaryBitmaps0(int16 wordPos) external view returns (uint256 word);

    /// @notice Returns 256 packed boundary initialized boolean values for token1
    function boundaryBitmaps1(int16 wordPos) external view returns (uint256 word);

    /// @notice Returns the amount owed for token0 and token1
    /// @param owner The address of owner
    /// @return token0 The amount of token0 owed
    /// @return token1 The amount of token1 owed
    function tokensOweds(address owner) external view returns (uint128 token0, uint128 token1);

    /// @notice Returns the information of a given bundle
    /// @param bundleId The unique identifier of the bundle
    /// @return boundaryLower The lower boundary of the bundle
    /// @return zero When zero is true, it represents token0, otherwise it represents token1
    /// @return makerAmountTotal The total amount of token0 or token1 that the maker added
    /// @return makerAmountRemaining The remaining amount of token0 or token1 that can be swapped out from the makers
    /// @return takerAmountRemaining The remaining amount of token0 or token1 that have been swapped in from the takers
    /// @return takerFeeAmountRemaining The remaining amount of fees that takers have paid in
    function bundles(
        uint64 bundleId
    )
        external
        view
        returns (
            int24 boundaryLower,
            bool zero,
            uint128 makerAmountTotal,
            uint128 makerAmountRemaining,
            uint128 takerAmountRemaining,
            uint128 takerFeeAmountRemaining
        );

    /// @notice Returns the information of a given order
    /// @param orderId The unique identifier of the order
    /// @return bundleId The unique identifier of the bundle -- represents which bundle this order belongs to
    /// @return owner The address of the owner of the order
    /// @return amount The amount of token0 or token1 to add
    function orders(uint256 orderId) external view returns (uint64 bundleId, address owner, uint128 amount);

    ///==================================== Grid Actions ====================================

    /// @notice Initializes the grid with the given parameters
    /// @dev The caller of this method receives a callback in the form of
    /// IGridPlaceMakerOrderCallback#gridexPlaceMakerOrderCallback.
    /// When initializing the grid, token0 and token1's liquidity must be added simultaneously.
    /// @param parameters The parameters used to initialize the grid
    /// @param data Any data to be passed through to the callback
    /// @return orderIds0 The unique identifiers of the orders for token0
    /// @return orderIds1 The unique identifiers of the orders for token1
    function initialize(
        IGridParameters.InitializeParameters memory parameters,
        bytes calldata data
    ) external returns (uint256[] memory orderIds0, uint256[] memory orderIds1);

    /// @notice Swaps token0 for token1, or vice versa
    /// @dev The caller of this method receives a callback in the form of IGridSwapCallback#gridexSwapCallback
    /// @param recipient The address to receive the output of the swap
    /// @param zeroForOne The swap direction, true for token0 to token1 and false otherwise
    /// @param amountSpecified The amount of the swap, configured as an exactInput (positive)
    /// or an exactOutput (negative)
    /// @param priceLimitX96 Swap price limit: if zeroForOne, the price will not be less than this value after swap,
    /// if oneForZero, it will not be greater than this value after swap, as a Q64.96
    /// @param data Any data to be passed through to the callback
    /// @return amount0 The balance change of the grid's token0. When negative, it will reduce the balance
    /// by the exact amount. When positive, it will increase by at least this amount
    /// @return amount1 The balance change of the grid's token1. When negative, it will reduce the balance
    /// by the exact amount. When positive, it will increase by at least this amount.
    function swap(
        address recipient,
        bool zeroForOne,
        int256 amountSpecified,
        uint160 priceLimitX96,
        bytes calldata data
    ) external returns (int256 amount0, int256 amount1);

    /// @notice Places a maker order on the grid
    /// @dev The caller of this method receives a callback in the form of
    /// IGridPlaceMakerOrderCallback#gridexPlaceMakerOrderCallback
    /// @param parameters The parameters used to place the maker order
    /// @param data Any data to be passed through to the callback
    /// @return orderId The unique identifier of the order
    function placeMakerOrder(
        IGridParameters.PlaceOrderParameters memory parameters,
        bytes calldata data
    ) external returns (uint256 orderId);

    /// @notice Places maker orders on the grid
    /// @dev The caller of this method receives a callback in the form of
    /// IGridPlaceMakerOrderCallback#gridexPlaceMakerOrderCallback
    /// @param parameters The parameters used to place the maker orders
    /// @param data Any data to be passed through to the callback
    /// @return orderIds The unique identifiers of the orders
    function placeMakerOrderInBatch(
        IGridParameters.PlaceOrderInBatchParameters memory parameters,
        bytes calldata data
    ) external returns (uint256[] memory orderIds);

    /// @notice Settles a maker order
    /// @param orderId The unique identifier of the order
    /// @return amount0 The amount of token0 that the maker received
    /// @return amount1 The amount of token1 that the maker received
    function settleMakerOrder(uint256 orderId) external returns (uint128 amount0, uint128 amount1);

    /// @notice Settle maker order and collect
    /// @param recipient The address to receive the output of the settlement
    /// @param orderId The unique identifier of the order
    /// @param unwrapWETH9 Whether to unwrap WETH9 to ETH
    /// @return amount0 The amount of token0 that the maker received
    /// @return amount1 The amount of token1 that the maker received
    function settleMakerOrderAndCollect(
        address recipient,
        uint256 orderId,
        bool unwrapWETH9
    ) external returns (uint128 amount0, uint128 amount1);

    /// @notice Settles maker orders and collects in a batch
    /// @param recipient The address to receive the output of the settlement
    /// @param orderIds The unique identifiers of the orders
    /// @param unwrapWETH9 Whether to unwrap WETH9 to ETH
    /// @return amount0Total The total amount of token0 that the maker received
    /// @return amount1Total The total amount of token1 that the maker received
    function settleMakerOrderAndCollectInBatch(
        address recipient,
        uint256[] memory orderIds,
        bool unwrapWETH9
    ) external returns (uint128 amount0Total, uint128 amount1Total);

    /// @notice For flash swaps. The caller borrows assets and returns them in the callback of the function,
    /// in addition to a fee
    /// @dev The caller of this function receives a callback in the form of IGridFlashCallback#gridexFlashCallback
    /// @param recipient The address which will receive the token0 and token1
    /// @param amount0 The amount of token0 to receive
    /// @param amount1 The amount of token1 to receive
    /// @param data Any data to be passed through to the callback
    function flash(address recipient, uint256 amount0, uint256 amount1, bytes calldata data) external;

    /// @notice Collects tokens owed
    /// @param recipient The address to receive the collected fees
    /// @param amount0Requested The maximum amount of token0 to send.
    /// Set to 0 if fees should only be collected in token1.
    /// @param amount1Requested The maximum amount of token1 to send.
    /// Set to 0 if fees should only be collected in token0.
    /// @return amount0 The amount of fees collected in token0
    /// @return amount1 The amount of fees collected in token1
    function collect(
        address recipient,
        uint128 amount0Requested,
        uint128 amount1Requested
    ) external returns (uint128 amount0, uint128 amount1);
}

File 3 of 28 : IWETHMinimum.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

interface IWETHMinimum {
    function deposit() external payable;

    function transfer(address dst, uint256 wad) external returns (bool);

    function withdraw(uint256) external;

    function approve(address guy, uint256 wad) external returns (bool);

    function balanceOf(address dst) external view returns (uint256);
}

File 4 of 28 : IGridDeployer.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

/// @title A contract interface for deploying grids
/// @notice A grid constructor must use the interface to pass arguments to the grid
/// @dev This is necessary to ensure there are no constructor arguments in the grid contract.
/// This keeps the grid init code hash constant, allowing a CREATE2 address to be computed on-chain gas-efficiently.
interface IGridDeployer {
    struct Parameters {
        address token0;
        address token1;
        int24 resolution;
        int24 takerFee;
        address priceOracle;
        address weth9;
    }

    /// @notice Returns the grid creation code
    function gridCreationCode() external view returns (bytes memory);

    /// @notice Getter for the arguments used in constructing the grid. These are set locally during grid creation
    /// @dev Retrieves grid parameters, after being called by the grid constructor
    /// @return token0 The first token in the grid, after sorting by address
    /// @return token1 The second token in the grid, after sorting by address
    /// @return resolution The step size in initialized boundaries for a grid created with a given fee
    /// @return takerFee The taker fee, denominated in hundredths of a bip (i.e. 1e-6)
    /// @return priceOracle The address of the price oracle contract
    /// @return weth9 The address of the WETH9 contract
    function parameters()
        external
        view
        returns (
            address token0,
            address token1,
            int24 resolution,
            int24 takerFee,
            address priceOracle,
            address weth9
        );
}

File 5 of 28 : IGridEvents.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import "./IGridStructs.sol";

/// @title Events emitted by the grid contract
interface IGridEvents {
    /// @notice Emitted exactly once by a grid when #initialize is first called on the grid
    /// @param priceX96 The initial price of the grid, as a Q64.96
    /// @param boundary The initial boundary of the grid
    event Initialize(uint160 priceX96, int24 boundary);

    /// @notice Emitted when the maker places an order to add liquidity for token0 or token1
    /// @param orderId The unique identifier of the order
    /// @param recipient The address that received the order
    /// @param bundleId The unique identifier of the bundle -- represents which bundle this order belongs to
    /// @param zero When zero is true, it represents token0, otherwise it represents token1
    /// @param boundaryLower The lower boundary of the order
    /// @param amount The amount of token0 or token1 to add
    event PlaceMakerOrder(
        uint256 indexed orderId,
        address indexed recipient,
        uint64 indexed bundleId,
        bool zero,
        int24 boundaryLower,
        uint128 amount
    );

    /// @notice Emitted when settling a single range order
    /// @param orderId The unique identifier of the order
    /// @param makerAmountOut The amount of token0 or token1 that the maker has removed
    /// @param takerAmountOut The amount of token0 or token1 that the taker has submitted
    /// @param takerFeeAmountOut The amount of token0 or token1 fees that the taker has paid
    event SettleMakerOrder(
        uint256 indexed orderId,
        uint128 makerAmountOut,
        uint128 takerAmountOut,
        uint128 takerFeeAmountOut
    );

    /// @notice Emitted when a maker settles an order
    /// @dev When either of the bundle's total maker amount or the remaining maker amount becomes 0,
    /// the bundle is closed
    /// @param bundleId The unique identifier of the bundle
    /// @param makerAmountTotal The change in the total maker amount in the bundle
    /// @param makerAmountRemaining The change in the remaining maker amount in the bundle
    event ChangeBundleForSettleOrder(uint64 indexed bundleId, int256 makerAmountTotal, int256 makerAmountRemaining);

    /// @notice Emitted when a taker is swapping
    /// @dev When the bundle's remaining maker amount becomes 0, the bundle is closed
    /// @param bundleId The unique identifier of the bundle
    /// @param makerAmountRemaining The change in the remaining maker amount in the bundle
    /// @param amountIn The change in the remaining taker amount in the bundle
    /// @param takerFeeAmountIn The change in the remaining taker fee amount in the bundle
    event ChangeBundleForSwap(
        uint64 indexed bundleId,
        int256 makerAmountRemaining,
        uint256 amountIn,
        uint128 takerFeeAmountIn
    );

    /// @notice Emitted by the grid for any swaps between token0 and token1
    /// @param sender The address that initiated the swap call, and that received the callback
    /// @param recipient The address that received the output of the swap
    /// @param amount0 The delta of the token0 balance of the grid
    /// @param amount1 The delta of the token1 balance of the grid
    /// @param priceX96 The price of the grid after the swap, as a Q64.96
    /// @param boundary The log base 1.0001 of the price of the grid after the swap
    event Swap(
        address indexed sender,
        address indexed recipient,
        int256 amount0,
        int256 amount1,
        uint160 priceX96,
        int24 boundary
    );

    /// @notice Emitted by the grid for any flashes of token0/token1
    /// @param sender The address that initiated the flash call, and that received the callback
    /// @param recipient The address that received the tokens from the flash
    /// @param amount0 The amount of token0 that was flashed
    /// @param amount1 The amount of token1 that was flashed
    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee
    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee
    event Flash(
        address indexed sender,
        address indexed recipient,
        uint256 amount0,
        uint256 amount1,
        uint128 paid0,
        uint128 paid1
    );

    /// @notice Emitted when the collected owed fees are withdrawn by the sender
    /// @param sender The address that collects the fees
    /// @param recipient The address that receives the fees
    /// @param amount0 The amount of token0 fees that is withdrawn
    /// @param amount1 The amount of token1 fees that is withdrawn
    event Collect(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);
}

File 6 of 28 : BoundaryMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

library BoundaryMath {
    int24 public constant MIN_BOUNDARY = -527400;
    int24 public constant MAX_BOUNDARY = 443635;

    /// @dev The minimum value that can be returned from #getPriceX96AtBoundary. Equivalent to getPriceX96AtBoundary(MIN_BOUNDARY)
    uint160 internal constant MIN_RATIO = 989314;
    /// @dev The maximum value that can be returned from #getPriceX96AtBoundary. Equivalent to getPriceX96AtBoundary(MAX_BOUNDARY)
    uint160 internal constant MAX_RATIO = 1461300573427867316570072651998408279850435624081;

    /// @dev Checks if a boundary is divisible by a resolution
    /// @param boundary The boundary to check
    /// @param resolution The step size in initialized boundaries for a grid created with a given fee
    /// @return isValid Whether or not the boundary is valid
    function isValidBoundary(int24 boundary, int24 resolution) internal pure returns (bool isValid) {
        return boundary % resolution == 0;
    }

    /// @dev Checks if a boundary is within the valid range
    /// @param boundary The boundary to check
    /// @return inRange Whether or not the boundary is in range
    function isInRange(int24 boundary) internal pure returns (bool inRange) {
        return boundary >= MIN_BOUNDARY && boundary <= MAX_BOUNDARY;
    }

    /// @dev Checks if a price is within the valid range
    /// @param priceX96 The price to check, as a Q64.96
    /// @return inRange Whether or not the price is in range
    function isPriceX96InRange(uint160 priceX96) internal pure returns (bool inRange) {
        return priceX96 >= MIN_RATIO && priceX96 <= MAX_RATIO;
    }

    /// @notice Calculates the price at a given boundary
    /// @dev priceX96 = pow(1.0001, boundary) * 2**96
    /// @param boundary The boundary to calculate the price at
    /// @return priceX96 The price at the boundary, as a Q64.96
    function getPriceX96AtBoundary(int24 boundary) internal pure returns (uint160 priceX96) {
        unchecked {
            uint256 absBoundary = boundary < 0 ? uint256(-int256(boundary)) : uint24(boundary);

            uint256 ratio = absBoundary & 0x1 != 0
                ? 0xfff97272373d413259a46990580e213a
                : 0x100000000000000000000000000000000;
            if (absBoundary & 0x2 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
            if (absBoundary & 0x4 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
            if (absBoundary & 0x8 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
            if (absBoundary & 0x10 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
            if (absBoundary & 0x20 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
            if (absBoundary & 0x40 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
            if (absBoundary & 0x80 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
            if (absBoundary & 0x100 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
            if (absBoundary & 0x200 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
            if (absBoundary & 0x400 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
            if (absBoundary & 0x800 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
            if (absBoundary & 0x1000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
            if (absBoundary & 0x2000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
            if (absBoundary & 0x4000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
            if (absBoundary & 0x8000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
            if (absBoundary & 0x10000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
            if (absBoundary & 0x20000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
            if (absBoundary & 0x40000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;
            if (absBoundary & 0x80000 != 0) ratio = (ratio * 0x149b34ee7ac263) >> 128;

            if (boundary > 0) ratio = type(uint256).max / ratio;

            // this divides by 1<<32 and rounds up to go from a Q128.128 to a Q128.96.
            // due to out boundary input limitations, we then proceed to downcast as the
            // result will always fit within 160 bits.
            // we round up in the division so that getBoundaryAtPriceX96 of the output price is always consistent
            priceX96 = uint160((ratio + 0xffffffff) >> 32);
        }
    }

    /// @notice Calculates the boundary at a given price
    /// @param priceX96 The price to calculate the boundary at, as a Q64.96
    /// @return boundary The boundary at the price
    function getBoundaryAtPriceX96(uint160 priceX96) internal pure returns (int24 boundary) {
        unchecked {
            uint256 ratio = uint256(priceX96) << 32;

            uint256 r = ratio;
            uint256 msb = 0;

            assembly {
                let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(5, gt(r, 0xFFFFFFFF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(4, gt(r, 0xFFFF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(3, gt(r, 0xFF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(2, gt(r, 0xF))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := shl(1, gt(r, 0x3))
                msb := or(msb, f)
                r := shr(f, r)
            }
            assembly {
                let f := gt(r, 0x1)
                msb := or(msb, f)
            }

            if (msb >= 128) r = ratio >> (msb - 127);
            else r = ratio << (127 - msb);

            int256 log_2 = (int256(msb) - 128) << 64;

            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(63, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(62, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(61, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(60, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(59, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(58, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(57, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(56, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(55, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(54, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(53, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(52, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(51, f))
                r := shr(f, r)
            }
            assembly {
                r := shr(127, mul(r, r))
                let f := shr(128, r)
                log_2 := or(log_2, shl(50, f))
            }

            int256 log10001 = log_2 * 127869479499801913173570;
            // 128.128 number

            int24 boundaryLow = int24((log10001 - 1701496478404566090792001455681771637) >> 128);
            int24 boundaryHi = int24((log10001 + 289637967442836604689790891002483458648) >> 128);

            boundary = boundaryLow == boundaryHi ? boundaryLow : getPriceX96AtBoundary(boundaryHi) <= priceX96
                ? boundaryHi
                : boundaryLow;
        }
    }

    /// @dev Returns the lower boundary for the given boundary and resolution.
    /// The lower boundary may not be valid (if out of the boundary range)
    /// @param boundary The boundary to get the lower boundary for
    /// @param resolution The step size in initialized boundaries for a grid created with a given fee
    /// @return boundaryLower The lower boundary for the given boundary and resolution
    function getBoundaryLowerAtBoundary(int24 boundary, int24 resolution) internal pure returns (int24 boundaryLower) {
        unchecked {
            return boundary - (((boundary % resolution) + resolution) % resolution);
        }
    }

    /// @dev Rewrite the lower boundary that is not in the range to a valid value
    /// @param boundaryLower The lower boundary to rewrite
    /// @param resolution The step size in initialized boundaries for a grid created with a given fee
    /// @return validBoundaryLower The valid lower boundary
    function rewriteToValidBoundaryLower(
        int24 boundaryLower,
        int24 resolution
    ) internal pure returns (int24 validBoundaryLower) {
        unchecked {
            if (boundaryLower < MIN_BOUNDARY) return boundaryLower + resolution;
            else if (boundaryLower + resolution > MAX_BOUNDARY) return boundaryLower - resolution;
            else return boundaryLower;
        }
    }
}

File 7 of 28 : IGridStructs.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

interface IGridStructs {
    struct Bundle {
        int24 boundaryLower;
        bool zero;
        uint128 makerAmountTotal;
        uint128 makerAmountRemaining;
        uint128 takerAmountRemaining;
        uint128 takerFeeAmountRemaining;
    }

    struct Boundary {
        uint64 bundle0Id;
        uint64 bundle1Id;
        uint128 makerAmountRemaining;
    }

    struct Order {
        uint64 bundleId;
        address owner;
        uint128 amount;
    }

    struct TokensOwed {
        uint128 token0;
        uint128 token1;
    }

    struct Slot0 {
        uint160 priceX96;
        int24 boundary;
        uint32 blockTimestamp;
        bool unlocked;
    }
}

File 8 of 28 : BoundaryBitmap.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import "./BitMath.sol";
import "./BoundaryMath.sol";

library BoundaryBitmap {
    /// @notice Calculates the position of the bit in the bitmap for a given boundary
    /// @param boundary The boundary for calculating the bit position
    /// @return wordPos The key within the mapping that contains the word storing the bit
    /// @return bitPos The bit position in the word where the flag is stored
    function position(int24 boundary) internal pure returns (int16 wordPos, uint8 bitPos) {
        wordPos = int16(boundary >> 8);
        bitPos = uint8(uint24(boundary));
    }

    /// @notice Flips the boolean value of the initialization state of the given boundary
    /// @param self The mapping that stores the initial state of the boundary
    /// @param boundary The boundary to flip
    /// @param resolution The step size in initialized boundaries for a grid created with a given fee
    function flipBoundary(mapping(int16 => uint256) storage self, int24 boundary, int24 resolution) internal {
        require(boundary % resolution == 0);
        (int16 wordPos, uint8 bitPos) = position(boundary / resolution);
        uint256 mask = 1 << bitPos;
        self[wordPos] ^= mask;
    }

    /// @notice Returns the next initialized boundary as the left boundary (less than)
    /// or the right boundary (more than)
    /// @param self The mapping that stores the initial state of the boundary
    /// @param boundary The starting boundary
    /// @param priceX96 Price of the initial boundary, as a Q64.96
    /// @param currentBoundaryInitialized Whether the starting boundary is initialized or not
    /// @param resolution The step size in initialized boundaries for a grid created with a given fee
    /// @param boundaryLower The starting lower boundary of the grid
    /// @param lte Whether or not to search for the next initialized boundary
    /// to the left (less than or equal to the starting boundary)
    /// @return next The next boundary, regardless of initialization state
    /// @return initialized Whether or not the next boundary is initialized
    /// @return initializedBoundaryLowerPriceX96 If the current boundary has been initialized and can be swapped,
    /// return the current left boundary price, otherwise return 0, as a Q64.96
    /// @return initializedBoundaryUpperPriceX96 If the current boundary has been initialized and can be swapped,
    /// return the current right boundary price, otherwise return 0, as a Q64.96
    function nextInitializedBoundary(
        mapping(int16 => uint256) storage self,
        int24 boundary,
        uint160 priceX96,
        bool currentBoundaryInitialized,
        int24 resolution,
        int24 boundaryLower,
        bool lte
    )
        internal
        view
        returns (
            int24 next,
            bool initialized,
            uint160 initializedBoundaryLowerPriceX96,
            uint160 initializedBoundaryUpperPriceX96
        )
    {
        int24 boundaryUpper = boundaryLower + resolution;
        if (currentBoundaryInitialized) {
            if (lte) {
                uint160 boundaryLowerPriceX96 = BoundaryMath.getPriceX96AtBoundary(boundaryLower);
                if (boundaryLowerPriceX96 < priceX96) {
                    return (
                        boundaryLower,
                        true,
                        boundaryLowerPriceX96,
                        BoundaryMath.getPriceX96AtBoundary(boundaryUpper)
                    );
                }
            } else {
                uint160 boundaryUpperPriceX96 = BoundaryMath.getPriceX96AtBoundary(boundaryUpper);
                if (boundaryUpperPriceX96 > priceX96) {
                    return (
                        boundaryLower,
                        true,
                        BoundaryMath.getPriceX96AtBoundary(boundaryLower),
                        boundaryUpperPriceX96
                    );
                }
            }
        }

        // When the price is rising and the current boundary coincides with the upper boundary, start searching
        // from the lower boundary. Otherwise, start searching from the current boundary
        boundary = !lte && boundaryUpper == boundary ? boundaryLower : boundary;
        while (BoundaryMath.isInRange(boundary)) {
            (next, initialized) = nextInitializedBoundaryWithinOneWord(self, boundary, resolution, lte);
            if (initialized) {
                unchecked {
                    return (
                        next,
                        true,
                        BoundaryMath.getPriceX96AtBoundary(next),
                        BoundaryMath.getPriceX96AtBoundary(next + resolution)
                    );
                }
            }
            boundary = next;
        }
    }

    /// @notice Returns the next initialized boundary contained in the same (or adjacent) word
    /// as the boundary that is either to the left (less than) or right (greater than)
    /// of the given boundary
    /// @param self The mapping that stores the initial state of the boundary
    /// @param boundary The starting boundary
    /// @param resolution The step size in initialized boundaries for a grid created with a given fee
    /// @param lte Whether or not to search to the left (less than or equal to the start boundary)
    /// for the next initialization
    /// @return next The next boundary, regardless of initialization state
    /// @return initialized Whether or not the next boundary is initialized
    function nextInitializedBoundaryWithinOneWord(
        mapping(int16 => uint256) storage self,
        int24 boundary,
        int24 resolution,
        bool lte
    ) internal view returns (int24 next, bool initialized) {
        int24 compressed = boundary / resolution;

        if (lte) {
            // Begin from the word of the next boundary, since the current boundary state is immaterial
            (int16 wordPos, uint8 bitPos) = position(compressed - 1);
            // all the 1s at or to the right of the current bitPos
            uint256 mask = ~uint256(0) >> (type(uint8).max - bitPos);
            uint256 masked = self[wordPos] & mask;

            // If no initialized boundaries exist to the right of the current boundary,
            // return the rightmost boundary in the word
            initialized = masked != 0;
            // Overflow/underflow is possible. The resolution and the boundary should be limited
            // when calling externally to prevent this
            next = initialized
                ? (compressed - 1 - int24(uint24(bitPos - BitMath.mostSignificantBit(masked)))) * resolution
                : (compressed - 1 - int24(uint24(bitPos))) * resolution;
        } else {
            if (boundary < 0 && boundary % resolution != 0) {
                // round towards negative infinity
                --compressed;
            }

            // Begin from the word of the next boundary, since the current boundary state is immaterial
            (int16 wordPos, uint8 bitPos) = position(compressed + 1);
            // all the 1s at or to the left of the bitPos
            uint256 mask = ~uint256(0) << bitPos;
            uint256 masked = self[wordPos] & mask;

            // If no initialized boundaries exist to the left of the current boundary,
            // return the leftmost boundary in the word
            initialized = masked != 0;
            // Overflow/underflow is possible. The resolution and the boundary should be limited
            // when calling externally to prevent this
            next = initialized
                ? (compressed + 1 + int24(uint24(BitMath.leastSignificantBit(masked) - bitPos))) * resolution
                : (compressed + 1 + int24(uint24(type(uint8).max - bitPos))) * resolution;
        }
    }
}

File 9 of 28 : IGridParameters.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

interface IGridParameters {
    /// @dev Parameters for initializing the grid
    struct InitializeParameters {
        /// @dev The initial price of the grid, as a Q64.96.
        /// Price is represented as an amountToken1/amountToken0 Q64.96 value.
        uint160 priceX96;
        /// @dev The address to receive orders
        address recipient;
        /// @dev Represents the order parameters for token0
        BoundaryLowerWithAmountParameters[] orders0;
        /// @dev Represents the order parameters for token1
        BoundaryLowerWithAmountParameters[] orders1;
    }

    /// @dev Parameters for placing an order
    struct PlaceOrderParameters {
        /// @dev The address to receive the order
        address recipient;
        /// @dev When zero is true, it represents token0, otherwise it represents token1
        bool zero;
        /// @dev The lower boundary of the order
        int24 boundaryLower;
        /// @dev The amount of token0 or token1 to add
        uint128 amount;
    }

    struct PlaceOrderInBatchParameters {
        /// @dev The address to receive the order
        address recipient;
        /// @dev When zero is true, it represents token0, otherwise it represents token1
        bool zero;
        BoundaryLowerWithAmountParameters[] orders;
    }

    struct BoundaryLowerWithAmountParameters {
        /// @dev The lower boundary of the order
        int24 boundaryLower;
        /// @dev The amount of token0 or token1 to add
        uint128 amount;
    }

    /// @dev Status during swap
    struct SwapState {
        /// @dev When true, token0 is swapped for token1, otherwise token1 is swapped for token0
        bool zeroForOne;
        /// @dev The remaining amount of the swap, which implicitly configures
        /// the swap as exact input (positive), or exact output (negative)
        int256 amountSpecifiedRemaining;
        /// @dev The calculated amount to be inputted
        uint256 amountInputCalculated;
        /// @dev The calculated amount of fee to be inputted
        uint256 feeAmountInputCalculated;
        /// @dev The calculated amount to be outputted
        uint256 amountOutputCalculated;
        /// @dev The price of the grid, as a Q64.96
        uint160 priceX96;
        uint160 priceLimitX96;
        /// @dev The boundary of the grid
        int24 boundary;
        /// @dev The lower boundary of the grid
        int24 boundaryLower;
        uint160 initializedBoundaryLowerPriceX96;
        uint160 initializedBoundaryUpperPriceX96;
        /// @dev Whether the swap has been completed
        bool stopSwap;
    }

    struct SwapForBoundaryState {
        /// @dev The price indicated by the lower boundary, as a Q64.96
        uint160 boundaryLowerPriceX96;
        /// @dev The price indicated by the upper boundary, as a Q64.96
        uint160 boundaryUpperPriceX96;
        /// @dev The price indicated by the lower or upper boundary, as a Q64.96.
        /// When using token0 to exchange token1, it is equal to boundaryLowerPriceX96,
        /// otherwise it is equal to boundaryUpperPriceX96
        uint160 boundaryPriceX96;
        /// @dev The price of the grid, as a Q64.96
        uint160 priceX96;
    }

    struct UpdateBundleForTakerParameters {
        /// @dev The amount to be swapped in to bundle0
        uint256 amountInUsed;
        /// @dev The remaining amount to be swapped in to bundle1
        uint256 amountInRemaining;
        /// @dev The amount to be swapped out to bundle0
        uint128 amountOutUsed;
        /// @dev The remaining amount to be swapped out to bundle1
        uint128 amountOutRemaining;
        /// @dev The amount to be paid to bundle0
        uint128 takerFeeForMakerAmountUsed;
        /// @dev The amount to be paid to bundle1
        uint128 takerFeeForMakerAmountRemaining;
    }
}

File 10 of 28 : Uint128Math.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

library Uint128Math {
    /// @dev Returns the minimum of the two values
    /// @param a The first value
    /// @param b The second value
    /// @return min The minimum of the two values
    function minUint128(uint128 a, uint128 b) internal pure returns (uint128 min) {
        return a < b ? a : b;
    }

    /// @dev Returns the maximum of the two values
    /// @param a The first value
    /// @param b The second value
    /// @return max The maximum of the two values
    function maxUint128(uint128 a, uint128 b) internal pure returns (uint128 max) {
        return a > b ? a : b;
    }
}

File 11 of 28 : BundleMath.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "../interfaces/IGridStructs.sol";
import "../interfaces/IGridParameters.sol";
import "./FixedPointX128.sol";

library BundleMath {
    using SafeCast for uint256;

    /// @dev Updates for a taker
    /// @param self The bundle
    /// @param amountIn The amount of swapped in token by the taker
    /// @param amountOut The amount of swapped out token by the taker. If amountOut is greater than bundle balance, the difference is transferred to bundle1
    /// @param takerFeeForMakerAmount The fee paid by the taker(excluding the protocol fee). If amountOut is greater than bundle balance, the difference is transferred to bundle1
    function updateForTaker(
        IGridStructs.Bundle storage self,
        uint256 amountIn,
        uint128 amountOut,
        uint128 takerFeeForMakerAmount
    ) internal returns (IGridParameters.UpdateBundleForTakerParameters memory parameters) {
        uint128 makerAmountRemaining = self.makerAmountRemaining;
        // the amount out actually paid to the taker
        parameters.amountOutUsed = amountOut <= makerAmountRemaining ? amountOut : makerAmountRemaining;

        if (parameters.amountOutUsed == amountOut) {
            parameters.amountInUsed = amountIn;

            parameters.takerFeeForMakerAmountUsed = takerFeeForMakerAmount;
        } else {
            parameters.amountInUsed = parameters.amountOutUsed * amountIn / amountOut; // amountOutUsed * amountIn may overflow here
            unchecked {
                parameters.amountInRemaining = amountIn - parameters.amountInUsed;

                parameters.amountOutRemaining = amountOut - parameters.amountOutUsed;

                parameters.takerFeeForMakerAmountUsed = uint128(
                    (uint256(parameters.amountOutUsed) * takerFeeForMakerAmount) / amountOut
                );
                parameters.takerFeeForMakerAmountRemaining =
                    takerFeeForMakerAmount -
                    parameters.takerFeeForMakerAmountUsed;
            }
        }

        // updates maker amount remaining
        unchecked {
            self.makerAmountRemaining = makerAmountRemaining - parameters.amountOutUsed;
        }

        self.takerAmountRemaining = self.takerAmountRemaining + (parameters.amountInUsed).toUint128();

        self.takerFeeAmountRemaining = self.takerFeeAmountRemaining + parameters.takerFeeForMakerAmountUsed;
    }

    /// @notice Maker adds liquidity to the bundle
    /// @param self The bundle to be updated
    /// @param makerAmount The amount of token to be added to the bundle
    function addLiquidity(IGridStructs.Bundle storage self, uint128 makerAmount) internal {
        self.makerAmountTotal = self.makerAmountTotal + makerAmount;
        unchecked {
            self.makerAmountRemaining = self.makerAmountRemaining + makerAmount;
        }
    }

    /// @notice Maker adds liquidity to the bundle
    /// @param self The bundle to be updated
    /// @param makerAmountTotal The total amount of token that the maker has added to the bundle
    /// @param makerAmountRemaining The amount of token that the maker has not yet swapped
    /// @param makerAmount The amount of token to be added to the bundle
    function addLiquidityWithAmount(
        IGridStructs.Bundle storage self,
        uint128 makerAmountTotal,
        uint128 makerAmountRemaining,
        uint128 makerAmount
    ) internal {
        self.makerAmountTotal = makerAmountTotal + makerAmount;
        unchecked {
            self.makerAmountRemaining = makerAmountRemaining + makerAmount;
        }
    }

    /// @notice Maker removes liquidity from the bundle
    /// @param self The bundle to be updated
    /// @param makerAmountRaw The amount of liquidity added by the maker when placing an order
    /// @return makerAmountOut The amount of token0 or token1 that the maker will receive
    /// @return takerAmountOut The amount of token1 or token0 that the maker will receive
    /// @return takerFeeAmountOut The amount of fees that the maker will receive
    /// @return makerAmountTotalNew The remaining amount of liquidity added by the maker
    function removeLiquidity(
        IGridStructs.Bundle storage self,
        uint128 makerAmountRaw
    )
        internal
        returns (uint128 makerAmountOut, uint128 takerAmountOut, uint128 takerFeeAmountOut, uint128 makerAmountTotalNew)
    {
        uint128 makerAmountTotal = self.makerAmountTotal;
        uint128 makerAmountRemaining = self.makerAmountRemaining;
        uint128 takerAmountRemaining = self.takerAmountRemaining;
        uint128 takerFeeAmountRemaining = self.takerFeeAmountRemaining;

        unchecked {
            makerAmountTotalNew = makerAmountTotal - makerAmountRaw;
            self.makerAmountTotal = makerAmountTotalNew;

            // This calculation won't overflow because makerAmountRaw divided by
            // makerAmountTotal will always have a value between 0 and 1 (excluding 0), and
            // multiplying that by a uint128 value won't result in an overflow. So the
            // calculation is designed to work within the constraints of the data types being used,
            // without exceeding their maximum values.
            makerAmountOut = uint128((uint256(makerAmountRaw) * makerAmountRemaining) / makerAmountTotal);
            self.makerAmountRemaining = makerAmountRemaining - makerAmountOut;

            takerAmountOut = uint128((uint256(makerAmountRaw) * takerAmountRemaining) / makerAmountTotal);
            self.takerAmountRemaining = takerAmountRemaining - takerAmountOut;

            takerFeeAmountOut = uint128((uint256(makerAmountRaw) * takerFeeAmountRemaining) / makerAmountTotal);
            self.takerFeeAmountRemaining = takerFeeAmountRemaining - takerFeeAmountOut;
        }
    }
}

File 12 of 28 : IPriceOracle.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

/// @title The interface for the price oracle
interface IPriceOracle {
    /// @notice Emitted when the capacity of the array in which the oracle can store prices has increased.
    /// @param grid The grid address whose capacity has been increased
    /// @param capacityOld Array capacity before the increase in capacity
    /// @param capacityNew Array capacity after the increase in capacity
    event IncreaseCapacity(address indexed grid, uint16 capacityOld, uint16 capacityNew);

    struct GridPriceData {
        /// @dev The block timestamp of the price data
        uint32 blockTimestamp;
        /// @dev The time-cumulative boundary
        int56 boundaryCumulative;
        /// @dev Whether or not the price data is initialized
        bool initialized;
    }

    struct GridOracleState {
        /// @dev The index of the last updated price
        uint16 index;
        /// @dev The array capacity used by the oracle
        uint16 capacity;
        /// @dev The capacity of the array that the oracle can use
        uint16 capacityNext;
    }

    /// @notice Returns the state of the oracle for a given grid
    /// @param grid The grid to retrieve the state of
    /// @return index The index of the last updated price
    /// @return capacity The array capacity used by the oracle
    /// @return capacityNext The capacity of the array that the oracle can use
    function gridOracleStates(address grid) external view returns (uint16 index, uint16 capacity, uint16 capacityNext);

    /// @notice Returns the price data of the oracle for a given grid and index
    /// @param grid The grid to get the price data of
    /// @param index The index of the price data to get
    /// @return blockTimestamp The block timestamp of the price data
    /// @return boundaryCumulative The time-cumulative boundary
    /// @return initialized Whether or not the price data is initialized
    function gridPriceData(
        address grid,
        uint256 index
    ) external view returns (uint32 blockTimestamp, int56 boundaryCumulative, bool initialized);

    /// @notice Register a grid to the oracle using a given token pair and resolution
    /// @param tokenA The contract address of either token0 or token1
    /// @param tokenB The contract address of the other token
    /// @param resolution The step size in initialized boundaries for a grid created with a given fee
    function register(address tokenA, address tokenB, int24 resolution) external;

    /// @notice Update the oracle price
    /// @param boundary The new boundary to write to the oracle
    /// @param blockTimestamp The timestamp of the oracle price to write
    function update(int24 boundary, uint32 blockTimestamp) external;

    /// @notice Increase the storage capacity of the oracle
    /// @param grid The grid whose capacity is to be increased
    /// @param capacityNext Array capacity after increase in capacity
    function increaseCapacity(address grid, uint16 capacityNext) external;

    /// @notice Get the time-cumulative price for a given time
    /// @param grid Get the price of a grid address
    /// @param secondsAgo The time elapsed (in seconds) to get the boundary for
    /// @return boundaryCumulative The time-cumulative boundary for the given time
    function getBoundaryCumulative(address grid, uint32 secondsAgo) external view returns (int56 boundaryCumulative);

    /// @notice Get a list of time-cumulative boundaries for given times
    /// @param grid The grid address to get the boundaries of
    /// @param secondsAgos A list of times elapsed (in seconds) to get the boundaries for
    /// @return boundaryCumulatives The list of time-cumulative boundaries for the given times
    function getBoundaryCumulatives(
        address grid,
        uint32[] calldata secondsAgos
    ) external view returns (int56[] memory boundaryCumulatives);
}

File 13 of 28 : SwapMath.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "./Uint128Math.sol";
import "./FixedPointX96.sol";
import "./FixedPointX192.sol";

library SwapMath {
    using SafeCast for uint256;

    struct ComputeSwapStep {
        /// @dev The price after swapping the amount in/out
        uint160 priceNextX96;
        /// @dev The amount to be swapped in, of either token0 or token1, based on the direction of the swap
        uint256 amountIn;
        /// @dev The amount to be swapped out, of either token0 or token1, based on the direction of the swap
        uint128 amountOut;
        /// @dev The amount of fees paid by the taker
        uint128 feeAmount;
    }

    /// @notice Calculates the result of the swap through the given boundary parameters
    /// @param priceCurrentX96 The current price of the grid, as a Q64.96
    /// @param boundaryPriceX96 It is the upper boundary price when using token1 to exchange for token0.
    /// Otherwise, it is the lower boundary price, as a Q64.96
    /// @param priceLimitX96 The price limit of the swap, as a Q64.96
    /// @param amountRemaining The remaining amount to be swapped in (positive) or swapped out (negative)
    /// @param makerAmount The remaining amount of token0 or token1 that can be swapped out from the makers
    /// @param takerFeePips The taker fee, denominated in hundredths of a bip (i.e. 1e-6)
    /// @return step The result of the swap step
    function computeSwapStep(
        uint160 priceCurrentX96,
        uint160 boundaryPriceX96,
        uint160 priceLimitX96,
        int256 amountRemaining,
        uint128 makerAmount,
        int24 takerFeePips
    ) internal pure returns (ComputeSwapStep memory step) {
        if (amountRemaining > 0) {
            return
                computeSwapStepForExactIn(
                    priceCurrentX96,
                    boundaryPriceX96,
                    priceLimitX96,
                    uint256(amountRemaining),
                    makerAmount,
                    takerFeePips
                );
        } else {
            uint256 absAmountRemaining;
            unchecked {
                absAmountRemaining = uint256(-amountRemaining);
            }
            return
                computeSwapStepForExactOut(
                    priceCurrentX96,
                    boundaryPriceX96,
                    priceLimitX96,
                    // The converted value will not overflow. The maximum amount of liquidity
                    // allowed in each boundary is less than or equal to uint128.
                    absAmountRemaining > makerAmount ? makerAmount : uint128(absAmountRemaining),
                    makerAmount,
                    takerFeePips
                );
        }
    }

    function computeSwapStepForExactIn(
        uint160 priceCurrentX96,
        uint160 boundaryPriceX96,
        uint160 priceLimitX96,
        uint256 takerAmountInRemaining,
        uint128 makerAmount,
        int24 takerFeePips
    ) internal pure returns (ComputeSwapStep memory step) {
        if (!_priceInRange(priceCurrentX96, boundaryPriceX96, priceLimitX96)) {
            return
                _computeSwapStepForExactIn(
                    priceCurrentX96,
                    boundaryPriceX96,
                    takerAmountInRemaining,
                    makerAmount,
                    takerFeePips
                );
        } else {
            step.amountOut = _computeAmountOutForPriceLimit(
                priceCurrentX96,
                boundaryPriceX96,
                priceLimitX96,
                makerAmount
            );

            step = _computeSwapStepForExactOut(
                priceCurrentX96,
                boundaryPriceX96,
                step.amountOut,
                makerAmount,
                takerFeePips
            );
            return
                step.amountIn + step.feeAmount > takerAmountInRemaining // the remaining amount in is not enough to reach the limit price
                    ? _computeSwapStepForExactIn(
                        priceCurrentX96,
                        boundaryPriceX96,
                        takerAmountInRemaining,
                        makerAmount,
                        takerFeePips
                    )
                    : step;
        }
    }

    function _computeSwapStepForExactIn(
        uint160 priceCurrentX96,
        uint160 boundaryPriceX96,
        uint256 takerAmountInRemaining,
        uint128 makerAmount,
        int24 takerFeePips
    ) private pure returns (ComputeSwapStep memory step) {
        bool zeroForOne = priceCurrentX96 >= boundaryPriceX96;

        uint256 takerAmountInWithoutFee = Math.mulDiv(takerAmountInRemaining, 1e6 - uint256(uint24(takerFeePips)), 1e6);

        uint160 priceDeltaX96;
        unchecked {
            priceDeltaX96 = zeroForOne ? priceCurrentX96 - boundaryPriceX96 : boundaryPriceX96 - priceCurrentX96;
        }

        uint256 amountOut;
        if (zeroForOne) {
            // (2 * takerAmountIn * priceCurrent) / (2 - (priceMax - priceCurrent) * takerAmountIn / makerAmount)
            uint256 numerator = 2 * takerAmountInWithoutFee * priceCurrentX96;

            uint256 denominator = Math.mulDiv(
                priceDeltaX96,
                takerAmountInWithoutFee,
                makerAmount,
                Math.Rounding.Up // round up
            );

            amountOut = numerator / (FixedPointX96.Q_2 + denominator);
        } else {
            // ((2 * takerAmountIn * (1/priceCurrent) / (2 - (1/priceMax - 1/priceCurrent) * takerAmountIn / makerAmount))
            // Specifically divide first, then multiply to ensure that the amountOut is smaller
            uint256 numerator = 2 * takerAmountInWithoutFee * (FixedPointX192.Q / priceCurrentX96);

            uint256 reversePriceDeltaX96 = Math.ceilDiv(
                FixedPointX192.Q,
                priceCurrentX96 // round up
            ) - (FixedPointX192.Q / boundaryPriceX96);
            uint256 denominator = Math.mulDiv(
                reversePriceDeltaX96,
                takerAmountInWithoutFee,
                makerAmount,
                Math.Rounding.Up // round up
            );
            amountOut = numerator / (FixedPointX96.Q_2 + denominator);
        }

        if (amountOut > makerAmount) {
            step.priceNextX96 = boundaryPriceX96;
            step.amountOut = makerAmount;
            (step.amountIn, step.feeAmount) = _computeAmountInAndFeeAmount(
                zeroForOne,
                priceCurrentX96,
                boundaryPriceX96,
                makerAmount,
                Math.Rounding.Down,
                takerFeePips
            );
        } else {
            step.amountOut = amountOut.toUint128();
            step.priceNextX96 = _computePriceNextX96(
                zeroForOne,
                priceCurrentX96,
                priceDeltaX96,
                step.amountOut,
                makerAmount
            );
            step.amountIn = takerAmountInWithoutFee;
            unchecked {
                step.feeAmount = (takerAmountInRemaining - takerAmountInWithoutFee).toUint128();
            }
        }
    }

    function computeSwapStepForExactOut(
        uint160 priceCurrentX96,
        uint160 boundaryPriceX96,
        uint160 priceLimitX96,
        uint128 takerAmountOutRemaining,
        uint128 makerAmount,
        int24 takerFeePips
    ) internal pure returns (ComputeSwapStep memory step) {
        // if the limit price is not within the range, it will be calculated directly
        if (!_priceInRange(priceCurrentX96, boundaryPriceX96, priceLimitX96)) {
            return
                _computeSwapStepForExactOut(
                    priceCurrentX96,
                    boundaryPriceX96,
                    takerAmountOutRemaining,
                    makerAmount,
                    takerFeePips
                );
        }

        // otherwise calculate the new takerAmountRemaining value
        uint128 availableAmountOut = _computeAmountOutForPriceLimit(
            priceCurrentX96,
            boundaryPriceX96,
            priceLimitX96,
            makerAmount
        );

        return
            _computeSwapStepForExactOut(
                priceCurrentX96,
                boundaryPriceX96,
                Uint128Math.minUint128(availableAmountOut, takerAmountOutRemaining),
                makerAmount,
                takerFeePips
            );
    }

    /// @dev Checks if the price limit is within the range
    /// @param priceCurrentX96 The current price of the grid, as a Q64.96
    /// @param boundaryPriceX96 It is the upper boundary price when using token1 to exchange for token0.
    /// Otherwise, it is the lower boundary price, as a Q64.96
    /// @param priceLimitX96 The price limit of the swap, as a Q64.96
    /// @return True if the price limit is within the range
    function _priceInRange(
        uint160 priceCurrentX96,
        uint160 boundaryPriceX96,
        uint160 priceLimitX96
    ) private pure returns (bool) {
        return
            priceCurrentX96 >= boundaryPriceX96
                ? (priceLimitX96 > boundaryPriceX96 && priceLimitX96 <= priceCurrentX96)
                : (priceLimitX96 >= priceCurrentX96 && priceLimitX96 < boundaryPriceX96);
    }

    function _computeSwapStepForExactOut(
        uint160 priceCurrentX96,
        uint160 boundaryPriceX96,
        uint128 takerAmountOutRemaining,
        uint128 makerAmount,
        int24 takerFeePips
    ) private pure returns (ComputeSwapStep memory step) {
        bool zeroForOne = priceCurrentX96 >= boundaryPriceX96;

        uint160 priceDeltaX96;
        Math.Rounding priceNextRounding;
        unchecked {
            (priceDeltaX96, priceNextRounding) = zeroForOne
                ? (priceCurrentX96 - boundaryPriceX96, Math.Rounding.Down)
                : (boundaryPriceX96 - priceCurrentX96, Math.Rounding.Up);
        }

        step.priceNextX96 = _computePriceNextX96(
            zeroForOne,
            priceCurrentX96,
            priceDeltaX96,
            takerAmountOutRemaining,
            makerAmount
        );

        (step.amountIn, step.feeAmount) = _computeAmountInAndFeeAmount(
            zeroForOne,
            priceCurrentX96,
            step.priceNextX96,
            takerAmountOutRemaining,
            priceNextRounding,
            takerFeePips
        );
        step.amountOut = takerAmountOutRemaining;
    }

    function _computePriceNextX96(
        bool zeroForOne,
        uint160 priceCurrentX96,
        uint160 priceDeltaX96,
        uint160 takerAmountOut,
        uint128 makerAmount
    ) private pure returns (uint160) {
        uint256 priceDeltaX96WithRate = Math.mulDiv(priceDeltaX96, takerAmountOut, makerAmount, Math.Rounding.Up);
        unchecked {
            return
                zeroForOne
                    ? (priceCurrentX96 - priceDeltaX96WithRate).toUint160()
                    : (priceCurrentX96 + priceDeltaX96WithRate).toUint160();
        }
    }

    function _computeAmountInAndFeeAmount(
        bool zeroForOne,
        uint160 priceCurrentX96,
        uint160 priceNextX96,
        uint128 amountOut,
        Math.Rounding priceNextRounding,
        int24 takerFeePips
    ) private pure returns (uint256 amountIn, uint128 feeAmount) {
        uint160 priceAvgX96;
        unchecked {
            uint256 priceAccumulateX96 = uint256(priceCurrentX96) + priceNextX96;
            priceAccumulateX96 = priceNextRounding == Math.Rounding.Up ? priceAccumulateX96 + 1 : priceAccumulateX96;
            priceAvgX96 = uint160(priceAccumulateX96 >> 1);
        }

        amountIn = zeroForOne
            ? Math.mulDiv(amountOut, FixedPointX96.Q, priceAvgX96, Math.Rounding.Up)
            : Math.mulDiv(priceAvgX96, amountOut, FixedPointX96.Q, Math.Rounding.Up);

        // feeAmount = amountIn * takerFeePips / (1e6 - takerFeePips)
        feeAmount = Math
            .mulDiv(uint24(takerFeePips), amountIn, 1e6 - uint24(takerFeePips), Math.Rounding.Up)
            .toUint128();
    }

    function _computeAmountOutForPriceLimit(
        uint160 priceCurrentX96,
        uint160 boundaryPriceX96,
        uint160 priceLimitX96,
        uint128 makerAmount
    ) private pure returns (uint128 availableAmountOut) {
        uint160 priceLimitDeltaX96;
        uint160 priceMaxDeltaX96;
        unchecked {
            (priceLimitDeltaX96, priceMaxDeltaX96) = priceLimitX96 >= priceCurrentX96
                ? (priceLimitX96 - priceCurrentX96, boundaryPriceX96 - priceCurrentX96)
                : (priceCurrentX96 - priceLimitX96, priceCurrentX96 - boundaryPriceX96);
        }

        uint256 tempX96 = _divUpForPriceX96(priceLimitDeltaX96, priceMaxDeltaX96);
        availableAmountOut = Math.mulDiv(tempX96, makerAmount, FixedPointX96.Q, Math.Rounding.Up).toUint128();
    }

    function _divUpForPriceX96(uint160 aX96, uint160 bX96) private pure returns (uint256) {
        if (aX96 == 0) {
            return 0;
        }
        unchecked {
            // never overflows
            uint256 tempX96 = uint256(aX96) * FixedPointX96.Q;
            // (a + b - 1) / b can overflow on addition, so we distribute
            return (tempX96 - 1) / bX96 + 1;
        }
    }
}

File 14 of 28 : Uint160Math.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

library Uint160Math {
    /// @dev Returns the minimum of the two values
    /// @param a The first value
    /// @param b The second value
    /// @return min The minimum of the two values
    function minUint160(uint160 a, uint160 b) internal pure returns (uint160 min) {
        return a < b ? a : b;
    }

    /// @dev Returns the maximum of the two values
    /// @param a The first value
    /// @param b The second value
    /// @return max The maximum of the two values
    function maxUint160(uint160 a, uint160 b) internal pure returns (uint160 max) {
        return a > b ? a : b;
    }
}

File 15 of 28 : IGridPlaceMakerOrderCallback.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

/// @title Callback for IGrid#placeMakerOrder
/// @notice Any contract that calls IGrid#placeMakerOrder must implement this interface
interface IGridPlaceMakerOrderCallback {
    /// @notice Called to `msg.sender` after executing a place maker order via IGrid#placeMakerOrder
    /// @dev In this implementation, you are required to pay the grid tokens owed for the maker order.
    /// The caller of the method must be a grid deployed by the canonical GridFactory.
    /// At most one of amount0 and amount1 is a positive number
    /// @param amount0 The grid will receive the amount of token0 upon placement of the maker order.
    /// In the receiving case, the callback must send this amount of token0 to the grid
    /// @param amount1 The grid will receive the amount of token1 upon placement of the maker order.
    /// In the receiving case, the callback must send this amount of token1 to the grid
    /// @param data Any data passed through by the caller via the IGrid#placeMakerOrder call
    function gridexPlaceMakerOrderCallback(uint256 amount0, uint256 amount1, bytes calldata data) external;
}

File 16 of 28 : IGridSwapCallback.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

/// @title Callback for IGrid#swap
/// @notice Any contract that calls IGrid#swap must implement this interface
interface IGridSwapCallback {
    /// @notice Called to `msg.sender` after executing a swap via IGrid#swap
    /// @dev In this implementation, you are required to pay the grid tokens owed for the swap.
    /// The caller of the method must be a grid deployed by the canonical GridFactory.
    /// If there is no token swap, both amount0Delta and amount1Delta are 0
    /// @param amount0Delta The grid will send or receive the amount of token0 upon completion of the swap.
    /// In the receiving case, the callback must send this amount of token0 to the grid
    /// @param amount1Delta The grid will send or receive the quantity of token1 upon completion of the swap.
    /// In the receiving case, the callback must send this amount of token1 to the grid
    /// @param data Any data passed through by the caller via the IGrid#swap call
    function gridexSwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external;
}

File 17 of 28 : IGridFlashCallback.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

/// @title Callback for IGrid#flash
/// @notice Any contract that calls IGrid#flash must implement this interface
interface IGridFlashCallback {
    /// @notice Called to `msg.sender` after executing a flash via IGrid#flash
    /// @dev In this implementation, you are required to repay the grid the tokens owed for the flash.
    /// The caller of the method must be a grid deployed by the canonical GridFactory.
    /// @param data Any data passed through by the caller via the IGrid@flash call
    function gridexFlashCallback(bytes calldata data) external;
}

File 18 of 28 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 19 of 28 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`.
        // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.
        // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.
        // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a
        // good first aproximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1;
        uint256 x = a;
        if (x >> 128 > 0) {
            x >>= 128;
            result <<= 64;
        }
        if (x >> 64 > 0) {
            x >>= 64;
            result <<= 32;
        }
        if (x >> 32 > 0) {
            x >>= 32;
            result <<= 16;
        }
        if (x >> 16 > 0) {
            x >>= 16;
            result <<= 8;
        }
        if (x >> 8 > 0) {
            x >>= 8;
            result <<= 4;
        }
        if (x >> 4 > 0) {
            x >>= 4;
            result <<= 2;
        }
        if (x >> 2 > 0) {
            result <<= 1;
        }

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        uint256 result = sqrt(a);
        if (rounding == Rounding.Up && result * result < a) {
            result += 1;
        }
        return result;
    }
}

File 20 of 28 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/SafeCast.sol)

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.2._
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v2.5._
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.2._
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v2.5._
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v2.5._
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v2.5._
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v2.5._
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     *
     * _Available since v3.0._
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toInt248(int256 value) internal pure returns (int248) {
        require(value >= type(int248).min && value <= type(int248).max, "SafeCast: value doesn't fit in 248 bits");
        return int248(value);
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toInt240(int256 value) internal pure returns (int240) {
        require(value >= type(int240).min && value <= type(int240).max, "SafeCast: value doesn't fit in 240 bits");
        return int240(value);
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toInt232(int256 value) internal pure returns (int232) {
        require(value >= type(int232).min && value <= type(int232).max, "SafeCast: value doesn't fit in 232 bits");
        return int232(value);
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.7._
     */
    function toInt224(int256 value) internal pure returns (int224) {
        require(value >= type(int224).min && value <= type(int224).max, "SafeCast: value doesn't fit in 224 bits");
        return int224(value);
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toInt216(int256 value) internal pure returns (int216) {
        require(value >= type(int216).min && value <= type(int216).max, "SafeCast: value doesn't fit in 216 bits");
        return int216(value);
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toInt208(int256 value) internal pure returns (int208) {
        require(value >= type(int208).min && value <= type(int208).max, "SafeCast: value doesn't fit in 208 bits");
        return int208(value);
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toInt200(int256 value) internal pure returns (int200) {
        require(value >= type(int200).min && value <= type(int200).max, "SafeCast: value doesn't fit in 200 bits");
        return int200(value);
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toInt192(int256 value) internal pure returns (int192) {
        require(value >= type(int192).min && value <= type(int192).max, "SafeCast: value doesn't fit in 192 bits");
        return int192(value);
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toInt184(int256 value) internal pure returns (int184) {
        require(value >= type(int184).min && value <= type(int184).max, "SafeCast: value doesn't fit in 184 bits");
        return int184(value);
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toInt176(int256 value) internal pure returns (int176) {
        require(value >= type(int176).min && value <= type(int176).max, "SafeCast: value doesn't fit in 176 bits");
        return int176(value);
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toInt168(int256 value) internal pure returns (int168) {
        require(value >= type(int168).min && value <= type(int168).max, "SafeCast: value doesn't fit in 168 bits");
        return int168(value);
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toInt160(int256 value) internal pure returns (int160) {
        require(value >= type(int160).min && value <= type(int160).max, "SafeCast: value doesn't fit in 160 bits");
        return int160(value);
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toInt152(int256 value) internal pure returns (int152) {
        require(value >= type(int152).min && value <= type(int152).max, "SafeCast: value doesn't fit in 152 bits");
        return int152(value);
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toInt144(int256 value) internal pure returns (int144) {
        require(value >= type(int144).min && value <= type(int144).max, "SafeCast: value doesn't fit in 144 bits");
        return int144(value);
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toInt136(int256 value) internal pure returns (int136) {
        require(value >= type(int136).min && value <= type(int136).max, "SafeCast: value doesn't fit in 136 bits");
        return int136(value);
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128) {
        require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
        return int128(value);
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toInt120(int256 value) internal pure returns (int120) {
        require(value >= type(int120).min && value <= type(int120).max, "SafeCast: value doesn't fit in 120 bits");
        return int120(value);
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toInt112(int256 value) internal pure returns (int112) {
        require(value >= type(int112).min && value <= type(int112).max, "SafeCast: value doesn't fit in 112 bits");
        return int112(value);
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toInt104(int256 value) internal pure returns (int104) {
        require(value >= type(int104).min && value <= type(int104).max, "SafeCast: value doesn't fit in 104 bits");
        return int104(value);
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.7._
     */
    function toInt96(int256 value) internal pure returns (int96) {
        require(value >= type(int96).min && value <= type(int96).max, "SafeCast: value doesn't fit in 96 bits");
        return int96(value);
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toInt88(int256 value) internal pure returns (int88) {
        require(value >= type(int88).min && value <= type(int88).max, "SafeCast: value doesn't fit in 88 bits");
        return int88(value);
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toInt80(int256 value) internal pure returns (int80) {
        require(value >= type(int80).min && value <= type(int80).max, "SafeCast: value doesn't fit in 80 bits");
        return int80(value);
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toInt72(int256 value) internal pure returns (int72) {
        require(value >= type(int72).min && value <= type(int72).max, "SafeCast: value doesn't fit in 72 bits");
        return int72(value);
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64) {
        require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
        return int64(value);
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toInt56(int256 value) internal pure returns (int56) {
        require(value >= type(int56).min && value <= type(int56).max, "SafeCast: value doesn't fit in 56 bits");
        return int56(value);
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toInt48(int256 value) internal pure returns (int48) {
        require(value >= type(int48).min && value <= type(int48).max, "SafeCast: value doesn't fit in 48 bits");
        return int48(value);
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toInt40(int256 value) internal pure returns (int40) {
        require(value >= type(int40).min && value <= type(int40).max, "SafeCast: value doesn't fit in 40 bits");
        return int40(value);
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32) {
        require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
        return int32(value);
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toInt24(int256 value) internal pure returns (int24) {
        require(value >= type(int24).min && value <= type(int24).max, "SafeCast: value doesn't fit in 24 bits");
        return int24(value);
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16) {
        require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
        return int16(value);
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8) {
        require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
        return int8(value);
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     *
     * _Available since v3.0._
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

File 21 of 28 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 22 of 28 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 23 of 28 : BitMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

/// @title BitMath
/// @dev Library for computing the bit properties of unsigned integer
library BitMath {
    /// @notice Returns the index of the most significant bit of the number,
    ///     where the least significant bit is at index 0 and the most significant bit is at index 255
    /// @dev The function satisfies the property:
    ///     x >= 2**mostSignificantBit(x) and x < 2**(mostSignificantBit(x)+1)
    /// @param x the value for which to compute the most significant bit, must be greater than 0
    /// @return r the index of the most significant bit
    function mostSignificantBit(uint256 x) internal pure returns (uint8 r) {
        require(x > 0);

        unchecked {
            if (x >= 0x100000000000000000000000000000000) {
                x >>= 128;
                r += 128;
            }
            if (x >= 0x10000000000000000) {
                x >>= 64;
                r += 64;
            }
            if (x >= 0x100000000) {
                x >>= 32;
                r += 32;
            }
            if (x >= 0x10000) {
                x >>= 16;
                r += 16;
            }
            if (x >= 0x100) {
                x >>= 8;
                r += 8;
            }
            if (x >= 0x10) {
                x >>= 4;
                r += 4;
            }
            if (x >= 0x4) {
                x >>= 2;
                r += 2;
            }
            if (x >= 0x2) {
                r += 1;
            }
        }
    }

    /// @notice Returns the index of the least significant bit of the number,
    ///     where the least significant bit is at index 0 and the most significant bit is at index 255
    /// @dev The function satisfies the property:
    ///     (x & 2**leastSignificantBit(x)) != 0 and (x & (2**(leastSignificantBit(x)) - 1)) == 0)
    /// @param x the value for which to compute the least significant bit, must be greater than 0
    /// @return r the index of the least significant bit
    function leastSignificantBit(uint256 x) internal pure returns (uint8 r) {
        require(x > 0);

        r = 255;
        unchecked {
            if (x & type(uint128).max > 0) {
                r -= 128;
            } else {
                x >>= 128;
            }
            if (x & type(uint64).max > 0) {
                r -= 64;
            } else {
                x >>= 64;
            }
            if (x & type(uint32).max > 0) {
                r -= 32;
            } else {
                x >>= 32;
            }
            if (x & type(uint16).max > 0) {
                r -= 16;
            } else {
                x >>= 16;
            }
            if (x & type(uint8).max > 0) {
                r -= 8;
            } else {
                x >>= 8;
            }
            if (x & 0xf > 0) {
                r -= 4;
            } else {
                x >>= 4;
            }
            if (x & 0x3 > 0) {
                r -= 2;
            } else {
                x >>= 2;
            }
            if (x & 0x1 > 0) {
                r -= 1;
            }
        }
    }
}

File 24 of 28 : FixedPointX128.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

library FixedPointX128 {
    uint160 internal constant RESOLUTION = 1 << 128;
    uint160 internal constant Q = 0x100000000000000000000000000000000;
}

File 25 of 28 : FixedPointX96.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

library FixedPointX96 {
    uint160 internal constant RESOLUTION = 1 << 96;
    uint160 internal constant Q = 0x1000000000000000000000000;
    uint160 internal constant Q_2 = 0x2000000000000000000000000;
}

File 26 of 28 : FixedPointX192.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

library FixedPointX192 {
    uint256 internal constant RESOLUTION = 1 << 192;
    uint256 internal constant Q = 0x1000000000000000000000000000000000000000000000000;
}

File 27 of 28 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 28 of 28 : draft-IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 8500
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"bundleId","type":"uint64"},{"indexed":false,"internalType":"int256","name":"makerAmountTotal","type":"int256"},{"indexed":false,"internalType":"int256","name":"makerAmountRemaining","type":"int256"}],"name":"ChangeBundleForSettleOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"bundleId","type":"uint64"},{"indexed":false,"internalType":"int256","name":"makerAmountRemaining","type":"int256"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"takerFeeAmountIn","type":"uint128"}],"name":"ChangeBundleForSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint128","name":"amount0","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"amount1","type":"uint128"}],"name":"Collect","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"paid0","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"paid1","type":"uint128"}],"name":"Flash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint160","name":"priceX96","type":"uint160"},{"indexed":false,"internalType":"int24","name":"boundary","type":"int24"}],"name":"Initialize","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"uint64","name":"bundleId","type":"uint64"},{"indexed":false,"internalType":"bool","name":"zero","type":"bool"},{"indexed":false,"internalType":"int24","name":"boundaryLower","type":"int24"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"}],"name":"PlaceMakerOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"makerAmountOut","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"takerAmountOut","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"takerFeeAmountOut","type":"uint128"}],"name":"SettleMakerOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"int256","name":"amount0","type":"int256"},{"indexed":false,"internalType":"int256","name":"amount1","type":"int256"},{"indexed":false,"internalType":"uint160","name":"priceX96","type":"uint160"},{"indexed":false,"internalType":"int24","name":"boundary","type":"int24"}],"name":"Swap","type":"event"},{"inputs":[{"internalType":"int24","name":"","type":"int24"}],"name":"boundaries0","outputs":[{"internalType":"uint64","name":"bundle0Id","type":"uint64"},{"internalType":"uint64","name":"bundle1Id","type":"uint64"},{"internalType":"uint128","name":"makerAmountRemaining","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int24","name":"","type":"int24"}],"name":"boundaries1","outputs":[{"internalType":"uint64","name":"bundle0Id","type":"uint64"},{"internalType":"uint64","name":"bundle1Id","type":"uint64"},{"internalType":"uint128","name":"makerAmountRemaining","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int16","name":"","type":"int16"}],"name":"boundaryBitmaps0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int16","name":"","type":"int16"}],"name":"boundaryBitmaps1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"bundles","outputs":[{"internalType":"int24","name":"boundaryLower","type":"int24"},{"internalType":"bool","name":"zero","type":"bool"},{"internalType":"uint128","name":"makerAmountTotal","type":"uint128"},{"internalType":"uint128","name":"makerAmountRemaining","type":"uint128"},{"internalType":"uint128","name":"takerAmountRemaining","type":"uint128"},{"internalType":"uint128","name":"takerFeeAmountRemaining","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint128","name":"amount0Requested","type":"uint128"},{"internalType":"uint128","name":"amount1Requested","type":"uint128"}],"name":"collect","outputs":[{"internalType":"uint128","name":"amount0","type":"uint128"},{"internalType":"uint128","name":"amount1","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint160","name":"priceX96","type":"uint160"},{"internalType":"address","name":"recipient","type":"address"},{"components":[{"internalType":"int24","name":"boundaryLower","type":"int24"},{"internalType":"uint128","name":"amount","type":"uint128"}],"internalType":"struct IGridParameters.BoundaryLowerWithAmountParameters[]","name":"orders0","type":"tuple[]"},{"components":[{"internalType":"int24","name":"boundaryLower","type":"int24"},{"internalType":"uint128","name":"amount","type":"uint128"}],"internalType":"struct IGridParameters.BoundaryLowerWithAmountParameters[]","name":"orders1","type":"tuple[]"}],"internalType":"struct IGridParameters.InitializeParameters","name":"parameters","type":"tuple"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"initialize","outputs":[{"internalType":"uint256[]","name":"orderIds0","type":"uint256[]"},{"internalType":"uint256[]","name":"orderIds1","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"orders","outputs":[{"internalType":"uint64","name":"bundleId","type":"uint64"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint128","name":"amount","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bool","name":"zero","type":"bool"},{"internalType":"int24","name":"boundaryLower","type":"int24"},{"internalType":"uint128","name":"amount","type":"uint128"}],"internalType":"struct IGridParameters.PlaceOrderParameters","name":"parameters","type":"tuple"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"placeMakerOrder","outputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bool","name":"zero","type":"bool"},{"components":[{"internalType":"int24","name":"boundaryLower","type":"int24"},{"internalType":"uint128","name":"amount","type":"uint128"}],"internalType":"struct IGridParameters.BoundaryLowerWithAmountParameters[]","name":"orders","type":"tuple[]"}],"internalType":"struct IGridParameters.PlaceOrderInBatchParameters","name":"parameters","type":"tuple"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"placeMakerOrderInBatch","outputs":[{"internalType":"uint256[]","name":"orderIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resolution","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"settleMakerOrder","outputs":[{"internalType":"uint128","name":"amount0","type":"uint128"},{"internalType":"uint128","name":"amount1","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"orderId","type":"uint256"},{"internalType":"bool","name":"unwrapWETH9","type":"bool"}],"name":"settleMakerOrderAndCollect","outputs":[{"internalType":"uint128","name":"amount0","type":"uint128"},{"internalType":"uint128","name":"amount1","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256[]","name":"orderIds","type":"uint256[]"},{"internalType":"bool","name":"unwrapWETH9","type":"bool"}],"name":"settleMakerOrderAndCollectInBatch","outputs":[{"internalType":"uint128","name":"amount0Total","type":"uint128"},{"internalType":"uint128","name":"amount1Total","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slot0","outputs":[{"internalType":"uint160","name":"priceX96","type":"uint160"},{"internalType":"int24","name":"boundary","type":"int24"},{"internalType":"uint32","name":"blockTimestamp","type":"uint32"},{"internalType":"bool","name":"unlocked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bool","name":"zeroForOne","type":"bool"},{"internalType":"int256","name":"amountSpecified","type":"int256"},{"internalType":"uint160","name":"priceLimitX96","type":"uint160"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swap","outputs":[{"internalType":"int256","name":"amount0","type":"int256"},{"internalType":"int256","name":"amount1","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"takerFee","outputs":[{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokensOweds","outputs":[{"internalType":"uint128","name":"token0","type":"uint128"},{"internalType":"uint128","name":"token1","type":"uint128"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

Deployed Bytecode

0x60806040526004361061016e5760003560e01c80637e071773116100cb578063b703179d1161007f578063dd5f8a7b11610059578063dd5f8a7b146106f5578063f12e768c14610715578063f8421a311461073557600080fd5b8063b703179d1461063a578063d18b83d114610667578063d21220a7146106c157600080fd5b80638455c01d116100b05780638455c01d14610564578063a54cfb2314610584578063a85c38ef146105a457600080fd5b80637e071773146104fc57806380281adb1461053757600080fd5b8063490e6cbc1161012257806360d49d531161010757806360d49d53146103f8578063624ac9a71461041857806371e21495146104c857600080fd5b8063490e6cbc1461037557806356ebe63c1461039757600080fd5b8063285d937911610153578063285d9379146102005780633850c7bd1461028a57806343f0179b1461032e57600080fd5b80630dfe16811461017a578063128acb08146101cb57600080fd5b3661017557005b600080fd5b34801561018657600080fd5b506101ae7f0000000000000000000000002f27118e3d2332afb7d165140cf1bb127ea6975d81565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101d757600080fd5b506101eb6101e63660046151e6565b610763565b604080519283526020830191909152016101c2565b34801561020c57600080fd5b5061025a61021b36600461527d565b60026020526000908152604090205467ffffffffffffffff8082169168010000000000000000810490911690600160801b90046001600160801b031683565b6040805167ffffffffffffffff94851681529390921660208401526001600160801b0316908201526060016101c2565b34801561029657600080fd5b506000546102f4906001600160a01b0381169074010000000000000000000000000000000000000000810460020b9077010000000000000000000000000000000000000000000000810463ffffffff1690600160d81b900460ff1684565b604080516001600160a01b03909516855260029390930b602085015263ffffffff90911691830191909152151560608201526080016101c2565b34801561033a57600080fd5b506103627f00000000000000000000000000000000000000000000000000000000000001f481565b60405160029190910b81526020016101c2565b34801561038157600080fd5b50610395610390366004615298565b610d34565b005b3480156103a357600080fd5b506103d86103b2366004615302565b6009602052600090815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b039384168152929091166020830152016101c2565b34801561040457600080fd5b506103d8610413366004615336565b610f4f565b34801561042457600080fd5b5061048561043336600461537b565b6008602052600090815260409020805460018201546002928301549282900b9260ff6301000000840416926001600160801b0364010000000090910481169280821692600160801b9091048216911686565b6040805160029790970b875294151560208701526001600160801b03938416948601949094529082166060850152811660808401521660a082015260c0016101c2565b3480156104d457600080fd5b506103627f000000000000000000000000000000000000000000000000000000000000000581565b34801561050857600080fd5b506105296105173660046153a5565b60036020526000908152604090205481565b6040519081526020016101c2565b34801561054357600080fd5b506105296105523660046153a5565b60046020526000908152604090205481565b34801561057057600080fd5b506103d861057f3660046153c8565b611045565b34801561059057600080fd5b506103d861059f36600461551b565b6110e7565b3480156105b057600080fd5b506106036105bf3660046155cd565b6006602052600090815260409020805460019091015467ffffffffffffffff8216916801000000000000000090046001600160a01b0316906001600160801b031683565b6040805167ffffffffffffffff90941684526001600160a01b0390921660208401526001600160801b0316908201526060016101c2565b34801561064657600080fd5b5061065a61065536600461567e565b61115b565b6040516101c29190615776565b34801561067357600080fd5b5061025a61068236600461527d565b60016020526000908152604090205467ffffffffffffffff8082169168010000000000000000810490911690600160801b90046001600160801b031683565b3480156106cd57600080fd5b506101ae7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab181565b34801561070157600080fd5b50610529610710366004615789565b61120e565b34801561072157600080fd5b506103d86107303660046155cd565b6112d5565b34801561074157600080fd5b50610755610750366004615820565b611407565b6040516101c29291906158e7565b600080856107b85760405162461bcd60e51b815260206004820152600560248201527f475f41535a00000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b604080516080810182526000546001600160a01b038116825274010000000000000000000000000000000000000000810460020b602083015277010000000000000000000000000000000000000000000000810463ffffffff1692820192909252600160d81b90910460ff1615156060820181905261087b5760405162461bcd60e51b81526004016107af9060208082526004908201527f475f474c00000000000000000000000000000000000000000000000000000000604082015260600190565b8761089e5780600001516001600160a01b0316866001600160a01b0316116108b8565b80600001516001600160a01b0316866001600160a01b0316105b6109045760405162461bcd60e51b815260206004820152600560248201527f475f504c4f00000000000000000000000000000000000000000000000000000060448201526064016107af565b6000805460ff60d81b1916815560408051610180810182528a1515815260208082018b9052918101839052606081018390526080810183905283516001600160a01b0390811660a0830152891660c0820152908301805160020b60e083015251610100820190610994907f00000000000000000000000000000000000000000000000000000000000000056118ea565b60020b81526000602082018190526040820181905260609091018190529091506109be8a15611924565b905060006109cc8b1561193a565b90505b6020830151158015906109e55750826101600151155b15610a9f5760e083015160a08401516101008501805160020b6000908152602085905260408120549151875191948594610a5a94899492939192600160801b9091046001600160801b03161515917f000000000000000000000000000000000000000000000000000000000000000591611950565b6001600160a01b039081166101408a015216610120880152909250905080610a83575050610a9f565b610a8f84848488611a80565b1515610160860152506109cf9050565b83600001516001600160a01b03168360a001516001600160a01b031614610c8457610acd8360a00151611f42565b600290810b60e0850181905260208601516000920b14801590610b0357504290508063ffffffff16856040015163ffffffff1614155b15610bfb5760208501516040517fcc2ef58c00000000000000000000000000000000000000000000000000000000815260029190910b600482015263ffffffff821660248201527f0000000000000000000000009da10a86f57e810a8a1d72f4a874419eb69bf16a6001600160a01b03169063cc2ef58c90604401600060405180830381600087803b158015610b9857600080fd5b505af1158015610bac573d6000803e3d6000fd5b5050600080547fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000063ffffffff86160217905550505b5060a083015160e0840151600080546001600160a01b039093167fffffffffffffffffffffffff000000000000000000000000000000000000000062ffffff9093167401000000000000000000000000000000000000000002929092167fffffffffffffffffff0000000000000000000000000000000000000000000000909316929092171790555b610c90838d8a8a61222b565b90965094506001600160a01b038c16336001600160a01b03167f41e82c9c8c68651be91e14fa6bb6d577822b5f6b66fda7d7f365faed56e2855e88888760a001518860e00151604051610d08949392919093845260208401929092526001600160a01b0316604083015260020b606082015260800190565b60405180910390a350506000805460ff60d81b1916600160d81b17905550919890975095505050505050565b600054600160d81b900460ff16610d8f5760405162461bcd60e51b81526004016107af9060208082526004908201527f475f474c00000000000000000000000000000000000000000000000000000000604082015260600190565b6000805460ff60d81b19168155808515610dd857610dab612533565b9150610dd87f0000000000000000000000002f27118e3d2332afb7d165140cf1bb127ea6975d88886125ec565b8415610e1357610de6612671565b9050610e137f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab188876125ec565b6040517f7b17fb300000000000000000000000000000000000000000000000000000000081523390637b17fb3090610e519087908790600401615955565b600060405180830381600087803b158015610e6b57600080fd5b505af1158015610e7f573d6000803e3d6000fd5b505050506000806000881115610eb1576000610e99612533565b9050610ead610ea88683615998565b6126d9565b9250505b8615610ed4576000610ec1612671565b9050610ed0610ea88583615998565b9150505b60408051898152602081018990526001600160801b03848116828401528316606082015290516001600160a01b038b169133917fab4f19a9f2e46fd590cecef736d778467430de8fd1f41cd7a7e3d23df9a86f4c9181900360800190a350506000805460ff60d81b1916600160d81b17905550505050505050565b600080548190600160d81b900460ff16610fad5760405162461bcd60e51b81526004016107af9060208082526004908201527f475f474c00000000000000000000000000000000000000000000000000000000604082015260600190565b6000805460ff60d81b19168155338152600960205260409020610fd29086868661275c565b604080516001600160801b0380851682528316602082015281519395509193506001600160a01b0388169233927f38c069c2e9bc192f8cf4f1b85be791ccc0d04bb12c4ca71a3fbfe96ea0932dd592908290030190a36000805460ff60d81b1916600160d81b1790559094909350915050565b600080548190600160d81b900460ff166110a35760405162461bcd60e51b81526004016107af9060208082526004908201527f475f474c00000000000000000000000000000000000000000000000000000000604082015260600190565b6000805460ff60d81b191690556110b984612869565b90925090506110ca858383866128b1565b6000805460ff60d81b1916600160d81b1790559094909350915050565b600080548190600160d81b900460ff166111455760405162461bcd60e51b81526004016107af9060208082526004908201527f475f474c00000000000000000000000000000000000000000000000000000000604082015260600190565b6000805460ff60d81b191690556110b98461297f565b600054606090600160d81b900460ff166111b95760405162461bcd60e51b81526004016107af9060208082526004908201527f475f474c00000000000000000000000000000000000000000000000000000000604082015260600190565b6000805460ff60d81b191681558451602086015160408701516111dd929190612a2b565b602087015191935091506111f390828686612b17565b506000805460ff60d81b1916600160d81b1790559392505050565b60008054600160d81b900460ff1661126a5760405162461bcd60e51b81526004016107af9060208082526004908201527f475f474c00000000000000000000000000000000000000000000000000000000604082015260600190565b6000805460ff60d81b1916905561127f612d7a565b905061129e818560000151866020015187604001518860600151612d95565b6112bb846020015185606001516001600160801b03168585612b17565b6000805460ff60d81b1916600160d81b1790559392505050565b600080548190600160d81b900460ff166113335760405162461bcd60e51b81526004016107af9060208082526004908201527f475f474c00000000000000000000000000000000000000000000000000000000604082015260600190565b6000805460ff60d81b1916905561134983612869565b33600090815260096020526040902091935091506001600160801b038316156113a75780546113829084906001600160801b03166159af565b81546fffffffffffffffffffffffffffffffff19166001600160801b03919091161781555b6001600160801b038216156113ec5780546113d3908390600160801b90046001600160801b03166159af565b81546001600160801b03918216600160801b0291161781555b506000805460ff60d81b1916600160d81b1790559092909150565b60005460609081906001600160a01b0316156114655760405162461bcd60e51b815260206004820152600560248201527f475f47414900000000000000000000000000000000000000000000000000000060448201526064016107af565b84516114709061326e565b6114bc5760405162461bcd60e51b815260206004820152600560248201527f475f504f5200000000000000000000000000000000000000000000000000000060448201526064016107af565b6000856040015151116115115760405162461bcd60e51b815260206004820152600560248201527f475f4f4e4500000000000000000000000000000000000000000000000000000060448201526064016107af565b6000856060015151116115665760405162461bcd60e51b815260206004820152600560248201527f475f4f4e4500000000000000000000000000000000000000000000000000000060448201526064016107af565b6040517f9dce66510000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000002f27118e3d2332afb7d165140cf1bb127ea6975d811660048301527f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1811660248301527f000000000000000000000000000000000000000000000000000000000000000560020b60448301527f0000000000000000000000009da10a86f57e810a8a1d72f4a874419eb69bf16a1690639dce665190606401600060405180830381600087803b15801561165357600080fd5b505af1158015611667573d6000803e3d6000fd5b50505050600061167a8660000151611f42565b6040805160808101825288516001600160a01b03908116808352600285900b60208085018290524263ffffffff168587018190526000606090960186905285547fffffffffffffffffff0000000000000000000000000000000000000000000000169093177401000000000000000000000000000000000000000062ffffff891602177fffffffff0000000000ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000090930260ff60d81b1916929092179093558a518451921682528101919091529192507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c95910160405180910390a1600061179b876020015160018960400151612a2b565b809250819550505060006117b9886020015160008a60600151612a2b565b90945090506000806117c9612533565b6117d1612671565b915091506117dc3390565b6001600160a01b0316638f61c9f785858c8c6040518563ffffffff1660e01b815260040161180d94939291906159da565b600060405180830381600087803b15801561182757600080fd5b505af115801561183b573d6000803e3d6000fd5b5050505060008061184a612533565b611852612671565b9092509050856118628584615998565b101580156118795750846118768483615998565b10155b6118c55760405162461bcd60e51b815260206004820152600560248201527f475f54504600000000000000000000000000000000000000000000000000000060448201526064016107af565b50506000805460ff60d81b1916600160d81b1790555094989397509295505050505050565b60008160020b828360020b8560020b81611906576119066159fa565b070160020b81611918576119186159fa565b07830390505b92915050565b60008161193257600461191e565b600392915050565b60008161194857600261191e565b600192915050565b6000808080806119608888615a29565b905088156119fc5785156119b7576000611979886132ae565b90508a6001600160a01b0316816001600160a01b031610156119b157876001826119a2856132ae565b95509550955095505050611a72565b506119fc565b60006119c2826132ae565b90508a6001600160a01b0316816001600160a01b031611156119fa578760016119ea8a6132ae565b8395509550955095505050611a72565b505b85158015611a0f57508a60020b8160020b145b611a19578a611a1b565b865b9a505b611a278b61358a565b15611a7057611a388c8c8a896135cb565b90955093508315611a6857846001611a4f876132ae565b611a5a8b89016132ae565b945094509450945050611a72565b849a50611a1e565b505b975097509750979350505050565b604080516080810182526101208301516001600160a01b0390811682526101408401511660208201526000918101829052606081018290528251611ada578060200151611ad582600001518560a00151613795565b611af1565b8060000151611af182602001518560a001516137bf565b6001600160a01b03908116606084015216604082015282518015611b2f57508260c001516001600160a01b031681606001516001600160a01b031611155b80611b5e57508251158015611b5e57508260c001516001600160a01b031681606001516001600160a01b031610155b15611b6d576001915050611f3a565b600284900b60009081526020868152604080832060608501519185015160c0880151938801518254929594611bd69493909190600160801b90046001600160801b03167f00000000000000000000000000000000000000000000000000000000000001f46137e0565b905080604001516001600160801b031660001415611bfa5760019350505050611f3a565b80602001518560400151611c0e9190615a70565b604086015260608082015190860151611c30916001600160801b031690615a70565b606086015260408101516080860151611c52916001600160801b031690615a70565b60808601526020850151600013611c9c5780606001516001600160801b0316611c7e8260200151613858565b8660200151611c8d9190615a88565b611c979190615a88565b611cb9565b80604001516001600160801b03168560200151611cb99190615afc565b602080870191909152825467ffffffffffffffff16600090815260088252604080822092840151908401516060850151611cf692859290916138f0565b8454604082015191925067ffffffffffffffff16907f700dec44bb198379f48560c2e4ea3ce1a6485d0beaf623dbcead52c7850ff3df90611d3f906001600160801b0316615b70565b835160808501516040805193845260208401929092526001600160801b03169082015260600160405180910390a260018201546001600160801b0316611eb657835468010000000000000000810467ffffffffffffffff166fffffffffffffffffffffffffffffffff1990911617845560608101516001600160801b031615611eb657835467ffffffffffffffff16600090815260086020908152604090912090820151606083015160a0840151611dfa92849290916138f0565b8554604082015191935067ffffffffffffffff16907f700dec44bb198379f48560c2e4ea3ce1a6485d0beaf623dbcead52c7850ff3df90611e43906001600160801b0316615b70565b845160808601516040805193845260208401929092526001600160801b03169082015260600160405180910390a260018101546001600160801b0316611eb457845468010000000000000000810467ffffffffffffffff166fffffffffffffffffffffffffffffffff199091161785555b505b5050604081015182546001600160801b03600160801b8083048216939093038082169384029190921617845590611f1257611f1289887f0000000000000000000000000000000000000000000000000000000000000005613ab7565b50516001600160a01b031660a0850152505050600282900b60e0820181905261010082015260005b949350505050565b600077ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c97908811961790941790921717909117171760808110611fe557607f810383901c9150611fef565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617691b13d180eb882abba64281027ffffffffffffffffffffffffffffffffffeb84dbf2a407dd93f221832f996e78b8101608090811d906fd9e63e52eeeb7828cf1af18004b842588301901d600281810b9083900b1461221c57886001600160a01b0316612201826132ae565b6001600160a01b03161115612216578161221e565b8061221e565b815b9998505050505050505050565b6000806000866060015187604001516122449190615a70565b608088015188519192509060009081906122ba577f0000000000000000000000002f27118e3d2332afb7d165140cf1bb127ea6975d7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16122a385613858565b6122ac90615b70565b6122b587613858565b612317565b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab17f0000000000000000000000002f27118e3d2332afb7d165140cf1bb127ea6975d61230586613858565b61230e86613858565b61231790615b70565b9098509650909250905061232c828a856125ec565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038316906370a082319060240160206040518083038186803b15801561238757600080fd5b505afa15801561239b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123bf9190615ba9565b6040517f8870c4f80000000000000000000000000000000000000000000000000000000081529091503390638870c4f890612404908a908a908e908e906004016159da565b600060405180830381600087803b15801561241e57600080fd5b505af1158015612432573d6000803e3d6000fd5b50506040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600092506001600160a01b03851691506370a082319060240160206040518083038186803b15801561249157600080fd5b505afa1580156124a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c99190615ba9565b9050856124d68383615998565b10156125245760405162461bcd60e51b815260206004820152600560248201527f475f54524600000000000000000000000000000000000000000000000000000060448201526064016107af565b50505050505094509492505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f0000000000000000000000002f27118e3d2332afb7d165140cf1bb127ea6975d6001600160a01b0316906370a08231906024015b60206040518083038186803b1580156125af57600080fd5b505afa1580156125c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e79190615ba9565b905090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261266c908490613b0a565b505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b0316906370a0823190602401612597565b60006001600160801b038211156127585760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201527f323820626974730000000000000000000000000000000000000000000000000060648201526084016107af565b5090565b6000806001600160801b038416156127df5785546127849085906001600160801b0316613bef565b86546fffffffffffffffffffffffffffffffff1981166001600160801b0391821683900382161788559092506127df907f0000000000000000000000002f27118e3d2332afb7d165140cf1bb127ea6975d90879085166125ec565b6001600160801b0383161561286057855461280b908490600160801b90046001600160801b0316613bef565b86546001600160801b03600160801b8083048216849003821602918116919091178855909150612860907f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab190879084166125ec565b94509492505050565b60008060008060008061287b87613c10565b9350935093509350836128985761289281836159af565b836128a3565b826128a382846159af565b909890975095505050505050565b6001600160801b038316156128ec576128ec847f0000000000000000000000002f27118e3d2332afb7d165140cf1bb127ea6975d8584613f37565b6001600160801b0382161561292757612927847f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab18484613f37565b604080516001600160801b0385811682528416602082015281516001600160a01b0387169233927f38c069c2e9bc192f8cf4f1b85be791ccc0d04bb12c4ca71a3fbfe96ea0932dd5929081900390910190a350505050565b60008060005b8351811015612a25576000806000806129b68886815181106129a9576129a9615bc2565b6020026020010151613c10565b9350935093509350836129e757806129ce83896159af565b6129d891906159af565b6129e284886159af565b612a06565b6129f183886159af565b816129fc84896159af565b612a0691906159af565b8097508198505050505050508080612a1d90615bf1565b915050612985565b50915091565b60606000825167ffffffffffffffff811115612a4957612a4961540a565b604051908082528060200260200182016040528015612a72578160200160208202803683370190505b5091506000612a818451614027565b905060005b8451811015612b0d576000858281518110612aa357612aa3615bc2565b60200260200101519050612ac283898984600001518560200151612d95565b82858381518110612ad557612ad5615bc2565b6020908102919091018101919091528101516001938401939290920191612b05906001600160801b031685615a70565b935050612a86565b5050935093915050565b600080600086612b4a577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1600087612b6f565b7f0000000000000000000000002f27118e3d2332afb7d165140cf1bb127ea6975d8660005b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015292955090935091506000906001600160a01b038516906370a082319060240160206040518083038186803b158015612bd257600080fd5b505afa158015612be6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0a9190615ba9565b6040517f8f61c9f70000000000000000000000000000000000000000000000000000000081529091503390638f61c9f790612c4f90869086908b908b906004016159da565b600060405180830381600087803b158015612c6957600080fd5b505af1158015612c7d573d6000803e3d6000fd5b50506040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600092506001600160a01b03871691506370a082319060240160206040518083038186803b158015612cdc57600080fd5b505afa158015612cf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d149190615ba9565b905087612d218383615998565b1015612d6f5760405162461bcd60e51b815260206004820152600560248201527f475f54504600000000000000000000000000000000000000000000000000000060448201526064016107af565b505050505050505050565b6000600560008154612d8b90615bf1565b9182905550919050565b6000816001600160801b031611612dee5760405162461bcd60e51b815260206004820152600560248201527f475f4f415a00000000000000000000000000000000000000000000000000000060448201526064016107af565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f3d8600283900b12801590612e5157506206c4f3612e4b7f000000000000000000000000000000000000000000000000000000000000000584615a29565b60020b13155b8015612e825750612e82827f000000000000000000000000000000000000000000000000000000000000000561403f565b612ece5760405162461bcd60e51b815260206004820152600560248201527f475f49424c00000000000000000000000000000000000000000000000000000060448201526064016107af565b6000612eda8385614056565b805490915060009068010000000000000000900467ffffffffffffffff168015612f285767ffffffffffffffff811660009081526008602052604090209150612f23828561408c565b6130da565b825467ffffffffffffffff1680612fd957612f43868861410d565b85547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff831617865580547fffffffffffffffffffffffff00000000000000000000000000000000ffffffff166401000000006001600160801b0389169081029190911782556001820180546fffffffffffffffffffffffffffffffff19169091179055935091506130d8565b67ffffffffffffffff811660009081526008602052604090208054600182015491945091925082916001600160801b0364010000000090910481169116818110156130c957613028888a61410d565b87547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff84160217885580547fffffffffffffffffffffffff00000000000000000000000000000000ffffffff166401000000006001600160801b038b169081029190911782556001820180546fffffffffffffffffffffffffffffffff19169091179055955093506130d5565b6130d58583838a614178565b50505b505b60405180606001604052808267ffffffffffffffff168152602001886001600160a01b03168152602001856001600160801b0316815250600660008a815260200190815260200160002060008201518160000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060208201518160000160086101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160006101000a8154816001600160801b0302191690836001600160801b031602179055509050508067ffffffffffffffff16876001600160a01b0316897fd0caf2c4677b4d382504eb6b0f15d030d6887b69dbcb3fc302a62fea5a9fc7a789898960405161321893929190921515835260029190910b60208301526001600160801b0316604082015260600190565b60405180910390a48254600160801b90046001600160801b0316806132415761324186886141e6565b61324b85826159af565b84546001600160801b03918216600160801b029116179093555050505050505050565b6000620f18826001600160a01b0383161080159061191e575073fff6fbe64b68d618d47c209fe40b0d8ee6e23c916001600160a01b038316111592915050565b60008060008360020b126132c7578262ffffff166132cf565b8260020b6000035b90506000600182166132e557600160801b6132f7565b6ffff97272373d413259a46990580e213a5b70ffffffffffffffffffffffffffffffffff169050600282161561332b576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b600482161561334a576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6008821615613369576fffcb9843d60f6159c9db58835c9266440260801c5b6010821615613388576fff973b41fa98c081472e6896dfb254c00260801c5b60208216156133a7576fff2ea16466c96a3843ec78b326b528610260801c5b60408216156133c6576ffe5dee046a99a2a811c461f1969c30530260801c5b60808216156133e5576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610100821615613405576ff987a7253ac413176f2b074cf7815e540260801c5b610200821615613425576ff3392b0822b70005940c7a398e4b70f30260801c5b610400821615613445576fe7159475a2c29b7443b29c7fa6e889d90260801c5b610800821615613465576fd097f3bdfd2022b8845ad8f792aa58250260801c5b611000821615613485576fa9f746462d870fdf8a65dc1f90e061e50260801c5b6120008216156134a5576f70d869a156d2a1b890bb3df62baf32f70260801c5b6140008216156134c5576f31be135f97d08fd981231505542fcfa60260801c5b6180008216156134e5576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62010000821615613505576e5d6af8dedb81196699c329225ee6040260801c5b62020000821615613524576d2216e584f5fa1ea926041bedfe980260801c5b62040000821615613541576b048a170391f7dc42444e8fa20260801c5b620800008216156135595766149b34ee7ac2630260801c5b60008460020b131561357a578060001981613576576135766159fa565b0490505b63ffffffff0160201c9392505050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f3d8600283900b1280159061191e5750506206c4f360029190910b131590565b600080806135d98587615c0c565b905083156136aa576000806135fd6135f2600185615c46565b600281900b60081d91565b9092509050600061360f8260ff615c8e565b600184900b600090815260208c9052604090205460001960ff929092169190911c908116801515965090915085613669578860ff8416613650600188615c46565b61365a9190615c46565b6136649190615cb1565b61369f565b886136738261421f565b61367d9085615c8e565b60ff1661368b600188615c46565b6136959190615c46565b61369f9190615cb1565b96505050505061378b565b60008660020b1280156136c857506136c28587615d3e565b60020b15155b156136d9576136d681615d60565b90505b6000806136ea6135f2846001615a29565b600182900b600090815260208c9052604090205460001960ff83161b9081168015159750929450909250908561374d57886137268460ff615c8e565b60ff16613734876001615a29565b61373e9190615a29565b6137489190615cb1565b613784565b8883613758836142c0565b6137629190615c8e565b60ff16613770876001615a29565b61377a9190615a29565b6137849190615cb1565b9650505050505b5094509492505050565b6000816001600160a01b0316836001600160a01b0316116137b657816137b8565b825b9392505050565b6000816001600160a01b0316836001600160a01b0316106137b657816137b8565b6040805160808101825260008082526020820181905291810182905260608101829052908413156138205761381987878787878761447c565b905061384e565b600084900361384a8888886001600160801b03881685116138415784613843565b875b888861451f565b9150505b9695505050505050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211156127585760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e206160448201527f6e20696e7432353600000000000000000000000000000000000000000000000060648201526084016107af565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915260018501546001600160801b039081169084168110156139425780613944565b835b6001600160801b03908116604084018190529085161415613976578482526001600160801b03831660808301526139f7565b836001600160801b03168583604001516001600160801b03166139999190615d84565b6139a39190615da3565b8083528503602083015260408201516001600160801b038186038116606085015280861691811690851602816139db576139db6159fa565b046001600160801b039081166080840181905284031660a08301525b60408201516001870180546fffffffffffffffffffffffffffffffff19169183036001600160801b03169190911790558151613a32906126d9565b6001870154613a519190600160801b90046001600160801b03166159af565b6001870180546001600160801b03928316600160801b0290831617905560808301516002880154613a8292166159af565b60029690960180546fffffffffffffffffffffffffffffffff19166001600160801b0390971696909617909555949350505050565b613ac18183615d3e565b60020b15613ace57600080fd5b600080613ade6135f28486615c0c565b600191820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b6000613b5f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166145859092919063ffffffff16565b80519091501561266c5780806020019051810190613b7d9190615db7565b61266c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016107af565b6000816001600160801b0316836001600160801b0316106137b657816137b8565b60008181526006602090815260408083208151606081018352815467ffffffffffffffff811682526801000000000000000090046001600160a01b03169381018490526001909101546001600160801b0316918101919091528291829182913314613cbd5760405162461bcd60e51b815260206004820152600560248201527f475f434f4f00000000000000000000000000000000000000000000000000000060448201526064016107af565b600086815260066020908152604080832080547fffffffff0000000000000000000000000000000000000000000000000000000016815560010180546fffffffffffffffffffffffffffffffff19169055835167ffffffffffffffff1683526008909152808220805491840151630100000090920460ff1697509190613d44908390614594565b86516040880151949a50929850909650925067ffffffffffffffff16907f7f4039a9e4ce7a4058dd4ca2b91b6b29590b989d4cea256fb3080141cdf3b7e490613d95906001600160801b0316615b70565b613da76001600160801b038a16615b70565b6040805192835260208301919091520160405180910390a28154600090613dd19060020b89614056565b8054855191925067ffffffffffffffff9081169116811480613e0e57508451825468010000000000000000900467ffffffffffffffff9081169116145b15613edd578154600090613e33908a90600160801b90046001600160801b0316615dd4565b83546001600160801b03908116600160801b838316021785559091508416613edb57855167ffffffffffffffff8381169116148015613e885750825468010000000000000000900467ffffffffffffffff1615155b15613ebe57825468010000000000000000810467ffffffffffffffff166fffffffffffffffffffffffffffffffff199091161783555b6001600160801b038116613edb578454613edb9060020b8b6141e6565b505b604080516001600160801b038a81168252898116602083015288168183015290518b917fa9d41f4c7e5cdf552e9bfe6d10327a427231e7905304c308dbf7455b6905556f919081900360600190a250505050509193509193565b808015613f7557507f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b0316836001600160a01b0316145b1561400d576040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526001600160801b03831660048201526001600160a01b03841690632e1a7d4d90602401600060405180830381600087803b158015613fdd57600080fd5b505af1158015613ff1573d6000803e3d6000fd5b5050505061400884836001600160801b0316614705565b614021565b6140218385846001600160801b03166125ec565b50505050565b6005546140348282615a70565b600555600101919050565b600061404b8284615d3e565b60020b159392505050565b60008161407657600283810b6000908152602091909152604090206137b8565b505060020b600090815260016020526040902090565b81546140aa90829064010000000090046001600160801b03166159af565b82547fffffffffffffffffffffffff00000000000000000000000000000000ffffffff166401000000006001600160801b0392831602178355600190920180546fffffffffffffffffffffffffffffffff19811690841692909201909216179055565b60008061411861481e565b67ffffffffffffffff8116600090815260086020526040902080549415156301000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000090951662ffffff909616959095179390931784555090929050565b61418281846159af565b84547fffffffffffffffffffffffff00000000000000000000000000000000ffffffff166401000000006001600160801b0392831602178555600190940180546fffffffffffffffffffffffffffffffff1916919092019093169290921790915550565b61421b827f000000000000000000000000000000000000000000000000000000000000000561421484611924565b9190613ab7565b5050565b600080821161422d57600080fd5b600160801b821061424057608091821c91015b68010000000000000000821061425857604091821c91015b640100000000821061426c57602091821c91015b62010000821061427e57601091821c91015b610100821061428f57600891821c91015b6010821061429f57600491821c91015b600482106142af57600291821c91015b600282106142bb576001015b919050565b60008082116142ce57600080fd5b5060ff6001600160801b03821615614307577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800161430f565b608082901c91505b67ffffffffffffffff821615614346577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00161434e565b604082901c91505b63ffffffff821615614381577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001614389565b602082901c91505b61ffff8216156143ba577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016143c2565b601082901c91505b60ff8216156143f2577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8016143fa565b600882901c91505b600f82161561442a577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc01614432565b600482901c91505b6003821615614462577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0161446a565b600282901c91505b60018216156142bb5760001901919050565b6040805160808101825260008082526020820181905291810182905260608101919091526144ab878787614865565b6144bc5761381987878686866148f4565b6144c887878786614b79565b6001600160801b0316604082018190526144e790889088908686614bef565b90508381606001516001600160801b031682602001516145079190615a70565b116145125780613819565b61381987878686866148f4565b60408051608081018252600080825260208201819052918101829052606081019190915261454e878787614865565b61455f576138198787868686614bef565b600061456d88888887614b79565b905061384a888861457e8489613bef565b8787614bef565b6060611f3a8484600085614c9f565b8154600183015460028401547fffffffffffffffffffffffff00000000000000000000000000000000ffffffff8316640100000000938490046001600160801b039081168681038083169096029290921787556000948594859491939280821692600160801b90920481169181169084908a16840281614616576146166159fa565b0497508783038a60010160006101000a8154816001600160801b0302191690836001600160801b03160217905550836001600160801b0316826001600160801b03168a6001600160801b03160281614670576146706159fa565b0496508682038a60010160106101000a8154816001600160801b0302191690836001600160801b03160217905550836001600160801b0316816001600160801b03168a6001600160801b031602816146ca576146ca6159fa565b0495508581038a60020160006101000a8154816001600160801b0302191690836001600160801b031602179055505050505092959194509250565b804710156147555760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016107af565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146147a2576040519150601f19603f3d011682016040523d82523d6000602084013e6147a7565b606091505b505090508061266c5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016107af565b6007805460009190829061483b9067ffffffffffffffff16615dfc565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055905090565b6000826001600160a01b0316846001600160a01b031610156148b957836001600160a01b0316826001600160a01b0316101580156148b45750826001600160a01b0316826001600160a01b0316105b611f3a565b826001600160a01b0316826001600160a01b0316118015611f3a5750836001600160a01b0316826001600160a01b0316111590509392505050565b6040805160808101825260008082526020820181905291810182905260608101919091526001600160a01b03808616908716101560006149498661494062ffffff8716620f4240615998565b620f4240614de7565b905060008261495a5788880361495e565b8789035b9050600083156149d85760006001600160a01b038b1661497f856002615d84565b6149899190615d84565b905060006149ac846001600160a01b0316868b6001600160801b03166001614e97565b90506149c5816c02000000000000000000000000615a70565b6149cf9083615da3565b92505050614ac4565b6000614a066001600160a01b038c167801000000000000000000000000000000000000000000000000615da3565b614a11856002615d84565b614a1b9190615d84565b90506000614a4b6001600160a01b038c167801000000000000000000000000000000000000000000000000615da3565b614a7778010000000000000000000000000000000000000000000000008e6001600160a01b0316614ef4565b614a819190615998565b90506000614a9b82878c6001600160801b03166001614e97565b9050614ab4816c02000000000000000000000000615a70565b614abe9084615da3565b93505050505b866001600160801b0316811115614b17576001600160a01b03891685526001600160801b0387166040860152614aff848b8b8a60008b614f2b565b6001600160801b031660608701526020860152614b6c565b614b20816126d9565b6001600160801b031660408601819052614b409085908c9085908b615001565b6001600160a01b0316855260208501839052614b5d8389036126d9565b6001600160801b031660608601525b5050505095945050505050565b6000806000866001600160a01b0316856001600160a01b03161015614ba357848703868803614baa565b8685038787035b90925090506000614bbb8383615060565b9050614be3610ea8826001600160801b0388166c010000000000000000000000006001614e97565b98975050505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526001600160a01b03808616908716101560008082614c35578888036001614c3b565b87890360005b9092509050614c56838a846001600160801b038b168a615001565b6001600160a01b0316808552614c729084908b908a858a614f2b565b6001600160801b039081166060870152602086019190915296909616604084015250909695505050505050565b606082471015614d175760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016107af565b6001600160a01b0385163b614d6e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107af565b600080866001600160a01b03168587604051614d8a9190615e50565b60006040518083038185875af1925050503d8060008114614dc7576040519150601f19603f3d011682016040523d82523d6000602084013e614dcc565b606091505b5091509150614ddc8282866150b4565b979650505050505050565b600080806000198587098587029250828110838203039150508060001415614e2257838281614e1857614e186159fa565b04925050506137b8565b808411614e2e57600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b600080614ea5868686614de7565b90506001836002811115614ebb57614ebb615e6c565b148015614ed8575060008480614ed357614ed36159fa565b868809115b15614eeb57614ee8600182615a70565b90505b95945050505050565b60008215614f225781614f08600185615998565b614f129190615da3565b614f1d906001615a70565b6137b8565b50600092915050565b600080806001600160a01b03888116908816016001866002811115614f5257614f52615e6c565b14614f5d5780614f62565b806001015b60011c9150899050614f9f57614f9a6001600160a01b0382166001600160801b0388166c010000000000000000000000006001614e97565b614fcb565b614fcb6001600160801b0387166c010000000000000000000000006001600160a01b0384166001614e97565b9250614ff3610ea862ffffff861685614fe788620f4240615e9b565b62ffffff166001614e97565b915050965096945050505050565b60008061502c856001600160a01b0316856001600160a01b0316856001600160801b03166001614e97565b90508661504c5761504781876001600160a01b0316016150ed565b614ddc565b614ddc81876001600160a01b0316036150ed565b60006001600160a01b0383166150785750600061191e565b6001600160a01b038381166c01000000000000000000000000029083166000198201816150a7576150a76159fa565b0460010191505092915050565b606083156150c35750816137b8565b8251156150d35782518084602001fd5b8160405162461bcd60e51b81526004016107af9190615eb7565b60006001600160a01b038211156127585760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201527f363020626974730000000000000000000000000000000000000000000000000060648201526084016107af565b6001600160a01b038116811461518157600080fd5b50565b801515811461518157600080fd5b80356142bb81615184565b60008083601f8401126151af57600080fd5b50813567ffffffffffffffff8111156151c757600080fd5b6020830191508360208285010111156151df57600080fd5b9250929050565b60008060008060008060a087890312156151ff57600080fd5b863561520a8161516c565b9550602087013561521a81615184565b94506040870135935060608701356152318161516c565b9250608087013567ffffffffffffffff81111561524d57600080fd5b61525989828a0161519d565b979a9699509497509295939492505050565b8035600281900b81146142bb57600080fd5b60006020828403121561528f57600080fd5b6137b88261526b565b6000806000806000608086880312156152b057600080fd5b85356152bb8161516c565b94506020860135935060408601359250606086013567ffffffffffffffff8111156152e557600080fd5b6152f18882890161519d565b969995985093965092949392505050565b60006020828403121561531457600080fd5b81356137b88161516c565b80356001600160801b03811681146142bb57600080fd5b60008060006060848603121561534b57600080fd5b83356153568161516c565b92506153646020850161531f565b91506153726040850161531f565b90509250925092565b60006020828403121561538d57600080fd5b813567ffffffffffffffff811681146137b857600080fd5b6000602082840312156153b757600080fd5b81358060010b81146137b857600080fd5b6000806000606084860312156153dd57600080fd5b83356153e88161516c565b92506020840135915060408401356153ff81615184565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561545c5761545c61540a565b60405290565b6040516060810167ffffffffffffffff8111828210171561545c5761545c61540a565b6040516080810167ffffffffffffffff8111828210171561545c5761545c61540a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156154ef576154ef61540a565b604052919050565b600067ffffffffffffffff8211156155115761551161540a565b5060051b60200190565b60008060006060848603121561553057600080fd5b833561553b8161516c565b925060208481013567ffffffffffffffff81111561555857600080fd5b8501601f8101871361556957600080fd5b803561557c615577826154f7565b6154a8565b81815260059190911b8201830190838101908983111561559b57600080fd5b928401925b828410156155b9578335825292840192908401906155a0565b809650505050505061537260408501615192565b6000602082840312156155df57600080fd5b5035919050565b600082601f8301126155f757600080fd5b81356020615607615577836154f7565b82815260069290921b8401810191818101908684111561562657600080fd5b8286015b8481101561567357604081890312156156435760008081fd5b61564b615439565b6156548261526b565b815261566185830161531f565b8186015283529183019160400161562a565b509695505050505050565b60008060006040848603121561569357600080fd5b833567ffffffffffffffff808211156156ab57600080fd5b90850190606082880312156156bf57600080fd5b6156c7615462565b82356156d28161516c565b815260208301356156e281615184565b60208201526040830135828111156156f957600080fd5b615705898286016155e6565b6040830152509450602086013591508082111561572157600080fd5b5061572e8682870161519d565b9497909650939450505050565b600081518084526020808501945080840160005b8381101561576b5781518752958201959082019060010161574f565b509495945050505050565b6020815260006137b8602083018461573b565b600080600083850360a081121561579f57600080fd5b60808112156157ad57600080fd5b506157b6615485565b84356157c18161516c565b815260208501356157d181615184565b60208201526157e26040860161526b565b60408201526157f36060860161531f565b60608201529250608084013567ffffffffffffffff81111561581457600080fd5b61572e8682870161519d565b60008060006040848603121561583557600080fd5b833567ffffffffffffffff8082111561584d57600080fd5b908501906080828803121561586157600080fd5b615869615485565b82356158748161516c565b815260208301356158848161516c565b602082015260408301358281111561589b57600080fd5b6158a7898286016155e6565b6040830152506060830135828111156158bf57600080fd5b6158cb898286016155e6565b6060830152509450602086013591508082111561572157600080fd5b6040815260006158fa604083018561573b565b8281036020840152614eeb818561573b565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000611f3a60208301848661590c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156159aa576159aa615969565b500390565b60006001600160801b038083168185168083038211156159d1576159d1615969565b01949350505050565b84815283602082015260606040820152600061384e60608301848661590c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008160020b8360020b6000821282627fffff03821381151615615a4f57615a4f615969565b82627fffff19038212811615615a6757615a67615969565b50019392505050565b60008219821115615a8357615a83615969565b500190565b6000808312837f800000000000000000000000000000000000000000000000000000000000000001831281151615615ac257615ac2615969565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018313811615615af657615af6615969565b50500390565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615b3657615b36615969565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615b6a57615b6a615969565b50500190565b60007f8000000000000000000000000000000000000000000000000000000000000000821415615ba257615ba2615969565b5060000390565b600060208284031215615bbb57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000600019821415615c0557615c05615969565b5060010190565b60008160020b8360020b80615c2357615c236159fa565b6000198114627fffff1983141615615c3d57615c3d615969565b90059392505050565b60008160020b8360020b6000811281627fffff1901831281151615615c6d57615c6d615969565b81627fffff018313811615615c8457615c84615969565b5090039392505050565b600060ff821660ff841680821015615ca857615ca8615969565b90039392505050565b60008160020b8360020b627fffff600082136000841383830485118282161615615cdd57615cdd615969565b627fffff196000851286820586128184161615615cfc57615cfc615969565b60008712925085820587128484161615615d1857615d18615969565b85850587128184161615615d2e57615d2e615969565b5050509290910295945050505050565b60008260020b80615d5157615d516159fa565b808360020b0791505092915050565b60008160020b627fffff19811415615d7a57615d7a615969565b6000190192915050565b6000816000190483118215151615615d9e57615d9e615969565b500290565b600082615db257615db26159fa565b500490565b600060208284031215615dc957600080fd5b81516137b881615184565b60006001600160801b0383811690831681811015615df457615df4615969565b039392505050565b600067ffffffffffffffff80831681811415615e1a57615e1a615969565b6001019392505050565b60005b83811015615e3f578181015183820152602001615e27565b838111156140215750506000910152565b60008251615e62818460208701615e24565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600062ffffff83811690831681811015615df457615df4615969565b6020815260008251806020840152615ed6816040850160208701615e24565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220149d394a07615e309a8e667a845d7982bc69068d58b46398e27bc077234037a064736f6c63430008090033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.