ETH Price: $2,936.33 (-0.77%)

Contract

0x60BF64CCAa52da304d456892dC0A8f1C5B159f61
 

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Claim31759332024-05-08 9:48:01626 days ago1715161681IN
Baseline Protocol : PreAsset
0 ETH0.0000080.01986549
Claim24015762024-04-20 11:36:07644 days ago1713612967IN
Baseline Protocol : PreAsset
0 ETH0.000009970.00097027
Claim20214532024-04-11 16:25:21653 days ago1712852721IN
Baseline Protocol : PreAsset
0 ETH0.000038140.00100035
Claim20214192024-04-11 16:24:13653 days ago1712852653IN
Baseline Protocol : PreAsset
0 ETH0.000037020.00100035
Claim13231282024-03-26 12:27:51669 days ago1711456071IN
Baseline Protocol : PreAsset
0 ETH0.000037650.00100065
Claim13231052024-03-26 12:27:05669 days ago1711456025IN
Baseline Protocol : PreAsset
0 ETH0.000035520.00100068
Claim13230462024-03-26 12:25:07669 days ago1711455907IN
Baseline Protocol : PreAsset
0 ETH0.000035850.00100075
Claim13230242024-03-26 12:24:23669 days ago1711455863IN
Baseline Protocol : PreAsset
0 ETH0.000035780.00100078
Claim13229262024-03-26 12:21:07669 days ago1711455667IN
Baseline Protocol : PreAsset
0 ETH0.00003210.00100093
Claim13224672024-03-26 12:05:49669 days ago1711454749IN
Baseline Protocol : PreAsset
0 ETH0.000035830.0010003
Claim12942652024-03-25 20:25:45670 days ago1711398345IN
Baseline Protocol : PreAsset
0 ETH0.000049840.00100029
Claim12635842024-03-25 3:23:03671 days ago1711336983IN
Baseline Protocol : PreAsset
0 ETH0.000025950.00094119
Claim12137342024-03-23 23:41:23672 days ago1711237283IN
Baseline Protocol : PreAsset
0 ETH0.000022760.00083325
Claim12136702024-03-23 23:39:15672 days ago1711237155IN
Baseline Protocol : PreAsset
0 ETH0.000021920.00054408
Claim11973732024-03-23 14:36:01672 days ago1711204561IN
Baseline Protocol : PreAsset
0 ETH0.000032090.00097028
Claim11973012024-03-23 14:33:37672 days ago1711204417IN
Baseline Protocol : PreAsset
0 ETH0.000033280.00083325
Claim9685212024-03-18 7:27:37677 days ago1710746857IN
Baseline Protocol : PreAsset
0 ETH0.000028110.00000056
Claim9581522024-03-18 1:41:59678 days ago1710726119IN
Baseline Protocol : PreAsset
0 ETH0.000036610.00097025
Claim6579642024-03-11 2:55:43685 days ago1710125743IN
Baseline Protocol : PreAsset
0 ETH0.00005670.00000026
Claim6579342024-03-11 2:54:43685 days ago1710125683IN
Baseline Protocol : PreAsset
0 ETH0.000052030.00000026
Claim6579112024-03-11 2:53:57685 days ago1710125637IN
Baseline Protocol : PreAsset
0 ETH0.000053440.00000026
Claim5534992024-03-08 16:53:33687 days ago1709916813IN
Baseline Protocol : PreAsset
0 ETH0.000100930.003
Claim4673752024-03-06 17:02:45689 days ago1709744565IN
Baseline Protocol : PreAsset
0 ETH0.000279541.50000026
Claim4535382024-03-06 9:21:31689 days ago1709716891IN
Baseline Protocol : PreAsset
0 ETH0.000184681.50012823
Claim4520812024-03-06 8:32:57689 days ago1709713977IN
Baseline Protocol : PreAsset
0 ETH0.000205521.50012863
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PreAsset

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 0 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity =0.8.23;

import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol";
import {MerkleProofLib} from "solady/utils/MerkleProofLib.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";
import {Owned} from "solmate/auth/Owned.sol";

import {IERC20Rebasing, YieldMode} from "../interfaces/IBlast.sol";

import {BAsset} from "./bAsset.sol";
import {BlastClaimer} from "./BlastClaimer.sol";

contract PreAsset is Owned {

    ERC20 public immutable reserve;
    bytes32 public immutable merkleRoot;
    address public immutable baselineFactory;
    uint256 public immutable deployTime;

    // allow anyone to abort presale after `timeLimit` from `deployTime`
    uint256 public constant timeLimit = 2 weeks;

    BAsset public bAsset;
    bool public active;
    uint256 public totalDeposits;
    mapping(address => uint256) public whitelist;
    mapping(address => uint256) public deposits;

    event Deposit(address indexed user, uint256 amount);
    event Claim(address indexed user, uint256 amount);
    event Withdraw(address indexed user, uint256 amount);
    event Seeded(uint256 amount);
    event Aborted();

    error InvalidCaller();
    error InvalidInput();
    error InvalidWithdraw();
    error MaxDepositExceeded();
    error MintInactive();
    error MintActive();
    error ClaimNotAvailable();

    constructor(
        ERC20 reserve_,
        address baselineFactory_,
        address owner_,
        bytes32 merkleRoot_
    ) Owned(owner_) {
        // set immutable variables
        reserve = reserve_;
        baselineFactory = baselineFactory_;
        merkleRoot = merkleRoot_;
        deployTime = block.timestamp;

        // turn on minting
        active = true;

        BlastClaimer.configure(owner_);
        IERC20Rebasing(address(reserve)).configure(YieldMode.CLAIMABLE);
    }

    // Verify user deposit against merkle tree and deposit
    function deposit(
        uint256 amount_,
        uint256 limit_,
        bytes32[] calldata proofs_
    ) external {

        // Verify user
        bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(msg.sender, limit_))));
        if (!MerkleProofLib.verifyCalldata(proofs_, merkleRoot, leaf)) revert InvalidCaller();

        _deposit(amount_, limit_);
    }

    // Verify user deposit against whitelist and deposit
    function whitelistDeposit(uint256 amount_) external {
        _deposit(amount_, whitelist[msg.sender]);
    }

    function _deposit(uint256 amount_, uint256 limit_) internal {
        if (amount_ == 0) revert InvalidInput();

        // If mint has ended revert
        if (!active) revert MintInactive();

        // If user has already deposited the max amount, revert
        if ((deposits[msg.sender] += amount_) > limit_) revert MaxDepositExceeded();

        // Take reserves
        totalDeposits += amount_;
        reserve.transferFrom(msg.sender, address(this), amount_);

        emit Deposit(msg.sender, amount_);
    }

    // Claim bAssets
    function claim() external returns (uint256){
        // Cannot claim while mint is active
        if (active) revert MintActive();

        // Cannot claim if there are no bAssets in the contract or if user has no deposits
        uint256 totalBAssets = bAsset.balanceOf(address(this));
        uint256 depositAmount = deposits[msg.sender];
        if (totalBAssets == 0 || depositAmount == 0) revert ClaimNotAvailable();

        // Calculate amount claimable
        uint256 percent = depositAmount * 1e18 / totalDeposits;
        uint256 claimable = percent * totalBAssets / 1e18;

        // Update state
        totalDeposits -= depositAmount;
        deposits[msg.sender] = 0;

        bAsset.transfer(msg.sender, claimable);

        emit Claim(msg.sender, claimable);
        return claimable;
    }

    // Allow users to withdraw their bAssets if the presale is cancelled
    function withdraw() external returns (uint256) {
        if (active) revert MintActive();

        // Ensure user has a deposit
        uint256 amount = deposits[msg.sender];
        if (amount == 0) revert InvalidWithdraw();

        // zero out users deposit
        deposits[msg.sender] = 0;
        totalDeposits -= amount;

        // send user back their deposit
        reserve.transfer(msg.sender, amount);

        emit Withdraw(msg.sender, amount);
        return amount;
    }

    // Transfer reserves to baseline to seed the pool
    function seed() external returns (uint256) {
        if (!active) revert MintInactive();

        // ensure caller is baseline
        address baseline = bAsset.baseline();
        if (msg.sender != baseline) revert InvalidCaller();

        active = false;
        uint256 totalReserves = reserve.balanceOf(address(this));
        reserve.transfer(baseline, totalReserves);

        emit Seeded(totalReserves);
        return totalReserves;
    }

    // Set the precalculated BAsset address, must be called before baseline deployment
    function setBAsset(BAsset bAsset_) external {
        if (msg.sender != baselineFactory) revert InvalidCaller();
        if (address(bAsset) != address(0)) revert InvalidInput();
        bAsset = bAsset_;
    }

    // Manually add users to whitelist to deposit through manual deposit
    function modifyWhitelist(
        address[] calldata users_,
        uint256[] calldata limits_
    ) external onlyOwner {
        if (users_.length != limits_.length) revert InvalidInput();

        uint256 totalUsers = users_.length;
        for (uint256 i; i < totalUsers; i++) {
            whitelist[users_[i]] = limits_[i];
        }
    }

    // Abort the presale and allow users to withdraw their reserves
    function abort() external {
        if (
            msg.sender == owner ||
            block.timestamp > deployTime + timeLimit
        ) {
            active = false;
            emit Aborted();
        } else {
            revert InvalidCaller();
        }

    }

    function claimYield() external onlyOwner {
        IERC20Rebasing(address(reserve)).claim(
            owner,
            IERC20Rebasing(address(reserve)).getClaimableAmount(address(this))
        );
    }

}

