ETH Price: $3,389.06 (+6.19%)
Gas: 24 Gwei

Contract

0x364626644d2C5E34a6f27c1bab3DCb73D43E12fB
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
184725032023-10-31 20:30:59257 days ago1698784259  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BridgeSteth

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
shanghai EvmVersion
File 1 of 8 : BridgeSteth.sol
// https://docs.lido.fi/contracts/wsteth
// https://github.com/lidofinance/lido-dao/blob/master/contracts/0.6.12/WstETH.sol

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.21;

import {U256} from "contracts/libraries/PRBMathHelper.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";

import {ISTETH} from "interfaces/ISTETH.sol";
import {IUNSTETH} from "interfaces/IUNSTETH.sol";
import {IBridge} from "contracts/interfaces/IBridge.sol";

contract BridgeSteth is IBridge, IERC721Receiver {
    using U256 for uint256;

    ISTETH private immutable steth;
    IUNSTETH private immutable unsteth;
    address private immutable diamond;

    constructor(ISTETH _steth, IUNSTETH _unsteth, address diamondAddr) {
        steth = ISTETH(_steth);
        unsteth = IUNSTETH(_unsteth);
        diamond = diamondAddr;

        steth.approve(
            address(unsteth),
            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
        );
    }

    modifier onlyDiamond() {
        if (msg.sender != diamond) {
            revert NotDiamond();
        }
        _;
    }

    function onERC721Received(
        address, /*operator*/
        address, /*from*/
        uint256, /*tokenId*/
        bytes calldata /*data*/
    ) external pure returns (bytes4) {
        return IERC721Receiver.onERC721Received.selector;
    }

    //@dev does not need read only re-entrancy
    function getBaseCollateral() external view returns (address) {
        return address(steth);
    }

    //@dev does not need read only re-entrancy
    function getDethValue() external view returns (uint256) {
        return steth.balanceOf(address(this));
    }

    // Bring stETH to system and credit dETH to user
    function deposit(address from, uint256 amount)
        external
        onlyDiamond
        returns (uint256)
    {
        // Transfer stETH to this bridge contract
        // @dev stETH uses OZ ERC-20, don't need to check success bool
        steth.transferFrom(from, address(this), amount);
        return amount;
    }

    // Deposit ETH and mint stETH (to system) and credit dETH to user
    function depositEth() external payable onlyDiamond returns (uint256) {
        uint256 originalBalance = steth.balanceOf(address(this));
        // @edv address(0) means no fee taken by the referring protocol
        steth.submit{value: msg.value}(address(0));
        uint256 netBalance = steth.balanceOf(address(this)) - originalBalance;
        if (netBalance == 0) revert NetBalanceZero();
        return netBalance;
    }

    // Exchange system stETH to fulfill dETH obligation to user
    function withdraw(address to, uint256 amount)
        external
        onlyDiamond
        returns (uint256)
    {
        // @dev stETH uses OZ ERC-20, don't need to check success bool
        steth.transfer(to, amount);
        return amount;
    }

    function unstake(address to, uint256 amount) external onlyDiamond {
        uint256[] memory amountArray = new uint256[](1);
        amountArray[0] = amount;
        uint256 requestId = unsteth.requestWithdrawals(amountArray, address(this))[0];
        unsteth.safeTransferFrom(address(this), to, requestId);
    }
}

File 2 of 8 : PRBMathHelper.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.21;

import {mulDiv as _mulDiv, mulDiv18, UNIT} from "@prb/math/src/Common.sol";
import {Errors} from "contracts/libraries/Errors.sol";

library U256 {
    function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {
        result = mulDiv18(x, y);
    }

    function div(uint256 x, uint256 y) internal pure returns (uint256 result) {
        result = _mulDiv(x, UNIT, y);
    }

    function mulDiv(uint256 x, uint256 y, uint256 denominator)
        internal
        pure
        returns (uint256 result)
    {
        return _mulDiv(x, y, denominator);
    }

    function inv(uint256 x) internal pure returns (uint256 result) {
        unchecked {
            // 1e36 is UNIT * UNIT.
            result = 1e36 / x;
        }
    }

    function divU80(uint256 x, uint256 y) internal pure returns (uint80 result) {
        uint256 _result = _mulDiv(x, UNIT, y);
        if (_result > type(uint80).max) revert Errors.InvalidAmount(); // assume amount?
        result = uint80(_result);
    }

    function divU64(uint256 x, uint256 y) internal pure returns (uint64 result) {
        uint256 _result = _mulDiv(x, UNIT, y);
        if (_result > type(uint64).max) revert Errors.InvalidAmount(); // assume amount?
        result = uint64(_result);
    }

    // test
    function divU88(uint256 x, uint256 y) internal pure returns (uint88 result) {
        uint256 _result = _mulDiv(x, UNIT, y);
        if (_result > type(uint88).max) revert Errors.InvalidAmount(); // assume amount?
        result = uint88(_result);
    }
}

// uint128
library Math128 {
    // just passing the result of casting the first param to 256
    function mul(uint128 x, uint256 y) internal pure returns (uint256 result) {
        result = mulDiv18(x, y);
    }

    function div(uint128 x, uint256 y) internal pure returns (uint256 result) {
        result = _mulDiv(x, UNIT, y);
    }
}

// uint104
library Math104 {
    // just passing the result of casting the first param to 256
    function mul(uint104 x, uint256 y) internal pure returns (uint256 result) {
        result = mulDiv18(x, y);
    }

    function div(uint104 x, uint256 y) internal pure returns (uint256 result) {
        result = _mulDiv(x, UNIT, y);
    }
}

