ETH Price: $2,432.91 (+0.21%)

Contract

0x34Dc47d9325631768116E67a095c6aDdf8Ab1778
 

Overview

ETH Balance

ETH Value

$0.00

Token Holdings

Sponsored

Transaction Hash
Method
Block
From
To
Set Manager26841432024-04-27 0:35:01165 days ago1714178101IN
0x34Dc47d9...df8Ab1778
0 ETH0.000081063.00000046
Set Points Opera...26841432024-04-27 0:35:01165 days ago1714178101IN
0x34Dc47d9...df8Ab1778
0 ETH0.000169543.00000046
Update Position ...26841432024-04-27 0:35:01165 days ago1714178101IN
0x34Dc47d9...df8Ab1778
0 ETH0.000164643.00000046
Update Curve26841432024-04-27 0:35:01165 days ago1714178101IN
0x34Dc47d9...df8Ab1778
0 ETH0.000136683.00000046
Update Yield Man...26841432024-04-27 0:35:01165 days ago1714178101IN
0x34Dc47d9...df8Ab1778
0 ETH0.000158563.00000046
0x6080604026841432024-04-27 0:35:01165 days ago1714178101IN
 Contract Creation
0 ETH0.010736893.00000046

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
98238782024-10-09 7:06:1126 mins ago1728457571
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
98225522024-10-09 6:21:591 hr ago1728454919
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
98225482024-10-09 6:21:511 hr ago1728454911
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
98135312024-10-09 1:21:176 hrs ago1728436877
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
98109702024-10-08 23:55:557 hrs ago1728431755
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
98072322024-10-08 21:51:199 hrs ago1728424279
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
98020122024-10-08 18:57:1912 hrs ago1728413839
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97989132024-10-08 17:14:0114 hrs ago1728407641
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97810042024-10-08 7:17:0324 hrs ago1728371823
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97805022024-10-08 7:00:1924 hrs ago1728370819
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97722932024-10-08 2:26:4129 hrs ago1728354401
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97637352024-10-07 21:41:2533 hrs ago1728337285
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97554812024-10-07 17:06:1738 hrs ago1728320777
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97540182024-10-07 16:17:3139 hrs ago1728317851
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97533962024-10-07 15:56:4739 hrs ago1728316607
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97408732024-10-07 8:59:2146 hrs ago1728291561
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97269142024-10-07 1:14:032 days ago1728263643
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97209322024-10-06 21:54:392 days ago1728251679
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97207682024-10-06 21:49:112 days ago1728251351
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97164152024-10-06 19:24:052 days ago1728242645
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
97112102024-10-06 16:30:352 days ago1728232235
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
96838342024-10-06 1:18:033 days ago1728177483
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
96677452024-10-05 16:21:453 days ago1728145305
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
96458032024-10-05 4:10:214 days ago1728101421
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
96445902024-10-05 3:29:554 days ago1728098995
0x34Dc47d9...df8Ab1778
 Contract Creation0 ETH
View All Internal Transactions

Loading...
Loading

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

Contract Name:
Vault

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 2000 runs

Other Settings:
paris EvmVersion
File 1 of 27 : Vault.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/security/ReentrancyGuard.sol";
import {Multicall} from "../lib/openzeppelin-contracts/contracts/utils/Multicall.sol";
import {ERC1967Proxy} from "../lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {IERC20} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import {SafeERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";

import {IVault} from "./interfaces/IVault.sol";
import {IYieldManager} from "./interfaces/IYieldManager.sol";
import {RateMapping, FixedRateTerm, VariableRateTerm, VariableRatePrincipal} from "./libraries/Structs.sol";
import {BlastManager} from "./libraries/BlastManager.sol";
import {FixedRate} from "./FixedRate.sol";
import {VariableRate} from "./VariableRate.sol";
import {CoreRef} from "./core/CoreRef.sol";

