Sepolia Testnet

Contract

0x7e0A97660B477a79C2e9f472bbFCFd8A715D9E6f

Overview

ETH Balance

0 ETH

Token Holdings

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Value

There are no matching entries

Please try again later

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To Value
54661382024-03-11 21:32:3677 days ago1710192756  Contract Creation0 ETH
Loading...
Loading

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

Contract Name:
ActivePool

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 28 : ActivePool.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

import "./Interfaces/IActivePool.sol";
import "./Interfaces/ICollSurplusPool.sol";
import "./Dependencies/ICollateralToken.sol";
import "./Interfaces/ICdpManagerData.sol";
import "./Interfaces/IBorrowerOperations.sol";
import "./Dependencies/ERC3156FlashLender.sol";
import "./Dependencies/SafeERC20.sol";
import "./Dependencies/ReentrancyGuard.sol";
import "./Dependencies/AuthNoOwner.sol";
import "./Dependencies/BaseMath.sol";
import "./Dependencies/TwapWeightedObserver.sol";
import "./Dependencies/EbtcMath.sol";

/**
 * @title The Active Pool holds the collateral and EBTC debt (only accounting but not EBTC tokens) for all active cdps.
 *
 * @notice When a cdp is liquidated, it's collateral will be transferred from the Active Pool
 * @notice (destination may vary depending on the liquidation conditions).
 * @dev ActivePool also allows ERC3156 compatible flashloan of stETH token
 */
contract ActivePool is
    IActivePool,
    ERC3156FlashLender,
    ReentrancyGuard,
    BaseMath,
    AuthNoOwner,
    TwapWeightedObserver
{
    using SafeERC20 for IERC20;
    string public constant NAME = "ActivePool";

    address public immutable borrowerOperationsAddress;
    address public immutable cdpManagerAddress;
    address public immutable collSurplusPoolAddress;
    address public immutable feeRecipientAddress;

    uint256 internal systemCollShares; // deposited collateral tracker
    uint256 internal systemDebt;
    uint256 internal feeRecipientCollShares; // coll shares claimable by fee recipient
    ICollateralToken public immutable collateral;

    // --- Contract setters ---

    /// @notice Constructor for the ActivePool contract
    /// @dev Initializes the contract with the borrowerOperationsAddress, cdpManagerAddress, collateral token address, collSurplusAddress, and feeRecipientAddress
    /// @param _borrowerOperationsAddress The address of the Borrower Operations contract
    /// @param _cdpManagerAddress The address of the Cdp Manager contract
    /// @param _collTokenAddress The address of the collateral token
    /// @param _collSurplusAddress The address of the collateral surplus pool

    constructor(
        address _borrowerOperationsAddress,
        address _cdpManagerAddress,
        address _collTokenAddress,
        address _collSurplusAddress
    ) TwapWeightedObserver(0) {
        borrowerOperationsAddress = _borrowerOperationsAddress;
        cdpManagerAddress = _cdpManagerAddress;
        collateral = ICollateralToken(_collTokenAddress);
        collSurplusPoolAddress = _collSurplusAddress;
        feeRecipientAddress = IBorrowerOperations(borrowerOperationsAddress).feeRecipientAddress();

        // TEMP: read authority to avoid signature change
        address _authorityAddress = address(AuthNoOwner(cdpManagerAddress).authority());
        if (_authorityAddress != address(0)) {
            _initializeAuthority(_authorityAddress);
        }

        require(systemDebt == 0, "ActivePool: systemDebt should be 0 for TWAP initialization");
    }

    // --- Getters for public variables. Required by IPool interface ---

    /// @notice Amount of stETH collateral shares in the contract
    /// @dev Not necessarily equal to the the contract's raw systemCollShares balance - tokens can be forcibly sent to contracts
    /// @return uint256 The amount of systemCollShares allocated to the pool

    function getSystemCollShares() external view override returns (uint256) {
        return systemCollShares;
    }

    /// @notice Returns the systemDebt state variable
    /// @dev The amount of EBTC debt in the pool. Like systemCollShares, this is not necessarily equal to the contract's EBTC token balance - tokens can be forcibly sent to contracts
    /// @return uint256 The amount of EBTC debt in the pool

    function getSystemDebt() external view override returns (uint256) {
        return systemDebt;
    }

    /// @notice The amount of stETH collateral shares claimable by the fee recipient
    /// @return uint256 The amount of collateral shares claimable by the fee recipient

    function getFeeRecipientClaimableCollShares() external view override returns (uint256) {
        return feeRecipientCollShares;
    }

    // --- Pool functionality ---

    /// @notice Sends stETH collateral shares to a specified account
    /// @dev Only for use by system contracts, the caller must be either BorrowerOperations or CdpManager
    /// @param _account The address of the account to send stETH to
    /// @param _shares The amount of stETH shares to send

    function transferSystemCollShares(address _account, uint256 _shares) public override {
        _requireCallerIsBOorCdpM();

        uint256 cachedSystemCollShares = systemCollShares;
        require(cachedSystemCollShares >= _shares, "!ActivePoolBal");
        unchecked {
            // Can use unchecked due to above
            cachedSystemCollShares -= _shares; // Updating here avoids an SLOAD
        }

        systemCollShares = cachedSystemCollShares;

        emit SystemCollSharesUpdated(cachedSystemCollShares);
        emit CollSharesTransferred(_account, _shares);

        _transferCollSharesWithContractHooks(_account, _shares);
    }

    /// @notice Sends stETH to a specified account, drawing from both core shares and liquidator rewards shares
    /// @notice Liquidator reward shares are not tracked via internal accounting in the active pool and are assumed to be present in expected amount as part of the intended behavior of BorowerOperations and CdpManager
    /// @dev Liquidator reward shares are added when a cdp is opened, and removed when it is closed
    /// @dev closeCdp() or liqudations result in the actor (borrower or liquidator respectively) receiving the liquidator reward shares
    /// @dev Redemptions result in the shares being sent to the coll surplus pool for claiming by the CDP owner
    /// @dev Note that funds in the coll surplus pool, just like liquidator reward shares, are not tracked as part of the system CR or coll of a CDP.
    /// @dev Requires that the caller is either BorrowerOperations or CdpManager
    /// @param _account The address of the account to send systemCollShares and the liquidator reward to
    /// @param _shares The amount of systemCollShares to send
    /// @param _liquidatorRewardShares The amount of the liquidator reward shares to send

    function transferSystemCollSharesAndLiquidatorReward(
        address _account,
        uint256 _shares,
        uint256 _liquidatorRewardShares
    ) external override {
        _requireCallerIsBOorCdpM();

        uint256 cachedSystemCollShares = systemCollShares;
        require(cachedSystemCollShares >= _shares, "ActivePool: Insufficient collateral shares");
        uint256 totalShares = _shares + _liquidatorRewardShares;
        unchecked {
            // Safe per the check above
            cachedSystemCollShares -= _shares;
        }
        systemCollShares = cachedSystemCollShares;

        emit SystemCollSharesUpdated(cachedSystemCollShares);
        emit CollSharesTransferred(_account, totalShares);

        _transferCollSharesWithContractHooks(_account, totalShares);
    }

    /// @notice Allocate stETH shares from the system to the fee recipient to claim at-will (pull model)
    /// @dev Requires that the caller is CdpManager
    /// @dev Only the current fee recipient address is able to claim the shares
    /// @dev If the fee recipient address is changed while outstanding claimable coll is available, only the new fee recipient will be able to claim the outstanding coll
    /// @param _shares The amount of systemCollShares to allocate to the fee recipient

    function allocateSystemCollSharesToFeeRecipient(uint256 _shares) external override {
        _requireCallerIsCdpManager();

        uint256 cachedSystemCollShares = systemCollShares;

        require(cachedSystemCollShares >= _shares, "ActivePool: Insufficient collateral shares");
        unchecked {
            // Safe per the check above
            cachedSystemCollShares -= _shares;
        }

        systemCollShares = cachedSystemCollShares;

        uint256 cachedFeeRecipientCollShares = feeRecipientCollShares + _shares;
        feeRecipientCollShares = cachedFeeRecipientCollShares;

        emit SystemCollSharesUpdated(cachedSystemCollShares);
        emit FeeRecipientClaimableCollSharesIncreased(cachedFeeRecipientCollShares, _shares);
    }

    /// @notice Helper function to transfer stETH shares to another address, ensuring to call hooks into other system pools if they are the recipient
    /// @param _account The address to transfer shares to
    /// @param _shares The amount of shares to transfer

    function _transferCollSharesWithContractHooks(address _account, uint256 _shares) internal {
        // NOTE: No need for safe transfer if the collateral asset is standard. Make sure this is the case!
        collateral.transferShares(_account, _shares);

        if (_account == collSurplusPoolAddress) {
            ICollSurplusPool(_account).increaseTotalSurplusCollShares(_shares);
        }
    }

    /// @notice Increases the tracked EBTC debt of the system by a specified amount
    /// @dev Managed by system contracts - requires that the caller is either BorrowerOperations or CdpManager
    /// @param _amount: The amount to increase the system EBTC debt by

    function increaseSystemDebt(uint256 _amount) external override {
        _requireCallerIsBOorCdpM();

        uint256 cachedSystemDebt = systemDebt + _amount;
        uint128 castedSystemDebt = EbtcMath.toUint128(cachedSystemDebt);

        if (!twapDisabled) {
            /// @audit If TWAP fails it should allow transaction to continue. Failure is preferrable to permanent DOS and can practically be mitigated by managing the redemption baseFee.
            try this.setValueAndUpdate(castedSystemDebt) {} catch {
                twapDisabled = true;
                emit TwapDisabled();
            }
        }

        /// @audit If above uint128 max, will have reverted in safeCast
        systemDebt = cachedSystemDebt;
        emit ActivePoolEBTCDebtUpdated(cachedSystemDebt);
    }

    /// @notice Decreases the tracked EBTC debt of the system by a specified amount
    /// @dev Managed by system contracts - requires that the caller is either BorrowerOperations or CdpManager
    /// @param _amount: The amount to decrease the system EBTC debt by

    function decreaseSystemDebt(uint256 _amount) external override {
        _requireCallerIsBOorCdpM();

        uint256 cachedSystemDebt = systemDebt - _amount;
        uint128 castedSystemDebt = EbtcMath.toUint128(cachedSystemDebt);

        if (!twapDisabled) {
            /// @audit If TWAP fails it should allow transaction to continue. Failure is preferrable to permanent DOS and can practically be mitigated by managing the redemption baseFee.
            try this.setValueAndUpdate(EbtcMath.toUint128(castedSystemDebt)) {} catch {
                twapDisabled = true;
                emit TwapDisabled();
            }
        }

        /// @audit If above uint128 max, will have reverted in safeCast
        systemDebt = cachedSystemDebt;
        emit ActivePoolEBTCDebtUpdated(cachedSystemDebt);
    }

    // --- 'require' functions ---

    /// @notice Checks if the caller is BorrowerOperations
    function _requireCallerIsBorrowerOperations() internal view {
        require(
            msg.sender == borrowerOperationsAddress,
            "ActivePool: Caller is not BorrowerOperations"
        );
    }

    /// @notice Checks if the caller is either BorrowerOperations or CdpManager
    function _requireCallerIsBOorCdpM() internal view {
        require(
            msg.sender == borrowerOperationsAddress || msg.sender == cdpManagerAddress,
            "ActivePool: Caller is neither BorrowerOperations nor CdpManager"
        );
    }

    /// @notice Checks if the caller is CdpManager
    function _requireCallerIsCdpManager() internal view {
        require(msg.sender == cdpManagerAddress, "ActivePool: Caller is not CdpManager");
    }

    /// @notice Notify that stETH collateral shares have been recieved, updating internal accounting accordingly
    /// @param _value The amount of collateral to receive

    function increaseSystemCollShares(uint256 _value) external override {
        _requireCallerIsBorrowerOperations();

        uint256 cachedSystemCollShares = systemCollShares + _value;
        systemCollShares = cachedSystemCollShares;
        emit SystemCollSharesUpdated(cachedSystemCollShares);
    }

    // === Flashloans === //

    /// @notice Borrow assets with a flash loan
    /// @dev The Collateral checks may cause reverts if you trigger a fee change big enough
    ///         consider calling `cdpManagerAddress.syncGlobalAccountingAndGracePeriod()`
    /// @param receiver The address to receive the flash loan
    /// @param token The address of the token to loan
    /// @param amount The amount of tokens to loan
    /// @param data Additional data
    /// @return A boolean value indicating whether the operation was successful

    function flashLoan(
        IERC3156FlashBorrower receiver,
        address token,
        uint256 amount,
        bytes calldata data
    ) external override returns (bool) {
        require(amount > 0, "ActivePool: 0 Amount");
        uint256 fee = flashFee(token, amount); // NOTE: Check for `token` is implicit in the requires above // also checks for paused
        require(amount <= maxFlashLoan(token), "ActivePool: Too much");

        uint256 amountWithFee = amount + fee;
        uint256 oldRate = collateral.getPooledEthByShares(DECIMAL_PRECISION);

        collateral.transfer(address(receiver), amount);

        // Callback
        require(
            receiver.onFlashLoan(msg.sender, token, amount, fee, data) == FLASH_SUCCESS_VALUE,
            "ActivePool: IERC3156: Callback failed"
        );

        // Transfer of (principal + Fee) from flashloan receiver
        collateral.transferFrom(address(receiver), address(this), amountWithFee);

        // Send earned fee to designated recipient
        collateral.transfer(feeRecipientAddress, fee);

        // Check new balance
        // NOTE: Invariant Check, technically breaks CEI but I think we must use it
        // NOTE: This means any balance > systemCollShares is stuck, this is also present in LUSD as is

        // NOTE: This check effectively prevents running 2 FL at the same time
        //  You technically could, but you'd be having to repay any amount below systemCollShares to get Fl2 to not revert
        require(
            collateral.balanceOf(address(this)) >= collateral.getPooledEthByShares(systemCollShares),
            "ActivePool: Must repay Balance"
        );
        require(
            collateral.sharesOf(address(this)) >= systemCollShares,
            "ActivePool: Must repay Share"
        );
        require(
            collateral.getPooledEthByShares(DECIMAL_PRECISION) == oldRate,
            "ActivePool: Should keep same collateral share rate"
        );

        emit FlashLoanSuccess(address(receiver), token, amount, fee);

        return true;
    }

    /// @notice Calculate the flash loan fee for a given token and amount loaned
    /// @param token The address of the token to calculate the fee for
    /// @param amount The amount of tokens to calculate the fee for
    /// @return The flashloan fee calcualted for given token and loan amount

    function flashFee(address token, uint256 amount) public view override returns (uint256) {
        require(token == address(collateral), "ActivePool: collateral Only");
        require(!flashLoansPaused, "ActivePool: Flash Loans Paused");

        return (amount * feeBps) / MAX_BPS;
    }

    /// @notice Get the maximum flash loan amount for a specific token
    /// @dev Exclusively used here for stETH collateral, equal to the current balance of the pool
    /// @param token The address of the token to get the maximum flash loan amount for
    /// @return The maximum available flashloan amount for the token
    function maxFlashLoan(address token) public view override returns (uint256) {
        if (token != address(collateral)) {
            return 0;
        }

        if (flashLoansPaused) {
            return 0;
        }

        return collateral.balanceOf(address(this));
    }

    // === Governed Functions === //

    /// @notice Claim outstanding shares for fee recipient, updating internal accounting and transferring the shares.
    /// @dev Call permissinos are managed via authority for flexibility, rather than gating call to just feeRecipient.
    /// @dev Is likely safe as an open permission though caution should be taken.
    /// @param _shares The amount of shares to claim to feeRecipient
    function claimFeeRecipientCollShares(uint256 _shares) external override requiresAuth {
        ICdpManagerData(cdpManagerAddress).syncGlobalAccountingAndGracePeriod(); // Calling this increases shares so do it first

        uint256 cachedFeeRecipientCollShares = feeRecipientCollShares;
        require(
            cachedFeeRecipientCollShares >= _shares,
            "ActivePool: Insufficient fee recipient coll"
        );

        unchecked {
            cachedFeeRecipientCollShares -= _shares;
        }

        feeRecipientCollShares = cachedFeeRecipientCollShares;
        emit FeeRecipientClaimableCollSharesDecreased(cachedFeeRecipientCollShares, _shares);

        collateral.transferShares(feeRecipientAddress, _shares);
    }

    /// @dev Function to move unintended dust that are not protected
    /// @notice moves given amount of given token (collateral is NOT allowed)
    /// @notice because recipient are fixed, this function is safe to be called by anyone
    /// @param token The token address to be swept
    /// @param amount The token amount to be swept

    function sweepToken(address token, uint256 amount) public nonReentrant requiresAuth {
        ICdpManagerData(cdpManagerAddress).syncGlobalAccountingAndGracePeriod(); // Accrue State First

        require(token != address(collateral), "ActivePool: Cannot Sweep Collateral");

        uint256 balance = IERC20(token).balanceOf(address(this));
        require(amount <= balance, "ActivePool: Attempt to sweep more than balance");

        address cachedFeeRecipientAddress = feeRecipientAddress; // Saves an SLOAD

        IERC20(token).safeTransfer(cachedFeeRecipientAddress, amount);

        emit SweepTokenSuccess(token, amount, cachedFeeRecipientAddress);
    }

    /// @notice Sets new Fee for FlashLoans
    /// @param _newFee The new flashloan fee to be set
    function setFeeBps(uint256 _newFee) external requiresAuth {
        ICdpManagerData(cdpManagerAddress).syncGlobalAccountingAndGracePeriod(); // Accrue State First

        require(_newFee <= MAX_FEE_BPS, "ERC3156FlashLender: _newFee should <= MAX_FEE_BPS");

        // set new flash fee
        uint256 _oldFee = feeBps;
        feeBps = uint16(_newFee);
        emit FlashFeeSet(msg.sender, _oldFee, _newFee);
    }

    /// @notice Should Flashloans be paused?
    /// @param _paused The flag (true or false) whether flashloan will be paused
    function setFlashLoansPaused(bool _paused) external requiresAuth {
        ICdpManagerData(cdpManagerAddress).syncGlobalAccountingAndGracePeriod(); // Accrue State First

        flashLoansPaused = _paused;
        emit FlashLoansPaused(msg.sender, _paused);
    }
}

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

