ETH Price: $3,412.95 (+1.74%)

Contract

0xCd0E5871c97C663D43c62B5049C123Bb45BfE2cC
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

More Info

Private Name Tags

TokenTracker

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Approve183435842023-10-13 19:33:35440 days ago1697225615IN
0xCd0E5871...b45BfE2cC
0 ETH0.000212298.76508103
Approve175595972023-06-25 22:56:59550 days ago1687733819IN
0xCd0E5871...b45BfE2cC
0 ETH0.000591712.81617276
Approve173204172023-05-23 7:19:59584 days ago1684826399IN
0xCd0E5871...b45BfE2cC
0 ETH0.0023512650.92735509
Approve173070562023-05-21 10:08:47586 days ago1684663727IN
0xCd0E5871...b45BfE2cC
0 ETH0.0013017828.19603751
Approve172360332023-05-11 8:50:35596 days ago1683795035IN
0xCd0E5871...b45BfE2cC
0 ETH0.0041421889.71789385
Approve172301672023-05-10 13:00:23596 days ago1683723623IN
0xCd0E5871...b45BfE2cC
0 ETH0.00493262106.83853589
Approve171028222023-04-22 15:37:59614 days ago1682177879IN
0xCd0E5871...b45BfE2cC
0 ETH0.0008695632.68417432
Approve171028212023-04-22 15:37:47614 days ago1682177867IN
0xCd0E5871...b45BfE2cC
0 ETH0.0015506433.34365417
Approve170972222023-04-21 20:48:11615 days ago1682110091IN
0xCd0E5871...b45BfE2cC
0 ETH0.0020899744.94097141
Transfer170922572023-04-21 3:59:47616 days ago1682049587IN
0xCd0E5871...b45BfE2cC
0 ETH0.0023625450.85873017
Approve170922142023-04-21 3:50:47616 days ago1682049047IN
0xCd0E5871...b45BfE2cC
0 ETH0.0016958436.46596326
Approve170922122023-04-21 3:50:23616 days ago1682049023IN
0xCd0E5871...b45BfE2cC
0 ETH0.000903137.28601516
Approve170922032023-04-21 3:48:35616 days ago1682048915IN
0xCd0E5871...b45BfE2cC
0 ETH0.0019880143.05961625
Approve170895612023-04-20 18:48:47616 days ago1682016527IN
0xCd0E5871...b45BfE2cC
0 ETH0.0032648170.2034518
Approve170893082023-04-20 17:57:23616 days ago1682013443IN
0xCd0E5871...b45BfE2cC
0 ETH0.0030379365.32489919

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
162408562022-12-22 14:31:23735 days ago1671719483  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
StakeableEulerERC4626

Compiler Version
v0.8.16+commit.07a7930e

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion
File 1 of 10 : StakeableEulerERC4626.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.13;

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

import {IEulerEToken} from "../external/IEulerEToken.sol";
import {IRewardsDistribution} from "../external/IRewardsDistribution.sol";
import {IStakingRewards} from "../external/IStakingRewards.sol";

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

/// @title StakeableEulerERC4626
/// @author Sam Bugs
/// @notice A ERC4626 wrapper for Euler Finance, that can handle staking
contract StakeableEulerERC4626 is EulerERC4626, Owned {

    /// -----------------------------------------------------------------------
    /// Errors
    /// -----------------------------------------------------------------------

    /// @notice Thrown when trying to assign an invalid rewards contract
    error StakeableEulerERC4626__InvalidRewardContract();

    /// -----------------------------------------------------------------------
    /// Libraries usage
    /// -----------------------------------------------------------------------

    using SafeTransferLib for ERC20;

    /// -----------------------------------------------------------------------
    /// Immutable params
    /// -----------------------------------------------------------------------

    /// @notice The rewards distribution address
    IRewardsDistribution public immutable rewardsDistribution;

    /// -----------------------------------------------------------------------
    /// Mutable params
    /// -----------------------------------------------------------------------

    /// @notice The staking rewards address
    IStakingRewards public stakingRewards;

    /// -----------------------------------------------------------------------
    /// Constructor
    /// -----------------------------------------------------------------------

    constructor(ERC20 asset_, address euler_, IEulerEToken eToken_, IRewardsDistribution rewardsDistribution_, address owner_)
        EulerERC4626(asset_, euler_, eToken_)
        Owned(owner_)
    {
        rewardsDistribution = rewardsDistribution_;
    }

    /// -----------------------------------------------------------------------
    /// ERC4626 overrides
    /// -----------------------------------------------------------------------

    function totalAssets() public view virtual override returns (uint256) {
        uint256 eTokenStakedBalance = _getStakedBalance();
        if (eTokenStakedBalance > 0) {
            // We add all eToken balance (staked and non-staked) and then convert to underlying
            // We do this to prevent rounding differences if we converted to underlying and then added the results
            uint256 eTokenBalanceInContract = eToken.balanceOf(address(this));
            return eToken.convertBalanceToUnderlying(eTokenStakedBalance + eTokenBalanceInContract);
        }
        return eToken.balanceOfUnderlying(address(this));
    }

    function beforeWithdraw(uint256 assets, uint256 shares) internal virtual override {
        uint256 underlyingBalanceInContract = eToken.balanceOfUnderlying(address(this));
        if (underlyingBalanceInContract < assets) {
            // Need to unstake to meet the demand
            uint256 neededUnderlying = assets - underlyingBalanceInContract;
            uint256 neededEToken = eToken.convertUnderlyingToBalance(neededUnderlying);

            // We also withdraw 5% of remaining staked eTokens so that we can avoid unstaking again in the next withdraw
            uint256 eTokenStakedBalance = _getStakedBalance();
            uint256 remaining = eTokenStakedBalance - neededEToken;
            uint256 withdrawAttempt = neededEToken + FixedPointMathLib.mulDivUp(remaining, 5, 100);

            // We make sure we don't try to withdraw more than available
            uint256 toWithdraw = eTokenStakedBalance < withdrawAttempt ? eTokenStakedBalance : withdrawAttempt;

            stakingRewards.withdraw(toWithdraw);
        }
        super.beforeWithdraw(assets, shares);
    }

    /// -----------------------------------------------------------------------
    /// Staking functions
    /// -----------------------------------------------------------------------

    /// @notice Returns how much was earned during staking
    function reward() public view returns (address rewardsToken, uint256 earned) {
        return _calculateReward(stakingRewards);
    }

    /// @notice Allows owner to set or update a new staking contract. Will claim rewards from previous staking if available
    function updateStakingAddress(uint256 rewardIndex, address recipient) external onlyOwner {
        _stopStaking(recipient);

        IRewardsDistribution.DistributionData memory data = rewardsDistribution.distributions(rewardIndex);
        IStakingRewards stakingRewards_ = IStakingRewards(data.destination);
        if (stakingRewards_.stakingToken() != address(eToken)) revert StakeableEulerERC4626__InvalidRewardContract();

        stakingRewards = stakingRewards_;
        ERC20(address(eToken)).safeApprove(address(stakingRewards_), type(uint256).max);
    }

     /// @notice Allows owner to claim rewards and stop staking all together
    function stopStaking(address recipient) external onlyOwner {
        _stopStaking(recipient);
        stakingRewards = IStakingRewards(address(0));
    }

    /// @notice Allows owner to stake a certain amount of tokens
    function stake(uint256 amount) external onlyOwner {
        stakingRewards.stake(amount);
    }

    /// @notice Allows owner to unstake a certain amount of tokens
    function unstake(uint256 amount) external onlyOwner {
        stakingRewards.withdraw(amount);
    }

    /// @notice Allows owner to claim all staking rewards
    function claimReward(address recipient) public onlyOwner returns (address rewardsToken, uint256 earned) {
        (rewardsToken, earned) = reward();
        stakingRewards.getReward();
        _transferRewardToken(rewardsToken, earned, recipient);
    }

    /// -----------------------------------------------------------------------
    /// Internal functions
    /// -----------------------------------------------------------------------

    function _getStakedBalance() internal view returns (uint256 eTokenStakedBalance) {
        IStakingRewards stakingRewards_ = stakingRewards;
        if (address(stakingRewards_) != address(0)) {
            return stakingRewards_.balanceOf(address(this));
        }
    } 

    function _calculateReward(IStakingRewards stakingRewards_) public view returns (address rewardToken, uint256 earned) {
        if (address(stakingRewards_) != address(0)) {
            rewardToken = stakingRewards_.rewardsToken();
            earned = stakingRewards_.earned(address(this));
        }
    }

    function _stopStaking(address recipient) internal {
        IStakingRewards stakingRewards_ = stakingRewards;
        if (address(stakingRewards_) != address(0)) {
            ERC20(address(eToken)).safeApprove(address(stakingRewards_), 0);
            (address rewardToken, uint256 earned) = _calculateReward(stakingRewards_);
            stakingRewards_.exit();
            _transferRewardToken(rewardToken, earned, recipient);
        }
    }

    function _transferRewardToken(address rewardToken, uint256 amount, address recipient) internal {
        if (amount > 0) {
            ERC20(rewardToken).safeTransfer(recipient, amount);
        }
    }
}