contract Vault is IVault, ReentrancyGuard, Multicall, CoreRef, BlastManager {
    using SafeERC20 for IERC20;

    /* Constants */
    uint256 public constant BASIS = 1 ether;

    /* Immutables */
    // solhint-disable var-name-mixedcase
    address public TOKEN;
    uint256 public MATURITY; // maturity period in seconds
    address public FIXED_RATE; // fixed rate implementation address
    address public VARIABLE_RATE; // variable rate implementation address

    /* Variables */
    uint256 private _nextId;
    uint256 public fixedRateLockedYield;
    uint256 public positionFeeRate;
    address public yieldManager;
    RateMapping public rateMapping;
    VariableRatePrincipal public variableRatePrincipal;

    /* Storage */
    mapping(uint256 => FixedRateTerm) public fixedRateTerms; // id => (owner, principal, yield, maturityTimestamp)
    mapping(address => VariableRateTerm) public variableRateTerms; // owner => principal

    constructor(
        address token,
        uint256 maturity,
        address fixedRate,
        address variableRate,
        address coreAddress
    ) CoreRef(coreAddress) {
        TOKEN = token;
        MATURITY = maturity;
        FIXED_RATE = fixedRate;
        VARIABLE_RATE = variableRate;
    }

    /*==============================================================
                         Fixed rate LP deposit
    ==============================================================*/

    /// @inheritdoc IVault
    function mintFixedRate(
        uint256 amount,
        uint256 minLockedYield,
        address recipient
    ) external override nonReentrant returns (address owner, uint256 lockedYield, uint256 maturityTimestamp) {
        require(amount > 0, "Vault: invalid value");

        // log principal for yield manager
        IYieldManager(yieldManager).depositPrincipal(amount);

        // create fixed rate contract
        ERC1967Proxy fixedRateProxy = new ERC1967Proxy(FIXED_RATE, "");
        FixedRate fixedRate = FixedRate(address(fixedRateProxy));
        fixedRate.initialize(TOKEN, address(this), recipient);
        owner = address(fixedRate);

        // take the fee
        if (positionFeeRate > 0) {
            uint256 fee = (amount * positionFeeRate) / BASIS;
            amount -= fee;
            // drip the fee to this countract
            IERC20(TOKEN).safeTransferFrom(msg.sender, address(this), fee);
        }

        // get current amount to lock
        lockedYield = getYieldToLock(amount);

        // check slippage
        require(lockedYield >= minLockedYield, "Vault: slippage");

        // check enough yield to lock
        require(lockedYield <= IYieldManager(yieldManager).getIdleYield(), "Vault: overspend");

        // update the locked yield in storage
        fixedRateLockedYield += lockedYield;

        // mint
        uint256 id = _nextId++;
        fixedRateTerms[id] = FixedRateTerm({
            owner: owner,
            principal: amount,
            yield: lockedYield,
            maturityTimestamp: maturityTimestamp = block.timestamp + MATURITY
        });

        // mint the yield to the fixed rate contract
        IYieldManager(yieldManager).mintYield(owner, lockedYield);

        // route the fund to the fixed rate contract
        IERC20(TOKEN).safeTransferFrom(msg.sender, owner, amount);
        fixedRate.mint(id, amount, lockedYield, maturityTimestamp); // record keeping for the contract

        emit MintFixedRate(owner, id, amount, lockedYield);
    }

    /*=============================================================
                         Fixed rate LP withdraw
    ==============================================================*/

    /// @inheritdoc IVault
    function burnFixedRate(
        uint256 id,
        uint256 amount
    ) external override nonReentrant returns (uint256 yieldToUnlock, uint256 yieldToRelease) {
        require(amount > 0, "Vault: invalid value");

        // log principal for yield manager
        IYieldManager(yieldManager).withdrawPrincipal(amount);

        // SLOAD to memory
        FixedRateTerm memory fixedRateTerm = fixedRateTerms[id];

        // check the owner
        require(fixedRateTerm.owner == msg.sender, "Vault: unauthorized");

        // check the amount
        require(amount <= fixedRateTerm.principal, "Vault: overspend");

        // calculate the yield to release, and the yield to return back to the vault
        /// @dev For principal 100, locked 10 yield, maturity 100 days
        ///      Example 1: at day 50, withdraw 50 principal gets 2.5 yield, and return 2.5 yield back to vault
        ///      Example 2: at day 50, withdraw 100 principal gets 5 yield, and return 5 yield back to vault
        ///      Example 3: at day 0, withdraw 50 principal gets 0 yield, and return 5 yield back to vault
        uint256 timeLeft = block.timestamp < fixedRateTerm.maturityTimestamp
            ? fixedRateTerm.maturityTimestamp - block.timestamp
            : 0;
        yieldToUnlock = (fixedRateTerm.yield * amount) / fixedRateTerm.principal;
        yieldToRelease = (yieldToUnlock * (MATURITY - timeLeft)) / MATURITY;

        // update the balance storage
        fixedRateLockedYield -= yieldToUnlock;

        // burn
        if (fixedRateTerm.principal == amount) {
            delete fixedRateTerms[id]; // delete at full withdrawn
        } else {
            // update the term
            fixedRateTerms[id].principal = fixedRateTerm.principal - amount;
            fixedRateTerms[id].yield = fixedRateTerm.yield - yieldToUnlock;
        }

        // execute unmatured yield burn
        if (yieldToUnlock > yieldToRelease) {
            uint256 yieldToBurn = yieldToUnlock - yieldToRelease;
            require(yieldToBurn <= FixedRate(msg.sender).yield(), "Vault: overburn yield");
            IYieldManager(yieldManager).burnUnmaturedYield(msg.sender, yieldToBurn);
        }

        emit BurnFixedRate(msg.sender, id, amount, yieldToRelease);
    }

    /*==============================================================
                        Variable rate LP deposit
    ==============================================================*/

    /// @inheritdoc IVault
    function mintVariableRate(
        uint256 amount,
        address recipient
    ) external override nonReentrant returns (address owner) {
        require(amount > 0, "Vault: invalid value");

        // log principal for yield manager
        IYieldManager(yieldManager).depositPrincipal(amount);

        // create variable rate contract
        ERC1967Proxy variableRateProxy = new ERC1967Proxy(VARIABLE_RATE, "");
        VariableRate variableRate = VariableRate(address(variableRateProxy));
        variableRate.initialize(TOKEN, address(this), recipient);
        owner = address(variableRate);

        // update the balance storage
        variableRatePrincipal.principalTimespan +=
            variableRatePrincipal.principal * // update principal timespan until now first
            (block.timestamp - variableRatePrincipal.checkpointTimestamp);
        variableRatePrincipal.checkpointTimestamp = block.timestamp;
        variableRatePrincipal.principal += amount;

        // mint
        variableRateTerms[owner] = VariableRateTerm({principal: amount, mintTimestamp: block.timestamp});

        // route the fund to the variable rate contract
        IERC20(TOKEN).safeTransferFrom(msg.sender, owner, amount);
        variableRate.mint(amount); // record keeping for the contract

        emit MintVariableRate(owner, amount);
    }

    /*==============================================================
                        Variable rate LP withdraw
    ==============================================================*/

    /// @inheritdoc IVault
    function burnVariableRate(
        uint256 amount,
        uint256 minYield
    ) external override nonReentrant returns (uint256 yield, uint256 fee) {
        require(amount > 0, "Vault: invalid value");

        // log principal for yield manager
        IYieldManager(yieldManager).withdrawPrincipal(amount);

        // SLOAD the principal
        uint256 principal = variableRateTerms[msg.sender].principal;

        // check the amount
        require(amount <= principal, "Vault: overspend");

        // update variable rate principal storage
        variableRatePrincipal.principalTimespan +=
            variableRatePrincipal.principal * // update principal timespan until now first
            (block.timestamp - variableRatePrincipal.checkpointTimestamp);
        variableRatePrincipal.checkpointTimestamp = block.timestamp;

        // calculate the proportion to distribute the yield and position fee
        uint256 amountTimespan;
        (amountTimespan, yield, fee) = _getVariableRatePortion(msg.sender, amount);

        // check slippage
        require(yield >= minYield, "Vault: slippage");

        ///@dev amount should be subtracted from principal here, because the balance should not be updated in
        ///     `_getVariableRatePortion` above just yet, for the proportion calculation
        variableRatePrincipal.principalTimespan -= amountTimespan;
        variableRatePrincipal.principal -= amount;

        // burn
        if (amount == principal) {
            delete variableRateTerms[msg.sender]; // delete at full withdrawn
        } else {
            // update the term
            variableRateTerms[msg.sender].principal = principal - amount;
        }

        // mint the yield
        IYieldManager(yieldManager).mintYield(msg.sender, yield);

        // transfer position fee
        IERC20(TOKEN).safeTransfer(msg.sender, fee);

        emit BurnVariableRate(msg.sender, amount, yield, fee);
    }

    /**
     * @notice Get the portion to distribute the yield with position fee
     * @dev This function is called by burnVariableRate and the rebalnce step of mintVariableRate
     * @dev The passed in values are assumed to be already checked
     * @param owner the owner of the principal
     * @param amount the amount of principal to burn
     * @return amountTimespan the amount with timespan
     * @return yield the amount of yield to distribute
     * @return fee the amount of position fee to distribute
     */
    function _getVariableRatePortion(
        address owner,
        uint256 amount
    ) internal view returns (uint256 amountTimespan, uint256 yield, uint256 fee) {
        // calculate the amount over time
        amountTimespan = amount * (block.timestamp - variableRateTerms[owner].mintTimestamp);

        // read protocol idle yield available to distribute
        ///@dev total yield >= locked yield should always hold, because yield is always locked or withdrawn from idle
        uint256 idleYield = IYieldManager(yieldManager).getIdleYield();

        // SLOAD to memory
        uint256 variableRateTotalPrincipalTimespan = variableRatePrincipal.principalTimespan;

        if (variableRateTotalPrincipalTimespan > 0) {
            // get the proportional yield to distribute
            yield = (idleYield * amountTimespan) / variableRateTotalPrincipalTimespan;

            // get the proportional position fee to distribute
            fee = (IERC20(TOKEN).balanceOf(address(this)) * amountTimespan) / variableRateTotalPrincipalTimespan;
        }
    }

    /*==============================================================
                            Helper Functions
    ==============================================================*/

    /// @inheritdoc IVault
    function getYieldToLock(uint256 amount) public view override returns (uint256 yieldToLock) {
        uint256 fixedRate = getFixedRate(amount);
        yieldToLock = (amount * fixedRate * MATURITY) / BASIS; // linear rate
    }

    /// @inheritdoc IVault
    function getMaxFixedRateAmount() external view override returns (uint256 amount) {
        uint256 idleYield = IYieldManager(yieldManager).getIdleYield();
        amount = (idleYield * BASIS) / (getFixedRate(0) * MATURITY);
    }

    /// @inheritdoc IVault
    function getFixedRate(uint256 amount) public view override returns (uint256 rate) {
        // read idle yield from yield stripped token
        uint256 idleYield = IYieldManager(yieldManager).getIdleYield();

        // read protocol total yield = idle yield + locked yield
        uint256 totalYield = idleYield + fixedRateLockedYield;

        // ratio = idle yield / total yield * BASIS
        uint256 ratio = totalYield > 0 ? (idleYield * BASIS) / totalYield : 0;

        // relative rate (upper end) using the current idle yield / total yield ratio
        uint256 relativeRate = _mapRatioToRelativeRate(ratio);

        // relativeRate / BASIS is now the relative yield, multiply by the current yield rate to get the fixed term rate
        rate = (IYieldManager(yieldManager).getYieldRate() * relativeRate) / BASIS;

        // using the current rate, lock the yield, update idle yield
        uint256 yieldToLock = (amount * rate * MATURITY) / BASIS; // linear rate

        // update the new idle yield, after locking the yield under the current rate
        idleYield = idleYield > yieldToLock ? idleYield - yieldToLock : 0;

        // with the new idle yield, calculate the new ratio
        ratio = totalYield > 0 ? (idleYield * BASIS) / totalYield : 0;

        // relative rate (lower end) using the new idle yield / total yield ratio
        relativeRate = _mapRatioToRelativeRate(ratio);

        // return the new rate at lower end
        rate = (IYieldManager(yieldManager).getYieldRate() * relativeRate) / BASIS;
    }

    /// @inheritdoc IVault
    function getTotalYield() public view override returns (uint256 totalYield) {
        totalYield = IYieldManager(yieldManager).getIdleYield() + fixedRateLockedYield;
    }

    /// @inheritdoc IVault
    function getCurrentVariableRate(address owner) external view override returns (uint256 yield, uint256 fee) {
        (, yield, fee) = _getVariableRatePortion(owner, variableRateTerms[owner].principal);
    }

    /**
     * @notice Map the ratio to the relative rate
     * @param ratio the ratio of idle yield to total yield
     * @return relativeRate the relative rate
     */
    function _mapRatioToRelativeRate(uint256 ratio) internal view returns (uint256 relativeRate) {
        // mapping from ratio (x) to rate (y), a piecewise linear function:
        // 0 <= x < r1:      y = s1 / BASIS * x
        // r1 <= x < r2:     y = s1 / BASIS * r1 + s2 / BASIS * (x - r1)
        // r2 <= x <= BASIS: y = s1 / BASIS * r1 + s2 / BASIS * (r2 - r1) + s3 / BASIS * (x - r2)
        // y is capped at BASIS (relative yield = 1)
        if (ratio < rateMapping.r1) {
            relativeRate = (rateMapping.s1 * ratio) / BASIS;
        } else if (ratio < rateMapping.r2) {
            relativeRate = (rateMapping.s1 * rateMapping.r1 + rateMapping.s2 * (ratio - rateMapping.r1)) / BASIS;
        } else {
            relativeRate =
                ((rateMapping.s1 * rateMapping.r1) +
                    (rateMapping.s2 * (rateMapping.r2 - rateMapping.r1)) +
                    (rateMapping.s3 * (ratio - rateMapping.r2))) /
                BASIS;
        }
        relativeRate = relativeRate > BASIS ? BASIS : relativeRate;
    }

    /*==============================================================
                              Admin Logic
    ==============================================================*/

    /// @inheritdoc IVault
    function updateYieldManager(address newYieldManager) external override onlyGuardianOrGovernor {
        yieldManager = newYieldManager;
        emit UpdateYieldManager(newYieldManager);
    }

    /// @inheritdoc IVault
    function updateCurve(
        uint256 s1,
        uint256 s2,
        uint256 s3,
        uint256 r1,
        uint256 r2
    ) external override onlyGuardianOrGovernor nonReentrant {
        require(r1 <= r2, "Vault: invalid curve");
        rateMapping = RateMapping(s1, s2, s3, r1, r2);
        emit UpdateCurve(s1, s2, s3, r1, r2);
    }

    /// @inheritdoc IVault
    function updatePositionFeeRate(uint256 fee) external override onlyGuardianOrGovernor nonReentrant {
        require(fee < BASIS, "Vault: invalid position fee");
        positionFeeRate = fee;
        emit UpdatePositionFeeRate(fee);
    }
}