pragma solidity 0.8.17;

/**
 * @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 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-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 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);
        }
    }

    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 4 of 28 : AuthNoOwner.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.17;

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

/// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic.
/// @author Modified by BadgerDAO to remove owner
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol)
/// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol)
contract AuthNoOwner {
    event AuthorityUpdated(address indexed user, Authority indexed newAuthority);

    Authority private _authority;
    bool private _authorityInitialized;

    modifier requiresAuth() virtual {
        require(isAuthorized(msg.sender, msg.sig), "Auth: UNAUTHORIZED");

        _;
    }

    function authority() public view returns (Authority) {
        return _authority;
    }

    function authorityInitialized() public view returns (bool) {
        return _authorityInitialized;
    }

    function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) {
        Authority auth = _authority; // Memoizing authority saves us a warm SLOAD, around 100 gas.

        // Checking if the caller is the owner only after calling the authority saves gas in most cases, but be
        // aware that this makes protected functions uncallable even to the owner if the authority is out of order.
        return (address(auth) != address(0) && auth.canCall(user, address(this), functionSig));
    }

    /// @notice Changed constructor to initialize to allow flexiblity of constructor vs initializer use
    /// @notice sets authorityInitiailzed flag to ensure only one use of
    function _initializeAuthority(address newAuthority) internal {
        require(address(_authority) == address(0), "Auth: authority is non-zero");
        require(!_authorityInitialized, "Auth: authority already initialized");

        _authority = Authority(newAuthority);
        _authorityInitialized = true;

        emit AuthorityUpdated(address(this), Authority(newAuthority));
    }
}

File 5 of 28 : Authority.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.17;

/// @notice A generic interface for a contract which provides authorization data to an Auth instance.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol)
/// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol)
interface Authority {
    function canCall(address user, address target, bytes4 functionSig) external view returns (bool);
}

File 6 of 28 : BaseMath.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

contract BaseMath {
    uint256 public constant DECIMAL_PRECISION = 1e18;
}

File 7 of 28 : EbtcMath.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

library EbtcMath {
    uint256 internal constant DECIMAL_PRECISION = 1e18;
    uint256 public constant MAX_TCR = type(uint256).max;

    /* Precision for Nominal ICR (independent of price). Rationale for the value:
     *
     * - Making it “too high” could lead to overflows.
     * - Making it “too low” could lead to an ICR equal to zero, due to truncation from Solidity floor division.
     *
     * This value of 1e20 is chosen for safety: the NICR will only overflow for numerator > ~1e39 ETH,
     * and will only truncate to 0 if the denominator is at least 1e20 times greater than the numerator.
     *
     */
    uint256 internal constant NICR_PRECISION = 1e20;

    function _min(uint256 _a, uint256 _b) internal pure returns (uint256) {
        return (_a < _b) ? _a : _b;
    }

    function _max(uint256 _a, uint256 _b) internal pure returns (uint256) {
        return (_a >= _b) ? _a : _b;
    }

    /**
     * credit to OpenZeppelin
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "EbtcMath: downcast to uint128 will overflow");
        return uint128(value);
    }

    /*
     * Multiply two decimal numbers and use normal rounding rules:
     * -round product up if 19'th mantissa digit >= 5
     * -round product down if 19'th mantissa digit < 5
     *
     * Used only inside the exponentiation, _decPow().
     */
    function decMul(uint256 x, uint256 y) internal pure returns (uint256 decProd) {
        uint256 prod_xy = x * y;

        decProd = (prod_xy + (DECIMAL_PRECISION / 2)) / DECIMAL_PRECISION;
    }

    /*
     * _decPow: Exponentiation function for 18-digit decimal base, and integer exponent n.
     *
     * Uses the efficient "exponentiation by squaring" algorithm. O(log(n)) complexity.
     *
     * Called by two functions that represent time in units of minutes:
     * 1) CdpManager._calcDecayedBaseRate
     * 2) CommunityIssuance._getCumulativeIssuanceFraction
     *
     * The exponent is capped to avoid reverting due to overflow. The cap 525600000 equals
     * "minutes in 1000 years": 60 * 24 * 365 * 1000
     *
     * If a period of > 1000 years is ever used as an exponent in either of the above functions, the result will be
     * negligibly different from just passing the cap, since:
     *
     * In function 1), the decayed base rate will be 0 for 1000 years or > 1000 years
     * In function 2), the difference in tokens issued at 1000 years and any time > 1000 years, will be negligible
     */
    function _decPow(uint256 _base, uint256 _minutes) internal pure returns (uint256) {
        if (_minutes > 525600000) {
            _minutes = 525600000;
        } // cap to avoid overflow

        if (_minutes == 0) {
            return DECIMAL_PRECISION;
        }

        uint256 y = DECIMAL_PRECISION;
        uint256 x = _base;
        uint256 n = _minutes;

        // Exponentiation-by-squaring
        while (n > 1) {
            if (n % 2 == 0) {
                x = decMul(x, x);
                n = n / 2;
            } else {
                // if (n % 2 != 0)
                y = decMul(x, y);
                x = decMul(x, x);
                n = (n - 1) / 2;
            }
        }

        return decMul(x, y);
    }

    function _getAbsoluteDifference(uint256 _a, uint256 _b) internal pure returns (uint256) {
        return (_a >= _b) ? (_a - _b) : (_b - _a);
    }

    function _computeNominalCR(uint256 _collShares, uint256 _debt) internal pure returns (uint256) {
        if (_debt > 0) {
            return (_collShares * NICR_PRECISION) / _debt;
        }
        // Return the maximal value for uint256 if the Cdp has a debt of 0. Represents "infinite" CR.
        else {
            // if (_debt == 0)
            return MAX_TCR;
        }
    }

    /// @dev Compute collateralization ratio, given stETH balance, price, and debt balance
    function _computeCR(
        uint256 _stEthBalance,
        uint256 _debt,
        uint256 _price
    ) internal pure returns (uint256) {
        if (_debt > 0) {
            uint256 newCollRatio = (_stEthBalance * _price) / _debt;

            return newCollRatio;
        }
        // Return the maximal value for uint256 if the Cdp has a debt of 0. Represents "infinite" CR.
        else {
            // if (_debt == 0)
            return MAX_TCR;
        }
    }
}