File 2 of 10 : ERC20.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

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

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

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

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

    string public name;

    string public symbol;

    uint8 public immutable decimals;

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

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

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

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

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

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

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

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

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

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

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

        return true;
    }

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

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

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

        return true;
    }

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

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

        balanceOf[from] -= amount;

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

        emit Transfer(from, to, amount);

        return true;
    }

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

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

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

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

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

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

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

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

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

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

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

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

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

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

File 3 of 10 : Owned.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

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

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

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

    address public owner;

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

        _;
    }

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

    constructor(address _owner) {
        owner = _owner;

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

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

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

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

File 4 of 10 : SafeTransferLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

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

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
            mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}

File 5 of 10 : FixedPointMathLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
    /*//////////////////////////////////////////////////////////////
                    SIMPLIFIED FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

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

    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
    }

    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
    }

    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
    }

    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
    }

    /*//////////////////////////////////////////////////////////////
                    LOW LEVEL FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function mulDivDown(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        assembly {
            // Store x * y in z for now.
            z := mul(x, y)

            // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
            if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
                revert(0, 0)
            }

            // Divide z by the denominator.
            z := div(z, denominator)
        }
    }

    function mulDivUp(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        assembly {
            // Store x * y in z for now.
            z := mul(x, y)

            // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
            if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
                revert(0, 0)
            }

            // First, divide z - 1 by the denominator and add 1.
            // We allow z - 1 to underflow if z is 0, because we multiply the
            // end result by 0 if z is zero, ensuring we return 0 if z is zero.
            z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))
        }
    }

    function rpow(
        uint256 x,
        uint256 n,
        uint256 scalar
    ) internal pure returns (uint256 z) {
        assembly {
            switch x
            case 0 {
                switch n
                case 0 {
                    // 0 ** 0 = 1
                    z := scalar
                }
                default {
                    // 0 ** n = 0
                    z := 0
                }
            }
            default {
                switch mod(n, 2)
                case 0 {
                    // If n is even, store scalar in z for now.
                    z := scalar
                }
                default {
                    // If n is odd, store x in z for now.
                    z := x
                }

                // Shifting right by 1 is like dividing by 2.
                let half := shr(1, scalar)

                for {
                    // Shift n right by 1 before looping to halve it.
                    n := shr(1, n)
                } n {
                    // Shift n right by 1 each iteration to halve it.
                    n := shr(1, n)
                } {
                    // Revert immediately if x ** 2 would overflow.
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
                    if shr(128, x) {
                        revert(0, 0)
                    }

                    // Store x squared.
                    let xx := mul(x, x)

                    // Round to the nearest number.
                    let xxRound := add(xx, half)

                    // Revert if xx + half overflowed.
                    if lt(xxRound, xx) {
                        revert(0, 0)
                    }

                    // Set x to scaled xxRound.
                    x := div(xxRound, scalar)

                    // If n is even:
                    if mod(n, 2) {
                        // Compute z * x.
                        let zx := mul(z, x)

                        // If z * x overflowed:
                        if iszero(eq(div(zx, x), z)) {
                            // Revert if x is non-zero.
                            if iszero(iszero(x)) {
                                revert(0, 0)
                            }
                        }

                        // Round to the nearest number.
                        let zxRound := add(zx, half)

                        // Revert if zx + half overflowed.
                        if lt(zxRound, zx) {
                            revert(0, 0)
                        }

                        // Return properly scaled zxRound.
                        z := div(zxRound, scalar)
                    }
                }
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                        GENERAL NUMBER UTILITIES
    //////////////////////////////////////////////////////////////*/

    function sqrt(uint256 x) internal pure returns (uint256 z) {
        assembly {
            let y := x // We start y at x, which will help us make our initial estimate.

            z := 181 // The "correct" value is 1, but this saves a multiplication later.

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

            // We check y >= 2^(k + 8) but shift right by k bits
            // each branch to ensure that if x >= 256, then y >= 256.
            if iszero(lt(y, 0x10000000000000000000000000000000000)) {
                y := shr(128, y)
                z := shl(64, z)
            }
            if iszero(lt(y, 0x1000000000000000000)) {
                y := shr(64, y)
                z := shl(32, z)
            }
            if iszero(lt(y, 0x10000000000)) {
                y := shr(32, y)
                z := shl(16, z)
            }
            if iszero(lt(y, 0x1000000)) {
                y := shr(16, y)
                z := shl(8, z)
            }

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

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

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

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

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

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

            // If x+1 is a perfect square, the Babylonian method cycles between
            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.
            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.
            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.
            z := sub(z, lt(div(x, z), z))
        }
    }

    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
        assembly {
            // Mod x by y. Note this will return
            // 0 instead of reverting if y is zero.
            z := mod(x, y)
        }
    }

    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
        assembly {
            // Divide x by y. Note this will return
            // 0 instead of reverting if y is zero.
            r := div(x, y)
        }
    }

    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        assembly {
            // Add 1 to x * y if x % y > 0. Note this will
            // return 0 instead of reverting if y is zero.
            z := add(gt(mod(x, y), 0), div(x, y))
        }
    }
}

File 6 of 10 : IEulerEToken.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.13;

/// @notice Tokenised representation of assets
interface IEulerEToken {