File 2 of 27 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

File 3 of 27 : Multicall.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Multicall.sol)

pragma solidity ^0.8.0;

import "./Address.sol";

/**
 * @dev Provides a function to batch together multiple calls in a single external call.
 *
 * _Available since v4.1._
 */
abstract contract Multicall {
    /**
     * @dev Receives and executes a batch of function calls on this contract.
     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
     */
    function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {
        results = new bytes[](data.length);
        for (uint256 i = 0; i < data.length; i++) {
            results[i] = Address.functionDelegateCall(address(this), data[i]);
        }
        return results;
    }
}

File 4 of 27 : ERC1967Proxy.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)

pragma solidity ^0.8.0;

import "../Proxy.sol";
import "./ERC1967Upgrade.sol";

/**
 * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
 * implementation address that can be changed. This address is stored in storage in the location specified by
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
 * implementation behind the proxy.
 */
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
    /**
     * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
     *
     * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
     * function call, and allows initializing the storage of the proxy like a Solidity constructor.
     */
    constructor(address _logic, bytes memory _data) payable {
        _upgradeToAndCall(_logic, _data, false);
    }

    /**
     * @dev Returns the current implementation address.
     */
    function _implementation() internal view virtual override returns (address impl) {
        return ERC1967Upgrade._getImplementation();
    }
}

File 5 of 27 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)

pragma solidity ^0.8.0;

import "../token/ERC20/IERC20.sol";

File 6 of 27 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

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

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

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

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

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

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

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

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}

File 7 of 27 : IVault.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

interface IVault {
    /*==============================================================
                               Event Logs
    ==============================================================*/

    event MintFixedRate(address indexed owner, uint256 id, uint256 mintAmount, uint256 lockedAmount);
    event BurnFixedRate(address indexed owner, uint256 id, uint256 burnAmount, uint256 yield);
    event MintVariableRate(address indexed owner, uint256 mintAmount);
    event BurnVariableRate(address indexed owner, uint256 burnAmount, uint256 yield, uint256 positionFee);
    event EstimateYield(uint256 currentRate, bool updated);
    event UpdateYieldManager(address indexed newYieldManager);
    event UpdateYieldEstimateWindow(uint256 window);
    event UpdateCurve(uint256 s1, uint256 s2, uint256 s3, uint256 r1, uint256 r2);
    event UpdatePositionFeeRate(uint256 fee);

    /*==============================================================
                         Fixed rate LP deposit
    ==============================================================*/

    /**
     * @notice Deposit a principal amount to lock a fixed yield rate until maturity
     * @param amount the deposit amount
     * @param minLockedYield the minimum amount to lock, for slippage protection
     * @param recipient the address to receive the fixedRate contract
     * @return owner the address to the fixedRate contract
     * @return lockedYield the amount locked, which over time releases the yield at fixed rate
     * @return maturityTimestamp the maturity timestamp
     */
    function mintFixedRate(
        uint256 amount,
        uint256 minLockedYield,
        address recipient
    ) external returns (address owner, uint256 lockedYield, uint256 maturityTimestamp);

    /*==============================================================
                        Fixed rate LP withdraw
    ==============================================================*/

    /**
     * @notice Withdraw a principal amount from a fixed yield rate deposit
     * @param id the deposit id
     * @param amount the amount of principal to withdraw
     * @return yieldToUnlock the yield to unlock from the locked amount
     * @return yieldToRelease the yield to release to the owner
     */
    function burnFixedRate(uint256 id, uint256 amount) external returns (uint256 yieldToUnlock, uint256 yieldToRelease);

    /*==============================================================
                       Variable rate LP deposit
    ==============================================================*/

    /**
     * @notice Deposit a principal amount for variable yield rate
     * @param amount the deposit amount
     * @param recipient the address to receive the variableRate contract
     * @return owner the address to the variableRate contract
     */
    function mintVariableRate(uint256 amount, address recipient) external returns (address owner);

    /*==============================================================
                      Variable rate LP withdraw
    ==============================================================*/

    /**
     * @notice Withdraw a principal amount from a variable yield rate deposit
     * @param amount the amount of principal to withdraw
     * @param minYield the minimum yield to receive, for slippage protection
     * @return yield the yield amount
     * @return fee the position fee
     */
    function burnVariableRate(uint256 amount, uint256 minYield) external returns (uint256 yield, uint256 fee);

    /*==============================================================
                            Helper Functions
    ==============================================================*/

    /**
     * @notice get the amount to lock based on the current fixed term rate and the deposit amount
     * @param amount the deposit amount
     * @return yieldToLock the amount to lock
     */
    function getYieldToLock(uint256 amount) external view returns (uint256 yieldToLock);

    /**
     * @notice get the maximum amount of principal for a fixed term rate
     * @return amount the maximum amount of principal
     */
    function getMaxFixedRateAmount() external view returns (uint256 amount);

    /**
     * @notice get the current fixed term rate from idle yield / total yield
     * @param amount the deposit amount
     * @return rate the current fixed term rate
     */
    function getFixedRate(uint256 amount) external view returns (uint256 rate);

    /**
     * @notice get the total yield from the protocol
     * @return totalYield the total yield
     */
    function getTotalYield() external view returns (uint256 totalYield);

    /**
     * @notice get the current yield and position fee accrued to a variable rate LP
     * @param owner the address of the LP
     * @return yield the current yield
     * @return fee the current position fee
     */
    function getCurrentVariableRate(address owner) external view returns (uint256 yield, uint256 fee);

    /*==============================================================
                              Admin Logic
    ==============================================================*/

    /**
     * @notice Update the yield manager
     * @param newYieldManager the new yield manager
     */
    function updateYieldManager(address newYieldManager) external;

    /**
     * @notice Update the fixed term rate curve
     * @param s1 the slope of chunk 1
     * @param s2 the slope of chunk 2
     * @param s3 the slope of chunk 3
     * @param r1 the ratio cutoff between chunk 1 and 2
     * @param r2 the ratio cutoff between chunk 2 and 3
     */
    function updateCurve(uint256 s1, uint256 s2, uint256 s3, uint256 r1, uint256 r2) external;

    /**
     * @notice Update the position fee
     * @param fee the new position fee
     */
    function updatePositionFeeRate(uint256 fee) external;
}

File 8 of 27 : IYieldManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

interface IYieldManager {
    /**
     * @notice drip the yield by minting the yield stripped token
     * @param recipient the recipient of the yield
     * @param yield the yield amount
     */
    function mintYield(address recipient, uint256 yield) external;

    /**
     * @notice return the yield by burning the yield stripped token
     * @param amount the amount of yield to burn
     */
    function burnUnmaturedYield(address fixedRate, uint256 amount) external;

    /**
     * @notice log a deposit event for the principal to the protocol
     * @param amount the amount of principal deposited
     */
    function depositPrincipal(uint256 amount) external;