File 8 of 28 : ERC3156FlashLender.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

import "../Interfaces/IERC3156FlashLender.sol";
import "../Interfaces/IWETH.sol";

abstract contract ERC3156FlashLender is IERC3156FlashLender {
    uint256 public constant MAX_BPS = 10_000;
    uint256 public constant MAX_FEE_BPS = 1_000; // 10%
    bytes32 public constant FLASH_SUCCESS_VALUE = keccak256("ERC3156FlashBorrower.onFlashLoan");

    // Functions to modify these variables must be included in impelemnting contracts if desired
    uint16 public feeBps = 3; // may be subject to future adjustments through protocol governance
    bool public flashLoansPaused;
}

File 9 of 28 : ICollateralToken.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import "./IERC20.sol";

/**
 * Based on the stETH:
 *  -   https://docs.lido.fi/contracts/lido#
 */
interface ICollateralToken is IERC20 {
    // Returns the amount of shares that corresponds to _ethAmount protocol-controlled Ether
    function getSharesByPooledEth(uint256 _ethAmount) external view returns (uint256);

    // Returns the amount of Ether that corresponds to _sharesAmount token shares
    function getPooledEthByShares(uint256 _sharesAmount) external view returns (uint256);

    // Moves `_sharesAmount` token shares from the caller's account to the `_recipient` account.
    function transferShares(address _recipient, uint256 _sharesAmount) external returns (uint256);

    // Returns the amount of shares owned by _account
    function sharesOf(address _account) external view returns (uint256);

    // Returns authorized oracle address
    function getOracle() external view returns (address);
}

File 10 of 28 : ICollateralTokenOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

/**
 * Based on the stETH:
 *  -   https://docs.lido.fi/contracts/lido#
 */
interface ICollateralTokenOracle {
    // Return beacon specification data.
    function getBeaconSpec()
        external
        view
        returns (
            uint64 epochsPerFrame,
            uint64 slotsPerEpoch,
            uint64 secondsPerSlot,
            uint64 genesisTime
        );
}

File 11 of 28 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

/**
 * Based on the OpenZeppelin IER20 interface:
 * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol
 *
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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 `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, 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);

    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);

    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);

    /**
     * @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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool);

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);

    /**
     * @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);
}

File 12 of 28 : IERC2612.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

/**
 * @dev Interface of the ERC2612 standard as defined in the EIP.
 *
 * Adds the {permit} method, which can be used to change one's
 * {IERC20-allowance} without having to send a transaction, by signing a
 * message. This allows users to spend tokens without having to hold Ether.
 *
 * See https://eips.ethereum.org/EIPS/eip-2612.
 *
 * Code adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2237/
 */
interface IERC2612 {
    /**
     * @dev Sets `amount` 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:
     *
     * - `owner` cannot be the zero address.
     * - `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 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current ERC2612 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.
     *
     * `owner` can limit the time a Permit is valid for by setting `deadline` to
     * a value in the near future. The deadline argument can be set to uint256(-1) to
     * create Permits that effectively never expire.
     */
    function nonces(address owner) external view returns (uint256);

    function version() external view returns (string memory);

    function permitTypeHash() external view returns (bytes32);

    function domainSeparator() external view returns (bytes32);
}

File 13 of 28 : ReentrancyGuard.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.17;

/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
    uint256 internal constant OPEN = 1;
    uint256 internal constant LOCKED = 2;

    uint256 public locked = OPEN;

    modifier nonReentrant() virtual {
        require(locked == OPEN, "ReentrancyGuard: Reentrancy in nonReentrant call");

        locked = LOCKED;

        _;

        locked = OPEN;
    }
}

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

pragma solidity 0.8.17;