    // @notice Retrieve the current allowance
    /// @param holder Xor with the desired sub-account ID (if applicable)
    /// @param spender Trusted address
    function allowance(address holder, address spender) external view returns (uint);

    /// @notice Address of underlying asset
    function underlyingAsset() external view returns (address);

    /// @notice Balance of a particular account, in underlying units (increases as interest is earned)
    function balanceOfUnderlying(address account) external view returns (uint256);

    /// @notice Balance of a particular account
    function balanceOf(address account) external view returns (uint256);

    /// @notice Transfer underlying tokens from sender to the Euler pool, and increase account's eTokens
    /// @param subAccountId 0 for primary, 1-255 for a sub-account
    /// @param amount In underlying units (use max uint256 for full underlying token balance)
    function deposit(uint256 subAccountId, uint256 amount) external;

    /// @notice Transfer underlying tokens from Euler pool to sender, and decrease account's eTokens
    /// @param subAccountId 0 for primary, 1-255 for a sub-account
    /// @param amount In underlying units (use max uint256 for full pool balance)
    function withdraw(uint256 subAccountId, uint256 amount) external;

    /// @notice Convert an eToken balance to an underlying amount, taking into account current exchange rate
    /// @param balance eToken balance, in internal book-keeping units (18 decimals)
    /// @return Amount in underlying units, (same decimals as underlying token)
    function convertBalanceToUnderlying(uint balance) external view returns (uint);

    /// @notice Convert an underlying amount to an eToken balance, taking into account current exchange rate
    /// @param underlyingAmount Amount in underlying units (same decimals as underlying token)
    /// @return eToken balance, in internal book-keeping units (18 decimals)
    function convertUnderlyingToBalance(uint underlyingAmount) external view returns (uint);
}

File 7 of 10 : IRewardsDistribution.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// Original contract can be found under the following link:
// https://github.com/Synthetixio/synthetix/blob/master/contracts/interfaces/IRewardsDistribution.sol
interface IRewardsDistribution {
    // Structs
    struct DistributionData {
        address destination;
        uint amount;
    }

    // Views
    function distributions(uint256 index) external view returns (DistributionData memory);
}

File 8 of 10 : IStakingRewards.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// Original contract can be found under the following link:
// https://github.com/Synthetixio/synthetix/blob/master/contracts/interfaces/IStakingRewards.sol
interface IStakingRewards {

    // Views
    function rewardsToken() external view returns (address);
    function stakingToken() external view returns (address);
    function balanceOf(address account) external view returns (uint256);
    function earned(address account) external view returns (uint256);

    // Mutative
    function exit() external;
    function getReward() external;
    function stake(uint256 amount) external;
    function withdraw(uint256 amount) external;
}

File 9 of 10 : EulerERC4626.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.13;

import {ERC20} from "solmate/tokens/ERC20.sol";
import {ERC4626} from "solmate/mixins/ERC4626.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";

import {IEulerEToken} from "./external/IEulerEToken.sol";

/// @title EulerERC4626
/// @author zefram.eth
/// @notice ERC4626 wrapper for Euler Finance
contract EulerERC4626 is ERC4626 {
    /// -----------------------------------------------------------------------
    /// Libraries usage
    /// -----------------------------------------------------------------------

    using SafeTransferLib for ERC20;

    /// -----------------------------------------------------------------------
    /// Immutable params
    /// -----------------------------------------------------------------------

    /// @notice The Euler main contract address
    /// @dev Target of ERC20 approval when depositing
    address public immutable euler;

    /// @notice The Euler eToken contract
    IEulerEToken public immutable eToken;

    /// -----------------------------------------------------------------------
    /// Constructor
    /// -----------------------------------------------------------------------

    constructor(ERC20 asset_, address euler_, IEulerEToken eToken_)
        ERC4626(asset_, _vaultName(asset_), _vaultSymbol(asset_))
    {
        euler = euler_;
        eToken = eToken_;
    }

    /// -----------------------------------------------------------------------
    /// ERC4626 overrides
    /// -----------------------------------------------------------------------

    function totalAssets() public view virtual override returns (uint256) {
        return eToken.balanceOfUnderlying(address(this));
    }

    function beforeWithdraw(uint256 assets, uint256 /*shares*/ ) internal virtual override {
        /// -----------------------------------------------------------------------
        /// Withdraw assets from Euler
        /// -----------------------------------------------------------------------

        eToken.withdraw(0, assets);
    }

    function afterDeposit(uint256 assets, uint256 /*shares*/ ) internal virtual override {
        /// -----------------------------------------------------------------------
        /// Deposit assets into Euler
        /// -----------------------------------------------------------------------

        // approve to euler
        asset.safeApprove(address(euler), assets);

        // deposit into eToken
        eToken.deposit(0, assets);
    }

    function maxWithdraw(address owner) public view override returns (uint256) {
        uint256 cash = asset.balanceOf(euler);
        uint256 assetsBalance = convertToAssets(balanceOf[owner]);
        return cash < assetsBalance ? cash : assetsBalance;
    }

    function maxRedeem(address owner) public view override returns (uint256) {
        uint256 cash = asset.balanceOf(euler);
        uint256 cashInShares = convertToShares(cash);
        uint256 shareBalance = balanceOf[owner];
        return cashInShares < shareBalance ? cashInShares : shareBalance;
    }

    /// -----------------------------------------------------------------------
    /// ERC20 metadata generation
    /// -----------------------------------------------------------------------

    function _vaultName(ERC20 asset_) internal view virtual returns (string memory vaultName) {
        vaultName = string.concat("ERC4626-Wrapped Euler ", asset_.symbol());
    }

    function _vaultSymbol(ERC20 asset_) internal view virtual returns (string memory vaultSymbol) {
        vaultSymbol = string.concat("we", asset_.symbol());
    }
}

File 10 of 10 : ERC4626.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {ERC20} from "../tokens/ERC20.sol";
import {SafeTransferLib} from "../utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "../utils/FixedPointMathLib.sol";