File 2 of 8 : FixedPointMathLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
library FixedPointMathLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The operation failed, as the output exceeds the maximum value of uint256.
    error ExpOverflow();

    /// @dev The operation failed, as the output exceeds the maximum value of uint256.
    error FactorialOverflow();

    /// @dev The operation failed, due to an overflow.
    error RPowOverflow();

    /// @dev The mantissa is too big to fit.
    error MantissaOverflow();

    /// @dev The operation failed, due to an multiplication overflow.
    error MulWadFailed();

    /// @dev The operation failed, either due to a
    /// multiplication overflow, or a division by a zero.
    error DivWadFailed();

    /// @dev The multiply-divide operation failed, either due to a
    /// multiplication overflow, or a division by a zero.
    error MulDivFailed();

    /// @dev The division failed, as the denominator is zero.
    error DivFailed();

    /// @dev The full precision multiply-divide operation failed, either due
    /// to the result being larger than 256 bits, or a division by a zero.
    error FullMulDivFailed();

    /// @dev The output is undefined, as the input is less-than-or-equal to zero.
    error LnWadUndefined();

    /// @dev The input outside the acceptable domain.
    error OutOfDomain();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The scalar of ETH and most ERC20s.
    uint256 internal constant WAD = 1e18;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*              SIMPLIFIED FIXED POINT OPERATIONS             */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `(x * y) / WAD` rounded down.
    function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.
            if mul(y, gt(x, div(not(0), y))) {
                mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.
                revert(0x1c, 0x04)
            }
            z := div(mul(x, y), WAD)
        }
    }

    /// @dev Equivalent to `(x * y) / WAD` rounded up.
    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.
            if mul(y, gt(x, div(not(0), y))) {
                mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.
                revert(0x1c, 0x04)
            }
            z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))
        }
    }

    /// @dev Equivalent to `(x * WAD) / y` rounded down.
    function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.
            if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {
                mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.
                revert(0x1c, 0x04)
            }
            z := div(mul(x, WAD), y)
        }
    }

    /// @dev Equivalent to `(x * WAD) / y` rounded up.
    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.
            if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {
                mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.
                revert(0x1c, 0x04)
            }
            z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))
        }
    }

    /// @dev Equivalent to `x` to the power of `y`.
    /// because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`.
    function powWad(int256 x, int256 y) internal pure returns (int256) {
        // Using `ln(x)` means `x` must be greater than 0.
        return expWad((lnWad(x) * y) / int256(WAD));
    }

    /// @dev Returns `exp(x)`, denominated in `WAD`.
    function expWad(int256 x) internal pure returns (int256 r) {
        unchecked {
            // When the result is less than 0.5 we return zero.
            // This happens when `x <= floor(log(0.5e18) * 1e18) ≈ -42e18`.
            if (x <= -42139678854452767551) return r;

            /// @solidity memory-safe-assembly
            assembly {
                // When the result is greater than `(2**255 - 1) / 1e18` we can not represent it as
                // an int. This happens when `x >= floor(log((2**255 - 1) / 1e18) * 1e18) ≈ 135`.
                if iszero(slt(x, 135305999368893231589)) {
                    mstore(0x00, 0xa37bfec9) // `ExpOverflow()`.
                    revert(0x1c, 0x04)
                }
            }

            // `x` is now in the range `(-42, 136) * 1e18`. Convert to `(-42, 136) * 2**96`
            // for more intermediate precision and a binary basis. This base conversion
            // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.
            x = (x << 78) / 5 ** 18;

            // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers
            // of two such that exp(x) = exp(x') * 2**k, where k is an integer.
            // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).
            int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96;
            x = x - k * 54916777467707473351141471128;

            // `k` is in the range `[-61, 195]`.

            // Evaluate using a (6, 7)-term rational approximation.
            // `p` is made monic, we'll multiply by a scale factor later.
            int256 y = x + 1346386616545796478920950773328;
            y = ((y * x) >> 96) + 57155421227552351082224309758442;
            int256 p = y + x - 94201549194550492254356042504812;
            p = ((p * y) >> 96) + 28719021644029726153956944680412240;
            p = p * x + (4385272521454847904659076985693276 << 96);

            // We leave `p` in `2**192` basis so we don't need to scale it back up for the division.
            int256 q = x - 2855989394907223263936484059900;
            q = ((q * x) >> 96) + 50020603652535783019961831881945;
            q = ((q * x) >> 96) - 533845033583426703283633433725380;
            q = ((q * x) >> 96) + 3604857256930695427073651918091429;
            q = ((q * x) >> 96) - 14423608567350463180887372962807573;
            q = ((q * x) >> 96) + 26449188498355588339934803723976023;

            /// @solidity memory-safe-assembly
            assembly {
                // Div in assembly because solidity adds a zero check despite the unchecked.
                // The q polynomial won't have zeros in the domain as all its roots are complex.
                // No scaling is necessary because p is already `2**96` too large.
                r := sdiv(p, q)
            }

            // r should be in the range `(0.09, 0.25) * 2**96`.

            // We now need to multiply r by:
            // - The scale factor `s ≈ 6.031367120`.
            // - The `2**k` factor from the range reduction.
            // - The `1e18 / 2**96` factor for base conversion.
            // We do this all at once, with an intermediate result in `2**213`
            // basis, so the final right shift is always by a positive amount.
            r = int256(
                (uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)
            );
        }
    }

    /// @dev Returns `ln(x)`, denominated in `WAD`.
    function lnWad(int256 x) internal pure returns (int256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(sgt(x, 0)) {
                mstore(0x00, 0x1615e638) // `LnWadUndefined()`.
                revert(0x1c, 0x04)
            }
            // We want to convert `x` from `10**18` fixed point to `2**96` fixed point.
            // We do this by multiplying by `2**96 / 10**18`. But since
            // `ln(x * C) = ln(x) + ln(C)`, we can simply do nothing here
            // and add `ln(2**96 / 10**18)` at the end.

            // Compute `k = log2(x) - 96`, `t = 159 - k = 255 - log2(x) = 255 ^ log2(x)`.
            let t := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
            t := or(t, shl(6, lt(0xffffffffffffffff, shr(t, x))))
            t := or(t, shl(5, lt(0xffffffff, shr(t, x))))
            t := or(t, shl(4, lt(0xffff, shr(t, x))))
            t := or(t, shl(3, lt(0xff, shr(t, x))))
            // forgefmt: disable-next-item
            t := xor(t, byte(and(0x1f, shr(shr(t, x), 0x8421084210842108cc6318c6db6d54be)),
                0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff))

            // Reduce range of x to (1, 2) * 2**96
            // ln(2^k * x) = k * ln(2) + ln(x)
            x := shr(159, shl(t, x))

            // Evaluate using a (8, 8)-term rational approximation.
            // `p` is made monic, we will multiply by a scale factor later.
            // forgefmt: disable-next-item
            let p := sub( // This heavily nested expression is to avoid stack-too-deep for via-ir.
                sar(96, mul(add(43456485725739037958740375743393,
                sar(96, mul(add(24828157081833163892658089445524,
                sar(96, mul(add(3273285459638523848632254066296,
                    x), x))), x))), x)), 11111509109440967052023855526967)
            p := sub(sar(96, mul(p, x)), 45023709667254063763336534515857)
            p := sub(sar(96, mul(p, x)), 14706773417378608786704636184526)
            p := sub(mul(p, x), shl(96, 795164235651350426258249787498))

            // We leave `p` in `2**192` basis so we don't need to scale it back up for the division.
            // `q` is monic by convention.
            let q := add(5573035233440673466300451813936, x)
            q := add(71694874799317883764090561454958, sar(96, mul(x, q)))
            q := add(283447036172924575727196451306956, sar(96, mul(x, q)))
            q := add(401686690394027663651624208769553, sar(96, mul(x, q)))
            q := add(204048457590392012362485061816622, sar(96, mul(x, q)))
            q := add(31853899698501571402653359427138, sar(96, mul(x, q)))
            q := add(909429971244387300277376558375, sar(96, mul(x, q)))

            // `r` is in the range `(0, 0.125) * 2**96`.

            // Finalization, we need to:
            // - Multiply by the scale factor `s = 5.549…`.
            // - Add `ln(2**96 / 10**18)`.
            // - Add `k * ln(2)`.
            // - Multiply by `10**18 / 2**96 = 5**18 >> 78`.

            // The q polynomial is known not to have zeros in the domain.
            // No scaling required because p is already `2**96` too large.
            r := sdiv(p, q)
            // Multiply by the scaling factor: `s * 5e18 * 2**96`, base is now `5**18 * 2**192`.
            r := mul(1677202110996718588342820967067443963516166, r)
            // Add `ln(2) * k * 5e18 * 2**192`.
            // forgefmt: disable-next-item
            r := add(mul(16597577552685614221487285958193947469193820559219878177908093499208371, sub(159, t)), r)
            // Add `ln(2**96 / 10**18) * 5e18 * 2**192`.
            r := add(600920179829731861736702779321621459595472258049074101567377883020018308, r)
            // Base conversion: mul `2**18 / 2**192`.
            r := sar(174, r)
        }
    }

    /// @dev Returns `W_0(x)`, denominated in `WAD`.
    /// See: https://en.wikipedia.org/wiki/Lambert_W_function
    /// a.k.a. Product log function. This is an approximation of the principal branch.
    function lambertW0Wad(int256 x) internal pure returns (int256 w) {
        if ((w = x) <= -367879441171442322) revert OutOfDomain(); // `x` less than `-1/e`.
        uint256 c; // Whether we need to avoid catastrophic cancellation.
        uint256 i = 4; // Number of iterations.
        if (w <= 0x1ffffffffffff) {
            if (-0x4000000000000 <= w) {
                i = 1; // Inputs near zero only take one step to converge.
            } else if (w <= -0x3ffffffffffffff) {
                i = 32; // Inputs near `-1/e` take very long to converge.
            }
        } else if (w >> 63 == 0) {
            /// @solidity memory-safe-assembly
            assembly {
                // Inline log2 for more performance, since the range is small.
                let v := shr(49, w)
                let l := shl(3, lt(0xff, v))
                // forgefmt: disable-next-item
                l := add(or(l, byte(and(0x1f, shr(shr(l, v), 0x8421084210842108cc6318c6db6d54be)),
                    0x0706060506020504060203020504030106050205030304010505030400000000)), 49)
                w := sdiv(shl(l, 7), byte(sub(l, 31), 0x0303030303030303040506080c13))
                c := gt(l, 60)
                i := add(2, add(gt(l, 53), c))
            }
        } else {
            // `ln(x) - ln(ln(x)) + b * ln(ln(x)) / ln(x)`.
            int256 ll = lnWad(w = lnWad(w));
            /// @solidity memory-safe-assembly
            assembly {
                w := add(sdiv(mul(ll, 1023715080943847266), w), sub(w, ll))
                i := add(3, iszero(shr(68, x)))
                c := iszero(shr(143, x))
            }
            if (c == 0) {
                int256 wad = int256(WAD);
                int256 p = x;
                // If `x` is big, use Newton's so that intermediate values won't overflow.
                do {
                    int256 e = expWad(w);
                    /// @solidity memory-safe-assembly
                    assembly {
                        let t := mul(w, div(e, wad))
                        w := sub(w, sdiv(sub(t, x), div(add(e, t), wad)))
                        i := sub(i, 1)
                    }
                    if (p <= w) break;
                    p = w;
                } while (i != 0);
                /// @solidity memory-safe-assembly
                assembly {
                    w := sub(w, sgt(w, 2))
                }
                return w;
            }
        }
        // forgefmt: disable-next-item
        unchecked {
            int256 wad = int256(WAD);
            int256 p = x;
            do { // Otherwise, use Halley's for faster convergence.
                int256 e = expWad(w);
                /// @solidity memory-safe-assembly
                assembly {
                    let t := add(w, wad)
                    let s := sub(mul(w, e), mul(x, wad))
                    w := sub(w, sdiv(mul(s, wad), sub(mul(e, t), sdiv(mul(add(t, wad), s), add(t, t)))))
                }
                if (p <= w) break;
                p = w;
            } while (--i != c);
            /// @solidity memory-safe-assembly
            assembly {
                w := sub(w, sgt(w, 2))
            }
            // For certain ranges of `x`, we'll use the quadratic-rate recursive formula of
            // R. Iacono and J.P. Boyd for the last iteration, to avoid catastrophic cancellation.
            if (c != 0) {
                /// @solidity memory-safe-assembly
                assembly {
                    x := sdiv(mul(x, wad), w)
                }
                x = (w * (wad + lnWad(x)));
                /// @solidity memory-safe-assembly
                assembly {
                    w := sdiv(x, add(wad, w))
                }
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  GENERAL NUMBER UTILITIES                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Calculates `floor(a * b / d)` with full precision.
    /// Throws if result overflows a uint256 or when `d` is zero.
    /// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv
    function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            for {} 1 {} {
                // 512-bit multiply `[p1 p0] = x * y`.
                // Compute the product mod `2**256` and mod `2**256 - 1`
                // then use the Chinese Remainder Theorem to reconstruct
                // the 512 bit result. The result is stored in two 256
                // variables such that `product = p1 * 2**256 + p0`.

                // Least significant 256 bits of the product.
                let p0 := mul(x, y)
                let mm := mulmod(x, y, not(0))
                // Most significant 256 bits of the product.
                let p1 := sub(mm, add(p0, lt(mm, p0)))

                // Handle non-overflow cases, 256 by 256 division.
                if iszero(p1) {
                    if iszero(d) {
                        mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
                        revert(0x1c, 0x04)
                    }
                    result := div(p0, d)
                    break
                }

                // Make sure the result is less than `2**256`. Also prevents `d == 0`.
                if iszero(gt(d, p1)) {
                    mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
                    revert(0x1c, 0x04)
                }

                /*------------------- 512 by 256 division --------------------*/

                // Make division exact by subtracting the remainder from `[p1 p0]`.
                // Compute remainder using mulmod.
                let r := mulmod(x, y, d)
                // `t` is the least significant bit of `d`.
                // Always greater or equal to 1.
                let t := and(d, sub(0, d))
                // Divide `d` by `t`, which is a power of two.
                d := div(d, t)
                // Invert `d mod 2**256`
                // Now that `d` is an odd number, it has an inverse
                // modulo `2**256` such that `d * inv = 1 mod 2**256`.
                // Compute the inverse by starting with a seed that is correct
                // correct for four bits. That is, `d * inv = 1 mod 2**4`.
                let inv := xor(mul(3, d), 2)
                // Now use 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.
                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8
                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16
                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32
                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64
                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128
                result :=
                    mul(
                        // Divide [p1 p0] by the factors of two.
                        // Shift in bits from `p1` into `p0`. For this we need
                        // to flip `t` such that it is `2**256 / t`.
                        or(mul(sub(p1, gt(r, p0)), add(div(sub(0, t), t), 1)), div(sub(p0, r), t)),
                        // inverse mod 2**256
                        mul(inv, sub(2, mul(d, inv)))
                    )
                break
            }
        }
    }

    /// @dev Calculates `floor(x * y / d)` with full precision, rounded up.
    /// Throws if result overflows a uint256 or when `d` is zero.
    /// Credit to Uniswap-v3-core under MIT license:
    /// https://github.com/Uniswap/v3-core/blob/contracts/libraries/FullMath.sol
    function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {
        result = fullMulDiv(x, y, d);
        /// @solidity memory-safe-assembly
        assembly {
            if mulmod(x, y, d) {
                result := add(result, 1)
                if iszero(result) {
                    mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
                    revert(0x1c, 0x04)
                }
            }
        }
    }

    /// @dev Returns `floor(x * y / d)`.
    /// Reverts if `x * y` overflows, or `d` is zero.
    function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {
                mstore(0x00, 0xad251c27) // `MulDivFailed()`.
                revert(0x1c, 0x04)
            }
            z := div(mul(x, y), d)
        }
    }

    /// @dev Returns `ceil(x * y / d)`.
    /// Reverts if `x * y` overflows, or `d` is zero.
    function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {
                mstore(0x00, 0xad251c27) // `MulDivFailed()`.
                revert(0x1c, 0x04)
            }
            z := add(iszero(iszero(mod(mul(x, y), d))), div(mul(x, y), d))
        }
    }

    /// @dev Returns `ceil(x / d)`.
    /// Reverts if `d` is zero.
    function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(d) {
                mstore(0x00, 0x65244e4e) // `DivFailed()`.
                revert(0x1c, 0x04)
            }
            z := add(iszero(iszero(mod(x, d))), div(x, d))
        }
    }

    /// @dev Returns `max(0, x - y)`.
    function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(gt(x, y), sub(x, y))
        }
    }

    /// @dev Exponentiate `x` to `y` by squaring, denominated in base `b`.
    /// Reverts if the computation overflows.
    function rpow(uint256 x, uint256 y, uint256 b) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(b, iszero(y)) // `0 ** 0 = 1`. Otherwise, `0 ** n = 0`.
            if x {
                z := xor(b, mul(xor(b, x), and(y, 1))) // `z = isEven(y) ? scale : x`
                let half := shr(1, b) // Divide `b` by 2.
                // Divide `y` by 2 every iteration.
                for { y := shr(1, y) } y { y := shr(1, y) } {
                    let xx := mul(x, x) // Store x squared.
                    let xxRound := add(xx, half) // Round to the nearest number.
                    // Revert if `xx + half` overflowed, or if `x ** 2` overflows.
                    if or(lt(xxRound, xx), shr(128, x)) {
                        mstore(0x00, 0x49f7642b) // `RPowOverflow()`.
                        revert(0x1c, 0x04)
                    }
                    x := div(xxRound, b) // Set `x` to scaled `xxRound`.
                    // If `y` is odd:
                    if and(y, 1) {
                        let zx := mul(z, x) // Compute `z * x`.
                        let zxRound := add(zx, half) // Round to the nearest number.
                        // If `z * x` overflowed or `zx + half` overflowed:
                        if or(xor(div(zx, x), z), lt(zxRound, zx)) {
                            // Revert if `x` is non-zero.
                            if iszero(iszero(x)) {
                                mstore(0x00, 0x49f7642b) // `RPowOverflow()`.
                                revert(0x1c, 0x04)
                            }
                        }
                        z := div(zxRound, b) // Return properly scaled `zxRound`.
                    }
                }
            }
        }
    }

    /// @dev Returns the square root of `x`.
    function sqrt(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`.
            z := 181 // The "correct" value is 1, but this saves a multiplication later.

            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.

            // Let `y = x / 2**r`. We check `y >= 2**(k + 8)`
            // but shift right by `k` bits to ensure that if `x >= 256`, then `y >= 256`.
            let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffffff, shr(r, x))))
            z := shl(shr(1, r), z)

            // Goal was to get `z*z*y` within a small factor of `x`. More iterations could
            // get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`.
            // We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small.
            // That's not possible if `x < 256` but we can just verify those cases exhaustively.

            // Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`.
            // Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`.
            // Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps.

            // For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)`
            // is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`,
            // with largest error when `s = 1` and when `s = 256` or `1/256`.

            // Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`.
            // Then we can estimate `sqrt(y)` using
            // `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`.

            // There is no overflow risk here since `y < 2**136` after the first branch above.
            z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181.

            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // If `x+1` is a perfect square, the Babylonian method cycles between
            // `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor.
            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
            z := sub(z, lt(div(x, z), z))
        }
    }

    /// @dev Returns the cube root of `x`.
    /// Credit to bout3fiddy and pcaversaccio under AGPLv3 license:
    /// https://github.com/pcaversaccio/snekmate/blob/main/src/utils/Math.vy
    function cbrt(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            let r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))

            z := div(shl(div(r, 3), shl(lt(0xf, shr(r, x)), 0xf)), xor(7, mod(r, 3)))

            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)

            z := sub(z, lt(div(x, mul(z, z)), z))
        }
    }

    /// @dev Returns the square root of `x`, denominated in `WAD`.
    function sqrtWad(uint256 x) internal pure returns (uint256 z) {
        unchecked {
            z = 10 ** 9;
            if (x <= type(uint256).max / 10 ** 36 - 1) {
                x *= 10 ** 18;
                z = 1;
            }
            z *= sqrt(x);
        }
    }

    /// @dev Returns the cube root of `x`, denominated in `WAD`.
    function cbrtWad(uint256 x) internal pure returns (uint256 z) {
        unchecked {
            z = 10 ** 12;
            if (x <= (type(uint256).max / 10 ** 36) * 10 ** 18 - 1) {
                if (x >= type(uint256).max / 10 ** 36) {
                    x *= 10 ** 18;
                    z = 10 ** 6;
                } else {
                    x *= 10 ** 36;
                    z = 1;
                }
            }
            z *= cbrt(x);
        }
    }

    /// @dev Returns the factorial of `x`.
    function factorial(uint256 x) internal pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(lt(x, 58)) {
                mstore(0x00, 0xaba0f2a2) // `FactorialOverflow()`.
                revert(0x1c, 0x04)
            }
            for { result := 1 } x { x := sub(x, 1) } { result := mul(result, x) }
        }
    }

    /// @dev Returns the log2 of `x`.
    /// Equivalent to computing the index of the most significant bit (MSB) of `x`.
    /// Returns 0 if `x` is zero.
    function log2(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            // forgefmt: disable-next-item
            r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
                0x0706060506020504060203020504030106050205030304010505030400000000))
        }
    }

    /// @dev Returns the log2 of `x`, rounded up.
    /// Returns 0 if `x` is zero.
    function log2Up(uint256 x) internal pure returns (uint256 r) {
        r = log2(x);
        /// @solidity memory-safe-assembly
        assembly {
            r := add(r, lt(shl(r, 1), x))
        }
    }

    /// @dev Returns the log10 of `x`.
    /// Returns 0 if `x` is zero.
    function log10(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(lt(x, 100000000000000000000000000000000000000)) {
                x := div(x, 100000000000000000000000000000000000000)
                r := 38
            }
            if iszero(lt(x, 100000000000000000000)) {
                x := div(x, 100000000000000000000)
                r := add(r, 20)
            }
            if iszero(lt(x, 10000000000)) {
                x := div(x, 10000000000)
                r := add(r, 10)
            }
            if iszero(lt(x, 100000)) {
                x := div(x, 100000)
                r := add(r, 5)
            }
            r := add(r, add(gt(x, 9), add(gt(x, 99), add(gt(x, 999), gt(x, 9999)))))
        }
    }

    /// @dev Returns the log10 of `x`, rounded up.
    /// Returns 0 if `x` is zero.
    function log10Up(uint256 x) internal pure returns (uint256 r) {
        r = log10(x);
        /// @solidity memory-safe-assembly
        assembly {
            r := add(r, lt(exp(10, r), x))
        }
    }

    /// @dev Returns the log256 of `x`.
    /// Returns 0 if `x` is zero.
    function log256(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(shr(3, r), lt(0xff, shr(r, x)))
        }
    }

    /// @dev Returns the log256 of `x`, rounded up.
    /// Returns 0 if `x` is zero.
    function log256Up(uint256 x) internal pure returns (uint256 r) {
        r = log256(x);
        /// @solidity memory-safe-assembly
        assembly {
            r := add(r, lt(shl(shl(3, r), 1), x))
        }
    }

    /// @dev Returns the scientific notation format `mantissa * 10 ** exponent` of `x`.
    /// Useful for compressing prices (e.g. using 25 bit mantissa and 7 bit exponent).
    function sci(uint256 x) internal pure returns (uint256 mantissa, uint256 exponent) {
        /// @solidity memory-safe-assembly
        assembly {
            mantissa := x
            if mantissa {
                if iszero(mod(mantissa, 1000000000000000000000000000000000)) {
                    mantissa := div(mantissa, 1000000000000000000000000000000000)
                    exponent := 33
                }
                if iszero(mod(mantissa, 10000000000000000000)) {
                    mantissa := div(mantissa, 10000000000000000000)
                    exponent := add(exponent, 19)
                }
                if iszero(mod(mantissa, 1000000000000)) {
                    mantissa := div(mantissa, 1000000000000)
                    exponent := add(exponent, 12)
                }
                if iszero(mod(mantissa, 1000000)) {
                    mantissa := div(mantissa, 1000000)
                    exponent := add(exponent, 6)
                }
                if iszero(mod(mantissa, 10000)) {
                    mantissa := div(mantissa, 10000)
                    exponent := add(exponent, 4)
                }
                if iszero(mod(mantissa, 100)) {
                    mantissa := div(mantissa, 100)
                    exponent := add(exponent, 2)
                }
                if iszero(mod(mantissa, 10)) {
                    mantissa := div(mantissa, 10)
                    exponent := add(exponent, 1)
                }
            }
        }
    }

    /// @dev Convenience function for packing `x` into a smaller number using `sci`.
    /// The `mantissa` will be in bits [7..255] (the upper 249 bits).
    /// The `exponent` will be in bits [0..6] (the lower 7 bits).
    /// Use `SafeCastLib` to safely ensure that the `packed` number is small
    /// enough to fit in the desired unsigned integer type:
    /// ```
    ///     uint32 packed = SafeCastLib.toUint32(FixedPointMathLib.packSci(777 ether));
    /// ```
    function packSci(uint256 x) internal pure returns (uint256 packed) {
        (x, packed) = sci(x); // Reuse for `mantissa` and `exponent`.
        /// @solidity memory-safe-assembly
        assembly {
            if shr(249, x) {
                mstore(0x00, 0xce30380c) // `MantissaOverflow()`.
                revert(0x1c, 0x04)
            }
            packed := or(shl(7, x), packed)
        }
    }

    /// @dev Convenience function for unpacking a packed number from `packSci`.
    function unpackSci(uint256 packed) internal pure returns (uint256 unpacked) {
        unchecked {
            unpacked = (packed >> 7) * 10 ** (packed & 0x7f);
        }
    }

    /// @dev Returns the average of `x` and `y`.
    function avg(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = (x & y) + ((x ^ y) >> 1);
        }
    }

    /// @dev Returns the average of `x` and `y`.
    function avg(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = (x >> 1) + (y >> 1) + (((x & 1) + (y & 1)) >> 1);
        }
    }

    /// @dev Returns the absolute value of `x`.
    function abs(int256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(sub(0, shr(255, x)), add(sub(0, shr(255, x)), x))
        }
    }

    /// @dev Returns the absolute distance between `x` and `y`.
    function dist(int256 x, int256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(mul(xor(sub(y, x), sub(x, y)), sgt(x, y)), sub(y, x))
        }
    }

    /// @dev Returns the minimum of `x` and `y`.
    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), lt(y, x)))
        }
    }

    /// @dev Returns the minimum of `x` and `y`.
    function min(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), slt(y, x)))
        }
    }

    /// @dev Returns the maximum of `x` and `y`.
    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), gt(y, x)))
        }
    }

    /// @dev Returns the maximum of `x` and `y`.
    function max(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), sgt(y, x)))
        }
    }

    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.
    function clamp(uint256 x, uint256 minValue, uint256 maxValue)
        internal
        pure
        returns (uint256 z)
    {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, minValue), gt(minValue, x)))
            z := xor(z, mul(xor(z, maxValue), lt(maxValue, z)))
        }
    }

    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.
    function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, minValue), sgt(minValue, x)))
            z := xor(z, mul(xor(z, maxValue), slt(maxValue, z)))
        }
    }

    /// @dev Returns greatest common divisor of `x` and `y`.
    function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            for { z := x } y {} {
                let t := y
                y := mod(z, y)
                z := t
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   RAW NUMBER OPERATIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `x + y`, without checking for overflow.
    function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = x + y;
        }
    }

    /// @dev Returns `x + y`, without checking for overflow.
    function rawAdd(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = x + y;
        }
    }

    /// @dev Returns `x - y`, without checking for underflow.
    function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = x - y;
        }
    }

    /// @dev Returns `x - y`, without checking for underflow.
    function rawSub(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = x - y;
        }
    }

    /// @dev Returns `x * y`, without checking for overflow.
    function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = x * y;
        }
    }

    /// @dev Returns `x * y`, without checking for overflow.
    function rawMul(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = x * y;
        }
    }

    /// @dev Returns `x / y`, returning 0 if `y` is zero.
    function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := div(x, y)
        }
    }

    /// @dev Returns `x / y`, returning 0 if `y` is zero.
    function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := sdiv(x, y)
        }
    }

    /// @dev Returns `x % y`, returning 0 if `y` is zero.
    function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mod(x, y)
        }
    }

    /// @dev Returns `x % y`, returning 0 if `y` is zero.
    function rawSMod(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := smod(x, y)
        }
    }

    /// @dev Returns `(x + y) % d`, return 0 if `d` if zero.
    function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := addmod(x, y, d)
        }
    }

    /// @dev Returns `(x * y) % d`, return 0 if `d` if zero.
    function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mulmod(x, y, d)
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol)
library MerkleProofLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*            MERKLE PROOF VERIFICATION OPERATIONS            */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf)
        internal
        pure
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if mload(proof) {
                // Initialize `offset` to the offset of `proof` elements in memory.
                let offset := add(proof, 0x20)
                // Left shift by 5 is equivalent to multiplying by 0x20.
                let end := add(offset, shl(5, mload(proof)))
                // Iterate over proof elements to compute root hash.
                for {} 1 {} {
                    // Slot of `leaf` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(leaf, mload(offset)))
                    // Store elements to hash contiguously in scratch space.
                    // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
                    mstore(scratch, leaf)
                    mstore(xor(scratch, 0x20), mload(offset))
                    // Reuse `leaf` to store the hash to reduce stack operations.
                    leaf := keccak256(0x00, 0x40)
                    offset := add(offset, 0x20)
                    if iszero(lt(offset, end)) { break }
                }
            }
            isValid := eq(leaf, root)
        }
    }

    /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf)
        internal
        pure
        returns (bool isValid)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if proof.length {
                // Left shift by 5 is equivalent to multiplying by 0x20.
                let end := add(proof.offset, shl(5, proof.length))
                // Initialize `offset` to the offset of `proof` in the calldata.
                let offset := proof.offset
                // Iterate over proof elements to compute root hash.
                for {} 1 {} {
                    // Slot of `leaf` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(leaf, calldataload(offset)))
                    // Store elements to hash contiguously in scratch space.
                    // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
                    mstore(scratch, leaf)
                    mstore(xor(scratch, 0x20), calldataload(offset))
                    // Reuse `leaf` to store the hash to reduce stack operations.
                    leaf := keccak256(0x00, 0x40)
                    offset := add(offset, 0x20)
                    if iszero(lt(offset, end)) { break }
                }
            }
            isValid := eq(leaf, root)
        }
    }

    /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
    /// given `proof` and `flags`.
    ///
    /// Note:
    /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
    ///   will always return false.
    /// - The sum of the lengths of `proof` and `leaves` must never overflow.
    /// - Any non-zero word in the `flags` array is treated as true.
    /// - The memory offset of `proof` must be non-zero
    ///   (i.e. `proof` is not pointing to the scratch space).
    function verifyMultiProof(
        bytes32[] memory proof,
        bytes32 root,
        bytes32[] memory leaves,
        bool[] memory flags
    ) internal pure returns (bool isValid) {
        // Rebuilds the root by consuming and producing values on a queue.
        // The queue starts with the `leaves` array, and goes into a `hashes` array.
        // After the process, the last element on the queue is verified
        // to be equal to the `root`.
        //
        // The `flags` array denotes whether the sibling
        // should be popped from the queue (`flag == true`), or
        // should be popped from the `proof` (`flag == false`).
        /// @solidity memory-safe-assembly
        assembly {
            // Cache the lengths of the arrays.
            let leavesLength := mload(leaves)
            let proofLength := mload(proof)
            let flagsLength := mload(flags)

            // Advance the pointers of the arrays to point to the data.
            leaves := add(0x20, leaves)
            proof := add(0x20, proof)
            flags := add(0x20, flags)

            // If the number of flags is correct.
            for {} eq(add(leavesLength, proofLength), add(flagsLength, 1)) {} {
                // For the case where `proof.length + leaves.length == 1`.
                if iszero(flagsLength) {
                    // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
                    isValid := eq(mload(xor(leaves, mul(xor(proof, leaves), proofLength))), root)
                    break
                }

                // The required final proof offset if `flagsLength` is not zero, otherwise zero.
                let proofEnd := add(proof, shl(5, proofLength))
                // We can use the free memory space for the queue.
                // We don't need to allocate, since the queue is temporary.
                let hashesFront := mload(0x40)
                // Copy the leaves into the hashes.
                // Sometimes, a little memory expansion costs less than branching.
                // Should cost less, even with a high free memory offset of 0x7d00.
                leavesLength := shl(5, leavesLength)
                for { let i := 0 } iszero(eq(i, leavesLength)) { i := add(i, 0x20) } {
                    mstore(add(hashesFront, i), mload(add(leaves, i)))
                }
                // Compute the back of the hashes.
                let hashesBack := add(hashesFront, leavesLength)
                // This is the end of the memory for the queue.
                // We recycle `flagsLength` to save on stack variables (sometimes save gas).
                flagsLength := add(hashesBack, shl(5, flagsLength))

                for {} 1 {} {
                    // Pop from `hashes`.
                    let a := mload(hashesFront)
                    // Pop from `hashes`.
                    let b := mload(add(hashesFront, 0x20))
                    hashesFront := add(hashesFront, 0x40)

                    // If the flag is false, load the next proof,
                    // else, pops from the queue.
                    if iszero(mload(flags)) {
                        // Loads the next proof.
                        b := mload(proof)
                        proof := add(proof, 0x20)
                        // Unpop from `hashes`.
                        hashesFront := sub(hashesFront, 0x20)
                    }

                    // Advance to the next flag.
                    flags := add(flags, 0x20)

                    // Slot of `a` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(a, b))
                    // Hash the scratch space and push the result onto the queue.
                    mstore(scratch, a)
                    mstore(xor(scratch, 0x20), b)
                    mstore(hashesBack, keccak256(0x00, 0x40))
                    hashesBack := add(hashesBack, 0x20)
                    if iszero(lt(hashesBack, flagsLength)) { break }
                }
                isValid :=
                    and(
                        // Checks if the last value in the queue is same as the root.
                        eq(mload(sub(hashesBack, 0x20)), root),
                        // And whether all the proofs are used, if required.
                        eq(proofEnd, proof)
                    )
                break
            }
        }
    }

    /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
    /// given `proof` and `flags`.
    ///
    /// Note:
    /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
    ///   will always return false.
    /// - Any non-zero word in the `flags` array is treated as true.
    /// - The calldata offset of `proof` must be non-zero
    ///   (i.e. `proof` is from a regular Solidity function with a 4-byte selector).
    function verifyMultiProofCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32[] calldata leaves,
        bool[] calldata flags
    ) internal pure returns (bool isValid) {
        // Rebuilds the root by consuming and producing values on a queue.
        // The queue starts with the `leaves` array, and goes into a `hashes` array.
        // After the process, the last element on the queue is verified
        // to be equal to the `root`.
        //
        // The `flags` array denotes whether the sibling
        // should be popped from the queue (`flag == true`), or
        // should be popped from the `proof` (`flag == false`).
        /// @solidity memory-safe-assembly
        assembly {
            // If the number of flags is correct.
            for {} eq(add(leaves.length, proof.length), add(flags.length, 1)) {} {
                // For the case where `proof.length + leaves.length == 1`.
                if iszero(flags.length) {
                    // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
                    // forgefmt: disable-next-item
                    isValid := eq(
                        calldataload(
                            xor(leaves.offset, mul(xor(proof.offset, leaves.offset), proof.length))
                        ),
                        root
                    )
                    break
                }

                // The required final proof offset if `flagsLength` is not zero, otherwise zero.
                let proofEnd := add(proof.offset, shl(5, proof.length))
                // We can use the free memory space for the queue.
                // We don't need to allocate, since the queue is temporary.
                let hashesFront := mload(0x40)
                // Copy the leaves into the hashes.
                // Sometimes, a little memory expansion costs less than branching.
                // Should cost less, even with a high free memory offset of 0x7d00.
                calldatacopy(hashesFront, leaves.offset, shl(5, leaves.length))
                // Compute the back of the hashes.
                let hashesBack := add(hashesFront, shl(5, leaves.length))
                // This is the end of the memory for the queue.
                // We recycle `flagsLength` to save on stack variables (sometimes save gas).
                flags.length := add(hashesBack, shl(5, flags.length))

                // We don't need to make a copy of `proof.offset` or `flags.offset`,
                // as they are pass-by-value (this trick may not always save gas).

                for {} 1 {} {
                    // Pop from `hashes`.
                    let a := mload(hashesFront)
                    // Pop from `hashes`.
                    let b := mload(add(hashesFront, 0x20))
                    hashesFront := add(hashesFront, 0x40)

                    // If the flag is false, load the next proof,
                    // else, pops from the queue.
                    if iszero(calldataload(flags.offset)) {
                        // Loads the next proof.
                        b := calldataload(proof.offset)
                        proof.offset := add(proof.offset, 0x20)
                        // Unpop from `hashes`.
                        hashesFront := sub(hashesFront, 0x20)
                    }

                    // Advance to the next flag offset.
                    flags.offset := add(flags.offset, 0x20)

                    // Slot of `a` in scratch space.
                    // If the condition is true: 0x20, otherwise: 0x00.
                    let scratch := shl(5, gt(a, b))
                    // Hash the scratch space and push the result onto the queue.
                    mstore(scratch, a)
                    mstore(xor(scratch, 0x20), b)
                    mstore(hashesBack, keccak256(0x00, 0x40))
                    hashesBack := add(hashesBack, 0x20)
                    if iszero(lt(hashesBack, flags.length)) { break }
                }
                isValid :=
                    and(
                        // Checks if the last value in the queue is same as the root.
                        eq(mload(sub(hashesBack, 0x20)), root),
                        // And whether all the proofs are used, if required.
                        eq(proofEnd, proof.offset)
                    )
                break
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes32 array.
    function emptyProof() internal pure returns (bytes32[] calldata proof) {
        /// @solidity memory-safe-assembly
        assembly {
            proof.length := 0
        }
    }

    /// @dev Returns an empty calldata bytes32 array.
    function emptyLeaves() internal pure returns (bytes32[] calldata leaves) {
        /// @solidity memory-safe-assembly
        assembly {
            leaves.length := 0
        }
    }

    /// @dev Returns an empty calldata bool array.
    function emptyFlags() internal pure returns (bool[] calldata flags) {
        /// @solidity memory-safe-assembly
        assembly {
            flags.length := 0
        }
    }
}

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event OwnershipTransferred(address indexed user, address indexed newOwner);

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

enum YieldMode {
    AUTOMATIC,
    VOID,
    CLAIMABLE
}

enum GasMode {
    VOID,
    CLAIMABLE 
}

interface IBlast{
    // configure
    function configureContract(address contractAddress, YieldMode _yield, GasMode gasMode, address governor) external;
    function configure(YieldMode _yield, GasMode gasMode, address governor) external;

    // base configuration options
    function configureClaimableYield() external;
    function configureClaimableYieldOnBehalf(address contractAddress) external;
    function configureAutomaticYield() external;
    function configureAutomaticYieldOnBehalf(address contractAddress) external;
    function configureVoidYield() external;
    function configureVoidYieldOnBehalf(address contractAddress) external;
    function configureClaimableGas() external;
    function configureClaimableGasOnBehalf(address contractAddress) external;
    function configureVoidGas() external;
    function configureVoidGasOnBehalf(address contractAddress) external;
    function configureGovernor(address _governor) external;
    function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external;

    // claim yield
    function claimYield(address contractAddress, address recipientOfYield, uint256 amount) external returns (uint256);
    function claimAllYield(address contractAddress, address recipientOfYield) external returns (uint256);

    // claim gas
    function claimAllGas(address contractAddress, address recipientOfGas) external returns (uint256);
    function claimGasAtMinClaimRate(address contractAddress, address recipientOfGas, uint256 minClaimRateBips) external returns (uint256);
    function claimMaxGas(address contractAddress, address recipientOfGas) external returns (uint256);
    function claimGas(address contractAddress, address recipientOfGas, uint256 gasToClaim, uint256 gasSecondsToConsume) external returns (uint256);

    // read functions
    function readClaimableYield(address contractAddress) external view returns (uint256);
    function readYieldConfiguration(address contractAddress) external view returns (uint8);
    function readGasParams(address contractAddress) external view returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode);
}

interface IERC20Rebasing {
    // changes the yield mode of the caller and update the balance
    // to reflect the configuration
    function configure(YieldMode) external returns (uint256);
    // "claimable" yield mode accounts can call this this claim their yield
    // to another address
    function claim(address recipient, uint256 amount) external returns (uint256);
    // read the claimable amount for an account
    function getClaimableAmount(address account) external view returns (uint256);
  }

// SPDX-License-Identifier: MIT
pragma solidity =0.8.23;

import {ERC20} from "solmate/tokens/ERC20.sol";
import {BlastClaimer} from "./BlastClaimer.sol";

// Baseline token implementation
contract BAsset is ERC20 {
    address public immutable baseline;

    error InvalidCaller();

    constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_, 18) {
        // start with 0 initial supply and mint it when we deploy Initial Liquidity in the callback
        baseline = msg.sender;
        BlastClaimer.configureGovernor(msg.sender);
    }

    function mint(address to, uint256 amount_) external {
        if (msg.sender != baseline) revert InvalidCaller();
        _mint(to, amount_);
    }

    // Burns all token supply greater than totalSupply
    function burn(uint256 amount_) external {
        if (msg.sender != baseline) revert InvalidCaller();
        _burn(baseline, amount_);
    }
}

//SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.23;

import {IBlast, YieldMode, GasMode} from "../interfaces/IBlast.sol";

library BlastClaimer {
    IBlast constant BLAST = IBlast(0x4300000000000000000000000000000000000002);

    function configure(address governor_) internal {
        BLAST.configure(
            YieldMode.CLAIMABLE,
            GasMode.CLAIMABLE,
            governor_
        );
    }

    function configureGovernor(address governor_) external {
        BLAST.configureGovernor(governor_);
    }

    function configureContract(address contract_, address governor_) external {
        BLAST.configureContract(
            contract_,
            YieldMode.CLAIMABLE,
            GasMode.CLAIMABLE,
            governor_
        );
    }
}

Settings
{
  "remappings": [
    "forge-std/=lib/forge-std/src/",
    "@uniswap/v3-core/=lib/v3-core/",
    "@uniswap/v3-core-0_8/=lib/v3-core-0_8/",
    "@uniswap/v3-periphery/=lib/v3-periphery/",
    "@uniswap/v3-periphery-0_8/=lib/v3-periphery-0_8/",
    "solmate/=lib/solmate/src/",
    "solady/=lib/solady/src/",
    "murky/=lib/murky/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "openzeppelin-contracts/=lib/murky/lib/openzeppelin-contracts/",
    "@openzeppelin/=lib/murky/lib/openzeppelin-contracts/",
    "v3-core-0_8/=lib/v3-core-0_8/contracts/",
    "v3-core/=lib/v3-core/contracts/",
    "v3-periphery-0_8/=lib/v3-periphery-0_8/contracts/",
    "v3-periphery/=lib/v3-periphery/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "joe-v2/=lib/joe-v2/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "prb-test/=lib/prb-test/src/",
    "v2-core/=lib/v2-core/contracts/",
    "vulcan/=lib/vulcan/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 0
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract ERC20","name":"reserve_","type":"address"},{"internalType":"address","name":"baselineFactory_","type":"address"},{"internalType":"address","name":"owner_","type":"address"},{"internalType":"bytes32","name":"merkleRoot_","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ClaimNotAvailable","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidWithdraw","type":"error"},{"inputs":[],"name":"MaxDepositExceeded","type":"error"},{"inputs":[],"name":"MintActive","type":"error"},{"inputs":[],"name":"MintInactive","type":"error"},{"anonymous":false,"inputs":[],"name":"Aborted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Seeded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"abort","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"active","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bAsset","outputs":[{"internalType":"contract BAsset","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baselineFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"uint256","name":"limit_","type":"uint256"},{"internalType":"bytes32[]","name":"proofs_","type":"bytes32[]"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"users_","type":"address[]"},{"internalType":"uint256[]","name":"limits_","type":"uint256[]"}],"name":"modifyWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"seed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract BAsset","name":"bAsset_","type":"address"}],"name":"setBAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timeLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"whitelistDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