    /**
     * @notice log a withdraw event for the principal from the protocol
     * @param amount the amount of principal withdrawn
     */
    function withdrawPrincipal(uint256 amount) external;

    /**
     * @notice get the idle yield from the protocol
     * @return idleYield the current idle yield
     */
    function getIdleYield() external view returns (uint256 idleYield);

    /**
     * @notice get the current yield rate
     * @return yieldRate the current yield rate
     */
    function getYieldRate() external view returns (uint256 yieldRate);
}

File 9 of 27 : Structs.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

struct VariableRatePrincipal {
    uint256 principal; // the principal amount
    uint256 principalTimespan; // principal amount across time (for yield estimation)
    uint256 checkpointTimestamp; // the deposit timestamp
}

struct RateMapping {
    uint256 s1; // slope of chunk 1
    uint256 s2; // slope of chunk 2
    uint256 s3; // slope of chunk 3
    uint256 r1; // ratio cutoff between chunk 1 and 2
    uint256 r2; // ratio cutoff between chunk 2 and 3
}

struct FixedRateTerm {
    address owner; // the owner of the deposit
    uint256 principal; // the principal amount
    uint256 yield; // the yield amount, locked at deposit time, released over time until maturity
    uint256 maturityTimestamp; // the maturity timestamp
}

struct VariableRateTerm {
    uint256 principal; // the principal amount
    uint256 mintTimestamp; // the timestamp at the deposit mint
}

File 10 of 27 : BlastManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {IBlast} from "../interfaces/IBlast.sol";
import {IBlastPoints} from "../interfaces/IBlastPoints.sol";

contract BlastManager {
    IBlast public constant BLAST = IBlast(0x4300000000000000000000000000000000000002);
    address public manager;

    modifier onlyManager() {
        require(msg.sender == manager, "Blast: not manager");
        _;
    }

    constructor() {
        manager = msg.sender;
        BLAST.configureClaimableGas();
    }

    function claimGas(address recipient, bool isMax) external onlyManager returns (uint256) {
        if (isMax) {
            return BLAST.claimMaxGas(address(this), recipient);
        } else {
            return BLAST.claimAllGas(address(this), recipient);
        }
    }

    function setManager(address _manager) external onlyManager {
        manager = _manager;
    }

    function setGasMode(address blastGas) external onlyManager {
        IBlast(blastGas).configureClaimableGas();
    }

    function setPointsOperator(address blastPoints, address operator) external onlyManager {
        IBlastPoints(blastPoints).configurePointsOperator(operator);
    }
}

File 11 of 27 : FixedRate.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/security/ReentrancyGuard.sol";
import {IERC20} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import {SafeERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {IVault} from "./interfaces/IVault.sol";
import {ICoreRef} from "./core/ICoreRef.sol";

contract FixedRate is ReentrancyGuard {
    using SafeERC20 for IERC20;

    /* Immutables */
    // solhint-disable var-name-mixedcase
    address public TOKEN;
    address public VAULT;
    address public OWNER;

    /* Variables */
    bool public initialized;
    uint256 public id;
    uint256 public principal;
    uint256 public yield;
    uint256 public maturityTimestamp;

    function initialize(address token, address vault, address owner) external nonReentrant {
        require(!initialized, "FixedRate: already initialized");
        initialized = true;
        TOKEN = token;
        VAULT = vault;
        OWNER = owner;
    }

    function mint(
        uint256 _id,
        uint256 _principal,
        uint256 _yield,
        uint256 _maturityTimestamp
    ) external nonReentrant onlyVault {
        require(IERC20(TOKEN).balanceOf(address(this)) == _principal + _yield, "FixedRate: insufficient fund");
        id = _id;
        principal = _principal;
        yield = _yield;
        maturityTimestamp = _maturityTimestamp;
    }

    function burn(
        uint256 amount
    ) external nonReentrant onlyOwner returns (uint256 yieldToUnlock, uint256 yieldToRelease) {
        require(amount <= principal, "FixedRate: overspend");
        (yieldToUnlock, yieldToRelease) = IVault(VAULT).burnFixedRate(id, amount);
        uint256 yieldBurned = yieldToUnlock - yieldToRelease;
        require(
            IERC20(TOKEN).balanceOf(address(this)) >= principal + yield - yieldBurned,
            "FixedRate: insufficient fund" // contract should now contain principal and remaining yield
        );
        principal -= amount;
        yield -= yieldToUnlock; // arithmetic check guarantees yieldToUnlock <= yield
        IERC20(TOKEN).safeTransfer(OWNER, amount + yieldToRelease);
    }

    function withdraw(uint256 amount) external nonReentrant onlyOwner onlyEmergency {
        require(amount <= principal, "FixedRate: overspend");
        principal -= amount;
        IERC20(TOKEN).safeTransfer(OWNER, amount);
    }

    modifier onlyOwner() {
        require(msg.sender == OWNER, "FixedRate: not owner");
        _;
    }

    modifier onlyVault() {
        require(msg.sender == VAULT, "FixedRate: not vault");
        _;
    }

    modifier onlyEmergency() {
        require(ICoreRef(VAULT).emergency(), "FixedRate: not emergency");
        _;
    }
}

File 12 of 27 : VariableRate.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {ReentrancyGuard} from "../lib/openzeppelin-contracts/contracts/security/ReentrancyGuard.sol";
import {IERC20} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import {SafeERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {IVault} from "./interfaces/IVault.sol";
import {ICoreRef} from "./core/ICoreRef.sol";

contract VariableRate is ReentrancyGuard {
    using SafeERC20 for IERC20;

    /* Immutables */
    // solhint-disable var-name-mixedcase
    address public TOKEN;
    address public VAULT;
    address public OWNER;

    /* Variables */
    bool public initialized;
    uint256 public principal;

    function initialize(address token, address vault, address owner) external nonReentrant {
        require(!initialized, "VariableRate: already initialized");
        initialized = true;
        TOKEN = token;
        VAULT = vault;
        OWNER = owner;
    }

    function mint(uint256 amount) external nonReentrant onlyVault {
        require(IERC20(TOKEN).balanceOf(address(this)) >= principal + amount, "VariableRate: insufficient fund");
        principal += amount;
    }

    function burn(
        uint256 amount,
        uint256 minYield
    ) external nonReentrant onlyOwner returns (uint256 yield, uint256 fee) {
        require(amount <= principal, "VariableRate: overspend");
        (yield, fee) = IVault(VAULT).burnVariableRate(amount, minYield);
        require(IERC20(TOKEN).balanceOf(address(this)) >= principal + yield + fee, "VariableRate: insufficient fund");
        principal -= amount;
        IERC20(TOKEN).safeTransfer(OWNER, amount + yield + fee);
    }

    function withdraw(uint256 amount) external nonReentrant onlyOwner onlyEmergency {
        require(amount <= principal, "VariableRate: overspend");
        principal -= amount;
        IERC20(TOKEN).safeTransfer(OWNER, amount);
    }

    modifier onlyOwner() {
        require(msg.sender == OWNER, "VariableRate: not owner");
        _;
    }

    modifier onlyVault() {
        require(msg.sender == VAULT, "VariableRate: not vault");
        _;
    }

    modifier onlyEmergency() {
        require(ICoreRef(VAULT).emergency(), "VariableRate: not emergency");
        _;
    }
}

File 13 of 27 : CoreRef.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {ICore} from "../core/ICore.sol";
import {ICoreRef} from "./ICoreRef.sol";

/// @title A Reference to Core
/// @notice defines some modifiers and utilities around interacting with Core
abstract contract CoreRef is ICoreRef {
    ICore private _core;

    // solhint-disable-next-line var-name-mixedcase
    bool public EMERGENCY;

    /// @notice CoreRef constructor
    /// @param coreAddress Few Core to reference
    constructor(address coreAddress) {
        _core = ICore(coreAddress);
    }

    modifier onlyMinter() {
        require(_core.isMinter(msg.sender), "CoreRef: Caller is not a minter");
        _;
    }

    modifier onlyBurner() {
        require(_core.isBurner(msg.sender), "CoreRef: Caller is not a burner");
        _;
    }

    modifier onlyGovernor() {
        require(_core.isGovernor(msg.sender), "CoreRef: Caller is not a governor");
        _;
    }

    modifier onlyGuardianOrGovernor() {
        require(
            _core.isGovernor(msg.sender) || _core.isGuardian(msg.sender),
            "CoreRef: Caller is not a guardian or governor"
        );
        _;
    }

    /// @notice set new Core reference address
    /// @param coreAddress the new core address
    function setCore(address coreAddress) external override onlyGovernor {
        _core = ICore(coreAddress);
        emit CoreUpdate(coreAddress);
    }

    function emergency() external view override returns (bool) {
        return EMERGENCY;
    }

    function startEmergency() external override onlyGuardianOrGovernor {
        EMERGENCY = true;
        emit EmergencyUpdate(true);
    }

    function stopEmergency() external override onlyGuardianOrGovernor {
        EMERGENCY = false;
        emit EmergencyUpdate(false);
    }

    /// @notice address of the Core contract referenced
    /// @return ICore implementation address
    function core() public view override returns (ICore) {
        return _core;
    }
}

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

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 15 of 27 : Proxy.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)

pragma solidity ^0.8.0;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overridden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}