// uint96
library U96 {
    // just passing the result of casting the first param to 256
    function mul(uint96 x, uint256 y) internal pure returns (uint256 result) {
        result = mulDiv18(x, y);
    }

    function div(uint96 x, uint256 y) internal pure returns (uint256 result) {
        result = _mulDiv(x, UNIT, y);
    }

    function divU64(uint96 x, uint256 y) internal pure returns (uint64 result) {
        uint256 _result = _mulDiv(x, UNIT, y);
        if (_result > type(uint64).max) revert Errors.InvalidAmount(); // assume amount?
        result = uint64(_result);
    }
}

// uint88
library U88 {
    // just passing the result of casting the first param to 256
    function mul(uint88 x, uint256 y) internal pure returns (uint256 result) {
        result = mulDiv18(x, y);
    }

    function mulU88(uint88 x, uint256 y) internal pure returns (uint88 result) {
        uint256 _result = mulDiv18(x, y);
        if (_result > type(uint88).max) revert Errors.InvalidAmount(); // assume amount?
        result = uint88(_result);
    }

    function div(uint88 x, uint256 y) internal pure returns (uint256 result) {
        result = _mulDiv(x, UNIT, y);
    }

    function divU88(uint88 x, uint256 y) internal pure returns (uint88 result) {
        uint256 _result = _mulDiv(x, UNIT, y);
        if (_result > type(uint88).max) revert Errors.InvalidAmount(); // assume amount?
        result = uint88(_result);
    }

    function divU80(uint88 x, uint256 y) internal pure returns (uint80 result) {
        uint256 _result = _mulDiv(x, UNIT, y);
        if (_result > type(uint80).max) revert Errors.InvalidAmount(); // assume amount?
        result = uint80(_result);
    }
}

// uint80
library U80 {
    // just passing the result of casting the first param to 256
    function mul(uint80 x, uint256 y) internal pure returns (uint256 result) {
        result = mulDiv18(x, y);
    }

    function mulU80(uint80 x, uint256 y) internal pure returns (uint80 result) {
        uint256 _result = mulDiv18(x, y);
        if (_result > type(uint80).max) revert Errors.InvalidPrice(); // assume price?
        result = uint80(_result);
    }

    function mulU88(uint80 x, uint256 y) internal pure returns (uint88 result) {
        uint256 _result = mulDiv18(x, y);
        if (_result > type(uint80).max) revert Errors.InvalidPrice(); // assume price?
        result = uint88(_result);
    }

    function div(uint80 x, uint256 y) internal pure returns (uint256 result) {
        result = _mulDiv(x, UNIT, y);
    }

    // test
    function inv(uint80 x) internal pure returns (uint256 result) {
        unchecked {
            // 1e36 is UNIT * UNIT.
            result = 1e36 / x;
        }
    }
}

File 3 of 8 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 4 of 8 : ISTETH.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.21;



interface ISTETH {

  // functions from node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol
  function name() external view returns (string memory);
  function symbol() external view returns (string memory);
  function decimals() external view returns (uint8);
  function totalSupply() external view returns (uint256);
  function balanceOf(address account) external view returns (uint256);
  function transfer(address to, uint256 amount) external returns (bool);
  function allowance(address owner, address spender) external view returns (uint256);
  function approve(address spender, uint256 amount) external returns (bool);
  function transferFrom(address from, address to, uint256 amount) external returns (bool);
  function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
  function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);

  // functions from node_modules/@openzeppelin/contracts/utils/cryptography/EIP712.sol
  function eip712Domain() external view returns (bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions);

  // functions from node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol
  function permit(
        address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
  function nonces(address owner) external view returns (uint256);
  function DOMAIN_SEPARATOR() external view returns (bytes32);

  // functions from contracts/mocks/STETH.sol
  function mint(address to, uint256 amount) external;
  function burn(uint256 amount) external;
  function transferWithdrawalEth(uint256 amount) external;
  function submit(address ref) external payable returns (uint256);
}

File 5 of 8 : IUNSTETH.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.21;



interface IUNSTETH {

  // functions from node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol
  function supportsInterface(bytes4 interfaceId) external view returns (bool);

  // functions from node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol
  function balanceOf(address owner) external view returns (uint256);
  function ownerOf(uint256 tokenId) external view returns (address);
  function name() external view returns (string memory);
  function symbol() external view returns (string memory);
  function tokenURI(uint256 tokenId) external view returns (string memory);
  function approve(address to, uint256 tokenId) external;
  function getApproved(uint256 tokenId) external view returns (address);
  function setApprovalForAll(address operator, bool approved) external;
  function isApprovedForAll(address owner, address operator) external view returns (bool);
  function transferFrom(address from, address to, uint256 tokenId) external;
  function safeTransferFrom(address from, address to, uint256 tokenId) external;
  function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) external;

  // functions from contracts/mocks/UNSTETH.sol
  receive() external payable;
  function claimWithdrawals(
        uint256[] calldata _requestIds, uint256[] calldata) external;
  function requestWithdrawals(uint256[] calldata _amounts, address _owner) external returns (uint256[] memory requestIds);
  function processWithdrawals() external;
}

File 6 of 8 : IBridge.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.21;

interface IBridge {
    error NotDiamond();
    error NetBalanceZero();

    function getBaseCollateral() external view returns (address);
    function getDethValue() external view returns (uint256);
    function deposit(address, uint256) external returns (uint256);
    function depositEth() external payable returns (uint256);
    function withdraw(address, uint256) external returns (uint256);
    function unstake(address, uint256) external;
}

File 7 of 8 : Common.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;

// Common.sol
//
// Common mathematical functions needed by both SD59x18 and UD60x18. Note that these global functions do not
// always operate with SD59x18 and UD60x18 numbers.

/*//////////////////////////////////////////////////////////////////////////
                                CUSTOM ERRORS
//////////////////////////////////////////////////////////////////////////*/

/// @notice Thrown when the resultant value in {mulDiv} overflows uint256.
error PRBMath_MulDiv_Overflow(uint256 x, uint256 y, uint256 denominator);