import "./IERC20.sol";
import "./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 Calls approve while checking bool return value, handles no-return tokens
    function safeApprove(IERC20 token, address spender, uint256 amount) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, amount));
    }

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

    /**
     * @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"
        );
    }
}

File 15 of 28 : TwapWeightedObserver.sol
// SPDX-License Identifier: MIT
pragma solidity 0.8.17;
import {ITwapWeightedObserver} from "../Interfaces/ITwapWeightedObserver.sol";

/// @title TwapWeightedObserver
/// @notice Given a value, applies a time-weighted TWAP that smooths out changes over a 7 days period
/// @dev Used to get the lowest value of total supply to prevent underpaying redemptions
contract TwapWeightedObserver is ITwapWeightedObserver {
    PackedData public data;
    uint128 public valueToTrack;
    bool public twapDisabled;

    constructor(uint128 initialValue) {
        PackedData memory cachedData = PackedData({
            observerCumuVal: initialValue,
            accumulator: initialValue,
            lastObserved: uint64(block.timestamp),
            lastAccrued: uint64(block.timestamp),
            lastObservedAverage: initialValue
        });

        valueToTrack = initialValue;
        data = cachedData;
    }

    /// TWAP ///
    event NewTrackValue(uint256 _oldValue, uint256 _newValue, uint256 _ts, uint256 _newAcc);

    // Set to new value, sync accumulator to now with old value
    // Changes in same block have no impact, as no time has expired
    // Effectively we use the previous block value, and we magnify it by weight
    function _setValue(uint128 newValue) internal {
        uint128 _newAcc = _updateAcc(valueToTrack);

        data.lastAccrued = uint64(block.timestamp);
        emit NewTrackValue(valueToTrack, newValue, block.timestamp, _newAcc);
        valueToTrack = newValue;
    }

    // Update the accumulator based on time passed
    function _updateAcc(uint128 oldValue) internal returns (uint128) {
        uint128 _newAcc = data.accumulator + oldValue * (timeToAccrue());
        data.accumulator = _newAcc;
        return _newAcc;
    }

    /// @notice Returns the time since the last update
    /// @return Duration since last update
    /// @dev Safe from overflow for tens of thousands of years
    function timeToAccrue() public view returns (uint64) {
        return uint64(block.timestamp) - data.lastAccrued;
    }

    /// @notice Returns the accumulator value, adjusted according to the current value and block timestamp
    // Return the update value to now
    function _syncToNow() internal view returns (uint128) {
        return data.accumulator + (valueToTrack * (timeToAccrue()));
    }

    // == Getters == //

    /// @notice Returns the accumulator value, adjusted according to the current value and block timestamp
    function getLatestAccumulator() public view returns (uint128) {
        return _syncToNow();
    }

    /// END TWAP ///

    /// TWAP WEIGHTED OBSERVER ///

    // Hardcoded TWAP Period of 7 days
    uint256 public constant PERIOD = 7 days;

    // Look at last
    // Linear interpolate (or prob TWAP already does that for you)

    /// @notice Returns the current value, adjusted according to the current value and block timestamp
    function observe() external returns (uint256) {
        // Here, we need to apply the new accumulator to skew the price in some way
        // The weight of the skew should be proportional to the time passed
        uint256 futureWeight = block.timestamp - data.lastObserved;

        if (futureWeight == 0) {
            return data.lastObservedAverage;
        }

        // A reference period is 7 days
        // For each second passed after update
        // Let's virtally sync TWAP
        // With a weight, that is higher, the more time has passed
        (uint128 virtualAvgValue, uint128 obsAcc) = _calcUpdatedAvg();

        if (_checkUpdatePeriod()) {
            _update(virtualAvgValue, obsAcc); // May as well update
            // Return virtual
            return virtualAvgValue;
        }

        uint256 weightedAvg = uint256(data.lastObservedAverage) *
            (uint256(PERIOD) - uint256(futureWeight));
        uint256 weightedVirtual = uint256(virtualAvgValue) * (uint256(futureWeight));

        uint256 weightedMean = (weightedAvg + weightedVirtual) / PERIOD;

        return weightedMean;
    }

    /// @dev Usual Accumulator Math, (newAcc - acc0) / (now - t0)
    function _calcUpdatedAvg() internal view returns (uint128, uint128) {
        uint128 latestAcc = getLatestAccumulator();
        uint128 avgValue = (latestAcc - data.observerCumuVal) /
            (uint64(block.timestamp) - data.lastObserved);
        return (avgValue, latestAcc);
    }

    /// @dev Utility to update internal data
    function _update(uint128 avgValue, uint128 obsAcc) internal {
        data.lastObservedAverage = avgValue;
        data.observerCumuVal = obsAcc;
        data.lastObserved = uint64(block.timestamp);
    }

    /// @dev Should we update in observe?
    function _checkUpdatePeriod() internal returns (bool) {
        return block.timestamp >= (data.lastObserved + PERIOD);
    }

    /// @dev update time-weighted Observer
    function update() public {
        if (_checkUpdatePeriod()) {
            (uint128 avgValue, uint128 latestAcc) = _calcUpdatedAvg();
            _update(avgValue, latestAcc);
        }
    }

    function setValueAndUpdate(uint128 value) external {
        require(msg.sender == address(this), "TwapWeightedObserver: Only self call");
        _setValue(value);
        update();
    }

    function getData() external view returns (PackedData memory) {
        return data;
    }

    /// END TWAP WEIGHTED OBSERVER ///
}

File 16 of 28 : IActivePool.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

import "./IPool.sol";
import "./ITwapWeightedObserver.sol";

interface IActivePool is IPool, ITwapWeightedObserver {
    // --- Events ---
    event ActivePoolEBTCDebtUpdated(uint256 _EBTCDebt);
    event SystemCollSharesUpdated(uint256 _coll);
    event FeeRecipientClaimableCollSharesIncreased(uint256 _coll, uint256 _fee);
    event FeeRecipientClaimableCollSharesDecreased(uint256 _coll, uint256 _fee);
    event FlashLoanSuccess(
        address indexed _receiver,
        address indexed _token,
        uint256 _amount,
        uint256 _fee
    );
    event SweepTokenSuccess(address indexed _token, uint256 _amount, address indexed _recipient);

    // --- Functions ---
    function transferSystemCollShares(address _account, uint256 _amount) external;

    function increaseSystemCollShares(uint256 _value) external;

    function transferSystemCollSharesAndLiquidatorReward(
        address _account,
        uint256 _shares,
        uint256 _liquidatorRewardShares
    ) external;

    function allocateSystemCollSharesToFeeRecipient(uint256 _shares) external;

    function claimFeeRecipientCollShares(uint256 _shares) external;

    function feeRecipientAddress() external view returns (address);

    function getFeeRecipientClaimableCollShares() external view returns (uint256);
}

File 17 of 28 : IBaseTwapWeightedObserver.sol
// SPDX-License Identifier: MIT
pragma solidity 0.8.17;

interface IBaseTwapWeightedObserver {
    // NOTE: Packing manually is cheaper, but this is simpler to understand and follow
    struct PackedData {
        // Slot 0
        // Seconds in a year: 3.154e+7
        /// @dev Accumulator value recorded for TWAP Observer until last update
        uint128 observerCumuVal; // 3.154e+7 * 80 * 100e27 = 2.5232e+38 | log_2(100e27 * 3.154e+7 * 80) = 127.568522171
        /// @dev Accumulator for TWAP globally
        uint128 accumulator; // 3.154e+7 * 80 * 100e27 = 2.5232e+38 | log_2(100e27 * 3.154e+7 * 80) = 127.568522171
        // NOTE: We can further compress this slot but we will not be able to use only one (see u72 impl)
        /// So what's the point of making the code more complex?

        // Slot 1
        /// @dev last update timestamp for TWAP Observer
        uint64 lastObserved; // Thousands of Years, if we use relative time we can use u32 | Relative to deploy time (as immutable)
        /// @dev last update timestamp for TWAP global track(spot) value
        uint64 lastAccrued; // Thousands of years
        // Expect eBTC debt to never surpass 100e27, which is 100 BILLION eBTC
        // log_2(100e27) = 96.3359147517 | log_2(100e27 / 1e18) = 36.5412090438
        // We could use a u64
        /// @dev average value since last observe
        uint128 lastObservedAverage;
    }
}

File 18 of 28 : IBorrowerOperations.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;
import "./IPositionManagers.sol";

// Common interface for the Cdp Manager.
interface IBorrowerOperations is IPositionManagers {
    // --- Events ---

    event FeeRecipientAddressChanged(address indexed _feeRecipientAddress);
    event FlashLoanSuccess(
        address indexed _receiver,
        address indexed _token,
        uint256 _amount,
        uint256 _fee
    );

    // --- Functions ---

    function openCdp(
        uint256 _EBTCAmount,
        bytes32 _upperHint,
        bytes32 _lowerHint,
        uint256 _stEthBalance
    ) external returns (bytes32);

    function openCdpFor(
        uint _EBTCAmount,
        bytes32 _upperHint,
        bytes32 _lowerHint,
        uint _collAmount,
        address _borrower
    ) external returns (bytes32);

    function addColl(
        bytes32 _cdpId,
        bytes32 _upperHint,
        bytes32 _lowerHint,
        uint256 _stEthBalanceIncrease
    ) external;

    function withdrawColl(
        bytes32 _cdpId,
        uint256 _stEthBalanceDecrease,
        bytes32 _upperHint,
        bytes32 _lowerHint
    ) external;

    function withdrawDebt(
        bytes32 _cdpId,
        uint256 _amount,
        bytes32 _upperHint,
        bytes32 _lowerHint
    ) external;

    function repayDebt(
        bytes32 _cdpId,
        uint256 _amount,
        bytes32 _upperHint,
        bytes32 _lowerHint
    ) external;

    function closeCdp(bytes32 _cdpId) external;

    function adjustCdp(
        bytes32 _cdpId,
        uint256 _stEthBalanceDecrease,
        uint256 _debtChange,
        bool isDebtIncrease,
        bytes32 _upperHint,
        bytes32 _lowerHint
    ) external;

    function adjustCdpWithColl(
        bytes32 _cdpId,
        uint256 _stEthBalanceDecrease,
        uint256 _debtChange,
        bool isDebtIncrease,
        bytes32 _upperHint,
        bytes32 _lowerHint,
        uint256 _stEthBalanceIncrease
    ) external;

    function claimSurplusCollShares() external;

    function feeRecipientAddress() external view returns (address);
}

File 19 of 28 : ICdpManagerData.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

import "./ICollSurplusPool.sol";
import "./IEBTCToken.sol";
import "./ISortedCdps.sol";
import "./IActivePool.sol";
import "./IRecoveryModeGracePeriod.sol";
import "../Dependencies/ICollateralTokenOracle.sol";

// Common interface for the Cdp Manager.
interface ICdpManagerData is IRecoveryModeGracePeriod {
    // --- Events ---

    event StakingRewardSplitSet(uint256 _stakingRewardSplit);
    event RedemptionFeeFloorSet(uint256 _redemptionFeeFloor);
    event MinuteDecayFactorSet(uint256 _minuteDecayFactor);
    event BetaSet(uint256 _beta);
    event RedemptionsPaused(bool _paused);

    event Liquidation(uint256 _liquidatedDebt, uint256 _liquidatedColl, uint256 _liqReward);
    event Redemption(
        uint256 _debtToRedeemExpected,
        uint256 _debtToRedeemActual,
        uint256 _collSharesSent,
        uint256 _feeCollShares,
        address indexed _redeemer
    );
    event CdpUpdated(
        bytes32 indexed _cdpId,
        address indexed _borrower,
        address indexed _executor,
        uint256 _oldDebt,
        uint256 _oldCollShares,
        uint256 _debt,
        uint256 _collShares,
        uint256 _stake,
        CdpOperation _operation
    );
    event CdpLiquidated(
        bytes32 indexed _cdpId,
        address indexed _borrower,
        uint _debt,
        uint _collShares,
        CdpOperation _operation,
        address indexed _liquidator,
        uint _premiumToLiquidator
    );
    event CdpPartiallyLiquidated(
        bytes32 indexed _cdpId,
        address indexed _borrower,
        uint256 _debt,
        uint256 _collShares,
        CdpOperation operation,
        address indexed _liquidator,
        uint _premiumToLiquidator
    );
    event BaseRateUpdated(uint256 _baseRate);
    event LastRedemptionTimestampUpdated(uint256 _lastFeeOpTime);
    event TotalStakesUpdated(uint256 _newTotalStakes);
    event SystemSnapshotsUpdated(uint256 _totalStakesSnapshot, uint256 _totalCollateralSnapshot);
    event SystemDebtRedistributionIndexUpdated(uint256 _systemDebtRedistributionIndex);
    event CdpDebtRedistributionIndexUpdated(bytes32 _cdpId, uint256 _cdpDebtRedistributionIndex);
    event CdpArrayIndexUpdated(bytes32 _cdpId, uint256 _newIndex);
    event StEthIndexUpdated(uint256 _oldIndex, uint256 _newIndex, uint256 _updTimestamp);
    event CollateralFeePerUnitUpdated(uint256 _oldPerUnit, uint256 _newPerUnit, uint256 _feeTaken);
    event CdpFeeSplitApplied(
        bytes32 _cdpId,
        uint256 _oldPerUnitCdp,
        uint256 _newPerUnitCdp,
        uint256 _collReduced,
        uint256 _collLeft
    );

    enum CdpOperation {
        openCdp,
        closeCdp,
        adjustCdp,
        syncAccounting,
        liquidateInNormalMode,
        liquidateInRecoveryMode,
        redeemCollateral,
        partiallyLiquidate,
        failedPartialRedemption
    }

    enum Status {
        nonExistent,
        active,
        closedByOwner,
        closedByLiquidation,
        closedByRedemption
    }

    // Store the necessary data for a cdp
    struct Cdp {
        uint256 debt;
        uint256 coll;
        uint256 stake;
        uint128 liquidatorRewardShares;
        Status status;
    }

    /*
     * --- Variable container structs for liquidations ---
     *
     * These structs are used to hold, return and assign variables inside the liquidation functions,
     * in order to avoid the error: "CompilerError: Stack too deep".
     **/

    struct CdpDebtAndCollShares {
        uint256 debt;
        uint256 collShares;
    }

    struct LiquidationLocals {
        bytes32 cdpId;
        uint256 partialAmount; // used only for partial liquidation, default 0 means full liquidation
        uint256 price;
        uint256 ICR;
        bytes32 upperPartialHint;
        bytes32 lowerPartialHint;
        bool recoveryModeAtStart;
        uint256 TCR;
        uint256 totalSurplusCollShares;
        uint256 totalCollSharesToSend;
        uint256 totalDebtToBurn;
        uint256 totalDebtToRedistribute;
        uint256 totalLiquidatorRewardCollShares;
    }

    struct LiquidationRecoveryModeLocals {
        uint256 entireSystemDebt;
        uint256 entireSystemColl;
        uint256 totalDebtToBurn;
        uint256 totalCollSharesToSend;
        uint256 totalSurplusCollShares;
        bytes32 cdpId;
        uint256 price;
        uint256 ICR;
        uint256 totalDebtToRedistribute;
        uint256 totalLiquidatorRewardCollShares;
    }

    struct LocalVariables_OuterLiquidationFunction {
        uint256 price;
        bool recoveryModeAtStart;
        uint256 liquidatedDebt;
        uint256 liquidatedColl;
    }

    struct LocalVariables_LiquidationSequence {
        uint256 i;
        uint256 ICR;
        bytes32 cdpId;
        bool backToNormalMode;
        uint256 entireSystemDebt;
        uint256 entireSystemColl;
        uint256 price;
        uint256 TCR;
    }

    struct SingleRedemptionInputs {
        bytes32 cdpId;
        uint256 maxEBTCamount;
        uint256 price;
        bytes32 upperPartialRedemptionHint;
        bytes32 lowerPartialRedemptionHint;
        uint256 partialRedemptionHintNICR;
    }

    struct LiquidationValues {
        uint256 entireCdpDebt;
        uint256 debtToBurn;
        uint256 totalCollToSendToLiquidator;
        uint256 debtToRedistribute;
        uint256 collSurplus;
        uint256 liquidatorCollSharesReward;
    }

    struct LiquidationTotals {
        uint256 totalDebtInSequence;
        uint256 totalDebtToBurn;
        uint256 totalCollToSendToLiquidator;
        uint256 totalDebtToRedistribute;
        uint256 totalCollSurplus;
        uint256 totalCollReward;
    }

    // --- Variable container structs for redemptions ---

    struct RedemptionTotals {
        uint256 remainingDebtToRedeem;
        uint256 debtToRedeem;
        uint256 collSharesDrawn;
        uint256 totalCollSharesSurplus;
        uint256 feeCollShares;
        uint256 collSharesToRedeemer;
        uint256 decayedBaseRate;
        uint256 price;
        uint256 systemDebtAtStart;
        uint256 twapSystemDebtAtStart;
        uint256 systemCollSharesAtStart;
        uint256 tcrAtStart;
    }

    struct SingleRedemptionValues {
        uint256 debtToRedeem;
        uint256 collSharesDrawn;
        uint256 collSurplus;
        uint256 liquidatorRewardShares;
        bool cancelledPartial;
        bool fullRedemption;
        uint256 newPartialNICR;
    }

    function getActiveCdpsCount() external view returns (uint256);

    function totalStakes() external view returns (uint256);

    function ebtcToken() external view returns (IEBTCToken);

    function systemStEthFeePerUnitIndex() external view returns (uint256);

    function systemStEthFeePerUnitIndexError() external view returns (uint256);

    function stEthIndex() external view returns (uint256);

    function calcFeeUponStakingReward(
        uint256 _newIndex,
        uint256 _prevIndex
    ) external view returns (uint256, uint256, uint256);

    function syncGlobalAccounting() external; // Accrues StEthFeeSplit without influencing Grace Period

    function syncGlobalAccountingAndGracePeriod() external; // Accrues StEthFeeSplit and influences Grace Period

    function getAccumulatedFeeSplitApplied(
        bytes32 _cdpId,
        uint256 _systemStEthFeePerUnitIndex
    ) external view returns (uint256, uint256);

    function getCachedNominalICR(bytes32 _cdpId) external view returns (uint256);

    function getCachedICR(bytes32 _cdpId, uint256 _price) external view returns (uint256);

    function getSyncedCdpDebt(bytes32 _cdpId) external view returns (uint256);

    function getSyncedCdpCollShares(bytes32 _cdpId) external view returns (uint256);

    function getSyncedICR(bytes32 _cdpId, uint256 _price) external view returns (uint256);

    function getSyncedTCR(uint256 _price) external view returns (uint256);

    function getSyncedSystemCollShares() external view returns (uint256);

    function getSyncedNominalICR(bytes32 _cdpId) external view returns (uint256);

    function getPendingRedistributedDebt(bytes32 _cdpId) external view returns (uint256);

    function hasPendingRedistributedDebt(bytes32 _cdpId) external view returns (bool);

    function getSyncedDebtAndCollShares(
        bytes32 _cdpId
    ) external view returns (uint256 debt, uint256 collShares);

    function canLiquidateRecoveryMode(uint256 icr, uint256 tcr) external view returns (bool);

    function totalCollateralSnapshot() external view returns (uint256);

    function totalStakesSnapshot() external view returns (uint256);
}