/// @notice Minimal ERC4626 tokenized Vault implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/mixins/ERC4626.sol)
abstract contract ERC4626 is ERC20 {
    using SafeTransferLib for ERC20;
    using FixedPointMathLib for uint256;

    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);

    event Withdraw(
        address indexed caller,
        address indexed receiver,
        address indexed owner,
        uint256 assets,
        uint256 shares
    );

    /*//////////////////////////////////////////////////////////////
                               IMMUTABLES
    //////////////////////////////////////////////////////////////*/

    ERC20 public immutable asset;

    constructor(
        ERC20 _asset,
        string memory _name,
        string memory _symbol
    ) ERC20(_name, _symbol, _asset.decimals()) {
        asset = _asset;
    }

    /*//////////////////////////////////////////////////////////////
                        DEPOSIT/WITHDRAWAL LOGIC
    //////////////////////////////////////////////////////////////*/

    function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) {
        // Check for rounding error since we round down in previewDeposit.
        require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");

        // Need to transfer before minting or ERC777s could reenter.
        asset.safeTransferFrom(msg.sender, address(this), assets);

        _mint(receiver, shares);

        emit Deposit(msg.sender, receiver, assets, shares);

        afterDeposit(assets, shares);
    }

    function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) {
        assets = previewMint(shares); // No need to check for rounding error, previewMint rounds up.

        // Need to transfer before minting or ERC777s could reenter.
        asset.safeTransferFrom(msg.sender, address(this), assets);

        _mint(receiver, shares);

        emit Deposit(msg.sender, receiver, assets, shares);

        afterDeposit(assets, shares);
    }

    function withdraw(
        uint256 assets,
        address receiver,
        address owner
    ) public virtual returns (uint256 shares) {
        shares = previewWithdraw(assets); // No need to check for rounding error, previewWithdraw rounds up.

        if (msg.sender != owner) {
            uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.

            if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
        }

        beforeWithdraw(assets, shares);

        _burn(owner, shares);

        emit Withdraw(msg.sender, receiver, owner, assets, shares);

        asset.safeTransfer(receiver, assets);
    }

    function redeem(
        uint256 shares,
        address receiver,
        address owner
    ) public virtual returns (uint256 assets) {
        if (msg.sender != owner) {
            uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.

            if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
        }

        // Check for rounding error since we round down in previewRedeem.
        require((assets = previewRedeem(shares)) != 0, "ZERO_ASSETS");

        beforeWithdraw(assets, shares);

        _burn(owner, shares);

        emit Withdraw(msg.sender, receiver, owner, assets, shares);

        asset.safeTransfer(receiver, assets);
    }

    /*//////////////////////////////////////////////////////////////
                            ACCOUNTING LOGIC
    //////////////////////////////////////////////////////////////*/

    function totalAssets() public view virtual returns (uint256);

    function convertToShares(uint256 assets) public view virtual returns (uint256) {
        uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.

        return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets());
    }

    function convertToAssets(uint256 shares) public view virtual returns (uint256) {
        uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.

        return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply);
    }

    function previewDeposit(uint256 assets) public view virtual returns (uint256) {
        return convertToShares(assets);
    }

    function previewMint(uint256 shares) public view virtual returns (uint256) {
        uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.

        return supply == 0 ? shares : shares.mulDivUp(totalAssets(), supply);
    }

    function previewWithdraw(uint256 assets) public view virtual returns (uint256) {
        uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.

        return supply == 0 ? assets : assets.mulDivUp(supply, totalAssets());
    }

    function previewRedeem(uint256 shares) public view virtual returns (uint256) {
        return convertToAssets(shares);
    }

    /*//////////////////////////////////////////////////////////////
                     DEPOSIT/WITHDRAWAL LIMIT LOGIC
    //////////////////////////////////////////////////////////////*/

    function maxDeposit(address) public view virtual returns (uint256) {
        return type(uint256).max;
    }

    function maxMint(address) public view virtual returns (uint256) {
        return type(uint256).max;
    }

    function maxWithdraw(address owner) public view virtual returns (uint256) {
        return convertToAssets(balanceOf[owner]);
    }

    function maxRedeem(address owner) public view virtual returns (uint256) {
        return balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                          INTERNAL HOOKS LOGIC
    //////////////////////////////////////////////////////////////*/

    function beforeWithdraw(uint256 assets, uint256 shares) internal virtual {}

    function afterDeposit(uint256 assets, uint256 shares) internal virtual {}
}