/// @notice Thrown when the resultant value in {mulDiv18} overflows uint256.
error PRBMath_MulDiv18_Overflow(uint256 x, uint256 y);

/// @notice Thrown when one of the inputs passed to {mulDivSigned} is `type(int256).min`.
error PRBMath_MulDivSigned_InputTooSmall();

/// @notice Thrown when the resultant value in {mulDivSigned} overflows int256.
error PRBMath_MulDivSigned_Overflow(int256 x, int256 y);

/*//////////////////////////////////////////////////////////////////////////
                                    CONSTANTS
//////////////////////////////////////////////////////////////////////////*/

/// @dev The maximum value a uint128 number can have.
uint128 constant MAX_UINT128 = type(uint128).max;

/// @dev The maximum value a uint40 number can have.
uint40 constant MAX_UINT40 = type(uint40).max;

/// @dev The unit number, which the decimal precision of the fixed-point types.
uint256 constant UNIT = 1e18;

/// @dev The unit number inverted mod 2^256.
uint256 constant UNIT_INVERSE = 78156646155174841979727994598816262306175212592076161876661_508869554232690281;

/// @dev The the largest power of two that divides the decimal value of `UNIT`. The logarithm of this value is the least significant
/// bit in the binary representation of `UNIT`.
uint256 constant UNIT_LPOTD = 262144;