6101006040818152346200022f57600091608081620011fe803803809162000028828562000234565b833981010312620002275780516001600160a01b0391849083831683036200022b5762000058602082016200026e565b90846060620000698884016200026e565b9201519116918260018060a01b031985541617845586519483857f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a360805260c05260a0524260e0526001805460ff60a01b1916600160a01b17905573430000000000000000000000000000000000000290813b1562000227578383819360649363c8992e6160e01b8452600260048501526001602485015260448401525af180156200021a57620001ed575b50916020819293608051166024855180948193631a33757d60e01b8352600260048401525af18015620001e357620001af575b8251610f7a90816200028482396080518181816101d2015281816104830152818161090a01528181610b360152610e7f015260a05181818161037d0152610c97015260c0518181816102340152610685015260e0518181816106340152610c390152f35b602090813d8311620001db575b620001c8818362000234565b81010312620001d857806200014b565b80fd5b503d620001bc565b83513d84823e3d90fd5b6001600160401b03811162000206578252602062000118565b634e487b7160e01b84526041600452602484fd5b50505051903d90823e3d90fd5b8280fd5b5080fd5b600080fd5b601f909101601f19168101906001600160401b038211908210176200025857604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036200022f5756fe6080604081815260048036101561001557600080fd5b600092833560e01c90816302fb0c5e14610cba575080632eb4a7ab14610c7f57806335a063b414610bd65780633ccfd60b14610ac35780633e10020d14610a0257838163406cf229146108dc575080634e71d92d1461070a57806361325e18146106e25780637a385da7146106575780637a40624b1461061c5780637d882097146105fd5780637d94792a1461040a57806384eb7731146102ed5780638da5cb5b146102c55780639b19251a1461028c578063b8ab24bd14610263578063bf3a9c721461021f578063c08d1fe514610201578063cd3293de146101bd578063f2fde38b1461014c5763fc7e286d1461010c57600080fd5b346101485760203660031901126101485780356001600160a01b03811690819003610144579282916020948252845220549051908152f35b8380fd5b8280fd5b8382346101b95760203660031901126101b957356001600160a01b038181169182900361014857819061018484549182163314610daf565b6001600160a01b031916178255337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b5080fd5b5050346101b957816003193601126101b957517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5050346101b957816003193601126101b95760209051621275008152f35b5050346101b957816003193601126101b957517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5050346101b957816003193601126101b95760015490516001600160a01b039091168152602090f35b503461014857602036600319011261014857356001600160a01b0381169081900361014857828291602094526003845220549051908152f35b5050346101b957816003193601126101b957905490516001600160a01b039091168152602090f35b509190346101b95760603660031901126101b957602435906001600160401b03604435818111610406576103249036908701610cde565b91835190602091602081019061034d8161033f8a3386610d94565b03601f198101835282610d43565b5190208551602080820192835281529091818701908111828210176103f357865251902092806103bf575b5050507f0000000000000000000000000000000000000000000000000000000000000000036103b057506103ad919235610e10565b80f35b516348f5c3ed60e01b81528390fd5b60059060051b830192935b82853591828111841b9081521852818588209401938385106103ca579350505050388080610378565b634e487b7160e01b895260418a52602489fd5b8480fd5b5090346101485782600319360112610148576001549260ff8460a01c16156105ef57815163ab2637af60e01b81526020946001600160a01b0390868387818486165afa92831561059d5784936105b7575b5081831633036105a75760ff60a01b191660015583516370a0823160e01b81523086820152947f00000000000000000000000000000000000000000000000000000000000000009190911691908686602481865afa95861561059d5790879392918597610560575b50918691856104e896959488519788958694859363a9059cbb60e01b85528401610d94565b03925af19081156105555750610528575b507ffe8b095e1a768e83a862933c32f2bd9b62b7b87f8fc8843d83ccce205208b656838251848152a151908152f35b61054790843d861161054e575b61053f8183610d43565b810190610d7c565b50386104f9565b503d610535565b8351903d90823e3d90fd5b8481939495929698503d8311610596575b61057b8183610d43565b8101031261059257519492869291906104e86104c3565b8580fd5b503d610571565b85513d86823e3d90fd5b84516348f5c3ed60e01b81528690fd5b9092508681813d83116105e8575b6105cf8183610d43565b810103126101445751818116810361014457913861045b565b503d6105c5565b5051630d0ca57160e21b8152fd5b5050346101b957816003193601126101b9576020906002549051908152f35b5050346101b957816003193601126101b957602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b509034610148576020366003190112610148576001600160a01b0382358181169391929084900361040657827f00000000000000000000000000000000000000000000000000000000000000001633036106d5576001549283166106c85750506001600160a01b0319161760015580f35b5163b4fa3fb360e01b8152fd5b516348f5c3ed60e01b8152fd5b5034610148576020366003190112610148576103ad9133845260036020528320549035610e10565b5090346101485782600319360112610148576001549260ff8460a01c166108ce5781516370a0823160e01b815230818501526020946001600160a01b03949086908390602490829089165afa9182156108c4578392610895575b5033835280865283832054948215801561088d575b61087e57670de0b6b3a7640000808702938785048214881517156108585760025494851561086b5785900481810291818304149015171561085857916107ca8994926107f997969404988994610d36565b6002553385528184528487812055600154169084875180978195829463a9059cbb60e01b845233908401610d94565b03925af1908115610555575061083b575b5080518281527f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4843392a251908152f35b61085190843d861161054e5761053f8183610d43565b503861080a565b634e487b7160e01b865260118452602486fd5b634e487b7160e01b875260128552602487fd5b508351633c21f90f60e01b8152fd5b508515610779565b9091508581813d83116108bd575b6108ad8183610d43565b8101031261014857519038610764565b503d6108a3565b84513d85823e3d90fd5b5051634a324f2160e11b8152fd5b828185346101b957816003193601126101b95781546001600160a01b0390811690610908338314610daf565b7f00000000000000000000000000000000000000000000000000000000000000001682519163e12f3a6160e01b835230868401526020958684602481865afa9384156109f85790879493929187946109c3575b509561097b96865197889586948593635569f64b60e11b85528401610d94565b03925af19081156109ba575061098f578280f35b813d83116109b3575b6109a28183610d43565b810103126109b05781808280f35b80fd5b503d610998565b513d85823e3d90fd5b8581969295503d83116109f1575b6109db8183610d43565b810103126105925792518693909261097b61095b565b503d6109d1565b85513d88823e3d90fd5b5090346101485780600319360112610148576001600160401b0390823582811161040657610a339036908501610cde565b93909260243590811161059257610a4d9036908301610cde565b9060018060a01b0392610a64848954163314610daf565b828703610ab55750865b868110610a79578780f35b610a84818484610dea565b3590610a91818989610dea565b3591858316809303610ab1576001928a526003602052868a205501610a6e565b8980fd5b845163b4fa3fb360e01b8152fd5b50903461014857826003193601126101485760ff60015460a01c16610bc95733835260209282845281812054928315610bbb57908484610b31933384528083528386812055610b1482600254610d36565b600255855163a9059cbb60e01b8152948592839233908401610d94565b0381847f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af19081156105555750610b9e575b5080518281527f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364843392a251908152f35b610bb490843d861161054e5761053f8183610d43565b5038610b6d565b82516335411d8b60e01b8152fd5b51634a324f2160e11b8152fd5b50903461014857826003193601126101485782546001600160a01b031633148015610c36575b156106d5576001805460ff60a01b19169055827f72c874aeff0b183a56e2b79c71b46e1aed4dee5e09862134b8821ba2fddbf8bf8180a180f35b507f0000000000000000000000000000000000000000000000000000000000000000621275008101809111610c6c574211610bfc565b634e487b7160e01b845260118352602484fd5b5050346101b957816003193601126101b957602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b8490346101b957816003193601126101b95760209060ff60015460a01c1615158152f35b9181601f84011215610d0e578235916001600160401b038311610d0e576020808501948460051b010111610d0e57565b600080fd5b91908201809211610d2057565b634e487b7160e01b600052601160045260246000fd5b91908203918211610d2057565b601f909101601f19168101906001600160401b03821190821017610d6657604052565b634e487b7160e01b600052604160045260246000fd5b90816020910312610d0e57518015158103610d0e5790565b6001600160a01b039091168152602081019190915260400190565b15610db657565b60405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606490fd5b9190811015610dfa5760051b0190565b634e487b7160e01b600052603260045260246000fd5b908115610f325760ff60015460a01c1615610f20573360005260046020526040600020610e3e838254610d13565b80915511610f0e57610e5281600254610d13565b6002556040516323b872dd60e01b81523360048201523060248201526044810182905260208160648160007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af18015610f0257610ee3575b506040519081527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c60203392a2565b610efb9060203d60201161054e5761053f8183610d43565b5038610eb4565b6040513d6000823e3d90fd5b604051636f7b6d7960e11b8152600490fd5b604051630d0ca57160e21b8152600490fd5b60405163b4fa3fb360e01b8152600490fdfea26469706673582212202237e1fb214e9649199babb884f15e6b77b28b5e9d91b4f2477e763271d1a18c64736f6c6343000817003300000000000000000000000043000000000000000000000000000000000000040000000000000000000000000c056b34f2afa70ee1351e3659dfbd20977652750000000000000000000000008044f710c58b6ea6a178cc540f9f1cd758f7d1b2135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd

Deployed Bytecode

0x6080604081815260048036101561001557600080fd5b600092833560e01c90816302fb0c5e14610cba575080632eb4a7ab14610c7f57806335a063b414610bd65780633ccfd60b14610ac35780633e10020d14610a0257838163406cf229146108dc575080634e71d92d1461070a57806361325e18146106e25780637a385da7146106575780637a40624b1461061c5780637d882097146105fd5780637d94792a1461040a57806384eb7731146102ed5780638da5cb5b146102c55780639b19251a1461028c578063b8ab24bd14610263578063bf3a9c721461021f578063c08d1fe514610201578063cd3293de146101bd578063f2fde38b1461014c5763fc7e286d1461010c57600080fd5b346101485760203660031901126101485780356001600160a01b03811690819003610144579282916020948252845220549051908152f35b8380fd5b8280fd5b8382346101b95760203660031901126101b957356001600160a01b038181169182900361014857819061018484549182163314610daf565b6001600160a01b031916178255337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b5080fd5b5050346101b957816003193601126101b957517f00000000000000000000000043000000000000000000000000000000000000046001600160a01b03168152602090f35b5050346101b957816003193601126101b95760209051621275008152f35b5050346101b957816003193601126101b957517f0000000000000000000000000c056b34f2afa70ee1351e3659dfbd20977652756001600160a01b03168152602090f35b5050346101b957816003193601126101b95760015490516001600160a01b039091168152602090f35b503461014857602036600319011261014857356001600160a01b0381169081900361014857828291602094526003845220549051908152f35b5050346101b957816003193601126101b957905490516001600160a01b039091168152602090f35b509190346101b95760603660031901126101b957602435906001600160401b03604435818111610406576103249036908701610cde565b91835190602091602081019061034d8161033f8a3386610d94565b03601f198101835282610d43565b5190208551602080820192835281529091818701908111828210176103f357865251902092806103bf575b5050507f135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd036103b057506103ad919235610e10565b80f35b516348f5c3ed60e01b81528390fd5b60059060051b830192935b82853591828111841b9081521852818588209401938385106103ca579350505050388080610378565b634e487b7160e01b895260418a52602489fd5b8480fd5b5090346101485782600319360112610148576001549260ff8460a01c16156105ef57815163ab2637af60e01b81526020946001600160a01b0390868387818486165afa92831561059d5784936105b7575b5081831633036105a75760ff60a01b191660015583516370a0823160e01b81523086820152947f00000000000000000000000043000000000000000000000000000000000000049190911691908686602481865afa95861561059d5790879392918597610560575b50918691856104e896959488519788958694859363a9059cbb60e01b85528401610d94565b03925af19081156105555750610528575b507ffe8b095e1a768e83a862933c32f2bd9b62b7b87f8fc8843d83ccce205208b656838251848152a151908152f35b61054790843d861161054e575b61053f8183610d43565b810190610d7c565b50386104f9565b503d610535565b8351903d90823e3d90fd5b8481939495929698503d8311610596575b61057b8183610d43565b8101031261059257519492869291906104e86104c3565b8580fd5b503d610571565b85513d86823e3d90fd5b84516348f5c3ed60e01b81528690fd5b9092508681813d83116105e8575b6105cf8183610d43565b810103126101445751818116810361014457913861045b565b503d6105c5565b5051630d0ca57160e21b8152fd5b5050346101b957816003193601126101b9576020906002549051908152f35b5050346101b957816003193601126101b957602090517f0000000000000000000000000000000000000000000000000000000065e0cd198152f35b509034610148576020366003190112610148576001600160a01b0382358181169391929084900361040657827f0000000000000000000000000c056b34f2afa70ee1351e3659dfbd20977652751633036106d5576001549283166106c85750506001600160a01b0319161760015580f35b5163b4fa3fb360e01b8152fd5b516348f5c3ed60e01b8152fd5b5034610148576020366003190112610148576103ad9133845260036020528320549035610e10565b5090346101485782600319360112610148576001549260ff8460a01c166108ce5781516370a0823160e01b815230818501526020946001600160a01b03949086908390602490829089165afa9182156108c4578392610895575b5033835280865283832054948215801561088d575b61087e57670de0b6b3a7640000808702938785048214881517156108585760025494851561086b5785900481810291818304149015171561085857916107ca8994926107f997969404988994610d36565b6002553385528184528487812055600154169084875180978195829463a9059cbb60e01b845233908401610d94565b03925af1908115610555575061083b575b5080518281527f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4843392a251908152f35b61085190843d861161054e5761053f8183610d43565b503861080a565b634e487b7160e01b865260118452602486fd5b634e487b7160e01b875260128552602487fd5b508351633c21f90f60e01b8152fd5b508515610779565b9091508581813d83116108bd575b6108ad8183610d43565b8101031261014857519038610764565b503d6108a3565b84513d85823e3d90fd5b5051634a324f2160e11b8152fd5b828185346101b957816003193601126101b95781546001600160a01b0390811690610908338314610daf565b7f00000000000000000000000043000000000000000000000000000000000000041682519163e12f3a6160e01b835230868401526020958684602481865afa9384156109f85790879493929187946109c3575b509561097b96865197889586948593635569f64b60e11b85528401610d94565b03925af19081156109ba575061098f578280f35b813d83116109b3575b6109a28183610d43565b810103126109b05781808280f35b80fd5b503d610998565b513d85823e3d90fd5b8581969295503d83116109f1575b6109db8183610d43565b810103126105925792518693909261097b61095b565b503d6109d1565b85513d88823e3d90fd5b5090346101485780600319360112610148576001600160401b0390823582811161040657610a339036908501610cde565b93909260243590811161059257610a4d9036908301610cde565b9060018060a01b0392610a64848954163314610daf565b828703610ab55750865b868110610a79578780f35b610a84818484610dea565b3590610a91818989610dea565b3591858316809303610ab1576001928a526003602052868a205501610a6e565b8980fd5b845163b4fa3fb360e01b8152fd5b50903461014857826003193601126101485760ff60015460a01c16610bc95733835260209282845281812054928315610bbb57908484610b31933384528083528386812055610b1482600254610d36565b600255855163a9059cbb60e01b8152948592839233908401610d94565b0381847f00000000000000000000000043000000000000000000000000000000000000046001600160a01b03165af19081156105555750610b9e575b5080518281527f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364843392a251908152f35b610bb490843d861161054e5761053f8183610d43565b5038610b6d565b82516335411d8b60e01b8152fd5b51634a324f2160e11b8152fd5b50903461014857826003193601126101485782546001600160a01b031633148015610c36575b156106d5576001805460ff60a01b19169055827f72c874aeff0b183a56e2b79c71b46e1aed4dee5e09862134b8821ba2fddbf8bf8180a180f35b507f0000000000000000000000000000000000000000000000000000000065e0cd19621275008101809111610c6c574211610bfc565b634e487b7160e01b845260118352602484fd5b5050346101b957816003193601126101b957602090517f135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd8152f35b8490346101b957816003193601126101b95760209060ff60015460a01c1615158152f35b9181601f84011215610d0e578235916001600160401b038311610d0e576020808501948460051b010111610d0e57565b600080fd5b91908201809211610d2057565b634e487b7160e01b600052601160045260246000fd5b91908203918211610d2057565b601f909101601f19168101906001600160401b03821190821017610d6657604052565b634e487b7160e01b600052604160045260246000fd5b90816020910312610d0e57518015158103610d0e5790565b6001600160a01b039091168152602081019190915260400190565b15610db657565b60405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606490fd5b9190811015610dfa5760051b0190565b634e487b7160e01b600052603260045260246000fd5b908115610f325760ff60015460a01c1615610f20573360005260046020526040600020610e3e838254610d13565b80915511610f0e57610e5281600254610d13565b6002556040516323b872dd60e01b81523360048201523060248201526044810182905260208160648160007f00000000000000000000000043000000000000000000000000000000000000046001600160a01b03165af18015610f0257610ee3575b506040519081527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c60203392a2565b610efb9060203d60201161054e5761053f8183610d43565b5038610eb4565b6040513d6000823e3d90fd5b604051636f7b6d7960e11b8152600490fd5b604051630d0ca57160e21b8152600490fd5b60405163b4fa3fb360e01b8152600490fdfea26469706673582212202237e1fb214e9649199babb884f15e6b77b28b5e9d91b4f2477e763271d1a18c64736f6c63430008170033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000043000000000000000000000000000000000000040000000000000000000000000c056b34f2afa70ee1351e3659dfbd20977652750000000000000000000000008044f710c58b6ea6a178cc540f9f1cd758f7d1b2135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd

-----Decoded View---------------
Arg [0] : reserve_ (address): 0x4300000000000000000000000000000000000004
Arg [1] : baselineFactory_ (address): 0x0C056B34F2AFa70Ee1351e3659DFBD2097765275
Arg [2] : owner_ (address): 0x8044f710c58B6eA6a178CC540f9F1Cd758F7d1B2
Arg [3] : merkleRoot_ (bytes32): 0x135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000004300000000000000000000000000000000000004
Arg [1] : 0000000000000000000000000c056b34f2afa70ee1351e3659dfbd2097765275
Arg [2] : 0000000000000000000000008044f710c58b6ea6a178cc540f9f1cd758f7d1b2
Arg [3] : 135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.