Settings
{
  "remappings": [
    "create3-factory/=lib/create3-factory/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "solmate/=lib/solmate/src/",
    "src/=src/",
    "script/=script/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract ERC20","name":"asset_","type":"address"},{"internalType":"address","name":"euler_","type":"address"},{"internalType":"contract IEulerEToken","name":"eToken_","type":"address"},{"internalType":"contract IRewardsDistribution","name":"rewardsDistribution_","type":"address"},{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"StakeableEulerERC4626__InvalidRewardContract","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IStakingRewards","name":"stakingRewards_","type":"address"}],"name":"_calculateReward","outputs":[{"internalType":"address","name":"rewardToken","type":"address"},{"internalType":"uint256","name":"earned","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"claimReward","outputs":[{"internalType":"address","name":"rewardsToken","type":"address"},{"internalType":"uint256","name":"earned","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"eToken","outputs":[{"internalType":"contract IEulerEToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"euler","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reward","outputs":[{"internalType":"address","name":"rewardsToken","type":"address"},{"internalType":"uint256","name":"earned","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDistribution","outputs":[{"internalType":"contract IRewardsDistribution","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingRewards","outputs":[{"internalType":"contract IStakingRewards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"stopStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rewardIndex","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"updateStakingAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

6101606040523480156200001257600080fd5b50604051620036873803806200368783398101604081905262000035916200032f565b808585858262000045816200016a565b6200005085620001fd565b8181846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000091573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b79190620003af565b6000620000c5848262000480565b506001620000d4838262000480565b5060ff81166080524660a052620000ea6200027a565b60c052505050506001600160a01b0391821660e0525091821661010052811661012052600680546001600160a01b03191691841691821790556040519091506000907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a350506001600160a01b031661014052506200071b915050565b6060816001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001ab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001d5919081019062000572565b604051602001620001e791906200062a565b6040516020818303038152906040529050919050565b6060816001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa1580156200023e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000268919081019062000572565b604051602001620001e7919062000671565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051620002ae91906200069d565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b6001600160a01b03811681146200032c57600080fd5b50565b600080600080600060a086880312156200034857600080fd5b8551620003558162000316565b6020870151909550620003688162000316565b60408701519094506200037b8162000316565b60608701519093506200038e8162000316565b6080870151909250620003a18162000316565b809150509295509295909350565b600060208284031215620003c257600080fd5b815160ff81168114620003d457600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200040657607f821691505b6020821081036200042757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200047b57600081815260208120601f850160051c81016020861015620004565750805b601f850160051c820191505b81811015620004775782815560010162000462565b5050505b505050565b81516001600160401b038111156200049c576200049c620003db565b620004b481620004ad8454620003f1565b846200042d565b602080601f831160018114620004ec5760008415620004d35750858301515b600019600386901b1c1916600185901b17855562000477565b600085815260208120601f198616915b828110156200051d57888601518255948401946001909101908401620004fc565b50858210156200053c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60005b83811015620005695781810151838201526020016200054f565b50506000910152565b6000602082840312156200058557600080fd5b81516001600160401b03808211156200059d57600080fd5b818401915084601f830112620005b257600080fd5b815181811115620005c757620005c7620003db565b604051601f8201601f19908116603f01168101908382118183101715620005f257620005f2620003db565b816040528281528760208487010111156200060c57600080fd5b6200061f8360208301602088016200054c565b979650505050505050565b7f455243343632362d577261707065642045756c65722000000000000000000000815260008251620006648160168501602087016200054c565b9190910160160192915050565b61776560f01b815260008251620006908160028501602087016200054c565b9190910160020192915050565b6000808354620006ad81620003f1565b60018281168015620006c85760018114620006de576200070f565b60ff19841687528215158302870194506200070f565b8760005260208060002060005b85811015620007065781548a820152908401908201620006eb565b50505082870194505b50929695505050505050565b60805160a05160c05160e051610100516101205161014051612e7e620008096000396000818161045b0152611e2601526000818161059401528181610738015281816107d10152818161089401528181611eb201528181611fee0152818161237401528181612423015281816124fb015281816125db01526129860152600081816106810152818161172301528181611c84015261231901526000818161040f01528181610fff0152818161116a015281816114c80152818161169f0152818161175001528181611cb101526122f701526000610e1c01526000610de7015260006103ce0152612e7e6000f3fe608060405234801561001057600080fd5b50600436106102d35760003560e01c80637c6967dc11610186578063ba087652116100e3578063d505accf11610097578063dd62ed3e11610071578063dd62ed3e146106a3578063e0bd6775146106ce578063ef8b30f7146106e157600080fd5b8063d505accf14610656578063d905777e14610669578063db661b711461067c57600080fd5b8063c6e6f592116100c8578063c6e6f5921461061d578063ce96cb7714610630578063d279c1911461064357600080fd5b8063ba0876521461060a578063c63d75b61461047d57600080fd5b806395d89b411161013a578063a9059cbb1161011f578063a9059cbb146105d1578063b3d7f6b9146105e4578063b460af94146105f757600080fd5b806395d89b41146105b6578063a694fc3a146105be57600080fd5b80638da5cb5b1161016b5780638da5cb5b1461055c57806394bf804d1461057c578063953d9cf11461058f57600080fd5b80637c6967dc146105295780637ecebe001461053c57600080fd5b8063313ce56711610234578063497f285d116101e857806364b87a70116101cd57806364b87a70146104d65780636e553f65146104f657806370a082311461050957600080fd5b8063497f285d146104b05780634cdad506146104c357600080fd5b806338d52e0f1161021957806338d52e0f1461040a5780633fc6df6e14610456578063402d267d1461047d57600080fd5b8063313ce567146103c95780633644e5151461040257600080fd5b806313af40351161028b578063228cb73311610270578063228cb7331461036f57806323b872dd146103a35780632e17de78146103b657600080fd5b806313af40351461035157806318160ddd1461036657600080fd5b806307a2d13a116102bc57806307a2d13a14610308578063095ea7b31461031b5780630a28a4771461033e57600080fd5b806301e1d114146102d857806306fdde03146102f3575b600080fd5b6102e06106f4565b6040519081526020015b60405180910390f35b6102fb61091b565b6040516102ea91906129ca565b6102e0610316366004612a36565b6109a9565b61032e610329366004612a74565b6109d6565b60405190151581526020016102ea565b6102e061034c366004612a36565b610a50565b61036461035f366004612aa0565b610a70565b005b6102e060025481565b610377610b67565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152016102ea565b61032e6103b1366004612abd565b610b96565b6103646103c4366004612a36565b610cda565b6103f07f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff90911681526020016102ea565b6102e0610de3565b6104317f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102ea565b6104317f000000000000000000000000000000000000000000000000000000000000000081565b6102e061048b366004612aa0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90565b6103776104be366004612aa0565b610e3e565b6102e06104d1366004612a36565b610f63565b6007546104319073ffffffffffffffffffffffffffffffffffffffff1681565b6102e0610504366004612afe565b610f6e565b6102e0610517366004612aa0565b60036020526000908152604090205481565b610364610537366004612aa0565b61108e565b6102e061054a366004612aa0565b60056020526000908152604090205481565b6006546104319073ffffffffffffffffffffffffffffffffffffffff1681565b6102e061058a366004612afe565b611143565b6104317f000000000000000000000000000000000000000000000000000000000000000081565b6102fb6111f9565b6103646105cc366004612a36565b611206565b61032e6105df366004612a74565b6112de565b6102e06105f2366004612a36565b611363565b6102e0610605366004612b2e565b611382565b6102e0610618366004612b2e565b6114ef565b6102e061062b366004612a36565b6116c6565b6102e061063e366004612aa0565b6116e6565b610377610651366004612aa0565b611807565b610364610664366004612b70565b611928565b6102e0610677366004612aa0565b611c47565b6104317f000000000000000000000000000000000000000000000000000000000000000081565b6102e06106b1366004612be7565b600460209081526000928352604080842090915290825290205481565b6103646106dc366004612afe565b611d6a565b6102e06106ef366004612a36565b61203b565b6000806106ff612046565b90508015610866576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610794573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b89190612c15565b905073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663010ad6d16108008385612c5d565b6040518263ffffffff1660e01b815260040161081e91815260200190565b602060405180830381865afa15801561083b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085f9190612c15565b9250505090565b6040517f3af9e6690000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690633af9e669906024015b602060405180830381865afa1580156108f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109159190612c15565b91505090565b6000805461092890612c70565b80601f016020809104026020016040519081016040528092919081815260200182805461095490612c70565b80156109a15780601f10610976576101008083540402835291602001916109a1565b820191906000526020600020905b81548152906001019060200180831161098457829003601f168201915b505050505081565b60025460009080156109cd576109c86109c06106f4565b8490836120be565b6109cf565b825b9392505050565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610a3e9086815260200190565b60405180910390a35060015b92915050565b60025460009080156109cd576109c881610a686106f4565b8591906120dd565b60065473ffffffffffffffffffffffffffffffffffffffff163314610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a350565b6007546000908190610b8e9073ffffffffffffffffffffffffffffffffffffffff16610e3e565b915091509091565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2a57610bf88382612cc3565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff851660009081526003602052604081208054859290610c5f908490612cc3565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610cc79087815260200190565b60405180910390a3506001949350505050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610d5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610aed565b6007546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d906024015b600060405180830381600087803b158015610dc857600080fd5b505af1158015610ddc573d6000803e3d6000fd5b5050505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610e1957610e1461210b565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b60008073ffffffffffffffffffffffffffffffffffffffff831615610f5e578273ffffffffffffffffffffffffffffffffffffffff1663d1af0c7d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ea8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ecc9190612cd6565b6040517e8cc26200000000000000000000000000000000000000000000000000000000815230600482015290925073ffffffffffffffffffffffffffffffffffffffff841690628cc26290602401602060405180830381865afa158015610f37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5b9190612c15565b90505b915091565b6000610a4a826109a9565b6000610f798361203b565b905080600003610fe5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f5348415245530000000000000000000000000000000000000000006044820152606401610aed565b61102773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163330866121a5565b6110318282612264565b604080518481526020810183905273ffffffffffffffffffffffffffffffffffffffff84169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a3610a4a83826122dd565b60065473ffffffffffffffffffffffffffffffffffffffff16331461110f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610aed565b611118816123ea565b50600780547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b600061114e83611363565b905061119273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163330846121a5565b61119c8284612264565b604080518281526020810185905273ffffffffffffffffffffffffffffffffffffffff84169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a3610a4a81846122dd565b6001805461092890612c70565b60065473ffffffffffffffffffffffffffffffffffffffff163314611287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610aed565b6007546040517fa694fc3a0000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff9091169063a694fc3a90602401610dae565b336000908152600360205260408120805483919083906112ff908490612cc3565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610a3e9086815260200190565b60025460009080156109cd576109c861137a6106f4565b8490836120dd565b600061138d84610a50565b90503373ffffffffffffffffffffffffffffffffffffffff8316146114425773ffffffffffffffffffffffffffffffffffffffff821660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146114405761140e8282612cc3565b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020555b505b61144c84826124ca565b6114568282612729565b604080518581526020810183905273ffffffffffffffffffffffffffffffffffffffff808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a46109cf73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001684866127b7565b60003373ffffffffffffffffffffffffffffffffffffffff8316146115a45773ffffffffffffffffffffffffffffffffffffffff821660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146115a2576115708582612cc3565b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020555b505b6115ad84610f63565b905080600003611619576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f4153534554530000000000000000000000000000000000000000006044820152606401610aed565b61162381856124ca565b61162d8285612729565b604080518281526020810186905273ffffffffffffffffffffffffffffffffffffffff808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a46109cf73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001684836127b7565b60025460009080156109cd576109c8816116de6106f4565b8591906120be565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015260009182917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611797573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bb9190612c15565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260036020526040812054919250906117ee906109a9565b90508082106117fd57806117ff565b815b949350505050565b600654600090819073ffffffffffffffffffffffffffffffffffffffff16331461188d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610aed565b611895610b67565b600754604080517f3d18b912000000000000000000000000000000000000000000000000000000008152905193955091935073ffffffffffffffffffffffffffffffffffffffff1691633d18b9129160048082019260009290919082900301818387803b15801561190557600080fd5b505af1158015611919573d6000803e3d6000fd5b50505050610f5e828285612870565b42841015611992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610aed565b6000600161199e610de3565b73ffffffffffffffffffffffffffffffffffffffff8a811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015611af0573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590611b6b57508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611bd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e45520000000000000000000000000000000000006044820152606401610aed565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015260009182917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611cf8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1c9190612c15565b90506000611d29826116c6565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260036020526040902054909150808210611d5f5780611d61565b815b95945050505050565b60065473ffffffffffffffffffffffffffffffffffffffff163314611deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610aed565b611df4816123ea565b6040517f4487d3df000000000000000000000000000000000000000000000000000000008152600481018390526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690634487d3df906024016040805180830381865afa158015611e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea59190612cf3565b90506000816000015190507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff166372f702f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f569190612cd6565b73ffffffffffffffffffffffffffffffffffffffff1614611fa3576040517f63eea51600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117909155612035907f000000000000000000000000000000000000000000000000000000000000000016827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612897565b50505050565b6000610a4a826116c6565b60075460009073ffffffffffffffffffffffffffffffffffffffff1680156120ba576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8216906370a08231906024016108d4565b5090565b8282028115158415858304851417166120d657600080fd5b0492915050565b8282028115158415858304851417166120f557600080fd5b6001826001830304018115150290509392505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f600060405161213d9190612d72565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610ddc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610aed565b80600260008282546122769190612c5d565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a35050565b61233e73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000084612897565b6040517fe2bbb15800000000000000000000000000000000000000000000000000000000815260006004820152602481018390527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e2bbb158906044015b600060405180830381600087803b1580156123ce57600080fd5b505af11580156123e2573d6000803e3d6000fd5b505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff1680156124c65761244b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016826000612897565b60008061245783610e3e565b915091508273ffffffffffffffffffffffffffffffffffffffff1663e9fad8ee6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156124a357600080fd5b505af11580156124b7573d6000803e3d6000fd5b50505050612035828286612870565b5050565b6040517f3af9e6690000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690633af9e66990602401602060405180830381865afa158015612557573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257b9190612c15565b90508281101561271a5760006125918285612cc3565b6040517f52eac8af0000000000000000000000000000000000000000000000000000000081526004810182905290915060009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906352eac8af90602401602060405180830381865afa158015612622573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126469190612c15565b90506000612652612046565b905060006126608383612cc3565b9050600061267182600560646120dd565b61267b9085612c5d565b9050600081841061268c578161268e565b835b6007546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810183905291925073ffffffffffffffffffffffffffffffffffffffff1690632e1a7d4d90602401600060405180830381600087803b1580156126fb57600080fd5b505af115801561270f573d6000803e3d6000fd5b505050505050505050505b6127248383612950565b505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120805483929061275e908490612cc3565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016122d1565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080612035576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610aed565b81156127245761272473ffffffffffffffffffffffffffffffffffffffff841682846127b7565b60006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080612035576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610aed565b6040517f441a3e7000000000000000000000000000000000000000000000000000000000815260006004820152602481018390527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063441a3e70906044016123b4565b600060208083528351808285015260005b818110156129f7578581018301518582016040015282016129db565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b600060208284031215612a4857600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114612a7157600080fd5b50565b60008060408385031215612a8757600080fd5b8235612a9281612a4f565b946020939093013593505050565b600060208284031215612ab257600080fd5b81356109cf81612a4f565b600080600060608486031215612ad257600080fd5b8335612add81612a4f565b92506020840135612aed81612a4f565b929592945050506040919091013590565b60008060408385031215612b1157600080fd5b823591506020830135612b2381612a4f565b809150509250929050565b600080600060608486031215612b4357600080fd5b833592506020840135612b5581612a4f565b91506040840135612b6581612a4f565b809150509250925092565b600080600080600080600060e0888a031215612b8b57600080fd5b8735612b9681612a4f565b96506020880135612ba681612a4f565b95506040880135945060608801359350608088013560ff81168114612bca57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215612bfa57600080fd5b8235612c0581612a4f565b91506020830135612b2381612a4f565b600060208284031215612c2757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610a4a57610a4a612c2e565b600181811c90821680612c8457607f821691505b602082108103612cbd577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b81810381811115610a4a57610a4a612c2e565b600060208284031215612ce857600080fd5b81516109cf81612a4f565b600060408284031215612d0557600080fd5b6040516040810181811067ffffffffffffffff82111715612d4f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528251612d5d81612a4f565b81526020928301519281019290925250919050565b600080835481600182811c915080831680612d8e57607f831692505b60208084108203612dc6577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b818015612dda5760018114612e0d57612e3a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952841515850289019650612e3a565b60008a81526020902060005b86811015612e325781548b820152908501908301612e19565b505084890196505b50949897505050505050505056fea26469706673582212205b2ec9951b3f843925558c2e058c3dd16626e97babb9bf6e691e03b57940817164736f6c63430008100033000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000027182842e098f60e3d576794a5bffb0777e025d3000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da716000000000000000000000000a9839d52e964d0ed0d6d546c27d2248fac610c4300000000000000000000000027d54d93c8f89988e20fc8ffd911218bac44a0f6

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102d35760003560e01c80637c6967dc11610186578063ba087652116100e3578063d505accf11610097578063dd62ed3e11610071578063dd62ed3e146106a3578063e0bd6775146106ce578063ef8b30f7146106e157600080fd5b8063d505accf14610656578063d905777e14610669578063db661b711461067c57600080fd5b8063c6e6f592116100c8578063c6e6f5921461061d578063ce96cb7714610630578063d279c1911461064357600080fd5b8063ba0876521461060a578063c63d75b61461047d57600080fd5b806395d89b411161013a578063a9059cbb1161011f578063a9059cbb146105d1578063b3d7f6b9146105e4578063b460af94146105f757600080fd5b806395d89b41146105b6578063a694fc3a146105be57600080fd5b80638da5cb5b1161016b5780638da5cb5b1461055c57806394bf804d1461057c578063953d9cf11461058f57600080fd5b80637c6967dc146105295780637ecebe001461053c57600080fd5b8063313ce56711610234578063497f285d116101e857806364b87a70116101cd57806364b87a70146104d65780636e553f65146104f657806370a082311461050957600080fd5b8063497f285d146104b05780634cdad506146104c357600080fd5b806338d52e0f1161021957806338d52e0f1461040a5780633fc6df6e14610456578063402d267d1461047d57600080fd5b8063313ce567146103c95780633644e5151461040257600080fd5b806313af40351161028b578063228cb73311610270578063228cb7331461036f57806323b872dd146103a35780632e17de78146103b657600080fd5b806313af40351461035157806318160ddd1461036657600080fd5b806307a2d13a116102bc57806307a2d13a14610308578063095ea7b31461031b5780630a28a4771461033e57600080fd5b806301e1d114146102d857806306fdde03146102f3575b600080fd5b6102e06106f4565b6040519081526020015b60405180910390f35b6102fb61091b565b6040516102ea91906129ca565b6102e0610316366004612a36565b6109a9565b61032e610329366004612a74565b6109d6565b60405190151581526020016102ea565b6102e061034c366004612a36565b610a50565b61036461035f366004612aa0565b610a70565b005b6102e060025481565b610377610b67565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152016102ea565b61032e6103b1366004612abd565b610b96565b6103646103c4366004612a36565b610cda565b6103f07f000000000000000000000000000000000000000000000000000000000000000681565b60405160ff90911681526020016102ea565b6102e0610de3565b6104317f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102ea565b6104317f000000000000000000000000a9839d52e964d0ed0d6d546c27d2248fac610c4381565b6102e061048b366004612aa0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90565b6103776104be366004612aa0565b610e3e565b6102e06104d1366004612a36565b610f63565b6007546104319073ffffffffffffffffffffffffffffffffffffffff1681565b6102e0610504366004612afe565b610f6e565b6102e0610517366004612aa0565b60036020526000908152604090205481565b610364610537366004612aa0565b61108e565b6102e061054a366004612aa0565b60056020526000908152604090205481565b6006546104319073ffffffffffffffffffffffffffffffffffffffff1681565b6102e061058a366004612afe565b611143565b6104317f000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da71681565b6102fb6111f9565b6103646105cc366004612a36565b611206565b61032e6105df366004612a74565b6112de565b6102e06105f2366004612a36565b611363565b6102e0610605366004612b2e565b611382565b6102e0610618366004612b2e565b6114ef565b6102e061062b366004612a36565b6116c6565b6102e061063e366004612aa0565b6116e6565b610377610651366004612aa0565b611807565b610364610664366004612b70565b611928565b6102e0610677366004612aa0565b611c47565b6104317f00000000000000000000000027182842e098f60e3d576794a5bffb0777e025d381565b6102e06106b1366004612be7565b600460209081526000928352604080842090915290825290205481565b6103646106dc366004612afe565b611d6a565b6102e06106ef366004612a36565b61203b565b6000806106ff612046565b90508015610866576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da71673ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610794573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b89190612c15565b905073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da7161663010ad6d16108008385612c5d565b6040518263ffffffff1660e01b815260040161081e91815260200190565b602060405180830381865afa15801561083b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085f9190612c15565b9250505090565b6040517f3af9e6690000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da71673ffffffffffffffffffffffffffffffffffffffff1690633af9e669906024015b602060405180830381865afa1580156108f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109159190612c15565b91505090565b6000805461092890612c70565b80601f016020809104026020016040519081016040528092919081815260200182805461095490612c70565b80156109a15780601f10610976576101008083540402835291602001916109a1565b820191906000526020600020905b81548152906001019060200180831161098457829003601f168201915b505050505081565b60025460009080156109cd576109c86109c06106f4565b8490836120be565b6109cf565b825b9392505050565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610a3e9086815260200190565b60405180910390a35060015b92915050565b60025460009080156109cd576109c881610a686106f4565b8591906120dd565b60065473ffffffffffffffffffffffffffffffffffffffff163314610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a350565b6007546000908190610b8e9073ffffffffffffffffffffffffffffffffffffffff16610e3e565b915091509091565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2a57610bf88382612cc3565b73ffffffffffffffffffffffffffffffffffffffff861660009081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff851660009081526003602052604081208054859290610c5f908490612cc3565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610cc79087815260200190565b60405180910390a3506001949350505050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610d5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610aed565b6007546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d906024015b600060405180830381600087803b158015610dc857600080fd5b505af1158015610ddc573d6000803e3d6000fd5b5050505050565b60007f00000000000000000000000000000000000000000000000000000000000000014614610e1957610e1461210b565b905090565b507f701beada56835bfc6de2d6298fdc34e160d9ff620310fa630d062faa0a6b08e590565b60008073ffffffffffffffffffffffffffffffffffffffff831615610f5e578273ffffffffffffffffffffffffffffffffffffffff1663d1af0c7d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ea8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ecc9190612cd6565b6040517e8cc26200000000000000000000000000000000000000000000000000000000815230600482015290925073ffffffffffffffffffffffffffffffffffffffff841690628cc26290602401602060405180830381865afa158015610f37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5b9190612c15565b90505b915091565b6000610a4a826109a9565b6000610f798361203b565b905080600003610fe5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f5348415245530000000000000000000000000000000000000000006044820152606401610aed565b61102773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48163330866121a5565b6110318282612264565b604080518481526020810183905273ffffffffffffffffffffffffffffffffffffffff84169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a3610a4a83826122dd565b60065473ffffffffffffffffffffffffffffffffffffffff16331461110f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610aed565b611118816123ea565b50600780547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b600061114e83611363565b905061119273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48163330846121a5565b61119c8284612264565b604080518281526020810185905273ffffffffffffffffffffffffffffffffffffffff84169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a3610a4a81846122dd565b6001805461092890612c70565b60065473ffffffffffffffffffffffffffffffffffffffff163314611287576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610aed565b6007546040517fa694fc3a0000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff9091169063a694fc3a90602401610dae565b336000908152600360205260408120805483919083906112ff908490612cc3565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610a3e9086815260200190565b60025460009080156109cd576109c861137a6106f4565b8490836120dd565b600061138d84610a50565b90503373ffffffffffffffffffffffffffffffffffffffff8316146114425773ffffffffffffffffffffffffffffffffffffffff821660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146114405761140e8282612cc3565b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020555b505b61144c84826124ca565b6114568282612729565b604080518581526020810183905273ffffffffffffffffffffffffffffffffffffffff808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a46109cf73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb481684866127b7565b60003373ffffffffffffffffffffffffffffffffffffffff8316146115a45773ffffffffffffffffffffffffffffffffffffffff821660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146115a2576115708582612cc3565b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020555b505b6115ad84610f63565b905080600003611619576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f4153534554530000000000000000000000000000000000000000006044820152606401610aed565b61162381856124ca565b61162d8285612729565b604080518281526020810186905273ffffffffffffffffffffffffffffffffffffffff808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a46109cf73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb481684836127b7565b60025460009080156109cd576109c8816116de6106f4565b8591906120be565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000027182842e098f60e3d576794a5bffb0777e025d38116600483015260009182917f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4816906370a0823190602401602060405180830381865afa158015611797573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bb9190612c15565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260036020526040812054919250906117ee906109a9565b90508082106117fd57806117ff565b815b949350505050565b600654600090819073ffffffffffffffffffffffffffffffffffffffff16331461188d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610aed565b611895610b67565b600754604080517f3d18b912000000000000000000000000000000000000000000000000000000008152905193955091935073ffffffffffffffffffffffffffffffffffffffff1691633d18b9129160048082019260009290919082900301818387803b15801561190557600080fd5b505af1158015611919573d6000803e3d6000fd5b50505050610f5e828285612870565b42841015611992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610aed565b6000600161199e610de3565b73ffffffffffffffffffffffffffffffffffffffff8a811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015611af0573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590611b6b57508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611bd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e45520000000000000000000000000000000000006044820152606401610aed565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000027182842e098f60e3d576794a5bffb0777e025d38116600483015260009182917f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4816906370a0823190602401602060405180830381865afa158015611cf8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1c9190612c15565b90506000611d29826116c6565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260036020526040902054909150808210611d5f5780611d61565b815b95945050505050565b60065473ffffffffffffffffffffffffffffffffffffffff163314611deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610aed565b611df4816123ea565b6040517f4487d3df000000000000000000000000000000000000000000000000000000008152600481018390526000907f000000000000000000000000a9839d52e964d0ed0d6d546c27d2248fac610c4373ffffffffffffffffffffffffffffffffffffffff1690634487d3df906024016040805180830381865afa158015611e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea59190612cf3565b90506000816000015190507f000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da71673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff166372f702f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f569190612cd6565b73ffffffffffffffffffffffffffffffffffffffff1614611fa3576040517f63eea51600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117909155612035907f000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da71616827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612897565b50505050565b6000610a4a826116c6565b60075460009073ffffffffffffffffffffffffffffffffffffffff1680156120ba576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8216906370a08231906024016108d4565b5090565b8282028115158415858304851417166120d657600080fd5b0492915050565b8282028115158415858304851417166120f557600080fd5b6001826001830304018115150290509392505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f600060405161213d9190612d72565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610ddc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610aed565b80600260008282546122769190612c5d565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a35050565b61233e73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48167f00000000000000000000000027182842e098f60e3d576794a5bffb0777e025d384612897565b6040517fe2bbb15800000000000000000000000000000000000000000000000000000000815260006004820152602481018390527f000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da71673ffffffffffffffffffffffffffffffffffffffff169063e2bbb158906044015b600060405180830381600087803b1580156123ce57600080fd5b505af11580156123e2573d6000803e3d6000fd5b505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff1680156124c65761244b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da71616826000612897565b60008061245783610e3e565b915091508273ffffffffffffffffffffffffffffffffffffffff1663e9fad8ee6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156124a357600080fd5b505af11580156124b7573d6000803e3d6000fd5b50505050612035828286612870565b5050565b6040517f3af9e6690000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da71673ffffffffffffffffffffffffffffffffffffffff1690633af9e66990602401602060405180830381865afa158015612557573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257b9190612c15565b90508281101561271a5760006125918285612cc3565b6040517f52eac8af0000000000000000000000000000000000000000000000000000000081526004810182905290915060009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da71616906352eac8af90602401602060405180830381865afa158015612622573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126469190612c15565b90506000612652612046565b905060006126608383612cc3565b9050600061267182600560646120dd565b61267b9085612c5d565b9050600081841061268c578161268e565b835b6007546040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810183905291925073ffffffffffffffffffffffffffffffffffffffff1690632e1a7d4d90602401600060405180830381600087803b1580156126fb57600080fd5b505af115801561270f573d6000803e3d6000fd5b505050505050505050505b6127248383612950565b505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120805483929061275e908490612cc3565b909155505060028054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016122d1565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080612035576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610aed565b81156127245761272473ffffffffffffffffffffffffffffffffffffffff841682846127b7565b60006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080612035576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610aed565b6040517f441a3e7000000000000000000000000000000000000000000000000000000000815260006004820152602481018390527f000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da71673ffffffffffffffffffffffffffffffffffffffff169063441a3e70906044016123b4565b600060208083528351808285015260005b818110156129f7578581018301518582016040015282016129db565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b600060208284031215612a4857600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114612a7157600080fd5b50565b60008060408385031215612a8757600080fd5b8235612a9281612a4f565b946020939093013593505050565b600060208284031215612ab257600080fd5b81356109cf81612a4f565b600080600060608486031215612ad257600080fd5b8335612add81612a4f565b92506020840135612aed81612a4f565b929592945050506040919091013590565b60008060408385031215612b1157600080fd5b823591506020830135612b2381612a4f565b809150509250929050565b600080600060608486031215612b4357600080fd5b833592506020840135612b5581612a4f565b91506040840135612b6581612a4f565b809150509250925092565b600080600080600080600060e0888a031215612b8b57600080fd5b8735612b9681612a4f565b96506020880135612ba681612a4f565b95506040880135945060608801359350608088013560ff81168114612bca57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215612bfa57600080fd5b8235612c0581612a4f565b91506020830135612b2381612a4f565b600060208284031215612c2757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610a4a57610a4a612c2e565b600181811c90821680612c8457607f821691505b602082108103612cbd577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b81810381811115610a4a57610a4a612c2e565b600060208284031215612ce857600080fd5b81516109cf81612a4f565b600060408284031215612d0557600080fd5b6040516040810181811067ffffffffffffffff82111715612d4f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528251612d5d81612a4f565b81526020928301519281019290925250919050565b600080835481600182811c915080831680612d8e57607f831692505b60208084108203612dc6577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b818015612dda5760018114612e0d57612e3a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952841515850289019650612e3a565b60008a81526020902060005b86811015612e325781548b820152908501908301612e19565b505084890196505b50949897505050505050505056fea26469706673582212205b2ec9951b3f843925558c2e058c3dd16626e97babb9bf6e691e03b57940817164736f6c63430008100033

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

000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000027182842e098f60e3d576794a5bffb0777e025d3000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da716000000000000000000000000a9839d52e964d0ed0d6d546c27d2248fac610c4300000000000000000000000027d54d93c8f89988e20fc8ffd911218bac44a0f6

-----Decoded View---------------
Arg [0] : asset_ (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [1] : euler_ (address): 0x27182842E098f60e3D576794A5bFFb0777E025d3
Arg [2] : eToken_ (address): 0xEb91861f8A4e1C12333F42DCE8fB0Ecdc28dA716
Arg [3] : rewardsDistribution_ (address): 0xA9839D52E964d0ed0d6D546c27D2248Fac610c43
Arg [4] : owner_ (address): 0x27d54D93c8F89988E20fC8FFD911218bAc44a0F6

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [1] : 00000000000000000000000027182842e098f60e3d576794a5bffb0777e025d3
Arg [2] : 000000000000000000000000eb91861f8a4e1c12333f42dce8fb0ecdc28da716
Arg [3] : 000000000000000000000000a9839d52e964d0ed0d6d546c27d2248fac610c43
Arg [4] : 00000000000000000000000027d54d93c8f89988e20fc8ffd911218bac44a0f6


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  ]
[ 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.