/*//////////////////////////////////////////////////////////////////////////
                                    FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/

/// @notice Calculates the binary exponent of x using the binary fraction method.
/// @dev Has to use 192.64-bit fixed-point numbers. See https://ethereum.stackexchange.com/a/96594/24693.
/// @param x The exponent as an unsigned 192.64-bit fixed-point number.
/// @return result The result as an unsigned 60.18-decimal fixed-point number.
/// @custom:smtchecker abstract-function-nondet
function exp2(uint256 x) pure returns (uint256 result) {
    unchecked {
        // Start from 0.5 in the 192.64-bit fixed-point format.
        result = 0x800000000000000000000000000000000000000000000000;

        // The following logic multiplies the result by $\sqrt{2^{-i}}$ when the bit at position i is 1. Key points:
        //
        // 1. Intermediate results will not overflow, as the starting point is 2^191 and all magic factors are under 2^65.
        // 2. The rationale for organizing the if statements into groups of 8 is gas savings. If the result of performing
        // a bitwise AND operation between x and any value in the array [0x80; 0x40; 0x20; 0x10; 0x08; 0x04; 0x02; 0x01] is 1,
        // we know that `x & 0xFF` is also 1.
        if (x & 0xFF00000000000000 > 0) {
            if (x & 0x8000000000000000 > 0) {
                result = (result * 0x16A09E667F3BCC909) >> 64;
            }
            if (x & 0x4000000000000000 > 0) {
                result = (result * 0x1306FE0A31B7152DF) >> 64;
            }
            if (x & 0x2000000000000000 > 0) {
                result = (result * 0x1172B83C7D517ADCE) >> 64;
            }
            if (x & 0x1000000000000000 > 0) {
                result = (result * 0x10B5586CF9890F62A) >> 64;
            }
            if (x & 0x800000000000000 > 0) {
                result = (result * 0x1059B0D31585743AE) >> 64;
            }
            if (x & 0x400000000000000 > 0) {
                result = (result * 0x102C9A3E778060EE7) >> 64;
            }
            if (x & 0x200000000000000 > 0) {
                result = (result * 0x10163DA9FB33356D8) >> 64;
            }
            if (x & 0x100000000000000 > 0) {
                result = (result * 0x100B1AFA5ABCBED61) >> 64;
            }
        }

        if (x & 0xFF000000000000 > 0) {
            if (x & 0x80000000000000 > 0) {
                result = (result * 0x10058C86DA1C09EA2) >> 64;
            }
            if (x & 0x40000000000000 > 0) {
                result = (result * 0x1002C605E2E8CEC50) >> 64;
            }
            if (x & 0x20000000000000 > 0) {
                result = (result * 0x100162F3904051FA1) >> 64;
            }
            if (x & 0x10000000000000 > 0) {
                result = (result * 0x1000B175EFFDC76BA) >> 64;
            }
            if (x & 0x8000000000000 > 0) {
                result = (result * 0x100058BA01FB9F96D) >> 64;
            }
            if (x & 0x4000000000000 > 0) {
                result = (result * 0x10002C5CC37DA9492) >> 64;
            }
            if (x & 0x2000000000000 > 0) {
                result = (result * 0x1000162E525EE0547) >> 64;
            }
            if (x & 0x1000000000000 > 0) {
                result = (result * 0x10000B17255775C04) >> 64;
            }
        }

        if (x & 0xFF0000000000 > 0) {
            if (x & 0x800000000000 > 0) {
                result = (result * 0x1000058B91B5BC9AE) >> 64;
            }
            if (x & 0x400000000000 > 0) {
                result = (result * 0x100002C5C89D5EC6D) >> 64;
            }
            if (x & 0x200000000000 > 0) {
                result = (result * 0x10000162E43F4F831) >> 64;
            }
            if (x & 0x100000000000 > 0) {
                result = (result * 0x100000B1721BCFC9A) >> 64;
            }
            if (x & 0x80000000000 > 0) {
                result = (result * 0x10000058B90CF1E6E) >> 64;
            }
            if (x & 0x40000000000 > 0) {
                result = (result * 0x1000002C5C863B73F) >> 64;
            }
            if (x & 0x20000000000 > 0) {
                result = (result * 0x100000162E430E5A2) >> 64;
            }
            if (x & 0x10000000000 > 0) {
                result = (result * 0x1000000B172183551) >> 64;
            }
        }

        if (x & 0xFF00000000 > 0) {
            if (x & 0x8000000000 > 0) {
                result = (result * 0x100000058B90C0B49) >> 64;
            }
            if (x & 0x4000000000 > 0) {
                result = (result * 0x10000002C5C8601CC) >> 64;
            }
            if (x & 0x2000000000 > 0) {
                result = (result * 0x1000000162E42FFF0) >> 64;
            }
            if (x & 0x1000000000 > 0) {
                result = (result * 0x10000000B17217FBB) >> 64;
            }
            if (x & 0x800000000 > 0) {
                result = (result * 0x1000000058B90BFCE) >> 64;
            }
            if (x & 0x400000000 > 0) {
                result = (result * 0x100000002C5C85FE3) >> 64;
            }
            if (x & 0x200000000 > 0) {
                result = (result * 0x10000000162E42FF1) >> 64;
            }
            if (x & 0x100000000 > 0) {
                result = (result * 0x100000000B17217F8) >> 64;
            }
        }

        if (x & 0xFF000000 > 0) {
            if (x & 0x80000000 > 0) {
                result = (result * 0x10000000058B90BFC) >> 64;
            }
            if (x & 0x40000000 > 0) {
                result = (result * 0x1000000002C5C85FE) >> 64;
            }
            if (x & 0x20000000 > 0) {
                result = (result * 0x100000000162E42FF) >> 64;
            }
            if (x & 0x10000000 > 0) {
                result = (result * 0x1000000000B17217F) >> 64;
            }
            if (x & 0x8000000 > 0) {
                result = (result * 0x100000000058B90C0) >> 64;
            }
            if (x & 0x4000000 > 0) {
                result = (result * 0x10000000002C5C860) >> 64;
            }
            if (x & 0x2000000 > 0) {
                result = (result * 0x1000000000162E430) >> 64;
            }
            if (x & 0x1000000 > 0) {
                result = (result * 0x10000000000B17218) >> 64;
            }
        }

        if (x & 0xFF0000 > 0) {
            if (x & 0x800000 > 0) {
                result = (result * 0x1000000000058B90C) >> 64;
            }
            if (x & 0x400000 > 0) {
                result = (result * 0x100000000002C5C86) >> 64;
            }
            if (x & 0x200000 > 0) {
                result = (result * 0x10000000000162E43) >> 64;
            }
            if (x & 0x100000 > 0) {
                result = (result * 0x100000000000B1721) >> 64;
            }
            if (x & 0x80000 > 0) {
                result = (result * 0x10000000000058B91) >> 64;
            }
            if (x & 0x40000 > 0) {
                result = (result * 0x1000000000002C5C8) >> 64;
            }
            if (x & 0x20000 > 0) {
                result = (result * 0x100000000000162E4) >> 64;
            }
            if (x & 0x10000 > 0) {
                result = (result * 0x1000000000000B172) >> 64;
            }
        }

        if (x & 0xFF00 > 0) {
            if (x & 0x8000 > 0) {
                result = (result * 0x100000000000058B9) >> 64;
            }
            if (x & 0x4000 > 0) {
                result = (result * 0x10000000000002C5D) >> 64;
            }
            if (x & 0x2000 > 0) {
                result = (result * 0x1000000000000162E) >> 64;
            }
            if (x & 0x1000 > 0) {
                result = (result * 0x10000000000000B17) >> 64;
            }
            if (x & 0x800 > 0) {
                result = (result * 0x1000000000000058C) >> 64;
            }
            if (x & 0x400 > 0) {
                result = (result * 0x100000000000002C6) >> 64;
            }
            if (x & 0x200 > 0) {
                result = (result * 0x10000000000000163) >> 64;
            }
            if (x & 0x100 > 0) {
                result = (result * 0x100000000000000B1) >> 64;
            }
        }

        if (x & 0xFF > 0) {
            if (x & 0x80 > 0) {
                result = (result * 0x10000000000000059) >> 64;
            }
            if (x & 0x40 > 0) {
                result = (result * 0x1000000000000002C) >> 64;
            }
            if (x & 0x20 > 0) {
                result = (result * 0x10000000000000016) >> 64;
            }
            if (x & 0x10 > 0) {
                result = (result * 0x1000000000000000B) >> 64;
            }
            if (x & 0x8 > 0) {
                result = (result * 0x10000000000000006) >> 64;
            }
            if (x & 0x4 > 0) {
                result = (result * 0x10000000000000003) >> 64;
            }
            if (x & 0x2 > 0) {
                result = (result * 0x10000000000000001) >> 64;
            }
            if (x & 0x1 > 0) {
                result = (result * 0x10000000000000001) >> 64;
            }
        }

        // In the code snippet below, two operations are executed simultaneously:
        //
        // 1. The result is multiplied by $(2^n + 1)$, where $2^n$ represents the integer part, and the additional 1
        // accounts for the initial guess of 0.5. This is achieved by subtracting from 191 instead of 192.
        // 2. The result is then converted to an unsigned 60.18-decimal fixed-point format.
        //
        // The underlying logic is based on the relationship $2^{191-ip} = 2^{ip} / 2^{191}$, where $ip$ denotes the,
        // integer part, $2^n$.
        result *= UNIT;
        result >>= (191 - (x >> 64));
    }
}

/// @notice Finds the zero-based index of the first 1 in the binary representation of x.
///
/// @dev See the note on "msb" in this Wikipedia article: https://en.wikipedia.org/wiki/Find_first_set
///
/// Each step in this implementation is equivalent to this high-level code:
///
/// ```solidity
/// if (x >= 2 ** 128) {
///     x >>= 128;
///     result += 128;
/// }
/// ```
///
/// Where 128 is replaced with each respective power of two factor. See the full high-level implementation here:
/// https://gist.github.com/PaulRBerg/f932f8693f2733e30c4d479e8e980948
///
/// The Yul instructions used below are:
///
/// - "gt" is "greater than"
/// - "or" is the OR bitwise operator
/// - "shl" is "shift left"
/// - "shr" is "shift right"
///
/// @param x The uint256 number for which to find the index of the most significant bit.
/// @return result The index of the most significant bit as a uint256.
/// @custom:smtchecker abstract-function-nondet
function msb(uint256 x) pure returns (uint256 result) {
    // 2^128
    assembly ("memory-safe") {
        let factor := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
        x := shr(factor, x)
        result := or(result, factor)
    }
    // 2^64
    assembly ("memory-safe") {
        let factor := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))
        x := shr(factor, x)
        result := or(result, factor)
    }
    // 2^32
    assembly ("memory-safe") {
        let factor := shl(5, gt(x, 0xFFFFFFFF))
        x := shr(factor, x)
        result := or(result, factor)
    }
    // 2^16
    assembly ("memory-safe") {
        let factor := shl(4, gt(x, 0xFFFF))
        x := shr(factor, x)
        result := or(result, factor)
    }
    // 2^8
    assembly ("memory-safe") {
        let factor := shl(3, gt(x, 0xFF))
        x := shr(factor, x)
        result := or(result, factor)
    }
    // 2^4
    assembly ("memory-safe") {
        let factor := shl(2, gt(x, 0xF))
        x := shr(factor, x)
        result := or(result, factor)
    }
    // 2^2
    assembly ("memory-safe") {
        let factor := shl(1, gt(x, 0x3))
        x := shr(factor, x)
        result := or(result, factor)
    }
    // 2^1
    // No need to shift x any more.
    assembly ("memory-safe") {
        let factor := gt(x, 0x1)
        result := or(result, factor)
    }
}

/// @notice Calculates x*y÷denominator with 512-bit precision.
///
/// @dev Credits to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.
///
/// Notes:
/// - The result is rounded toward zero.
///
/// Requirements:
/// - The denominator must not be zero.
/// - The result must fit in uint256.
///
/// @param x The multiplicand as a uint256.
/// @param y The multiplier as a uint256.
/// @param denominator The divisor as a uint256.
/// @return result The result as a uint256.
/// @custom:smtchecker abstract-function-nondet
function mulDiv(uint256 x, uint256 y, uint256 denominator) pure returns (uint256 result) {
    // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
    // use the Chinese Remainder Theorem to reconstruct the 512-bit result. The result is stored in two 256
    // variables such that product = prod1 * 2^256 + prod0.
    uint256 prod0; // Least significant 256 bits of the product
    uint256 prod1; // Most significant 256 bits of the product
    assembly ("memory-safe") {
        let mm := mulmod(x, y, not(0))
        prod0 := mul(x, y)
        prod1 := sub(sub(mm, prod0), lt(mm, prod0))
    }

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

    // Make sure the result is less than 2^256. Also prevents denominator == 0.
    if (prod1 >= denominator) {
        revert PRBMath_MulDiv_Overflow(x, y, denominator);
    }

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

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

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

    unchecked {
        // Calculate the largest power of two divisor of the denominator using the unary operator ~. This operation cannot overflow
        // because the denominator cannot be zero at this point in the function execution. The result is always >= 1.
        // For more detail, see https://cs.stackexchange.com/q/138556/92363.
        uint256 lpotdod = denominator & (~denominator + 1);
        uint256 flippedLpotdod;

        assembly ("memory-safe") {
            // Factor powers of two out of denominator.
            denominator := div(denominator, lpotdod)

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

            // Get the flipped value `2^256 / lpotdod`. If the `lpotdod` is zero, the flipped value is one.
            // `sub(0, lpotdod)` produces the two's complement version of `lpotdod`, which is equivalent to flipping all the bits.
            // However, `div` interprets this value as an unsigned value: https://ethereum.stackexchange.com/q/147168/24693
            flippedLpotdod := add(div(sub(0, lpotdod), lpotdod), 1)
        }

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

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

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

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

/// @notice Calculates x*y÷1e18 with 512-bit precision.
///
/// @dev A variant of {mulDiv} with constant folding, i.e. in which the denominator is hard coded to 1e18.
///
/// Notes:
/// - The body is purposely left uncommented; to understand how this works, see the documentation in {mulDiv}.
/// - The result is rounded toward zero.
/// - We take as an axiom that the result cannot be `MAX_UINT256` when x and y solve the following system of equations:
///
/// $$
/// \begin{cases}
///     x * y = MAX\_UINT256 * UNIT \\
///     (x * y) \% UNIT \geq \frac{UNIT}{2}
/// \end{cases}
/// $$
///
/// Requirements:
/// - Refer to the requirements in {mulDiv}.
/// - The result must fit in uint256.
///
/// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
/// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
/// @return result The result as an unsigned 60.18-decimal fixed-point number.
/// @custom:smtchecker abstract-function-nondet
function mulDiv18(uint256 x, uint256 y) pure returns (uint256 result) {
    uint256 prod0;
    uint256 prod1;
    assembly ("memory-safe") {
        let mm := mulmod(x, y, not(0))
        prod0 := mul(x, y)
        prod1 := sub(sub(mm, prod0), lt(mm, prod0))
    }

    if (prod1 == 0) {
        unchecked {
            return prod0 / UNIT;
        }
    }

    if (prod1 >= UNIT) {
        revert PRBMath_MulDiv18_Overflow(x, y);
    }

    uint256 remainder;
    assembly ("memory-safe") {
        remainder := mulmod(x, y, UNIT)
        result :=
            mul(
                or(
                    div(sub(prod0, remainder), UNIT_LPOTD),
                    mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1))
                ),
                UNIT_INVERSE
            )
    }
}

/// @notice Calculates x*y÷denominator with 512-bit precision.
///
/// @dev This is an extension of {mulDiv} for signed numbers, which works by computing the signs and the absolute values separately.
///
/// Notes:
/// - The result is rounded toward zero.
///
/// Requirements:
/// - Refer to the requirements in {mulDiv}.
/// - None of the inputs can be `type(int256).min`.
/// - The result must fit in int256.
///
/// @param x The multiplicand as an int256.
/// @param y The multiplier as an int256.
/// @param denominator The divisor as an int256.
/// @return result The result as an int256.
/// @custom:smtchecker abstract-function-nondet
function mulDivSigned(int256 x, int256 y, int256 denominator) pure returns (int256 result) {
    if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {
        revert PRBMath_MulDivSigned_InputTooSmall();
    }

    // Get hold of the absolute values of x, y and the denominator.
    uint256 xAbs;
    uint256 yAbs;
    uint256 dAbs;
    unchecked {
        xAbs = x < 0 ? uint256(-x) : uint256(x);
        yAbs = y < 0 ? uint256(-y) : uint256(y);
        dAbs = denominator < 0 ? uint256(-denominator) : uint256(denominator);
    }

    // Compute the absolute value of x*y÷denominator. The result must fit in int256.
    uint256 resultAbs = mulDiv(xAbs, yAbs, dAbs);
    if (resultAbs > uint256(type(int256).max)) {
        revert PRBMath_MulDivSigned_Overflow(x, y);
    }

    // Get the signs of x, y and the denominator.
    uint256 sx;
    uint256 sy;
    uint256 sd;
    assembly ("memory-safe") {
        // "sgt" is the "signed greater than" assembly instruction and "sub(0,1)" is -1 in two's complement.
        sx := sgt(x, sub(0, 1))
        sy := sgt(y, sub(0, 1))
        sd := sgt(denominator, sub(0, 1))
    }

    // XOR over sx, sy and sd. What this does is to check whether there are 1 or 3 negative signs in the inputs.
    // If there are, the result should be negative. Otherwise, it should be positive.
    unchecked {
        result = sx ^ sy ^ sd == 0 ? -int256(resultAbs) : int256(resultAbs);
    }
}

/// @notice Calculates the square root of x using the Babylonian method.
///
/// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
///
/// Notes:
/// - If x is not a perfect square, the result is rounded down.
/// - Credits to OpenZeppelin for the explanations in comments below.
///
/// @param x The uint256 number for which to calculate the square root.
/// @return result The result as a uint256.
/// @custom:smtchecker abstract-function-nondet
function sqrt(uint256 x) pure returns (uint256 result) {
    if (x == 0) {
        return 0;
    }

    // For our first guess, we calculate the biggest power of 2 which is smaller than the square root of x.
    //
    // We know that the "msb" (most significant bit) of x is a power of 2 such that we have:
    //
    // $$
    // msb(x) <= x <= 2*msb(x)$
    // $$
    //
    // We write $msb(x)$ as $2^k$, and we get:
    //
    // $$
    // k = log_2(x)
    // $$
    //
    // Thus, we can write the initial inequality as:
    //
    // $$
    // 2^{log_2(x)} <= x <= 2*2^{log_2(x)+1} \\
    // sqrt(2^k) <= sqrt(x) < sqrt(2^{k+1}) \\
    // 2^{k/2} <= sqrt(x) < 2^{(k+1)/2} <= 2^{(k/2)+1}
    // $$
    //
    // Consequently, $2^{log_2(x) /2} is a good first approximation of sqrt(x) with at least one correct bit.
    uint256 xAux = uint256(x);
    result = 1;
    if (xAux >= 2 ** 128) {
        xAux >>= 128;
        result <<= 64;
    }
    if (xAux >= 2 ** 64) {
        xAux >>= 64;
        result <<= 32;
    }
    if (xAux >= 2 ** 32) {
        xAux >>= 32;
        result <<= 16;
    }
    if (xAux >= 2 ** 16) {
        xAux >>= 16;
        result <<= 8;
    }
    if (xAux >= 2 ** 8) {
        xAux >>= 8;
        result <<= 4;
    }
    if (xAux >= 2 ** 4) {
        xAux >>= 4;
        result <<= 2;
    }
    if (xAux >= 2 ** 2) {
        result <<= 1;
    }

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

        // If x is not a perfect square, round the result toward zero.
        uint256 roundedResult = x / result;
        if (result >= roundedResult) {
            result = roundedResult;
        }
    }
}

File 8 of 8 : Errors.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.21;

library Errors {
    error AlreadyMinted();
    error AssetIsFrozen();
    error AssetIsNotPermanentlyFrozen();
    error BadHintIdArray();
    error BadShortHint();
    error BridgeAlreadyCreated();
    error CannotCancelMoreThan1000Orders();
    error CannotExitPartialFillSR();
    error CannotFlagSelf();
    error CannotLeaveDustAmount();
    error CannotLiquidateSelf();
    error CannotMintAnymoreNFTs();
    error CannotMintLastShortRecord();
    error CannotSocializeDebt();
    error CannotTransferFlaggableShort();
    error CannotTransferFlaggedShort();
    error CollateralHigherThanMax();
    error CRLowerThanMin();
    error DifferentVaults();
    error ExitShortPriceTooLow();
    error FirstShortDeleted();
    error FirstShortMustBeNFT();
    error FunctionNotFound(bytes4 _functionSelector);
    error AlreadyLiquidatable();
    error InvalidAmount();
    error InvalidAsset();
    error InvalidBridge();
    error InvalidBuyback();
    error InvalidFlaggerHint();
    error InvalidInitialCR();
    error InvalidMsgValue();
    error InvalidPrice();
    error InvalidShortId();
    error InvalidTithe();
    error InvalidTokenId();
    error InvalidTwapPrice();
    error InvalidTWAPSecondsAgo();
    error InvalidVault();
    error InvalidDeth();
    error InsufficientWalletBalance();
    error InsufficientCollateral();
    error InsufficientERCEscrowed();
    error InsufficientETHEscrowed();
    error InsufficientEthInLiquidityPool();
    error InsufficientNumberOfShorts();
    error IsNotNFT();
    error LiquidationAlreadyFlagged();
    error LiquidationIneligibleWindow();
    error SecondaryLiquidationNoValidShorts();
    error MarketAlreadyCreated();
    error NoDittoReward();
    error NoSells();
    error NoShares();
    error NotActiveOrder();
    error NotBridgeForBaseCollateral();
    error NotDiamond();
    error NotLastOrder();
    error NotMinted();
    error NotOwner();
    error NotOwnerOrAdmin();
    error NotOwnerCandidate();
    error NoYield();
    error OrderIdCountTooLow();
    error OrderUnderMinimumSize();
    error OriginalShortRecordCancelled();
    error ParameterIsZero();
    error PostExitCRLtPreExitCR();
    error PriceOrAmountIs0();
    error ReceiverExceededShortRecordLimit();
    error ReentrantCall();
    error ReentrantCallView();
    error ShortNotFlagged();
    error ShortRecordIdOverflow();
    error ShortRecordIdsNotSorted();
    error SufficientCollateral();
    error TooManyHints();
    error UnderMinimum();
    error UnderMinimumDeposit();
    error VaultAlreadyCreated();

    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);
    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);
    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);
    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);
    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);
}

Settings
{
  "remappings": [
    "forge-std/=lib/forge-std/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "interfaces/=interfaces/",
    "contracts/=contracts/",
    "test/=test/",
    "test-gas/=test-gas/",
    "deploy/=deploy/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@chainlink/=node_modules/@chainlink/",
    "@eth-optimism/=node_modules/@eth-optimism/",
    "@prb/=node_modules/@prb/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "shanghai",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract ISTETH","name":"_steth","type":"address"},{"internalType":"contract IUNSTETH","name":"_unsteth","type":"address"},{"internalType":"address","name":"diamondAddr","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NetBalanceZero","type":"error"},{"inputs":[],"name":"NotDiamond","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositEth","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getBaseCollateral","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDethValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

60e060405234801561000f575f80fd5b50604051610e8d380380610e8d83398101604081905261002e916100d2565b6001600160a01b03838116608081905283821660a081905291831660c05260405163095ea7b360e01b815260048101929092525f1960248301529063095ea7b3906044016020604051808303815f875af115801561008e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100b2919061011c565b50505050610142565b6001600160a01b03811681146100cf575f80fd5b50565b5f805f606084860312156100e4575f80fd5b83516100ef816100bb565b6020850151909350610100816100bb565b6040850151909250610111816100bb565b809150509250925092565b5f6020828403121561012c575f80fd5b8151801515811461013b575f80fd5b9392505050565b60805160a05160c051610cdb6101b25f395f81816102910152818161055e0152818161069501526108ea01525f818161076a015261087201525f818161015b015281816101f501528181610318015281816103dc0152818161049101528181610607015261098d0152610cdb5ff3fe60806040526004361061006e575f3560e01c806347e7ef241161004c57806347e7ef241461011657806370b7294414610135578063c2a672e014610185578063f3fef3a3146101a6575f80fd5b8063150b7a02146100725780631e70f195146100ec578063439370b11461010e575b5f80fd5b34801561007d575f80fd5b506100b661008c3660046109e4565b7f150b7a020000000000000000000000000000000000000000000000000000000095945050505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020015b60405180910390f35b3480156100f7575f80fd5b506101006101c5565b6040519081526020016100e3565b610100610278565b348015610121575f80fd5b50610100610130366004610a77565b610545565b348015610140575f80fd5b5060405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100e3565b348015610190575f80fd5b506101a461019f366004610a77565b61067d565b005b3480156101b1575f80fd5b506101006101c0366004610a77565b6108d1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561024f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102739190610a9f565b905090565b5f3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146102e8576040517fd04b63aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610372573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103969190610a9f565b6040517fa1903eab0000000000000000000000000000000000000000000000000000000081525f600482015290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a1903eab90349060240160206040518083038185885af1158015610424573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906104499190610a9f565b506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90829073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156104d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fa9190610a9f565b6105049190610ab6565b9050805f0361053f576040517f9d5710a400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b91505090565b5f3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146105b5576040517fd04b63aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152306024830152604482018490527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064015b6020604051808303815f875af115801561064e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106729190610aee565b508190505b92915050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106ec576040517fd04b63aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160018082528183019092525f916020808301908036833701905050905081815f8151811061072057610720610b41565b60209081029190910101526040517fd66810420000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063d6681042906107a19085903090600401610b6e565b5f604051808303815f875af11580156107bc573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108019190810190610bce565b5f8151811061081257610812610b41565b60209081029190910101516040517f42842e0e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8681166024830152604482018390529192507f0000000000000000000000000000000000000000000000000000000000000000909116906342842e0e906064015f604051808303815f87803b1580156108b5575f80fd5b505af11580156108c7573d5f803e3d5ffd5b5050505050505050565b5f3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610941576040517fd04b63aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90604401610632565b803573ffffffffffffffffffffffffffffffffffffffff811681146109df575f80fd5b919050565b5f805f805f608086880312156109f8575f80fd5b610a01866109bc565b9450610a0f602087016109bc565b935060408601359250606086013567ffffffffffffffff80821115610a32575f80fd5b818801915088601f830112610a45575f80fd5b813581811115610a53575f80fd5b896020828501011115610a64575f80fd5b9699959850939650602001949392505050565b5f8060408385031215610a88575f80fd5b610a91836109bc565b946020939093013593505050565b5f60208284031215610aaf575f80fd5b5051919050565b81810381811115610677577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215610afe575f80fd5b81518015158114610b0d575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b604080825283519082018190525f906020906060840190828701845b82811015610ba657815184529284019290840190600101610b8a565b50505073ffffffffffffffffffffffffffffffffffffffff9490941692019190915250919050565b5f6020808385031215610bdf575f80fd5b825167ffffffffffffffff80821115610bf6575f80fd5b818501915085601f830112610c09575f80fd5b815181811115610c1b57610c1b610b14565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f83011681018181108582111715610c5e57610c5e610b14565b604052918252848201925083810185019188831115610c7b575f80fd5b938501935b82851015610c9957845184529385019392850192610c80565b9897505050505050505056fea2646970667358221220658f157a9379aafbc9be2522175893feca54d6f4ac06f9061af3a0abade94a3764736f6c63430008150033000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84000000000000000000000000889edc2edab5f40e902b864ad4d7ade8e412f9b1000000000000000000000000d177000be70ea4efc23987acd1a79eaba8b758f1

Deployed Bytecode

0x60806040526004361061006e575f3560e01c806347e7ef241161004c57806347e7ef241461011657806370b7294414610135578063c2a672e014610185578063f3fef3a3146101a6575f80fd5b8063150b7a02146100725780631e70f195146100ec578063439370b11461010e575b5f80fd5b34801561007d575f80fd5b506100b661008c3660046109e4565b7f150b7a020000000000000000000000000000000000000000000000000000000095945050505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020015b60405180910390f35b3480156100f7575f80fd5b506101006101c5565b6040519081526020016100e3565b610100610278565b348015610121575f80fd5b50610100610130366004610a77565b610545565b348015610140575f80fd5b5060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe841681526020016100e3565b348015610190575f80fd5b506101a461019f366004610a77565b61067d565b005b3480156101b1575f80fd5b506101006101c0366004610a77565b6108d1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f907f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8473ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561024f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102739190610a9f565b905090565b5f3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d177000be70ea4efc23987acd1a79eaba8b758f116146102e8576040517fd04b63aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f907f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8473ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610372573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103969190610a9f565b6040517fa1903eab0000000000000000000000000000000000000000000000000000000081525f600482015290915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84169063a1903eab90349060240160206040518083038185885af1158015610424573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906104499190610a9f565b506040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90829073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8416906370a0823190602401602060405180830381865afa1580156104d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104fa9190610a9f565b6105049190610ab6565b9050805f0361053f576040517f9d5710a400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b91505090565b5f3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d177000be70ea4efc23987acd1a79eaba8b758f116146105b5576040517fd04b63aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152306024830152604482018490527f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8416906323b872dd906064015b6020604051808303815f875af115801561064e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106729190610aee565b508190505b92915050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d177000be70ea4efc23987acd1a79eaba8b758f116146106ec576040517fd04b63aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160018082528183019092525f916020808301908036833701905050905081815f8151811061072057610720610b41565b60209081029190910101526040517fd66810420000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000889edc2edab5f40e902b864ad4d7ade8e412f9b1169063d6681042906107a19085903090600401610b6e565b5f604051808303815f875af11580156107bc573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108019190810190610bce565b5f8151811061081257610812610b41565b60209081029190910101516040517f42842e0e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8681166024830152604482018390529192507f000000000000000000000000889edc2edab5f40e902b864ad4d7ade8e412f9b1909116906342842e0e906064015f604051808303815f87803b1580156108b5575f80fd5b505af11580156108c7573d5f803e3d5ffd5b5050505050505050565b5f3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d177000be70ea4efc23987acd1a79eaba8b758f11614610941576040517fd04b63aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490527f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84169063a9059cbb90604401610632565b803573ffffffffffffffffffffffffffffffffffffffff811681146109df575f80fd5b919050565b5f805f805f608086880312156109f8575f80fd5b610a01866109bc565b9450610a0f602087016109bc565b935060408601359250606086013567ffffffffffffffff80821115610a32575f80fd5b818801915088601f830112610a45575f80fd5b813581811115610a53575f80fd5b896020828501011115610a64575f80fd5b9699959850939650602001949392505050565b5f8060408385031215610a88575f80fd5b610a91836109bc565b946020939093013593505050565b5f60208284031215610aaf575f80fd5b5051919050565b81810381811115610677577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215610afe575f80fd5b81518015158114610b0d575f80fd5b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b604080825283519082018190525f906020906060840190828701845b82811015610ba657815184529284019290840190600101610b8a565b50505073ffffffffffffffffffffffffffffffffffffffff9490941692019190915250919050565b5f6020808385031215610bdf575f80fd5b825167ffffffffffffffff80821115610bf6575f80fd5b818501915085601f830112610c09575f80fd5b815181811115610c1b57610c1b610b14565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f83011681018181108582111715610c5e57610c5e610b14565b604052918252848201925083810185019188831115610c7b575f80fd5b938501935b82851015610c9957845184529385019392850192610c80565b9897505050505050505056fea2646970667358221220658f157a9379aafbc9be2522175893feca54d6f4ac06f9061af3a0abade94a3764736f6c63430008150033

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

000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84000000000000000000000000889edc2edab5f40e902b864ad4d7ade8e412f9b1000000000000000000000000d177000be70ea4efc23987acd1a79eaba8b758f1

-----Decoded View---------------
Arg [0] : _steth (address): 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84
Arg [1] : _unsteth (address): 0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1
Arg [2] : diamondAddr (address): 0xd177000Be70Ea4EfC23987aCD1a79EaBa8b758f1

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84
Arg [1] : 000000000000000000000000889edc2edab5f40e902b864ad4d7ade8e412f9b1
Arg [2] : 000000000000000000000000d177000be70ea4efc23987acd1a79eaba8b758f1


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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