File 16 of 27 : ERC1967Upgrade.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)

pragma solidity ^0.8.2;

import "../beacon/IBeacon.sol";
import "../../interfaces/IERC1967.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";

/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 *
 * _Available since v4.1._
 */
abstract contract ERC1967Upgrade is IERC1967 {
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
        // Upgrades from old implementations will perform a rollback test. This test requires the new
        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
        // this special case will break upgrade paths from old UUPS implementation to new ones.
        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
            _setImplementation(newImplementation);
        } else {
            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
            } catch {
                revert("ERC1967Upgrade: new implementation is not UUPS");
            }
            _upgradeToAndCall(newImplementation, data, forceCall);
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(
            Address.isContract(IBeacon(newBeacon).implementation()),
            "ERC1967: beacon implementation is not a contract"
        );
        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
        }
    }
}

File 17 of 27 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

File 18 of 27 : IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.0;

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

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

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

File 19 of 27 : IBlast.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

enum YieldMode {
    AUTOMATIC,
    DISABLED,
    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
        );
}

File 20 of 27 : IBlastPoints.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

interface IBlastPoints {
    /**
     * @notice Blast standard: configure for blast point operator address
     * @param operator the blast points operator address
     */
    function configurePointsOperator(address operator) external;
}

File 21 of 27 : ICoreRef.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {ICore} from "../core/ICore.sol";

/// @title CoreRef interface
interface ICoreRef {
    event CoreUpdate(address indexed _core);
    event EmergencyUpdate(bool _emergency);
    event MinterUpdate(address indexed _minter, bool _status);
    event BurnerUpdate(address indexed _burner, bool _status);

    function emergency() external view returns (bool);

    function startEmergency() external;

    function stopEmergency() external;

    function setCore(address coreAddress) external;

    function core() external view returns (ICore);
}

File 22 of 27 : ICore.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {IPermissions} from "./IPermissions.sol";

/// @title Core Interface
interface ICore is IPermissions {
    function init() external;
}

File 23 of 27 : IBeacon.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeacon {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}

File 24 of 27 : IERC1967.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
 *
 * _Available since v4.8.3._
 */
interface IERC1967 {
    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Emitted when the beacon is changed.
     */
    event BeaconUpgraded(address indexed beacon);
}

File 25 of 27 : draft-IERC1822.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
 * proxy whose upgrades are fully controlled by the current implementation.
 */
interface IERC1822Proxiable {
    /**
     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
     * address.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy.
     */
    function proxiableUUID() external view returns (bytes32);
}

File 26 of 27 : StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}

File 27 of 27 : IPermissions.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/// @title Permissions interface
interface IPermissions {
    // ----------- Governor only state changing api -----------

    function createRole(bytes32 role, bytes32 adminRole) external;

    function grantGovernor(address governor) external;

    function grantGuardian(address guardian) external;

    function grantMinter(address minter) external;

    function grantBurner(address burner) external;

    function revokeGovernor(address governor) external;

    function revokeGuardian(address guardian) external;

    function revokeMinter(address minter) external;

    function revokeBurner(address burner) external;

    // ----------- Revoker only state changing api -----------

    function revokeOverride(bytes32 role, address account) external;

    // ----------- Getters -----------

    function isGovernor(address _address) external view returns (bool);

    function isGuardian(address _address) external view returns (bool);

    function isMinter(address _address) external view returns (bool);

    function isBurner(address _address) external view returns (bool);
}