File 20 of 28 : ICollSurplusPool.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

interface ICollSurplusPool {
    // --- Events ---

    event SurplusCollSharesAdded(
        bytes32 indexed _cdpId,
        address indexed _account,
        uint256 _claimableSurplusCollShares,
        uint256 _surplusCollSharesAddedFromCollateral,
        uint256 _surplusCollSharesAddedFromLiquidatorReward
    );
    event CollSharesTransferred(address indexed _to, uint256 _amount);

    event SweepTokenSuccess(address indexed _token, uint256 _amount, address indexed _recipient);

    // --- Contract setters ---

    function getTotalSurplusCollShares() external view returns (uint256);

    function getSurplusCollShares(address _account) external view returns (uint256);

    function increaseSurplusCollShares(
        bytes32 _cdpId,
        address _account,
        uint256 _collateralShares,
        uint256 _liquidatorRewardShares
    ) external;

    function claimSurplusCollShares(address _account) external;

    function increaseTotalSurplusCollShares(uint256 _value) external;
}

File 21 of 28 : IEBTCToken.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

import "../Dependencies/IERC20.sol";
import "../Dependencies/IERC2612.sol";

interface IEBTCToken is IERC20, IERC2612 {
    // --- Functions ---

    function mint(address _account, uint256 _amount) external;

    function burn(address _account, uint256 _amount) external;
}

File 22 of 28 : IERC3156FlashBorrower.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

interface IERC3156FlashBorrower {
    /**
     * @dev Receive a flash loan.
     * @param initiator The initiator of the loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param fee The additional amount of tokens to repay.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan"
     */
    function onFlashLoan(
        address initiator,
        address token,
        uint256 amount,
        uint256 fee,
        bytes calldata data
    ) external returns (bytes32);
}

File 23 of 28 : IERC3156FlashLender.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

import "./IERC3156FlashBorrower.sol";

interface IERC3156FlashLender {
    event FlashFeeSet(address indexed _setter, uint256 _oldFee, uint256 _newFee);
    event MaxFlashFeeSet(address indexed _setter, uint256 _oldMaxFee, uint256 _newMaxFee);
    event FlashLoansPaused(address indexed _setter, bool _paused);

    /// @dev The amount of currency available to be lent.
    /// @param token The loan currency.
    /// @return The amount of `token` that can be borrowed.
    function maxFlashLoan(address token) external view returns (uint256);

    /// @dev The fee to be charged for a given loan.
    /// @param token The loan currency.
    /// @param amount The amount of tokens lent.
    /// @return The amount of `token` to be charged for the loan, on top of the returned principal.
    function flashFee(address token, uint256 amount) external view returns (uint256);

    /// @dev Initiate a flash loan.
    /// @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
    /// @param token The loan currency.
    /// @param amount The amount of tokens lent.
    /// @param data Arbitrary data structure, intended to contain user-defined parameters.
    function flashLoan(
        IERC3156FlashBorrower receiver,
        address token,
        uint256 amount,
        bytes calldata data
    ) external returns (bool);
}

File 24 of 28 : IPool.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

// Common interface for the Pools.
interface IPool {
    // --- Events ---

    event ETHBalanceUpdated(uint256 _newBalance);
    event EBTCBalanceUpdated(uint256 _newBalance);
    event CollSharesTransferred(address indexed _to, uint256 _amount);

    // --- Functions ---

    function getSystemCollShares() external view returns (uint256);

    function getSystemDebt() external view returns (uint256);

    function increaseSystemDebt(uint256 _amount) external;

    function decreaseSystemDebt(uint256 _amount) external;
}

File 25 of 28 : IPositionManagers.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

interface IPositionManagers {
    enum PositionManagerApproval {
        None,
        OneTime,
        Persistent
    }

    event PositionManagerApprovalSet(
        address indexed _borrower,
        address indexed _positionManager,
        PositionManagerApproval _approval
    );

    function getPositionManagerApproval(
        address _borrower,
        address _positionManager
    ) external view returns (PositionManagerApproval);

    function setPositionManagerApproval(
        address _positionManager,
        PositionManagerApproval _approval
    ) external;

    function revokePositionManagerApproval(address _positionManager) external;

    function renouncePositionManagerApproval(address _borrower) external;

    function permitPositionManagerApproval(
        address _borrower,
        address _positionManager,
        PositionManagerApproval _approval,
        uint _deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    function version() external view returns (string memory);

    function permitTypeHash() external view returns (bytes32);

    function domainSeparator() external view returns (bytes32);
}

File 26 of 28 : IRecoveryModeGracePeriod.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

// Interface for State Updates that can trigger RM Liquidations
interface IRecoveryModeGracePeriod {
    event TCRNotified(uint256 TCR); /// NOTE: Mostly for debugging to ensure synch

    // NOTE: Ts is implicit in events (it's added by GETH)
    event GracePeriodStart();
    event GracePeriodEnd();
    event GracePeriodDurationSet(uint256 _recoveryModeGracePeriodDuration);

    function notifyStartGracePeriod(uint256 tcr) external;

    function notifyEndGracePeriod(uint256 tcr) external;
}

File 27 of 28 : ISortedCdps.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

// Common interface for the SortedCdps Doubly Linked List.
interface ISortedCdps {
    // --- Events ---

    event NodeAdded(bytes32 _id, uint _NICR);
    event NodeRemoved(bytes32 _id);

    // --- Functions ---

    function remove(bytes32 _id) external;

    function batchRemove(bytes32[] memory _ids) external;

    function reInsert(bytes32 _id, uint256 _newICR, bytes32 _prevId, bytes32 _nextId) external;

    function contains(bytes32 _id) external view returns (bool);

    function isFull() external view returns (bool);

    function isEmpty() external view returns (bool);

    function getSize() external view returns (uint256);

    function getMaxSize() external view returns (uint256);

    function getFirst() external view returns (bytes32);

    function getLast() external view returns (bytes32);

    function getNext(bytes32 _id) external view returns (bytes32);

    function getPrev(bytes32 _id) external view returns (bytes32);

    function validInsertPosition(
        uint256 _ICR,
        bytes32 _prevId,
        bytes32 _nextId
    ) external view returns (bool);

    function findInsertPosition(
        uint256 _ICR,
        bytes32 _prevId,
        bytes32 _nextId
    ) external view returns (bytes32, bytes32);

    function insert(
        address owner,
        uint256 _ICR,
        bytes32 _prevId,
        bytes32 _nextId
    ) external returns (bytes32);

    function getOwnerAddress(bytes32 _id) external pure returns (address);

    function nonExistId() external view returns (bytes32);

    function cdpCountOf(address owner) external view returns (uint256);

    function getCdpCountOf(
        address owner,
        bytes32 startNodeId,
        uint maxNodes
    ) external view returns (uint256, bytes32);

    function getCdpsOf(address owner) external view returns (bytes32[] memory);

    function getAllCdpsOf(
        address owner,
        bytes32 startNodeId,
        uint maxNodes
    ) external view returns (bytes32[] memory, uint256, bytes32);

    function cdpOfOwnerByIndex(address owner, uint256 index) external view returns (bytes32);

    function cdpOfOwnerByIdx(
        address owner,
        uint256 index,
        bytes32 startNodeId,
        uint maxNodes
    ) external view returns (bytes32, bool);

    function toCdpId(
        address owner,
        uint256 blockHeight,
        uint256 nonce
    ) external pure returns (bytes32);

    function nextCdpNonce() external view returns (uint256);
}

File 28 of 28 : ITwapWeightedObserver.sol
// SPDX-License Identifier: MIT
pragma solidity 0.8.17;
import {IBaseTwapWeightedObserver} from "./IBaseTwapWeightedObserver.sol";

interface ITwapWeightedObserver is IBaseTwapWeightedObserver {
    event TwapDisabled();

    function PERIOD() external view returns (uint256);

    function valueToTrack() external view returns (uint128);

    function timeToAccrue() external view returns (uint64);

    function getLatestAccumulator() external view returns (uint128);

    function observe() external returns (uint256);

    function update() external;

    function twapDisabled() external view returns (bool);
}

File 29 of 28 : IWETH.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;

interface IWETH {
    function deposit() external payable;

    function withdraw(uint256) external;