Settings
{
  "remappings": [
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 2000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"address","name":"fixedRate","type":"address"},{"internalType":"address","name":"variableRate","type":"address"},{"internalType":"address","name":"coreAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burnAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yield","type":"uint256"}],"name":"BurnFixedRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"burnAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yield","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"positionFee","type":"uint256"}],"name":"BurnVariableRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_burner","type":"address"},{"indexed":false,"internalType":"bool","name":"_status","type":"bool"}],"name":"BurnerUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_core","type":"address"}],"name":"CoreUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_emergency","type":"bool"}],"name":"EmergencyUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"currentRate","type":"uint256"},{"indexed":false,"internalType":"bool","name":"updated","type":"bool"}],"name":"EstimateYield","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockedAmount","type":"uint256"}],"name":"MintFixedRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"MintVariableRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_minter","type":"address"},{"indexed":false,"internalType":"bool","name":"_status","type":"bool"}],"name":"MinterUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"s1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"s2","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"s3","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"r1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"r2","type":"uint256"}],"name":"UpdateCurve","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"UpdatePositionFeeRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"window","type":"uint256"}],"name":"UpdateYieldEstimateWindow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newYieldManager","type":"address"}],"name":"UpdateYieldManager","type":"event"},{"inputs":[],"name":"BASIS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BLAST","outputs":[{"internalType":"contract IBlast","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMERGENCY","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FIXED_RATE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MATURITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VARIABLE_RATE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFixedRate","outputs":[{"internalType":"uint256","name":"yieldToUnlock","type":"uint256"},{"internalType":"uint256","name":"yieldToRelease","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minYield","type":"uint256"}],"name":"burnVariableRate","outputs":[{"internalType":"uint256","name":"yield","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bool","name":"isMax","type":"bool"}],"name":"claimGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"core","outputs":[{"internalType":"contract ICore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergency","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fixedRateLockedYield","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"fixedRateTerms","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"yield","type":"uint256"},{"internalType":"uint256","name":"maturityTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getCurrentVariableRate","outputs":[{"internalType":"uint256","name":"yield","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getFixedRate","outputs":[{"internalType":"uint256","name":"rate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxFixedRateAmount","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalYield","outputs":[{"internalType":"uint256","name":"totalYield","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getYieldToLock","outputs":[{"internalType":"uint256","name":"yieldToLock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minLockedYield","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"mintFixedRate","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"lockedYield","type":"uint256"},{"internalType":"uint256","name":"maturityTimestamp","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"mintVariableRate","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"positionFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rateMapping","outputs":[{"internalType":"uint256","name":"s1","type":"uint256"},{"internalType":"uint256","name":"s2","type":"uint256"},{"internalType":"uint256","name":"s3","type":"uint256"},{"internalType":"uint256","name":"r1","type":"uint256"},{"internalType":"uint256","name":"r2","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"coreAddress","type":"address"}],"name":"setCore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"blastGas","type":"address"}],"name":"setGasMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"blastPoints","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"setPointsOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startEmergency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopEmergency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"s1","type":"uint256"},{"internalType":"uint256","name":"s2","type":"uint256"},{"internalType":"uint256","name":"s3","type":"uint256"},{"internalType":"uint256","name":"r1","type":"uint256"},{"internalType":"uint256","name":"r2","type":"uint256"}],"name":"updateCurve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"updatePositionFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newYieldManager","type":"address"}],"name":"updateYieldManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"variableRatePrincipal","outputs":[{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"principalTimespan","type":"uint256"},{"internalType":"uint256","name":"checkpointTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"variableRateTerms","outputs":[{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"mintTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yieldManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

Deployed Bytecode

0x60806040523480156200001157600080fd5b5060043610620002aa5760003560e01c806397d75776116200017c578063b3b5130b11620000e9578063ce245c801162000097578063e220831d116200007a578063e220831d14620006a5578063f2f4eb2614620006bc578063f3f35e2314620006ce57600080fd5b8063ce245c80146200067a578063d0ebdbe7146200068e57600080fd5b8063c3e0b63611620000cc578063c3e0b6361462000628578063c8b11dfe146200063f578063caa6fea4146200065657600080fd5b8063b3b5130b14620005fa578063bf2a9cd7146200061157600080fd5b8063a295b6281162000147578063ac9650d8116200012a578063ac9650d81462000550578063ad0546161462000576578063ad6694c214620005e357600080fd5b8063a295b628146200050f578063a9359d92146200051957600080fd5b806397d7577614620004bb57806397db7edb14620004d757806398e8e38b14620004e15780639c3750c714620004f857600080fd5b80637f5a259f116200021b57806387fc557711620001e65780638e12c0cd11620001c95780638e12c0cd146200046757806390ed8f9e1462000471578063935d96e214620004b157600080fd5b806387fc557714620004465780638cf35e7d146200045057600080fd5b80637f5a259f14620003f357806380009630146200040757806380b7af18146200041e57806382bfefc8146200043257600080fd5b8063528cfa9811620002795780637aec978d116200025c5780637aec978d14620003955780637c14c697146200039f5780637deb4cfd14620003dc57600080fd5b8063528cfa981462000332578063565920e2146200035157600080fd5b80630fb7e60214620002af578063190c3a4a14620002bb5780632d195bd214620002ee578063481c6a751462000305575b600080fd5b620002b9620006e5565b005b601054601154601254620002ce92919083565b604080519384526020840192909252908201526060015b60405180910390f35b620002b9620002ff36600462003292565b620008a7565b60025462000319906001600160a01b031681565b6040516001600160a01b039091168152602001620002e5565b62000342670de0b6b3a764000081565b604051908152602001620002e5565b600b54600c54600d54600e54600f546200036c949392919085565b604080519586526020860194909452928401919091526060830152608082015260a001620002e5565b620003426200095b565b620003b6620003b0366004620032b0565b620009fa565b604080516001600160a01b039094168452602084019290925290820152606001620002e5565b620002b9620003ed366004620032e8565b62000f96565b60055462000319906001600160a01b031681565b620002b96200041836600462003292565b62001188565b600a5462000319906001600160a01b031681565b60035462000319906001600160a01b031681565b6200034260095481565b6200034262000461366004620032e8565b620012c2565b6200034260045481565b6200049b6200048236600462003292565b6014602052600090815260409020805460019091015482565b60408051928352602083019190915201620002e5565b6200034260085481565b6200031973430000000000000000000000000000000000000281565b620002b962001573565b620002b9620004f236600462003302565b62001716565b6200049b620005093660046200333e565b62001953565b6200034262001c9a565b6001546200053f9074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001620002e5565b620005676200056136600462003361565b62001d5a565b604051620002e591906200342f565b620005b862000587366004620032e8565b60136020526000908152604090208054600182015460028301546003909301546001600160a01b0390921692909184565b604080516001600160a01b0390951685526020850193909352918301526060820152608001620002e5565b620002b9620005f436600462003292565b62001e56565b6200049b6200060b3660046200333e565b62001ff6565b6200031962000622366004620034b5565b6200247c565b6200049b6200063936600462003292565b620027ab565b6200034262000650366004620034f3565b620027de565b60015474010000000000000000000000000000000000000000900460ff166200053f565b60065462000319906001600160a01b031681565b620002b96200069f36600462003292565b6200294d565b620002b9620006b63660046200352f565b620029d8565b6001546001600160a01b031662000319565b62000342620006df366004620032e8565b62002aae565b600154604051631c86b03760e31b81523360048201526001600160a01b039091169063e43581b890602401602060405180830381865afa1580156200072e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200075491906200355e565b80620007ca5750600154604051630c68ba2160e01b81523360048201526001600160a01b0390911690630c68ba2190602401602060405180830381865afa158015620007a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620007ca91906200355e565b620008325760405162461bcd60e51b815260206004820152602d60248201527f436f72655265663a2043616c6c6572206973206e6f742061206775617264696160448201526c371037b91033b7bb32b93737b960991b60648201526084015b60405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001781556040519081527ffb42c1145c310d3034571b76a56346cc592d8c24144acd44c3bb098ef0f9aed8906020015b60405180910390a1565b6002546001600160a01b03163314620009035760405162461bcd60e51b815260206004820152601260248201527f426c6173743a206e6f74206d616e616765720000000000000000000000000000604482015260640162000829565b806001600160a01b0316634e606c476040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200093f57600080fd5b505af115801562000954573d6000803e3d6000fd5b5050505050565b600854600a54604080517faca2dfdd0000000000000000000000000000000000000000000000000000000081529051600093926001600160a01b03169163aca2dfdd9160048083019260209291908290030181865afa158015620009c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620009e991906200357e565b620009f59190620035ae565b905090565b600080600062000a0962002af7565b6000861162000a5b5760405162461bcd60e51b815260206004820152601460248201527f5661756c743a20696e76616c69642076616c7565000000000000000000000000604482015260640162000829565b600a546040517fef8d4964000000000000000000000000000000000000000000000000000000008152600481018890526001600160a01b039091169063ef8d496490602401600060405180830381600087803b15801562000abb57600080fd5b505af115801562000ad0573d6000803e3d6000fd5b5050600554604051600093506001600160a01b03909116915062000af49062003267565b6001600160a01b039091168152604060208201819052600090820152606001604051809103906000f08015801562000b30573d6000803e3d6000fd5b506003546040517fc0c53b8b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152306024820152878216604482015291925082919082169063c0c53b8b90606401600060405180830381600087803b15801562000ba557600080fd5b505af115801562000bba573d6000803e3d6000fd5b505050508094506000600954111562000c21576000670de0b6b3a76400006009548a62000be89190620035c4565b62000bf49190620035de565b905062000c02818a62003601565b60035490995062000c1f906001600160a01b031633308462002b52565b505b62000c2c8862002aae565b93508684101562000c805760405162461bcd60e51b815260206004820152600f60248201527f5661756c743a20736c6970706167650000000000000000000000000000000000604482015260640162000829565b600a60009054906101000a90046001600160a01b03166001600160a01b031663aca2dfdd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000cd4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000cfa91906200357e565b84111562000d4b5760405162461bcd60e51b815260206004820152601060248201527f5661756c743a206f7665727370656e6400000000000000000000000000000000604482015260640162000829565b836008600082825462000d5f9190620035ae565b9091555050600780546000918262000d778362003617565b9190505590506040518060800160405280876001600160a01b031681526020018a81526020018681526020016004544262000db39190620035ae565b908190526000838152601360209081526040918290208451815473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03918216178255918501516001820155848301516002820155606090940151600390940193909355600a5490517f06ddf8b9000000000000000000000000000000000000000000000000000000008152898416600482015260248101899052919650909116906306ddf8b990604401600060405180830381600087803b15801562000e7557600080fd5b505af115801562000e8a573d6000803e3d6000fd5b505060035462000ea992506001600160a01b0316905033888c62002b52565b6040517f6582ccd300000000000000000000000000000000000000000000000000000000815260048101829052602481018a905260448101869052606481018590526001600160a01b03831690636582ccd390608401600060405180830381600087803b15801562000f1a57600080fd5b505af115801562000f2f573d6000803e3d6000fd5b505060408051848152602081018d90529081018890526001600160a01b03891692507f99c6f10d63a2f504df3974aff51e30a8e92b00709f0d8f775fc31c4fa7757dd5915060600160405180910390a250505062000f8d6001600055565b93509350939050565b600154604051631c86b03760e31b81523360048201526001600160a01b039091169063e43581b890602401602060405180830381865afa15801562000fdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200100591906200355e565b806200107b5750600154604051630c68ba2160e01b81523360048201526001600160a01b0390911690630c68ba2190602401602060405180830381865afa15801562001055573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200107b91906200355e565b620010df5760405162461bcd60e51b815260206004820152602d60248201527f436f72655265663a2043616c6c6572206973206e6f742061206775617264696160448201526c371037b91033b7bb32b93737b960991b606482015260840162000829565b620010e962002af7565b670de0b6b3a76400008110620011425760405162461bcd60e51b815260206004820152601b60248201527f5661756c743a20696e76616c696420706f736974696f6e206665650000000000604482015260640162000829565b60098190556040518181527fab1d3e07938b634a0b668c6970231076f1b5f3d2d8bca22394b0abeeffc679759060200160405180910390a1620011856001600055565b50565b600154604051631c86b03760e31b81523360048201526001600160a01b039091169063e43581b890602401602060405180830381865afa158015620011d1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011f791906200355e565b6200126b5760405162461bcd60e51b815260206004820152602160248201527f436f72655265663a2043616c6c6572206973206e6f74206120676f7665726e6f60448201527f7200000000000000000000000000000000000000000000000000000000000000606482015260840162000829565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517fad9400e618eb1344fde53db22397a1b82c765527ecbba3a5c86bcac15090828b90600090a250565b600080600a60009054906101000a90046001600160a01b03166001600160a01b031663aca2dfdd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001319573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200133f91906200357e565b9050600060085482620013539190620035ae565b905060008082116200136757600062001388565b816200137c670de0b6b3a764000085620035c4565b620013889190620035de565b90506000620013978262002c0b565b9050670de0b6b3a764000081600a60009054906101000a90046001600160a01b03166001600160a01b031663f10098996040518163ffffffff1660e01b8152600401602060405180830381865afa158015620013f7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200141d91906200357e565b620014299190620035c4565b620014359190620035de565b94506000670de0b6b3a76400006004548789620014539190620035c4565b6200145f9190620035c4565b6200146b9190620035de565b90508085116200147d57600062001489565b62001489818662003601565b9450600084116200149c576000620014bd565b83620014b1670de0b6b3a764000087620035c4565b620014bd9190620035de565b9250620014ca8362002c0b565b9150670de0b6b3a764000082600a60009054906101000a90046001600160a01b03166001600160a01b031663f10098996040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200152a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200155091906200357e565b6200155c9190620035c4565b620015689190620035de565b979650505050505050565b600154604051631c86b03760e31b81523360048201526001600160a01b039091169063e43581b890602401602060405180830381865afa158015620015bc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015e291906200355e565b80620016585750600154604051630c68ba2160e01b81523360048201526001600160a01b0390911690630c68ba2190602401602060405180830381865afa15801562001632573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200165891906200355e565b620016bc5760405162461bcd60e51b815260206004820152602d60248201527f436f72655265663a2043616c6c6572206973206e6f742061206775617264696160448201526c371037b91033b7bb32b93737b960991b606482015260840162000829565b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055604051600081527ffb42c1145c310d3034571b76a56346cc592d8c24144acd44c3bb098ef0f9aed8906020016200089d565b600154604051631c86b03760e31b81523360048201526001600160a01b039091169063e43581b890602401602060405180830381865afa1580156200175f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200178591906200355e565b80620017fb5750600154604051630c68ba2160e01b81523360048201526001600160a01b0390911690630c68ba2190602401602060405180830381865afa158015620017d5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620017fb91906200355e565b6200185f5760405162461bcd60e51b815260206004820152602d60248201527f436f72655265663a2043616c6c6572206973206e6f742061206775617264696160448201526c371037b91033b7bb32b93737b960991b606482015260840162000829565b6200186962002af7565b80821115620018bb5760405162461bcd60e51b815260206004820152601460248201527f5661756c743a20696e76616c6964206375727665000000000000000000000000604482015260640162000829565b6040805160a08082018352878252602080830188905282840187905260608084018790526080938401869052600b8a9055600c899055600d889055600e879055600f86905584518a81529182018990529381018790529283018590529082018390527f53a7e026ff03c8aad8b2e01b95b1ca803d654f9ccbb71e95f829c1a48ea3609c910160405180910390a1620009546001600055565b6000806200196062002af7565b60008411620019b25760405162461bcd60e51b815260206004820152601460248201527f5661756c743a20696e76616c69642076616c7565000000000000000000000000604482015260640162000829565b600a546040517f658e28a4000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b039091169063658e28a490602401600060405180830381600087803b15801562001a1257600080fd5b505af115801562001a27573d6000803e3d6000fd5b5050336000908152601460205260409020549150508085111562001a8e5760405162461bcd60e51b815260206004820152601060248201527f5661756c743a206f7665727370656e6400000000000000000000000000000000604482015260640162000829565b60125462001a9d904262003601565b60105462001aac9190620035c4565b6011805460009062001ac0908490620035ae565b909155505042601255600062001ad7338762002d40565b909550935090508484101562001b305760405162461bcd60e51b815260206004820152600f60248201527f5661756c743a20736c6970706167650000000000000000000000000000000000604482015260640162000829565b806010600101600082825462001b47919062003601565b90915550506010805487919060009062001b6390849062003601565b909155505081860362001b8c573360009081526014602052604081208181556001015562001ba9565b62001b98868362003601565b336000908152601460205260409020555b600a546040517f06ddf8b9000000000000000000000000000000000000000000000000000000008152336004820152602481018690526001600160a01b03909116906306ddf8b990604401600060405180830381600087803b15801562001c0f57600080fd5b505af115801562001c24573d6000803e3d6000fd5b505060035462001c4292506001600160a01b03169050338562002ecd565b604080518781526020810186905290810184905233907f4986227c8eddf18e5ae06327b851a4d48e5b3f3ab9ab4149e90ae436178fe3be906060015b60405180910390a2505062001c936001600055565b9250929050565b600080600a60009054906101000a90046001600160a01b03166001600160a01b031663aca2dfdd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001cf1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001d1791906200357e565b905060045462001d286000620012c2565b62001d349190620035c4565b62001d48670de0b6b3a764000083620035c4565b62001d549190620035de565b91505090565b60608167ffffffffffffffff81111562001d785762001d7862003652565b60405190808252806020026020018201604052801562001dad57816020015b606081526020019060019003908162001d975790505b50905060005b8281101562001e4e5762001e253085858481811062001dd65762001dd662003668565b905060200281019062001dea91906200367e565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062002f1d92505050565b82828151811062001e3a5762001e3a62003668565b602090810291909101015260010162001db3565b505b92915050565b600154604051631c86b03760e31b81523360048201526001600160a01b039091169063e43581b890602401602060405180830381865afa15801562001e9f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001ec591906200355e565b8062001f3b5750600154604051630c68ba2160e01b81523360048201526001600160a01b0390911690630c68ba2190602401602060405180830381865afa15801562001f15573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001f3b91906200355e565b62001f9f5760405162461bcd60e51b815260206004820152602d60248201527f436f72655265663a2043616c6c6572206973206e6f742061206775617264696160448201526c371037b91033b7bb32b93737b960991b606482015260840162000829565b600a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f9d136a534af018ec3d88e4718a01a3f5ebe51f5258f66427890fdece6dc3308290600090a250565b6000806200200362002af7565b60008311620020555760405162461bcd60e51b815260206004820152601460248201527f5661756c743a20696e76616c69642076616c7565000000000000000000000000604482015260640162000829565b600a546040517f658e28a4000000000000000000000000000000000000000000000000000000008152600481018590526001600160a01b039091169063658e28a490602401600060405180830381600087803b158015620020b557600080fd5b505af1158015620020ca573d6000803e3d6000fd5b505050600085815260136020908152604091829020825160808101845281546001600160a01b03168082526001830154938201939093526002820154938101939093526003015460608301529091503314620021695760405162461bcd60e51b815260206004820152601360248201527f5661756c743a20756e617574686f72697a656400000000000000000000000000604482015260640162000829565b8060200151841115620021bf5760405162461bcd60e51b815260206004820152601060248201527f5661756c743a206f7665727370656e6400000000000000000000000000000000604482015260640162000829565b600081606001514210620021d5576000620021e7565b428260600151620021e7919062003601565b90508160200151858360400151620022009190620035c4565b6200220c9190620035de565b6004549094506200221e828262003601565b6200222a9086620035c4565b620022369190620035de565b925083600860008282546200224c919062003601565b909155505060208201518590036200229f576000868152601360205260408120805473ffffffffffffffffffffffffffffffffffffffff19168155600181018290556002810182905560030155620022eb565b848260200151620022b1919062003601565b6000878152601360205260409081902060010191909155820151620022d890859062003601565b6000878152601360205260409020600201555b828411156200243b57600062002302848662003601565b9050336001600160a01b031663285939846040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200236991906200357e565b811115620023ba5760405162461bcd60e51b815260206004820152601560248201527f5661756c743a206f7665726275726e207969656c640000000000000000000000604482015260640162000829565b600a546040517f485f062b000000000000000000000000000000000000000000000000000000008152336004820152602481018390526001600160a01b039091169063485f062b90604401600060405180830381600087803b1580156200242057600080fd5b505af115801562002435573d6000803e3d6000fd5b50505050505b604080518781526020810187905290810184905233907f6450cf2f9be10ce3f0a739de98adc5a617abe0af91a14a8a7849ec2a78bfac929060600162001c7e565b60006200248862002af7565b60008311620024da5760405162461bcd60e51b815260206004820152601460248201527f5661756c743a20696e76616c69642076616c7565000000000000000000000000604482015260640162000829565b600a546040517fef8d4964000000000000000000000000000000000000000000000000000000008152600481018590526001600160a01b039091169063ef8d496490602401600060405180830381600087803b1580156200253a57600080fd5b505af11580156200254f573d6000803e3d6000fd5b5050600654604051600093506001600160a01b039091169150620025739062003267565b6001600160a01b039091168152604060208201819052600090820152606001604051809103906000f080158015620025af573d6000803e3d6000fd5b506003546040517fc0c53b8b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152306024820152858216604482015291925082919082169063c0c53b8b90606401600060405180830381600087803b1580156200262457600080fd5b505af115801562002639573d6000803e3d6000fd5b505050508092506010600201544262002653919062003601565b601054620026629190620035c4565b6011805460009062002676908490620035ae565b9091555050426012556010805486919060009062002696908490620035ae565b90915550506040805180820182528681524260208083019182526001600160a01b03808816600090815260149092529390209151825551600190910155600354620026e5911633858862002b52565b6040517fa0712d68000000000000000000000000000000000000000000000000000000008152600481018690526001600160a01b0382169063a0712d6890602401600060405180830381600087803b1580156200274157600080fd5b505af115801562002756573d6000803e3d6000fd5b50505050826001600160a01b03167f6f10d1d0041b2bc384cd3a0953a1c1b751d7f870241c7a87cdd28cc03bc279c0866040516200279691815260200190565b60405180910390a2505062001e506001600055565b6001600160a01b0381166000908152601460205260408120548190620027d390849062002d40565b909590945092505050565b6002546000906001600160a01b031633146200283d5760405162461bcd60e51b815260206004820152601260248201527f426c6173743a206e6f74206d616e616765720000000000000000000000000000604482015260640162000829565b8115620028ed576040517f662aa11d0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03841660248201527343000000000000000000000000000000000000029063662aa11d906044015b6020604051808303816000875af1158015620028bf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620028e591906200357e565b905062001e50565b6040517f954fa5ee0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03841660248201527343000000000000000000000000000000000000029063954fa5ee906044016200289f565b6002546001600160a01b03163314620029a95760405162461bcd60e51b815260206004820152601260248201527f426c6173743a206e6f74206d616e616765720000000000000000000000000000604482015260640162000829565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6002546001600160a01b0316331462002a345760405162461bcd60e51b815260206004820152601260248201527f426c6173743a206e6f74206d616e616765720000000000000000000000000000604482015260640162000829565b6040517f36b91f2b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301528316906336b91f2b90602401600060405180830381600087803b15801562002a9157600080fd5b505af115801562002aa6573d6000803e3d6000fd5b505050505050565b60008062002abc83620012c2565b9050670de0b6b3a7640000600454828562002ad89190620035c4565b62002ae49190620035c4565b62002af09190620035de565b9392505050565b60026000540362002b4b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000829565b6002600055565b6040516001600160a01b038085166024830152831660448201526064810182905262002c059085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915262002f45565b50505050565b600e5460009082101562002c4757600b54670de0b6b3a76400009062002c33908490620035c4565b62002c3f9190620035de565b905062002d1a565b600f5482101562002c9857600e54670de0b6b3a76400009062002c6b908462003601565b600c5462002c7a9190620035c4565b600e54600b5462002c8c9190620035c4565b62002c339190620035ae565b600f54670de0b6b3a76400009062002cb1908462003601565b600d5462002cc09190620035c4565b600e54600f5462002cd2919062003601565b600c5462002ce19190620035c4565b600e54600b5462002cf39190620035c4565b62002cff9190620035ae565b62002d0b9190620035ae565b62002d179190620035de565b90505b670de0b6b3a7640000811162002d31578062001e50565b670de0b6b3a764000092915050565b6001600160a01b0382166000908152601460205260408120600101548190819062002d6c904262003601565b62002d789085620035c4565b92506000600a60009054906101000a90046001600160a01b03166001600160a01b031663aca2dfdd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002dd0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002df691906200357e565b601154909150801562002ec4578062002e108684620035c4565b62002e1c9190620035de565b6003546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919550829187916001600160a01b0316906370a0823190602401602060405180830381865afa15801562002e83573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002ea991906200357e565b62002eb59190620035c4565b62002ec19190620035de565b92505b50509250925092565b6040516001600160a01b03831660248201526044810182905262002f189084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640162002ba0565b505050565b606062002af0838360405180606001604052806027815260200162003c086027913962003034565b600062002f9c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620030b29092919063ffffffff16565b905080516000148062002fc057508080602001905181019062002fc091906200355e565b62002f185760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162000829565b6060600080856001600160a01b031685604051620030539190620036e6565b600060405180830381855af49150503d806000811462003090576040519150601f19603f3d011682016040523d82523d6000602084013e62003095565b606091505b5091509150620030a886838387620030cb565b9695505050505050565b6060620030c384846000856200314b565b949350505050565b606083156200313f57825160000362003137576001600160a01b0385163b620031375760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000829565b5081620030c3565b620030c383836200323a565b606082471015620031c55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840162000829565b600080866001600160a01b03168587604051620031e39190620036e6565b60006040518083038185875af1925050503d806000811462003222576040519150601f19603f3d011682016040523d82523d6000602084013e62003227565b606091505b50915091506200156887838387620030cb565b8151156200324b5781518083602001fd5b8060405162461bcd60e51b815260040162000829919062003704565b6104ee806200371a83390190565b80356001600160a01b03811681146200328d57600080fd5b919050565b600060208284031215620032a557600080fd5b62002af08262003275565b600080600060608486031215620032c657600080fd5b8335925060208401359150620032df6040850162003275565b90509250925092565b600060208284031215620032fb57600080fd5b5035919050565b600080600080600060a086880312156200331b57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b600080604083850312156200335257600080fd5b50508035926020909101359150565b600080602083850312156200337557600080fd5b823567ffffffffffffffff808211156200338e57600080fd5b818501915085601f830112620033a357600080fd5b813581811115620033b357600080fd5b8660208260051b8501011115620033c957600080fd5b60209290920196919550909350505050565b60005b83811015620033f8578181015183820152602001620033de565b50506000910152565b600081518084526200341b816020860160208601620033db565b601f01601f19169290920160200192915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015620034a8577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200349585835162003401565b9450928501929085019060010162003458565b5092979650505050505050565b60008060408385031215620034c957600080fd5b82359150620034db6020840162003275565b90509250929050565b80151581146200118557600080fd5b600080604083850312156200350757600080fd5b620035128362003275565b915060208301356200352481620034e4565b809150509250929050565b600080604083850312156200354357600080fd5b6200354e8362003275565b9150620034db6020840162003275565b6000602082840312156200357157600080fd5b815162002af081620034e4565b6000602082840312156200359157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562001e505762001e5062003598565b808202811582820484141762001e505762001e5062003598565b600082620035fc57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111562001e505762001e5062003598565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036200364b576200364b62003598565b5060010190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112620036b457600080fd5b83018035915067ffffffffffffffff821115620036d057600080fd5b60200191503681900382131562001c9357600080fd5b60008251620036fa818460208701620033db565b9190910192915050565b60208152600062002af060208301846200340156fe60806040526040516104ee3803806104ee833981016040819052610022916102de565b61002e82826000610035565b50506103fb565b61003e83610061565b60008251118061004b5750805b1561005c5761005a83836100a1565b505b505050565b61006a816100cd565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100c683836040518060600160405280602781526020016104c760279139610180565b9392505050565b6001600160a01b0381163b61013f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080856001600160a01b03168560405161019d91906103ac565b600060405180830381855af49150503d80600081146101d8576040519150601f19603f3d011682016040523d82523d6000602084013e6101dd565b606091505b5090925090506101ef868383876101f9565b9695505050505050565b60608315610268578251600003610261576001600160a01b0385163b6102615760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610136565b5081610272565b610272838361027a565b949350505050565b81511561028a5781518083602001fd5b8060405162461bcd60e51b815260040161013691906103c8565b634e487b7160e01b600052604160045260246000fd5b60005b838110156102d55781810151838201526020016102bd565b50506000910152565b600080604083850312156102f157600080fd5b82516001600160a01b038116811461030857600080fd5b60208401519092506001600160401b038082111561032557600080fd5b818501915085601f83011261033957600080fd5b81518181111561034b5761034b6102a4565b604051601f8201601f19908116603f01168101908382118183101715610373576103736102a4565b8160405282815288602084870101111561038c57600080fd5b61039d8360208301602088016102ba565b80955050505050509250929050565b600082516103be8184602087016102ba565b9190910192915050565b60208152600082518060208401526103e78160408501602087016102ba565b601f01601f19169190910160400192915050565b60be806104096000396000f3fe608060405236601057600e6013565b005b600e5b601f601b6021565b6065565b565b600060607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156083573d6000f35b3d6000fdfea26469706673582212200cf704dd6658aecb7fda11b94812cc52047db6ddc348a0bce2b8b6ef8266a39964736f6c63430008170033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212203cf11c1f3d3b7cf556925a73265856620df3b8246ffa5677c3f2194da991b83664736f6c63430008170033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ 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.