    function transfer(address to, uint256 amount) external returns (bool);

    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

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

Contract ABI

[{"inputs":[{"internalType":"address","name":"_borrowerOperationsAddress","type":"address"},{"internalType":"address","name":"_cdpManagerAddress","type":"address"},{"internalType":"address","name":"_collTokenAddress","type":"address"},{"internalType":"address","name":"_collSurplusAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_EBTCDebt","type":"uint256"}],"name":"ActivePoolEBTCDebtUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"CollSharesTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_newBalance","type":"uint256"}],"name":"EBTCBalanceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_newBalance","type":"uint256"}],"name":"ETHBalanceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_coll","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"FeeRecipientClaimableCollSharesDecreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_coll","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"FeeRecipientClaimableCollSharesIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_setter","type":"address"},{"indexed":false,"internalType":"uint256","name":"_oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newFee","type":"uint256"}],"name":"FlashFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_receiver","type":"address"},{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"FlashLoanSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_setter","type":"address"},{"indexed":false,"internalType":"bool","name":"_paused","type":"bool"}],"name":"FlashLoansPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_setter","type":"address"},{"indexed":false,"internalType":"uint256","name":"_oldMaxFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newMaxFee","type":"uint256"}],"name":"MaxFlashFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_oldValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_ts","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newAcc","type":"uint256"}],"name":"NewTrackValue","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"_recipient","type":"address"}],"name":"SweepTokenSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_coll","type":"uint256"}],"name":"SystemCollSharesUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"TwapDisabled","type":"event"},{"inputs":[],"name":"DECIMAL_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FLASH_SUCCESS_VALUE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"allocateSystemCollSharesToFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract Authority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authorityInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowerOperationsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cdpManagerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"claimFeeRecipientCollShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collSurplusPoolAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"contract ICollateralToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"data","outputs":[{"internalType":"uint128","name":"observerCumuVal","type":"uint128"},{"internalType":"uint128","name":"accumulator","type":"uint128"},{"internalType":"uint64","name":"lastObserved","type":"uint64"},{"internalType":"uint64","name":"lastAccrued","type":"uint64"},{"internalType":"uint128","name":"lastObservedAverage","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"decreaseSystemDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipientAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"flashFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC3156FlashBorrower","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"flashLoan","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flashLoansPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getData","outputs":[{"components":[{"internalType":"uint128","name":"observerCumuVal","type":"uint128"},{"internalType":"uint128","name":"accumulator","type":"uint128"},{"internalType":"uint64","name":"lastObserved","type":"uint64"},{"internalType":"uint64","name":"lastAccrued","type":"uint64"},{"internalType":"uint128","name":"lastObservedAverage","type":"uint128"}],"internalType":"struct IBaseTwapWeightedObserver.PackedData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeRecipientClaimableCollShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLatestAccumulator","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSystemCollShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSystemDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"increaseSystemCollShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"increaseSystemDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"locked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"maxFlashLoan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"observe","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newFee","type":"uint256"}],"name":"setFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setFlashLoansPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"value","type":"uint128"}],"name":"setValueAndUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sweepToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timeToAccrue","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"transferSystemCollShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_shares","type":"uint256"},{"internalType":"uint256","name":"_liquidatorRewardShares","type":"uint256"}],"name":"transferSystemCollSharesAndLiquidatorReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"twapDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"valueToTrack","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102535760003560e01c80639f03866b11610146578063d3e0947a116100c3578063e56bb75c11610087578063e56bb75c146106dd578063e90a182f146106e5578063f1bab2ec146106f8578063f2fb47c91461071f578063facc051114610732578063fd967f471461073a57600080fd5b8063d3e0947a1461067f578063d55be8c614610692578063d8dfeb451461069b578063d9d98ce4146106c2578063e3f68388146106d557600080fd5b8063b4d1d7951161010a578063b4d1d79514610621578063b7f8cf9b1461062b578063beb8d5de14610652578063bf7e214f14610665578063cf3090121461067657600080fd5b80639f03866b1461059a578063a20baee6146105c1578063a2e62045146105d0578063a3f4df7e146105d8578063b13285ff1461060e57600080fd5b8063703dfa9a116101d45780638e0b2e0e116101985780638e0b2e0e1461052e578063970c297f1461054257806397bc1e1b146105555780639af31356146105675780639b503bae1461058757600080fd5b8063703dfa9a1461045557806370673a621461047557806372c27b621461048857806373d4a13a1461049b5780638ccfa9e61461051b57600080fd5b80633bc5de301161021b5780633bc5de301461030f57806349f047bb146103f95780635cffe9de1461040c5780635fdefb951461042f578063613255ab1461044257600080fd5b806302f6567f146102585780631424027f1461029c57806314fc78fc146102b157806324a9d853146102c75780632a9043ec146102e8575b600080fd5b61027f7f000000000000000000000000e89a0378237c21b94126f77ed5fa0fdd2ede2b3681565b6040516001600160a01b0390911681526020015b60405180910390f35b6102af6102aa36600461269e565b610743565b005b6102b96107f8565b604051908152602001610293565b6000546102d59061ffff1681565b60405161ffff9091168152602001610293565b61027f7f000000000000000000000000d5e6e5c5f46fa1a038b62b0625e21b97a4897f8f81565b6103996040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526003546001600160801b038082168352600160801b91829004811660208401526004546001600160401b0380821695850195909552600160401b810490941660608401529204909116608082015290565b6040516102939190600060a0820190506001600160801b0380845116835280602085015116602084015260408401516001600160401b03808216604086015280606087015116606086015250508060808501511660808401525092915050565b6102af61040736600461269e565b6108d5565b61041f61041a3660046126cc565b6109ef565b6040519015158152602001610293565b6102af61043d36600461276a565b6111ae565b6102b9610450366004612793565b61121d565b61045d611307565b6040516001600160801b039091168152602001610293565b6102af6104833660046127b0565b611316565b6102af61049636600461269e565b6113dd565b6003546004546104dc916001600160801b0380821692600160801b928390048216926001600160401b0380831693600160401b840490911692919091041685565b604080516001600160801b03968716815294861660208601526001600160401b039384169085015291166060830152909116608082015260a001610293565b6102af6105293660046127dc565b61154e565b60055461041f90600160801b900460ff1681565b6102af61055036600461281f565b611607565b600254600160a01b900460ff1661041f565b61056f611704565b6040516001600160401b039091168152602001610293565b60005461041f9062010000900460ff1681565b6102b97f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd981565b6102b9670de0b6b3a764000081565b6102af611724565b6106016040518060400160405280600a8152602001691058dd1a5d99541bdbdb60b21b81525081565b6040516102939190612860565b6102af61061c36600461269e565b61174f565b6102b962093a8081565b61027f7f00000000000000000000000058aa3de50cfef7450657c52766dd43da8747285e81565b6102af61066036600461269e565b611794565b6002546001600160a01b031661027f565b6102b960015481565b6102af61068d36600461269e565b6117f9565b6102b96103e881565b61027f7f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f01581565b6102b96106d03660046127b0565b6119fa565b6006546102b9565b6008546102b9565b6102af6106f33660046127b0565b611afc565b61027f7f0000000000000000000000005c1246e0b464060919301273781a266ac119a0bb81565b60055461045d906001600160801b031681565b6007546102b9565b6102b961271081565b61074b611dfd565b600654818110156107775760405162461bcd60e51b815260040161076e90612893565b60405180910390fd5b81900360068190556008546000906107909084906128f3565b6008819055604051838152909150600080516020612aed8339815191529060200160405180910390a160408051828152602081018590527f68ba5291de991d26abd65cbf507d6355ef4e4594ce2d0c65c3ea89270e41234b91015b60405180910390a1505050565b6004546000908190610813906001600160401b031642612906565b905080600003610835575050600454600160801b90046001600160801b031690565b600080610840611e81565b9150915061084c611ee1565b1561086b5761085b8282611f06565b506001600160801b031692915050565b600061087a8462093a80612906565b6004546108979190600160801b90046001600160801b0316612919565b905060006108ae856001600160801b038616612919565b9050600062093a806108c083856128f3565b6108ca9190612946565b979650505050505050565b6108dd611f60565b6000816007546108ed9190612906565b905060006108fa82612031565b600554909150600160801b900460ff166109ba5730635fdefb956109266001600160801b038416612031565b6040516001600160e01b031960e084901b1681526001600160801b0390911660048201526024015b600060405180830381600087803b15801561096857600080fd5b505af1925050508015610979575060015b6109ba576005805460ff60801b1916600160801b1790556040517fca4fc4fded1c94f9363d4949ff2be652aa20d482c12207b0e7b6290a2c03f90990600090a15b60078290556040518281527f7b49d039828591b5bc8d4f0552ab8f4d6b2499043328550c75c655d427e29613906020016107eb565b6000808411610a375760405162461bcd60e51b81526020600482015260146024820152731058dd1a5d99541bdbdb0e880c08105b5bdd5b9d60621b604482015260640161076e565b6000610a4386866119fa565b9050610a4e8661121d565b851115610a945760405162461bcd60e51b8152602060048201526014602482015273082c6e8d2eccaa0deded87440a8dede40daeac6d60631b604482015260640161076e565b6000610aa082876128f3565b604051630f451f7160e31b8152670de0b6b3a764000060048201529091506000906001600160a01b037f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0151690637a28fb8890602401602060405180830381865afa158015610b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b36919061295a565b60405163a9059cbb60e01b81526001600160a01b038b81166004830152602482018a90529192507f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0159091169063a9059cbb906044016020604051808303816000875af1158015610baa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bce9190612973565b506040516323e30c8b60e01b81527f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9906001600160a01b038b16906323e30c8b90610c279033908d908d908a908e908e90600401612990565b6020604051808303816000875af1158015610c46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6a919061295a565b14610cc55760405162461bcd60e51b815260206004820152602560248201527f416374697665506f6f6c3a2049455243333135363a2043616c6c6261636b2066604482015264185a5b195960da1b606482015260840161076e565b6040516323b872dd60e01b81526001600160a01b038a81166004830152306024830152604482018490527f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f01516906323b872dd906064016020604051808303816000875af1158015610d3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5e9190612973565b5060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000005c1246e0b464060919301273781a266ac119a0bb81166004830152602482018590527f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f015169063a9059cbb906044016020604051808303816000875af1158015610dee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e129190612973565b50600654604051630f451f7160e31b815260048101919091527f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0156001600160a01b031690637a28fb8890602401602060405180830381865afa158015610e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea0919061295a565b6040516370a0823160e01b81523060048201527f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0156001600160a01b0316906370a0823190602401602060405180830381865afa158015610f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f28919061295a565b1015610f765760405162461bcd60e51b815260206004820152601e60248201527f416374697665506f6f6c3a204d7573742072657061792042616c616e63650000604482015260640161076e565b600654604051633d7ad0b760e21b81523060048201527f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0156001600160a01b03169063f5eb42dc90602401602060405180830381865afa158015610fdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611001919061295a565b101561104f5760405162461bcd60e51b815260206004820152601c60248201527f416374697665506f6f6c3a204d75737420726570617920536861726500000000604482015260640161076e565b604051630f451f7160e31b8152670de0b6b3a7640000600482015281907f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0156001600160a01b031690637a28fb8890602401602060405180830381865afa1580156110bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e1919061295a565b146111495760405162461bcd60e51b815260206004820152603260248201527f416374697665506f6f6c3a2053686f756c64206b6565702073616d6520636f6c6044820152716c61746572616c207368617265207261746560701b606482015260840161076e565b876001600160a01b0316896001600160a01b03167fbc26d11fd70e2cdca20b501a51cf33594c9f434ee2c77fe035ef21b0cf14000b8986604051611197929190918252602082015260400190565b60405180910390a350600198975050505050505050565b3330146112095760405162461bcd60e51b8152602060048201526024808201527f5477617057656967687465644f627365727665723a204f6e6c792073656c662060448201526318d85b1b60e21b606482015260840161076e565b611212816120a2565b61121a611724565b50565b60007f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0156001600160a01b0316826001600160a01b03161461126057506000919050565b60005462010000900460ff161561127957506000919050565b6040516370a0823160e01b81523060048201527f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0156001600160a01b0316906370a0823190602401602060405180830381865afa1580156112dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611301919061295a565b92915050565b6000611311612169565b905090565b61131e611f60565b600654818110156113625760405162461bcd60e51b815260206004820152600e60248201526d085058dd1a5d99541bdbdb10985b60921b604482015260640161076e565b8190036006819055604051818152600080516020612aed8339815191529060200160405180910390a1826001600160a01b03167f1fb7e7fce5abe8f5c5d0af41f7598d317a42cc8b71d6e75f13774066263a2814836040516113c691815260200190565b60405180910390a26113d883836121af565b505050565b6113f3336000356001600160e01b0319166122da565b61140f5760405162461bcd60e51b815260040161076e906129ec565b7f000000000000000000000000e89a0378237c21b94126f77ed5fa0fdd2ede2b366001600160a01b03166307902c556040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561146a57600080fd5b505af115801561147e573d6000803e3d6000fd5b505050506103e88111156114ee5760405162461bcd60e51b815260206004820152603160248201527f45524333313536466c6173684c656e6465723a205f6e65774665652073686f756044820152706c64203c3d204d41585f4645455f42505360781b606482015260840161076e565b6000805461ffff83811661ffff1983161790925560405191169033907f36d567e1fd131473c440012eaa0903f9a646c89a1ee00ecc01c477d63d94d287906115429084908690918252602082015260400190565b60405180910390a25050565b611556611f60565b600654828110156115795760405162461bcd60e51b815260040161076e90612893565b600061158583856128f3565b91849003600681905560405181815290929150600080516020612aed8339815191529060200160405180910390a1846001600160a01b03167f1fb7e7fce5abe8f5c5d0af41f7598d317a42cc8b71d6e75f13774066263a2814826040516115ee91815260200190565b60405180910390a261160085826121af565b5050505050565b61161d336000356001600160e01b0319166122da565b6116395760405162461bcd60e51b815260040161076e906129ec565b7f000000000000000000000000e89a0378237c21b94126f77ed5fa0fdd2ede2b366001600160a01b03166307902c556040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561169457600080fd5b505af11580156116a8573d6000803e3d6000fd5b505060008054841515620100000262ff000019909116179055505060405133907fa5b0db65e66479c7d3871018efb8f6b08c5bcd03b257b342d53b13c91396c3df906116f990841515815260200190565b60405180910390a250565b60045460009061131190600160401b90046001600160401b031642612a18565b61172c611ee1565b1561174d5760008061173c611e81565b9150915061174a8282611f06565b50505b565b61175761237b565b60008160065461176791906128f3565b6006819055604051818152909150600080516020612aed8339815191529060200160405180910390a15050565b61179c611f60565b6000816007546117ac91906128f3565b905060006117b982612031565b600554909150600160801b900460ff166109ba57604051635fdefb9560e01b81526001600160801b03821660048201523090635fdefb959060240161094e565b61180f336000356001600160e01b0319166122da565b61182b5760405162461bcd60e51b815260040161076e906129ec565b7f000000000000000000000000e89a0378237c21b94126f77ed5fa0fdd2ede2b366001600160a01b03166307902c556040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561188657600080fd5b505af115801561189a573d6000803e3d6000fd5b5050600854915050818110156119065760405162461bcd60e51b815260206004820152602b60248201527f416374697665506f6f6c3a20496e73756666696369656e74206665652072656360448201526a1a5c1a595b9d0818dbdb1b60aa1b606482015260840161076e565b819003600881905560408051828152602081018490527f056ac240f7874fd765a8fb2abe56cda7b943cf5aa3376e5e12f39a8160aae458910160405180910390a1604051638fcb4e5b60e01b81526001600160a01b037f0000000000000000000000005c1246e0b464060919301273781a266ac119a0bb81166004830152602482018490527f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0151690638fcb4e5b906044016020604051808303816000875af11580156119d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d8919061295a565b60007f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0156001600160a01b0316836001600160a01b031614611a7d5760405162461bcd60e51b815260206004820152601b60248201527f416374697665506f6f6c3a20636f6c6c61746572616c204f6e6c790000000000604482015260640161076e565b60005462010000900460ff1615611ad65760405162461bcd60e51b815260206004820152601e60248201527f416374697665506f6f6c3a20466c617368204c6f616e73205061757365640000604482015260640161076e565b60005461271090611aeb9061ffff1684612919565b611af59190612946565b9392505050565b6001805414611b665760405162461bcd60e51b815260206004820152603060248201527f5265656e7472616e637947756172643a205265656e7472616e637920696e206e60448201526f1bdb9499595b9d1c985b9d0818d85b1b60821b606482015260840161076e565b6002600155611b81336001600160e01b0319600035166122da565b611b9d5760405162461bcd60e51b815260040161076e906129ec565b7f000000000000000000000000e89a0378237c21b94126f77ed5fa0fdd2ede2b366001600160a01b03166307902c556040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611bf857600080fd5b505af1158015611c0c573d6000803e3d6000fd5b505050507f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0156001600160a01b0316826001600160a01b031603611c9d5760405162461bcd60e51b815260206004820152602360248201527f416374697665506f6f6c3a2043616e6e6f7420537765657020436f6c6c6174656044820152621c985b60ea1b606482015260840161076e565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611ce4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d08919061295a565b905080821115611d715760405162461bcd60e51b815260206004820152602e60248201527f416374697665506f6f6c3a20417474656d707420746f207377656570206d6f7260448201526d65207468616e2062616c616e636560901b606482015260840161076e565b7f0000000000000000000000005c1246e0b464060919301273781a266ac119a0bb611da66001600160a01b0385168285612408565b806001600160a01b0316846001600160a01b03167fbd14a55ba056360d3fefd3db4cd1bef985de81f4de4ddc725962aecd0b5909e285604051611deb91815260200190565b60405180910390a35050600180555050565b336001600160a01b037f000000000000000000000000e89a0378237c21b94126f77ed5fa0fdd2ede2b36161461174d5760405162461bcd60e51b8152602060048201526024808201527f416374697665506f6f6c3a2043616c6c6572206973206e6f74204364704d616e60448201526330b3b2b960e11b606482015260840161076e565b6000806000611e8e611307565b600454909150600090611eaa906001600160401b031642612a18565b6003546001600160401b039190911690611ecd906001600160801b031684612a3f565b611ed79190612a5f565b9491935090915050565b600454600090611efe9062093a80906001600160401b03166128f3565b421015905090565b60048054600380546001600160801b0319166001600160801b039485161790556fffffffffffffffff000000000000000016600160801b939092169290920267ffffffffffffffff191617426001600160401b0316179055565b336001600160a01b037f00000000000000000000000058aa3de50cfef7450657c52766dd43da8747285e161480611fbf5750336001600160a01b037f000000000000000000000000e89a0378237c21b94126f77ed5fa0fdd2ede2b3616145b61174d5760405162461bcd60e51b815260206004820152603f60248201527f416374697665506f6f6c3a2043616c6c6572206973206e65697468657220426f60448201527f72726f7765724f7065726174696f6e73206e6f72204364704d616e6167657200606482015260840161076e565b60006001600160801b0382111561209e5760405162461bcd60e51b815260206004820152602b60248201527f456274634d6174683a20646f776e6361737420746f2075696e7431323820776960448201526a6c6c206f766572666c6f7760a81b606482015260840161076e565b5090565b6005546000906120ba906001600160801b031661245a565b600480546fffffffffffffffff00000000000000001916600160401b426001600160401b0381169190910291909117909155600554604080516001600160801b039283168152868316602082015290810192909252821660608201529091507fd8e8737aab1e0322d94269935b3e71b256749666a1a909818cd79a6766b217379060800160405180910390a150600580546001600160801b0319166001600160801b0392909216919091179055565b6000612173611704565b600554612192916001600160401b0316906001600160801b0316612a85565b6003546113119190600160801b90046001600160801b0316612ab0565b604051638fcb4e5b60e01b81526001600160a01b038381166004830152602482018390527f00000000000000000000000097ba9aa7b7dc74f7a74864a62c4ff93b2b22f0151690638fcb4e5b906044016020604051808303816000875af115801561221e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612242919061295a565b507f000000000000000000000000d5e6e5c5f46fa1a038b62b0625e21b97a4897f8f6001600160a01b0316826001600160a01b03160361174a5760405163855ff31760e01b8152600481018290526001600160a01b0383169063855ff31790602401600060405180830381600087803b1580156122be57600080fd5b505af11580156122d2573d6000803e3d6000fd5b505050505050565b6002546000906001600160a01b03168015801590612373575060405163b700961360e01b81526001600160a01b0385811660048301523060248301526001600160e01b03198516604483015282169063b700961390606401602060405180830381865afa15801561234f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123739190612973565b949350505050565b336001600160a01b037f00000000000000000000000058aa3de50cfef7450657c52766dd43da8747285e161461174d5760405162461bcd60e51b815260206004820152602c60248201527f416374697665506f6f6c3a2043616c6c6572206973206e6f7420426f72726f7760448201526b65724f7065726174696f6e7360a01b606482015260840161076e565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526113d89084906124b6565b600080612465611704565b612478906001600160401b031684612a85565b6003546124959190600160801b90046001600160801b0316612ab0565b600380546001600160801b03808416600160801b0291161790559392505050565b600061250b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661258b9092919063ffffffff16565b905080516000148061252c57508080602001905181019061252c9190612973565b6113d85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161076e565b6060612373848460008585600080866001600160a01b031685876040516125b29190612ad0565b60006040518083038185875af1925050503d80600081146125ef576040519150601f19603f3d011682016040523d82523d6000602084013e6125f4565b606091505b50915091506108ca878383876060831561266f578251600003612668576001600160a01b0385163b6126685760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161076e565b5081612373565b61237383838151156126845781518083602001fd5b8060405162461bcd60e51b815260040161076e9190612860565b6000602082840312156126b057600080fd5b5035919050565b6001600160a01b038116811461121a57600080fd5b6000806000806000608086880312156126e457600080fd5b85356126ef816126b7565b945060208601356126ff816126b7565b93506040860135925060608601356001600160401b038082111561272257600080fd5b818801915088601f83011261273657600080fd5b81358181111561274557600080fd5b89602082850101111561275757600080fd5b9699959850939650602001949392505050565b60006020828403121561277c57600080fd5b81356001600160801b0381168114611af557600080fd5b6000602082840312156127a557600080fd5b8135611af5816126b7565b600080604083850312156127c357600080fd5b82356127ce816126b7565b946020939093013593505050565b6000806000606084860312156127f157600080fd5b83356127fc816126b7565b95602085013595506040909401359392505050565b801515811461121a57600080fd5b60006020828403121561283157600080fd5b8135611af581612811565b60005b8381101561285757818101518382015260200161283f565b50506000910152565b602081526000825180602084015261287f81604085016020870161283c565b601f01601f19169190910160400192915050565b6020808252602a908201527f416374697665506f6f6c3a20496e73756666696369656e7420636f6c6c61746560408201526972616c2073686172657360b01b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b80820180821115611301576113016128dd565b81810381811115611301576113016128dd565b8082028115828204841417611301576113016128dd565b634e487b7160e01b600052601260045260246000fd5b60008261295557612955612930565b500490565b60006020828403121561296c57600080fd5b5051919050565b60006020828403121561298557600080fd5b8151611af581612811565b6001600160a01b03878116825286166020820152604081018590526060810184905260a06080820181905281018290526000828460c0840137600060c0848401015260c0601f19601f8501168301019050979650505050505050565b602080825260129082015271105d5d1a0e8815539055551213d49256915160721b604082015260600190565b6001600160401b03828116828216039080821115612a3857612a386128dd565b5092915050565b6001600160801b03828116828216039080821115612a3857612a386128dd565b60006001600160801b0380841680612a7957612a79612930565b92169190910492915050565b6001600160801b03818116838216028082169190828114612aa857612aa86128dd565b505092915050565b6001600160801b03818116838216019080821115612a3857612a386128dd565b60008251612ae281846020870161283c565b919091019291505056fed16483466b463d83139bd6faa077189744e8d5b1ba48b88c0f6d06eda7660ca8a2646970667358221220bba8b45d7ad1633b1d758db3c05c60d02b543144d795281abda5d622758e521b64736f6c63430008110033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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