Contract 0xc6a8EA07A8eFab27bAa4a03956105e078053C467 1

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x9eddb77f03323a7911d6ee0bbee0f0655208b7fa307a7aad2521c4778f45c9470x61018060227966482022-11-24 20:42:483 days 18 hrs ago0xdc6ca6116d69171b4aea7acbd1a739cf7c565f53 IN  Create: BenqiNativeERC4626Reinvest0 AVAX0.063254716 28
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BenqiNativeERC4626Reinvest

Compiler Version
v0.8.14+commit.80d49f37

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU AGPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at snowtrace.io on 2022-11-24
*/

// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.14;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/Rari-Capital/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);
    }
}

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/Rari-Capital/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");
    }
}

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/Rari-Capital/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 {
            // Start off with z at 1.
            z := 1

            // Used below to help find a nearby power of 2.
            let y := x

            // Find the lowest power of 2 that is at least sqrt(x).
            if iszero(lt(y, 0x100000000000000000000000000000000)) {
                y := shr(128, y) // Like dividing by 2 ** 128.
                z := shl(64, z) // Like multiplying by 2 ** 64.
            }
            if iszero(lt(y, 0x10000000000000000)) {
                y := shr(64, y) // Like dividing by 2 ** 64.
                z := shl(32, z) // Like multiplying by 2 ** 32.
            }
            if iszero(lt(y, 0x100000000)) {
                y := shr(32, y) // Like dividing by 2 ** 32.
                z := shl(16, z) // Like multiplying by 2 ** 16.
            }
            if iszero(lt(y, 0x10000)) {
                y := shr(16, y) // Like dividing by 2 ** 16.
                z := shl(8, z) // Like multiplying by 2 ** 8.
            }
            if iszero(lt(y, 0x100)) {
                y := shr(8, y) // Like dividing by 2 ** 8.
                z := shl(4, z) // Like multiplying by 2 ** 4.
            }
            if iszero(lt(y, 0x10)) {
                y := shr(4, y) // Like dividing by 2 ** 4.
                z := shl(2, z) // Like multiplying by 2 ** 2.
            }
            if iszero(lt(y, 0x8)) {
                // Equivalent to 2 ** z.
                z := shl(1, z)
            }

            // Shifting right by 1 is like dividing by 2.
            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)))

            // Compute a rounded down version of z.
            let zRoundDown := div(x, z)

            // If zRoundDown is smaller, use it.
            if lt(zRoundDown, z) {
                z := zRoundDown
            }
        }
    }
}

/// @notice Minimal ERC4626 tokenized Vault implementation.
/// @author Solmate (https://github.com/Rari-Capital/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 {}
}

abstract contract ICEther is ERC20 {
    function comptroller() external view virtual returns (address);

    function getCash() external view virtual returns (uint256);

    function getAccountSnapshot(address)
        external
        view
        virtual
        returns (
            uint256,
            uint256,
            uint256,
            uint256
        );
    function redeemUnderlying(uint256) external virtual returns (uint256);
    function mint() external payable virtual;
    
    function exchangeRateStored() external virtual view returns (uint);
}

interface IInterestRateModel {
    function getBorrowRate(
        uint256,
        uint256,
        uint256
    ) external view returns (uint256);

    function getSupplyRate(
        uint256,
        uint256,
        uint256,
        uint256
    ) external view returns (uint256);
}

abstract contract ICERC20 is ERC20 {
    function mint(uint256 underlyingAmount) external virtual returns (uint256);

    function underlying() external view virtual returns (ERC20);

    function getCash() external view virtual returns (uint256);

    function totalBorrows() external view virtual returns (uint256);

    function totalReserves() external view virtual returns (uint256);

    function exchangeRateStored() external view virtual returns (uint256);

    function accrualBlockNumber() external view virtual returns (uint256);

    function redeemUnderlying(uint256 underlyingAmount)
        external
        virtual
        returns (uint256);

    function balanceOfUnderlying(address) external virtual returns (uint256);

    function reserveFactorMantissa() external view virtual returns (uint256);

    function interestRateModel()
        external
        view
        virtual
        returns (IInterestRateModel);

    function initialExchangeRateMantissa()
        external
        view
        virtual
        returns (uint256);
}

/// @notice Get up to date cToken data without mutating state.
/// @author Transmissions11 (https://github.com/transmissions11/libcompound)
library LibCompound {
    using FixedPointMathLib for uint256;

    function viewUnderlyingBalanceOf(ICERC20 cToken, address user) internal view returns (uint256) {
        return cToken.balanceOf(user).mulWadDown(viewExchangeRate(cToken));
    }

    function viewExchangeRate(ICERC20 cToken) internal view returns (uint256) {
        uint256 accrualBlockNumberPrior = cToken.accrualBlockNumber();

        if (accrualBlockNumberPrior == block.number) {
            return cToken.exchangeRateStored();
        }

        uint256 totalCash = cToken.underlying().balanceOf(address(cToken));
        uint256 borrowsPrior = cToken.totalBorrows();
        uint256 reservesPrior = cToken.totalReserves();

        uint256 borrowRateMantissa = cToken.interestRateModel().getBorrowRate(totalCash, borrowsPrior, reservesPrior);

        require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH"); // Same as borrowRateMaxMantissa in CTokenInterfaces.sol

        uint256 interestAccumulated =
            borrowRateMantissa * block.number - accrualBlockNumberPrior.mulWadDown(borrowsPrior);

        uint256 totalReserves = cToken.reserveFactorMantissa().mulWadDown(interestAccumulated) + reservesPrior;
        uint256 totalBorrows = interestAccumulated + borrowsPrior;
        uint256 totalSupply = cToken.totalSupply();

        return
            totalSupply == 0
            ? cToken.initialExchangeRateMantissa()
            : totalCash + totalBorrows - totalReserves.divWadDown(totalSupply);
    }
}

interface IComptroller {

    function qiAddress() external view returns (address);

    function getAllMarkets() external view returns (address[] memory);

    function allMarkets(uint256 index) external view returns (address);

    function claimReward(uint8 rewardType, address holder) external;

    function mintGuardianPaused(address cToken) external view returns (bool);

    function rewardAccrued(uint8, address) external view returns (uint256);
}

interface IPair {
    function getReserves()
        external
        view
        returns (
            uint112 reserve0,
            uint112 reserve1,
            uint32 blockTimestampLast
        );

    function swap(
        uint256 amount0Out,
        uint256 amount1Out,
        address to,
        bytes calldata data
    ) external;
}

library DexSwap {
    using SafeTransferLib for ERC20;

    /**
     * @notice Swap directly through a Pair
     * @param amountIn input amount
     * @param fromToken address
     * @param toToken address
     * @param pairToken Pair used for swap
     * @return output amount
     */
    function swap(
        uint256 amountIn,
        address fromToken,
        address toToken,
        address pairToken
    ) internal returns (uint256) {
        IPair pair = IPair(pairToken);
        (address token0, ) = sortTokens(fromToken, toToken);
        (uint112 reserve0, uint112 reserve1, ) = pair.getReserves();
        if (token0 != fromToken) (reserve0, reserve1) = (reserve1, reserve0);
        uint256 amountOut1 = 0;
        uint256 amountOut2 = getAmountOut(amountIn, reserve0, reserve1);
        if (token0 != fromToken)
            (amountOut1, amountOut2) = (amountOut2, amountOut1);
        ERC20(fromToken).safeTransfer(address(pair), amountIn);
        pair.swap(amountOut1, amountOut2, address(this), new bytes(0));
        return amountOut2 > amountOut1 ? amountOut2 : amountOut1;
    }

    /**
     * @notice Given an input amount of an asset and pair reserves, returns maximum output amount of the other asset
     * @dev Assumes swap fee is 0.30%
     * @param amountIn input asset
     * @param reserveIn size of input asset reserve
     * @param reserveOut size of output asset reserve
     * @return maximum output amount
     */
    function getAmountOut(
        uint256 amountIn,
        uint256 reserveIn,
        uint256 reserveOut
    ) internal pure returns (uint256) {
        uint256 amountInWithFee = amountIn * 997;
        uint256 numerator = amountInWithFee * (reserveOut);
        uint256 denominator = (reserveIn * 1000) + (amountInWithFee);
        return numerator / (denominator);
    }

    /**
     * @notice Given two tokens, it'll return the tokens in the right order for the tokens pair
     * @dev TokenA must be different from TokenB, and both shouldn't be address(0), no validations
     * @param tokenA address
     * @param tokenB address
     * @return sorted tokens
     */
    function sortTokens(address tokenA, address tokenB)
        internal
        pure
        returns (address, address)
    {
        return tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
    }
}

interface WrappedNative {
    function deposit() external payable;
    function withdraw(uint wad) external;
}

/// @title BenqiERC4626Reinvest - Custom implementation of yield-daddy wrappers with flexible reinvesting logic
/// @notice Extended with payable function to accept native token transfer
contract BenqiNativeERC4626Reinvest is ERC4626 {
    /// -----------------------------------------------------------------------
    /// Libraries usage
    /// -----------------------------------------------------------------------

    using LibCompound for ICEther;
    using SafeTransferLib for ERC20;
    using FixedPointMathLib for uint256;

    /// -----------------------------------------------------------------------
    /// Constants
    /// -----------------------------------------------------------------------

    uint256 internal constant NO_ERROR = 0;

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

    /// @notice cEther token reference
    ICEther public immutable cEther;

    /// @notice The Compound comptroller contract
    IComptroller public immutable comptroller;

    /// @notice Access Control for harvest() route
    address public immutable manager;

    /// @notice The COMP-like token contract
    ERC20 public immutable reward;

    /// @notice Pointer to swapInfo
    swapInfo public SwapInfo;

    /// Compact struct to make two swaps (PancakeSwap on BSC)
    /// A => B (using pair1) then B => asset (of Wrapper) (using pair2)
    struct swapInfo {
        address token;
        address pair1;
        address pair2;
    }

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

    /// @notice Thrown when a call to Compound returned an error.
    /// @param errorCode The error code returned by Compound
    error CompoundERC4626__CompoundError(uint256 errorCode);

    /// @notice Thrown when the deposited assets doesnot return any shares.
    error CompoundERC4626_ZEROSHARES_Error();

    /// @notice Thrown when the redeems shares doesnot return any assets.
    error CompoundERC4626_ZEROASSETS_Error();

    /// -----------------------------------------------------------------------
    /// Constructor
    /// -----------------------------------------------------------------------
    constructor(
        ERC20 asset_, // underlying
        ERC20 reward_, // comp token or other
        ICEther cEther_, // compound concept of a share
        address manager_
    ) ERC4626(asset_, _vaultName(asset_), _vaultSymbol(asset_)) {
        reward = reward_;
        cEther = cEther_;
        comptroller = IComptroller(cEther.comptroller());
        manager = manager_;
    }

    /// -----------------------------------------------------------------------
    /// Compound liquidity mining
    /// -----------------------------------------------------------------------

    function setRoute(
        address token,
        address pair1,
        address pair2
    ) external {
        require(msg.sender == manager, "onlyOwner");
        SwapInfo = swapInfo(token, pair1, pair2);
        ERC20(reward).approve(SwapInfo.pair1, type(uint256).max); /// max approve
        ERC20(SwapInfo.token).approve(SwapInfo.pair2, type(uint256).max); /// max approve
    }

    /// @notice Claims liquidity mining rewards from Compound and performs low-lvl swap with instant reinvesting
    /// Calling harvest() claims COMP-Fork token through direct Pair swap for best control and lowest cost
    /// harvest() can be called by anybody. ideally this function should be adjusted per needs (e.g add fee for harvesting)
    function harvest() external {
        ICEther[] memory cTokens = new ICEther[](1);
        cTokens[0] = cEther;

        /// TODO: Setter for rewardType
        comptroller.claimReward(1, address(this));

        uint256 earned = ERC20(reward).balanceOf(address(this));
        address rewardToken = address(reward);

        /// If only one swap needed (high liquidity pair) - set swapInfo.token0/token/pair2 to 0x
        if (SwapInfo.token == address(asset)) {
            DexSwap.swap(
                earned, /// REWARDS amount to swap
                rewardToken, // from REWARD (because of liquidity)
                address(asset), /// to target underlying of this Vault ie USDC
                SwapInfo.pair1 /// pairToken (pool)
            );
            /// If two swaps needed
        } else {
            uint256 swapTokenAmount = DexSwap.swap(
                earned, /// REWARDS amount to swap
                rewardToken, /// fromToken REWARD
                SwapInfo.token, /// to intermediary token with high liquidity (no direct pools)
                SwapInfo.pair1 /// pairToken (pool)
            );

            DexSwap.swap(
                swapTokenAmount,
                SwapInfo.token, // from received BUSD (because of liquidity)
                address(asset), /// to target underlying of this Vault ie USDC
                SwapInfo.pair2 /// pairToken (pool)
            );
        }

        afterDeposit(asset.balanceOf(address(this)), 0);
    }

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

    function beforeWithdraw(uint256 assets, uint256) internal override {
        // Withdraw the underlying tokens from the cEther.
        uint256 errorCode = cEther.redeemUnderlying(assets);
        if (errorCode != NO_ERROR) {
            revert CompoundERC4626__CompoundError(errorCode);
        }
    }

    function viewUnderlyingBalanceOf() internal view returns (uint256) {
        return
            cEther.balanceOf(address(this)).mulWadDown(
                cEther.exchangeRateStored()
            );
    }

    function afterDeposit(uint256 assets, uint256) internal override {
        WrappedNative(address(asset)).withdraw(assets);
        // mint tokens
        cEther.mint{value: assets}();
    }

    function deposit(address receiver)
        public
        payable
        returns (uint256 shares)
    {
        // Check for rounding error since we round down in previewDeposit.
        if ((shares = previewDeposit(msg.value)) == 0)
            revert CompoundERC4626_ZEROSHARES_Error();
        require((shares = previewDeposit(msg.value)) != 0, "ZERO_SHARES");

        WrappedNative(address(asset)).deposit{value: msg.value}();

        _mint(receiver, shares);

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

        afterDeposit(msg.value, shares);
    }

    /// Standard ERC4626 deposit can only accept ERC20
    function deposit(uint256 assets, address receiver)
        public
        override
        returns (uint256 shares)
    {
        require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");

        asset.safeTransferFrom(msg.sender, address(this), assets);

        _mint(receiver, shares);

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

        afterDeposit(assets, shares);
    }

    /// @notice Total amount of the underlying asset that
    /// is "managed" by Vault.
    function totalAssets() public view override returns (uint256) {
        return viewUnderlyingBalanceOf();
    }

    /// @notice maximum amount of assets that can be deposited.
    /// This is capped by the amount of assets the cEther can be
    /// supplied with.
    /// This is 0 if minting is paused on the cEther.
    function maxDeposit(address) public view override returns (uint256) {
        if (comptroller.mintGuardianPaused(address(cEther))) return 0;
        return type(uint256).max;
    }

    /// @notice maximum amount of shares that can be minted.
    /// This is capped by the amount of assets the cEther can be
    /// supplied with.
    /// This is 0 if minting is paused on the cEther.
    function maxMint(address) public view override returns (uint256) {
        if (comptroller.mintGuardianPaused(address(cEther))) return 0;
        return type(uint256).max;
    }

    /// @notice Maximum amount of assets that can be withdrawn.
    /// This is capped by the amount of cash available on the cEther,
    /// if all assets are borrowed, a user can't withdraw from the vault.
    function maxWithdraw(address owner) public view override returns (uint256) {
        uint256 cash = cEther.getCash();
        uint256 assetsBalance = convertToAssets(balanceOf[owner]);
        return cash < assetsBalance ? cash : assetsBalance;
    }

    /// @notice Maximum amount of shares that can be redeemed.
    /// This is capped by the amount of cash available on the cEther,
    /// if all assets are borrowed, a user can't redeem from the vault.
    function maxRedeem(address owner) public view override returns (uint256) {
        uint256 cash = cEther.getCash();
        uint256 cashInShares = convertToShares(cash);
        uint256 shareBalance = balanceOf[owner];
        return cashInShares < shareBalance ? cashInShares : shareBalance;
    }

    /// @notice withdraw assets of the owner.
    function withdraw(
        uint256 assets,
        address receiver,
        address owner
    ) public override 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);
        WrappedNative(address(asset)).deposit{value: assets}();
        asset.safeTransfer(receiver, assets);
    }

    function redeem(
        uint256 shares,
        address receiver,
        address owner
    ) public override 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.
        if ((assets = previewRedeem(shares)) == 0)
            revert CompoundERC4626_ZEROASSETS_Error();

        beforeWithdraw(assets, shares);

        _burn(owner, shares);

        emit Withdraw(msg.sender, receiver, owner, assets, shares);
        WrappedNative(address(asset)).deposit{value: assets}();
        asset.safeTransfer(receiver, assets);
    }

    receive() external payable {}

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

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

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

Contract ABI

[{"inputs":[{"internalType":"contract ERC20","name":"asset_","type":"address"},{"internalType":"contract ERC20","name":"reward_","type":"address"},{"internalType":"contract ICEther","name":"cEther_","type":"address"},{"internalType":"address","name":"manager_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CompoundERC4626_ZEROASSETS_Error","type":"error"},{"inputs":[],"name":"CompoundERC4626_ZEROSHARES_Error","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorCode","type":"uint256"}],"name":"CompoundERC4626__CompoundError","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":"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":[],"name":"SwapInfo","outputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"pair1","type":"address"},{"internalType":"address","name":"pair2","type":"address"}],"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":[],"name":"cEther","outputs":[{"internalType":"contract ICEther","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"comptroller","outputs":[{"internalType":"contract IComptroller","name":"","type":"address"}],"stateMutability":"view","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":[{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"manager","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":[{"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":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"pair1","type":"address"},{"internalType":"address","name":"pair2","type":"address"}],"name":"setRoute","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":"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"},{"stateMutability":"payable","type":"receive"}]

6101806040523480156200001257600080fd5b5060405162002e9038038062002e90833981016040819052620000359162000404565b83620000418162000199565b6200004c866200022c565b8181846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200008d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b391906200046c565b8251620000c890600090602086019062000345565b508151620000de90600190602085019062000345565b5060ff81166080524660a052620000f4620002a9565b60c0525050506001600160a01b0392831660e052505083811661016052821661010081905260408051635fe3b56760e01b81529051635fe3b567916004808201926020929091908290030181865afa15801562000155573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200017b919062000498565b6001600160a01b03908116610120521661014052506200070e915050565b6060816001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620001da573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000204919081019062000501565b604051602001620002169190620005b9565b6040516020818303038152906040529050919050565b6060816001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa1580156200026d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000297919081019062000501565b60405160200162000216919062000600565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051620002dd91906200066b565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b82805462000353906200062f565b90600052602060002090601f016020900481019282620003775760008555620003c2565b82601f106200039257805160ff1916838001178555620003c2565b82800160010185558215620003c2579182015b82811115620003c2578251825591602001919060010190620003a5565b50620003d0929150620003d4565b5090565b5b80821115620003d05760008155600101620003d5565b6001600160a01b03811681146200040157600080fd5b50565b600080600080608085870312156200041b57600080fd5b84516200042881620003eb565b60208601519094506200043b81620003eb565b60408601519093506200044e81620003eb565b60608601519092506200046181620003eb565b939692955090935050565b6000602082840312156200047f57600080fd5b815160ff811681146200049157600080fd5b9392505050565b600060208284031215620004ab57600080fd5b81516200049181620003eb565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620004eb578181015183820152602001620004d1565b83811115620004fb576000848401525b50505050565b6000602082840312156200051457600080fd5b81516001600160401b03808211156200052c57600080fd5b818401915084601f8301126200054157600080fd5b815181811115620005565762000556620004b8565b604051601f8201601f19908116603f01168101908382118183101715620005815762000581620004b8565b816040528281528760208487010111156200059b57600080fd5b620005ae836020830160208801620004ce565b979650505050505050565b7f455243343632362d577261707065642042656e7169202d200000000000000000815260008251620005f3816018850160208701620004ce565b9190910160180192915050565b64627134362d60d81b81526000825162000622816005850160208701620004ce565b9190910160050192915050565b600181811c908216806200064457607f821691505b6020821081036200066557634e487b7160e01b600052602260045260246000fd5b50919050565b600080835481600182811c9150808316806200068857607f831692505b60208084108203620006a857634e487b7160e01b86526022600452602486fd5b818015620006bf5760018114620006d15762000700565b60ff1986168952848901965062000700565b60008a81526020902060005b86811015620006f85781548b820152908501908301620006dd565b505084890196505b509498975050505050505050565b60805160a05160c05160e051610100516101205161014051610160516126666200082a6000396000818161034d01528181610bbd01528181610c3901526117d6015260008181610467015261170901526000818161051201528181610a3d0152610b4801526000818161030101528181610a1201528181610ae4015281816113350152818161163d01528181611a2201528181611ab701528181611e090152611f7c0152600081816103fc01528181610c6301528181610c9801528181610d0c01528181610d4e01528181610e3501528181610ed1015281816110c10152818161113f01528181611267015281816112e50152818161194a0152611da3015260006109d9015260006109a9015260006103a101526126666000f3fe6080604052600436106102135760003560e01c80636e553f6511610118578063c63d75b6116100a0578063d905777e1161006f578063d905777e146106c3578063dd62ed3e146106e3578063ec42be771461071b578063ef8b30f71461073b578063f340fa011461075b57600080fd5b8063c63d75b61461041e578063c6e6f59214610663578063ce96cb7714610683578063d505accf146106a357600080fd5b806395d89b41116100e757806395d89b41146105ce578063a9059cbb146105e3578063b3d7f6b914610603578063b460af9414610623578063ba0876521461064357600080fd5b80636e553f651461053457806370a08231146105545780637ecebe001461058157806394bf804d146105ae57600080fd5b8063313ce5671161019b5780634641257d1161016a5780634641257d1461043e578063481c6a75146104555780634cdad5061461048957806353104b8e146104a95780635fe3b5671461050057600080fd5b8063313ce5671461038f5780633644e515146103d557806338d52e0f146103ea578063402d267d1461041e57600080fd5b80630a28a477116101e25780630a28a477146102b957806318160ddd146102d957806319b68c00146102ef578063228cb7331461033b57806323b872dd1461036f57600080fd5b806301e1d1141461021f57806306fdde031461024757806307a2d13a14610269578063095ea7b31461028957600080fd5b3661021a57005b600080fd5b34801561022b57600080fd5b5061023461076e565b6040519081526020015b60405180910390f35b34801561025357600080fd5b5061025c61077d565b60405161023e91906121d1565b34801561027557600080fd5b506102346102843660046121e4565b61080b565b34801561029557600080fd5b506102a96102a4366004612214565b610838565b604051901515815260200161023e565b3480156102c557600080fd5b506102346102d43660046121e4565b6108a5565b3480156102e557600080fd5b5061023460025481565b3480156102fb57600080fd5b506103237f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161023e565b34801561034757600080fd5b506103237f000000000000000000000000000000000000000000000000000000000000000081565b34801561037b57600080fd5b506102a961038a36600461223e565b6108c5565b34801561039b57600080fd5b506103c37f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff909116815260200161023e565b3480156103e157600080fd5b506102346109a5565b3480156103f657600080fd5b506103237f000000000000000000000000000000000000000000000000000000000000000081565b34801561042a57600080fd5b5061023461043936600461227a565b6109fb565b34801561044a57600080fd5b50610453610ac0565b005b34801561046157600080fd5b506103237f000000000000000000000000000000000000000000000000000000000000000081565b34801561049557600080fd5b506102346104a43660046121e4565b610dcd565b3480156104b557600080fd5b506006546007546008546104d6926001600160a01b03908116928116911683565b604080516001600160a01b039485168152928416602084015292169181019190915260600161023e565b34801561050c57600080fd5b506103237f000000000000000000000000000000000000000000000000000000000000000081565b34801561054057600080fd5b5061023461054f366004612295565b610dd8565b34801561056057600080fd5b5061023461056f36600461227a565b60036020526000908152604090205481565b34801561058d57600080fd5b5061023461059c36600461227a565b60056020526000908152604090205481565b3480156105ba57600080fd5b506102346105c9366004612295565b610eb7565b3480156105da57600080fd5b5061025c610f53565b3480156105ef57600080fd5b506102a96105fe366004612214565b610f60565b34801561060f57600080fd5b5061023461061e3660046121e4565b610fc6565b34801561062f57600080fd5b5061023461063e3660046122c1565b610fe5565b34801561064f57600080fd5b5061023461065e3660046122c1565b61116a565b34801561066f57600080fd5b5061023461067e3660046121e4565b611310565b34801561068f57600080fd5b5061023461069e36600461227a565b611330565b3480156106af57600080fd5b506104536106be3660046122fd565b6113f4565b3480156106cf57600080fd5b506102346106de36600461227a565b611638565b3480156106ef57600080fd5b506102346106fe366004612370565b600460209081526000928352604080842090915290825290205481565b34801561072757600080fd5b5061045361073636600461239a565b6116fe565b34801561074757600080fd5b506102346107563660046121e4565b6118c6565b61023461076936600461227a565b6118d1565b6000610778611a1b565b905090565b6000805461078a906123c6565b80601f01602080910402602001604051908101604052809291908181526020018280546107b6906123c6565b80156108035780601f106107d857610100808354040283529160200191610803565b820191906000526020600020905b8154815290600101906020018083116107e657829003601f168201915b505050505081565b600254600090801561082f5761082a61082261076e565b849083611b30565b610831565b825b9392505050565b3360008181526004602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906108939086815260200190565b60405180910390a35060015b92915050565b600254600090801561082f5761082a816108bd61076e565b859190611b4f565b6001600160a01b03831660009081526004602090815260408083203384529091528120546000198114610921576108fc8382612416565b6001600160a01b03861660009081526004602090815260408083203384529091529020555b6001600160a01b03851660009081526003602052604081208054859290610949908490612416565b90915550506001600160a01b0380851660008181526003602052604090819020805487019055519091871690600080516020612611833981519152906109929087815260200190565b60405180910390a3506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146109d657610778611b7d565b507f000000000000000000000000000000000000000000000000000000000000000090565b60405163731f0c2b60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063731f0c2b90602401602060405180830381865afa158015610a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aaa919061242d565b15610ab757506000919050565b50600019919050565b604080516001808252818301909252600091602080830190803683370190505090507f000000000000000000000000000000000000000000000000000000000000000081600081518110610b1657610b1661244f565b6001600160a01b039283166020918202929092010152604051630952c56360e01b8152600160048201523060248201527f000000000000000000000000000000000000000000000000000000000000000090911690630952c56390604401600060405180830381600087803b158015610b8e57600080fd5b505af1158015610ba2573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691506370a0823190602401602060405180830381865afa158015610c0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c319190612465565b6006549091507f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911603610ccc57600754610cc690839083907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b0316611c17565b50610d35565b600654600754600091610cef91859185916001600160a01b039182169116611c17565b600654600854919250610d329183916001600160a01b03908116917f00000000000000000000000000000000000000000000000000000000000000009116611c17565b50505b6040516370a0823160e01b8152306004820152610dc8907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610d9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc19190612465565b6000611d8d565b505050565b600061089f8261080b565b6000610de3836118c6565b905080600003610e285760405162461bcd60e51b815260206004820152600b60248201526a5a45524f5f53484152455360a81b60448201526064015b60405180910390fd5b610e5d6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333086611e7f565b610e678282611f09565b60408051848152602081018390526001600160a01b0384169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a361089f8382611d8d565b6000610ec283610fc6565b9050610ef96001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084611e7f565b610f038284611f09565b60408051828152602081018590526001600160a01b0384169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a361089f8184611d8d565b6001805461078a906123c6565b33600090815260036020526040812080548391908390610f81908490612416565b90915550506001600160a01b03831660008181526003602052604090819020805485019055513390600080516020612611833981519152906108939086815260200190565b600254600090801561082f5761082a610fdd61076e565b849083611b4f565b6000610ff0846108a5565b9050336001600160a01b03831614611060576001600160a01b0382166000908152600460209081526040808320338452909152902054600019811461105e576110398282612416565b6001600160a01b03841660009081526004602090815260408083203384529091529020555b505b61106a8482611f63565b6110748282612015565b60408051858152602081018390526001600160a01b03808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a47f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561111a57600080fd5b505af115801561112e573d6000803e3d6000fd5b506108319350506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915085905086612077565b6000336001600160a01b038316146111da576001600160a01b038216600090815260046020908152604080832033845290915290205460001981146111d8576111b38582612416565b6001600160a01b03841660009081526004602090815260408083203384529091529020555b505b6111e384610dcd565b90508060000361120657604051631c3b296560e11b815260040160405180910390fd5b6112108185611f63565b61121a8285612015565b60408051828152602081018690526001600160a01b03808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a47f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156112c057600080fd5b505af11580156112d4573d6000803e3d6000fd5b506108319350506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915085905083612077565b600254600090801561082f5761082a8161132861076e565b859190611b30565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611391573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b59190612465565b6001600160a01b038416600090815260036020526040812054919250906113db9061080b565b90508082106113ea57806113ec565b815b949350505050565b428410156114445760405162461bcd60e51b815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610e1f565b600060016114506109a5565b6001600160a01b038a811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa15801561155c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906115925750876001600160a01b0316816001600160a01b0316145b6115cf5760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a4a3a722a960911b6044820152606401610e1f565b6001600160a01b0390811660009081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611699573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bd9190612465565b905060006116ca82611310565b6001600160a01b0385166000908152600360205260409020549091508082106116f357806116f5565b815b95945050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117625760405162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b6044820152606401610e1f565b604080516060810182526001600160a01b0385811680835285821660208401819052858316938501849052600680546001600160a01b0319908116909317905560078054831682179055600880549092169093179055915163095ea7b360e01b8152600481019190915260001960248201527f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015611821573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611845919061242d565b5060065460085460405163095ea7b360e01b81526001600160a01b039182166004820152600019602482015291169063095ea7b3906044016020604051808303816000875af115801561189c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c0919061242d565b50505050565b600061089f82611310565b60006118dc346118c6565b9050806000036118ff57604051632090dad160e01b815260040160405180910390fd5b611908346118c6565b9050806000036119485760405162461bcd60e51b815260206004820152600b60248201526a5a45524f5f53484152455360a81b6044820152606401610e1f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156119a357600080fd5b505af11580156119b7573d6000803e3d6000fd5b50505050506119c68282611f09565b60408051348152602081018390526001600160a01b0384169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a3611a163482611d8d565b919050565b60006107787f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa29190612465565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611b06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2a9190612465565b906120ef565b828202811515841585830485141716611b4857600080fd5b0492915050565b828202811515841585830485141716611b6757600080fd5b6001826001830304018115150290509392505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000604051611baf919061247e565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60008181611c258686612104565b509050600080836001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8d9190612530565b5091509150876001600160a01b0316836001600160a01b031614611cad57905b600080611ccd8b856001600160701b0316856001600160701b0316612135565b9050896001600160a01b0316856001600160a01b031614611cea57905b611cfe6001600160a01b038b16878d612077565b6040805160008152602081019182905263022c0d9f60e01b9091526001600160a01b0387169063022c0d9f90611d3d9085908590309060248101612580565b600060405180830381600087803b158015611d5757600080fd5b505af1158015611d6b573d6000803e3d6000fd5b50505050818111611d7c5781611d7e565b805b9b9a5050505050505050505050565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015611def57600080fd5b505af1158015611e03573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631249c58b836040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e6257600080fd5b505af1158015611e76573d6000803e3d6000fd5b50505050505050565b60006040516323b872dd60e01b81528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080611f025760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606401610e1f565b5050505050565b8060026000828254611f1b91906125b7565b90915550506001600160a01b03821660008181526003602090815260408083208054860190555184815260008051602061261183398151915291015b60405180910390a35050565b60405163852a12e360e01b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063852a12e3906024016020604051808303816000875af1158015611fcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ff19190612465565b90508015610dc85760405163c309609960e01b815260048101829052602401610e1f565b6001600160a01b0382166000908152600360205260408120805483929061203d908490612416565b90915550506002805482900390556040518181526000906001600160a01b0384169060008051602061261183398151915290602001611f57565b600060405163a9059cbb60e01b8152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806118c05760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610e1f565b60006108318383670de0b6b3a7640000611b30565b600080826001600160a01b0316846001600160a01b03161061212757828461212a565b83835b915091509250929050565b600080612144856103e56125cf565b9050600061215284836125cf565b9050600082612163876103e86125cf565b61216d91906125b7565b905061217981836125ee565b979650505050505050565b6000815180845260005b818110156121aa5760208185018101518683018201520161218e565b818111156121bc576000602083870101525b50601f01601f19169290920160200192915050565b6020815260006108316020830184612184565b6000602082840312156121f657600080fd5b5035919050565b80356001600160a01b0381168114611a1657600080fd5b6000806040838503121561222757600080fd5b612230836121fd565b946020939093013593505050565b60008060006060848603121561225357600080fd5b61225c846121fd565b925061226a602085016121fd565b9150604084013590509250925092565b60006020828403121561228c57600080fd5b610831826121fd565b600080604083850312156122a857600080fd5b823591506122b8602084016121fd565b90509250929050565b6000806000606084860312156122d657600080fd5b833592506122e6602085016121fd565b91506122f4604085016121fd565b90509250925092565b600080600080600080600060e0888a03121561231857600080fd5b612321886121fd565b965061232f602089016121fd565b95506040880135945060608801359350608088013560ff8116811461235357600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561238357600080fd5b61238c836121fd565b91506122b8602084016121fd565b6000806000606084860312156123af57600080fd5b6123b8846121fd565b92506122e6602085016121fd565b600181811c908216806123da57607f821691505b6020821081036123fa57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008282101561242857612428612400565b500390565b60006020828403121561243f57600080fd5b8151801515811461083157600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561247757600080fd5b5051919050565b600080835481600182811c91508083168061249a57607f831692505b602080841082036124b957634e487b7160e01b86526022600452602486fd5b8180156124cd57600181146124de5761250b565b60ff1986168952848901965061250b565b60008a81526020902060005b868110156125035781548b8201529085019083016124ea565b505084890196505b509498975050505050505050565b80516001600160701b0381168114611a1657600080fd5b60008060006060848603121561254557600080fd5b61254e84612519565b925061255c60208501612519565b9150604084015163ffffffff8116811461257557600080fd5b809150509250925092565b84815283602082015260018060a01b03831660408201526080606082015260006125ad6080830184612184565b9695505050505050565b600082198211156125ca576125ca612400565b500190565b60008160001904831182151516156125e9576125e9612400565b500290565b60008261260b57634e487b7160e01b600052601260045260246000fd5b50049056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220ae705acf5320f163b43d9c683429306e82ec7b221c1601b9a05cdc3bc5bb693764736f6c634300080e0033000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c70000000000000000000000008729438eb15e2c8b576fcc6aecda6a148776c0f50000000000000000000000005c0401e81bc07ca70fad469b451682c0d747ef1c000000000000000000000000486af39519b4dc9a7fccd318217352830e8ad9b4

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

000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c70000000000000000000000008729438eb15e2c8b576fcc6aecda6a148776c0f50000000000000000000000005c0401e81bc07ca70fad469b451682c0d747ef1c000000000000000000000000486af39519b4dc9a7fccd318217352830e8ad9b4

-----Decoded View---------------
Arg [0] : asset_ (address): 0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7
Arg [1] : reward_ (address): 0x8729438eb15e2c8b576fcc6aecda6a148776c0f5
Arg [2] : cEther_ (address): 0x5c0401e81bc07ca70fad469b451682c0d747ef1c
Arg [3] : manager_ (address): 0x486af39519b4dc9a7fccd318217352830e8ad9b4

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000b31f66aa3c1e785363f0875a1b74e27b85fd66c7
Arg [1] : 0000000000000000000000008729438eb15e2c8b576fcc6aecda6a148776c0f5
Arg [2] : 0000000000000000000000005c0401e81bc07ca70fad469b451682c0d747ef1c
Arg [3] : 000000000000000000000000486af39519b4dc9a7fccd318217352830e8ad9b4


Deployed ByteCode Sourcemap

34459:11504:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41686:113;;;;;;;;;;;;;:::i;:::-;;;160:25:1;;;148:2;133:18;41686:113:0;;;;;;;;1043:18;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;25147:261::-;;;;;;;;;;-1:-1:-1;25147:261:0;;;;;:::i;:::-;;:::i;2520:217::-;;;;;;;;;;-1:-1:-1;2520:217:0;;;;;:::i;:::-;;:::i;:::-;;;1685:14:1;;1678:22;1660:41;;1648:2;1633:18;2520:217:0;1520:187:1;25814:259:0;;;;;;;;;;-1:-1:-1;25814:259:0;;;;;:::i;:::-;;:::i;1326:26::-;;;;;;;;;;;;;;;;35280:31;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1892:32:1;;;1874:51;;1862:2;1847:18;35280:31:0;1712:219:1;35560:29:0;;;;;;;;;;;;;;;3138:612;;;;;;;;;;-1:-1:-1;3138:612:0;;;;;:::i;:::-;;:::i;1099:31::-;;;;;;;;;;;;;;;;;;2662:4:1;2650:17;;;2632:36;;2620:2;2605:18;1099:31:0;2490:184:1;5480:179:0;;;;;;;;;;;;;:::i;21735:28::-;;;;;;;;;;;;;;;42017:183;;;;;;;;;;-1:-1:-1;42017:183:0;;;;;:::i;:::-;;:::i;38064:1515::-;;;;;;;;;;;;;:::i;:::-;;35473:32;;;;;;;;;;;;;;;26081:126;;;;;;;;;;-1:-1:-1;26081:126:0;;;;;:::i;:::-;;:::i;35635:24::-;;;;;;;;;;-1:-1:-1;35635:24:0;;;;;;;;-1:-1:-1;;;;;35635:24:0;;;;;;;;;;;;;;-1:-1:-1;;;;;3518:15:1;;;3500:34;;3570:15;;;3565:2;3550:18;;3543:43;3622:15;;3602:18;;;3595:43;;;;3450:2;3435:18;35635:24:0;3260:384:1;35371:41:0;;;;;;;;;;;;;;;41172:415;;;;;;;;;;-1:-1:-1;41172:415:0;;;;;:::i;:::-;;:::i;1361:44::-;;;;;;;;;;-1:-1:-1;1361:44:0;;;;;:::i;:::-;;;;;;;;;;;;;;1787:41;;;;;;;;;;-1:-1:-1;1787:41:0;;;;;:::i;:::-;;;;;;;;;;;;;;22686:478;;;;;;;;;;-1:-1:-1;22686:478:0;;;;;:::i;:::-;;:::i;1070:20::-;;;;;;;;;;;;;:::i;2745:385::-;;;;;;;;;;-1:-1:-1;2745:385:0;;;;;:::i;:::-;;:::i;25551:255::-;;;;;;;;;;-1:-1:-1;25551:255:0;;;;;:::i;:::-;;:::i;43642:780::-;;;;;;;;;;-1:-1:-1;43642:780:0;;;;;:::i;:::-;;:::i;44430:851::-;;;;;;;;;;-1:-1:-1;44430:851:0;;;;;:::i;:::-;;:::i;24878:261::-;;;;;;;;;;-1:-1:-1;24878:261:0;;;;;:::i;:::-;;:::i;42814:254::-;;;;;;;;;;-1:-1:-1;42814:254:0;;;;;:::i;:::-;;:::i;3945:1527::-;;;;;;;;;;-1:-1:-1;3945:1527:0;;;;;:::i;:::-;;:::i;43284:303::-;;;;;;;;;;-1:-1:-1;43284:303:0;;;;;:::i;:::-;;:::i;1414:64::-;;;;;;;;;;-1:-1:-1;1414:64:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;37316:393;;;;;;;;;;-1:-1:-1;37316:393:0;;;;;:::i;:::-;;:::i;25416:127::-;;;;;;;;;;-1:-1:-1;25416:127:0;;;;;:::i;:::-;;:::i;40513:595::-;;;;;;:::i;:::-;;:::i;41686:113::-;41739:7;41766:25;:23;:25::i;:::-;41759:32;;41686:113;:::o;1043:18::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;25147:261::-;25254:11;;25217:7;;25337:11;;:63;;25360:40;25378:13;:11;:13::i;:::-;25360:6;;25393;25360:17;:40::i;:::-;25337:63;;;25351:6;25337:63;25330:70;25147:261;-1:-1:-1;;;25147:261:0:o;2520:217::-;2621:10;2594:4;2611:21;;;:9;:21;;;;;;;;-1:-1:-1;;;;;2611:30:0;;;;;;;;;;:39;;;2668:37;2594:4;;2611:30;;2668:37;;;;2644:6;160:25:1;;148:2;133:18;;14:177;2668:37:0;;;;;;;;-1:-1:-1;2725:4:0;2520:217;;;;;:::o;25814:259::-;25921:11;;25884:7;;26004:11;;:61;;26027:38;26043:6;26051:13;:11;:13::i;:::-;26027:6;;:38;:15;:38::i;3138:612::-;-1:-1:-1;;;;;3295:15:0;;3260:4;3295:15;;;:9;:15;;;;;;;;3311:10;3295:27;;;;;;;;-1:-1:-1;;3375:28:0;;3371:80;;3435:16;3445:6;3435:7;:16;:::i;:::-;-1:-1:-1;;;;;3405:15:0;;;;;;:9;:15;;;;;;;;3421:10;3405:27;;;;;;;:46;3371:80;-1:-1:-1;;;;;3464:15:0;;;;;;:9;:15;;;;;:25;;3483:6;;3464:15;:25;;3483:6;;3464:25;:::i;:::-;;;;-1:-1:-1;;;;;;;3640:13:0;;;;;;;:9;:13;;;;;;;:23;;;;;;3692:26;3640:13;;3692:26;;;-1:-1:-1;;;;;;;;;;;3692:26:0;;;3657:6;160:25:1;;148:2;133:18;;14:177;3692:26:0;;;;;;;;-1:-1:-1;3738:4:0;;3138:612;-1:-1:-1;;;;3138:612:0:o;5480:179::-;5537:7;5581:16;5564:13;:33;:87;;5627:24;:22;:24::i;5564:87::-;-1:-1:-1;5600:24:0;;5480:179::o;42017:183::-;42100:47;;-1:-1:-1;;;42100:47:0;;-1:-1:-1;;;;;42139:6:0;1892:32:1;;42100:47:0;;;1874:51:1;-1:-1:-1;;42100:11:0;:30;;;;;;1847:18:1;;42100:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42096:61;;;-1:-1:-1;42156:1:0;;42017:183;-1:-1:-1;42017:183:0:o;42096:61::-;-1:-1:-1;;;42175:17:0;42017:183;-1:-1:-1;42017:183:0:o;38064:1515::-;38130:16;;;38144:1;38130:16;;;;;;;;;38103:24;;38130:16;;;;;;;;;;;-1:-1:-1;38130:16:0;38103:43;;38170:6;38157:7;38165:1;38157:10;;;;;;;;:::i;:::-;-1:-1:-1;;;;;38157:19:0;;;:10;;;;;;;;;:19;38230:41;;-1:-1:-1;;;38230:41:0;;38254:1;38230:41;;;7145:36:1;38265:4:0;7197:18:1;;;7190:60;38230:11:0;:23;;;;;;7118:18:1;;38230:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;38301:38:0;;-1:-1:-1;;;38301:38:0;;38333:4;38301:38;;;1874:51:1;38284:14:0;;-1:-1:-1;38307:6:0;-1:-1:-1;;;;;38301:23:0;;-1:-1:-1;38301:23:0;;1847:18:1;;38301:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38503:8;:14;38284:55;;-1:-1:-1;38380:6:0;;-1:-1:-1;;;;;38529:5:0;38503:32;;:14;;:32;38499:1013;;38783:14;;38552:281;;38583:6;;38635:11;;38711:5;;-1:-1:-1;;;;;38783:14:0;38552:12;:281::i;:::-;;38499:1013;;;39063:8;:14;39160;;38903:23;;38929:281;;38960:6;;39012:11;;-1:-1:-1;;;;;39063:14:0;;;;39160;38929:12;:281::i;:::-;39292:8;:14;39450;;38903:307;;-1:-1:-1;39227:273:0;;38903:307;;-1:-1:-1;;;;;39292:14:0;;;;39378:5;;39450:14;39227:12;:273::i;:::-;;38888:624;38499:1013;39537:30;;-1:-1:-1;;;39537:30:0;;39561:4;39537:30;;;1874:51:1;39524:47:0;;39537:5;-1:-1:-1;;;;;39537:15:0;;;;1847:18:1;;39537:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39569:1;39524:12;:47::i;:::-;38092:1487;;;38064:1515::o;26081:126::-;26149:7;26176:23;26192:6;26176:15;:23::i;41172:415::-;41275:14;41325:22;41340:6;41325:14;:22::i;:::-;41316:31;;;41352:1;41315:38;41307:62;;;;-1:-1:-1;;;41307:62:0;;7652:2:1;41307:62:0;;;7634:21:1;7691:2;7671:18;;;7664:30;-1:-1:-1;;;7710:18:1;;;7703:41;7761:18;;41307:62:0;;;;;;;;;41382:57;-1:-1:-1;;;;;41382:5:0;:22;41405:10;41425:4;41432:6;41382:22;:57::i;:::-;41452:23;41458:8;41468:6;41452:5;:23::i;:::-;41493:45;;;7964:25:1;;;8020:2;8005:18;;7998:34;;;-1:-1:-1;;;;;41493:45:0;;;41501:10;;41493:45;;7937:18:1;41493:45:0;;;;;;;41551:28;41564:6;41572;41551:12;:28::i;22686:478::-;22758:14;22794:19;22806:6;22794:11;:19::i;:::-;22785:28;-1:-1:-1;22959:57:0;-1:-1:-1;;;;;22959:5:0;:22;22982:10;23002:4;22785:28;22959:22;:57::i;:::-;23029:23;23035:8;23045:6;23029:5;:23::i;:::-;23070:45;;;7964:25:1;;;8020:2;8005:18;;7998:34;;;-1:-1:-1;;;;;23070:45:0;;;23078:10;;23070:45;;7937:18:1;23070:45:0;;;;;;;23128:28;23141:6;23149;23128:12;:28::i;1070:20::-;;;;;;;:::i;2745:385::-;2842:10;2815:4;2832:21;;;:9;:21;;;;;:31;;2857:6;;2832:21;2815:4;;2832:31;;2857:6;;2832:31;:::i;:::-;;;;-1:-1:-1;;;;;;;3014:13:0;;;;;;:9;:13;;;;;;;:23;;;;;;3066:32;3075:10;;-1:-1:-1;;;;;;;;;;;3066:32:0;;;3031:6;160:25:1;;148:2;133:18;;14:177;25551:255:0;25654:11;;25617:7;;25737:11;;:61;;25760:38;25776:13;:11;:13::i;:::-;25760:6;;25791;25760:15;:38::i;43642:780::-;43768:14;43804:23;43820:6;43804:15;:23::i;:::-;43795:32;-1:-1:-1;43911:10:0;-1:-1:-1;;;;;43911:19:0;;;43907:249;;-1:-1:-1;;;;;43965:16:0;;43947:15;43965:16;;;:9;:16;;;;;;;;43982:10;43965:28;;;;;;;;-1:-1:-1;;44050:28:0;;44046:98;;44128:16;44138:6;44128:7;:16;:::i;:::-;-1:-1:-1;;;;;44097:16:0;;;;;;:9;:16;;;;;;;;44114:10;44097:28;;;;;;;:47;44046:98;43932:224;43907:249;44168:30;44183:6;44191;44168:14;:30::i;:::-;44211:20;44217:5;44224:6;44211:5;:20::i;:::-;44249:53;;;7964:25:1;;;8020:2;8005:18;;7998:34;;;-1:-1:-1;;;;;44249:53:0;;;;;;;;44258:10;;44249:53;;7937:18:1;44249:53:0;;;;;;;44335:5;-1:-1:-1;;;;;44313:37:0;;44358:6;44313:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;44378:36:0;;-1:-1:-1;;;;;;;44378:5:0;:18;;-1:-1:-1;44397:8:0;;-1:-1:-1;44407:6:0;44378:18;:36::i;44430:851::-;44554:14;44585:10;-1:-1:-1;;;;;44585:19:0;;;44581:249;;-1:-1:-1;;;;;44639:16:0;;44621:15;44639:16;;;:9;:16;;;;;;;;44656:10;44639:28;;;;;;;;-1:-1:-1;;44724:28:0;;44720:98;;44802:16;44812:6;44802:7;:16;:::i;:::-;-1:-1:-1;;;;;44771:16:0;;;;;;:9;:16;;;;;;;;44788:10;44771:28;;;;;;;:47;44720:98;44606:224;44581:249;44931:21;44945:6;44931:13;:21::i;:::-;44922:30;;;44957:1;44921:37;44917:97;;44980:34;;-1:-1:-1;;;44980:34:0;;;;;;;;;;;44917:97;45027:30;45042:6;45050;45027:14;:30::i;:::-;45070:20;45076:5;45083:6;45070:5;:20::i;:::-;45108:53;;;7964:25:1;;;8020:2;8005:18;;7998:34;;;-1:-1:-1;;;;;45108:53:0;;;;;;;;45117:10;;45108:53;;7937:18:1;45108:53:0;;;;;;;45194:5;-1:-1:-1;;;;;45172:37:0;;45217:6;45172:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;45237:36:0;;-1:-1:-1;;;;;;;45237:5:0;:18;;-1:-1:-1;45256:8:0;;-1:-1:-1;45266:6:0;45237:18;:36::i;24878:261::-;24985:11;;24948:7;;25068:11;;:63;;25091:40;25109:6;25117:13;:11;:13::i;:::-;25091:6;;:40;:17;:40::i;42814:254::-;42880:7;42900:12;42915:6;-1:-1:-1;;;;;42915:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;42982:16:0;;42942:21;42982:16;;;:9;:16;;;;;;42900:31;;-1:-1:-1;42942:21:0;42966:33;;:15;:33::i;:::-;42942:57;;43024:13;43017:4;:20;:43;;43047:13;43017:43;;;43040:4;43017:43;43010:50;42814:254;-1:-1:-1;;;;42814:254:0:o;3945:1527::-;4173:15;4161:8;:27;;4153:63;;;;-1:-1:-1;;;4153:63:0;;8245:2:1;4153:63:0;;;8227:21:1;8284:2;8264:18;;;8257:30;8323:25;8303:18;;;8296:53;8366:18;;4153:63:0;8043:347:1;4153:63:0;4386:24;4413:827;4553:18;:16;:18::i;:::-;-1:-1:-1;;;;;5007:13:0;;;;;;;:6;:13;;;;;;;;;:15;;;;;;;;4638:458;;4683:167;4638:458;;;8682:25:1;8761:18;;;8754:43;;;;8833:15;;;8813:18;;;8806:43;8865:18;;;8858:34;;;8908:19;;;8901:35;;;;8952:19;;;;8945:35;;;4638:458:0;;;;;;;;;;8654:19:1;;;4638:458:0;;;4598:525;;;;;;;;-1:-1:-1;;;4473:673:0;;;9249:27:1;9292:11;;;9285:27;;;;9328:12;;;9321:28;;;;9365:12;;4473:673:0;;;-1:-1:-1;;4473:673:0;;;;;;;;;4441:724;;4473:673;4441:724;;;;4413:827;;;;;;;;;9615:25:1;9688:4;9676:17;;9656:18;;;9649:45;9710:18;;;9703:34;;;9753:18;;;9746:34;;;9587:19;;4413:827:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4413:827:0;;-1:-1:-1;;4413:827:0;;;-1:-1:-1;;;;;;;5265:30:0;;;;;;:59;;;5319:5;-1:-1:-1;;;;;5299:25:0;:16;-1:-1:-1;;;;;5299:25:0;;5265:59;5257:86;;;;-1:-1:-1;;;5257:86:0;;9993:2:1;5257:86:0;;;9975:21:1;10032:2;10012:18;;;10005:30;-1:-1:-1;;;10051:18:1;;;10044:44;10105:18;;5257:86:0;9791:338:1;5257:86:0;-1:-1:-1;;;;;5360:27:0;;;;;;;:9;:27;;;;;;;;:36;;;;;;;;;;;;;:44;;;5433:31;160:25:1;;;5360:36:0;;5433:31;;;;;133:18:1;5433:31:0;;;;;;;3945:1527;;;;;;;:::o;43284:303::-;43348:7;43368:12;43383:6;-1:-1:-1;;;;;43383:14:0;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43368:31;;43410:20;43433:21;43449:4;43433:15;:21::i;:::-;-1:-1:-1;;;;;43488:16:0;;43465:20;43488:16;;;:9;:16;;;;;;43410:44;;-1:-1:-1;43522:27:0;;;:57;;43567:12;43522:57;;;43552:12;43522:57;43515:64;43284:303;-1:-1:-1;;;;;43284:303:0:o;37316:393::-;37441:10;-1:-1:-1;;;;;37455:7:0;37441:21;;37433:43;;;;-1:-1:-1;;;37433:43:0;;10336:2:1;37433:43:0;;;10318:21:1;10375:1;10355:18;;;10348:29;-1:-1:-1;;;10393:18:1;;;10386:39;10442:18;;37433:43:0;10134:332:1;37433:43:0;37498:29;;;;;;;;-1:-1:-1;;;;;37498:29:0;;;;;;;;;;;;;;;;;;;;;;;;37487:8;:40;;-1:-1:-1;;;;;;37487:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;37538:56;;-1:-1:-1;;;37538:56:0;;;;;10645:51:1;;;;-1:-1:-1;;10712:18:1;;;10705:34;37544:6:0;37538:21;;;;;;10618:18:1;;37538:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;37627:8:0;:14;37651;;37621:64;;-1:-1:-1;;;37621:64:0;;-1:-1:-1;;;;;37651:14:0;;;37621:64;;;10645:51:1;-1:-1:-1;;10712:18:1;;;10705:34;37627:14:0;;;37621:29;;10618:18:1;;37621:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;37316:393;;;:::o;25416:127::-;25485:7;25512:23;25528:6;25512:15;:23::i;40513:595::-;40599:14;40721:25;40736:9;40721:14;:25::i;:::-;40712:34;;;40751:1;40711:41;40707:101;;40774:34;;-1:-1:-1;;;40774:34:0;;;;;;;;;;;40707:101;40837:25;40852:9;40837:14;:25::i;:::-;40828:34;;;40867:1;40827:41;40819:65;;;;-1:-1:-1;;;40819:65:0;;7652:2:1;40819:65:0;;;7634:21:1;7691:2;7671:18;;;7664:30;-1:-1:-1;;;7710:18:1;;;7703:41;7761:18;;40819:65:0;7450:335:1;40819:65:0;40919:5;-1:-1:-1;;;;;40897:37:0;;40942:9;40897:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40967:23;40973:8;40983:6;40967:5;:23::i;:::-;41008:48;;;41038:9;7964:25:1;;8020:2;8005:18;;7998:34;;;-1:-1:-1;;;;;41008:48:0;;;41016:10;;41008:48;;7937:18:1;41008:48:0;;;;;;;41069:31;41082:9;41093:6;41069:12;:31::i;:::-;40513:595;;;:::o;40095:209::-;40153:7;40193:103;40254:6;-1:-1:-1;;;;;40254:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40193:31;;-1:-1:-1;;;40193:31:0;;40218:4;40193:31;;;1874:51:1;40193:6:0;-1:-1:-1;;;;;40193:16:0;;;;1847:18:1;;40193:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:42;;:103::i;14267:552::-;14480:9;;;14614:19;;14607:27;14639:9;;14653;;;14650:16;;14636:31;14603:65;14593:123;;14699:1;14696;14689:12;14593:123;14782:19;;14267:552;-1:-1:-1;;14267:552:0:o;14827:771::-;15038:9;;;15172:19;;15165:27;15197:9;;15211;;;15208:16;;15194:31;15161:65;15151:123;;15257:1;15254;15247:12;15151:123;15577:1;15563:11;15559:1;15556;15552:9;15548:27;15544:35;15539:1;15532:9;15525:17;15521:59;15516:64;;14827:771;;;;;:::o;5667:457::-;5732:7;5833:95;5967:4;5951:22;;;;;;:::i;:::-;;;;;;;;;;5800:301;;;12247:25:1;;;;12288:18;;12281:34;;;;5996:14:0;12331:18:1;;;12324:34;6033:13:0;12374:18:1;;;12367:34;6077:4:0;12417:19:1;;;12410:61;12219:19;;5800:301:0;;;;;;;;;;;;5772:344;;;;;;5752:364;;5667:457;:::o;32057:828::-;32205:7;32244:9;32205:7;32286:30;32297:9;32308:7;32286:10;:30::i;:::-;32265:51;;;32328:16;32346;32368:4;-1:-1:-1;;;;;32368:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;32327:59;;;;;32411:9;-1:-1:-1;;;;;32401:19:0;:6;-1:-1:-1;;;;;32401:19:0;;32397:68;;32446:8;32397:68;32476:18;32509;32530:42;32543:8;32553;-1:-1:-1;;;;;32530:42:0;32563:8;-1:-1:-1;;;;;32530:42:0;:12;:42::i;:::-;32509:63;;32597:9;-1:-1:-1;;;;;32587:19:0;:6;-1:-1:-1;;;;;32587:19:0;;32583:89;;32649:10;32583:89;32683:54;-1:-1:-1;;;;;32683:29:0;;32721:4;32728:8;32683:29;:54::i;:::-;32797:12;;;32807:1;32797:12;;;;;;;;;-1:-1:-1;;;32748:62:0;;;-1:-1:-1;;;;;32748:9:0;;;;;:62;;32758:10;;32770;;32790:4;;32748:62;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32841:10;32828;:23;:49;;32867:10;32828:49;;;32854:10;32828:49;32821:56;32057:828;-1:-1:-1;;;;;;;;;;;32057:828:0:o;40312:193::-;40388:46;;-1:-1:-1;;;40388:46:0;;;;;160:25:1;;;40410:5:0;-1:-1:-1;;;;;40388:38:0;;;;133:18:1;;40388:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40469:6;-1:-1:-1;;;;;40469:11:0;;40488:6;40469:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40312:193;;:::o;8206:1604::-;8350:12;8481:4;8475:11;-1:-1:-1;;;8607:17:0;8600:93;8741:4;8737:1;8718:17;8714:25;8707:39;8826:2;8821;8802:17;8798:26;8791:38;8907:6;8902:2;8883:17;8879:26;8872:42;9721:2;9718:1;9713:3;9694:17;9691:1;9684:5;9677;9672:52;9235:16;9228:24;9222:2;9204:16;9201:24;9197:1;9193;9187:8;9184:15;9180:46;9177:76;8974:765;8963:776;;;9770:7;9762:40;;;;-1:-1:-1;;;9762:40:0;;13796:2:1;9762:40:0;;;13778:21:1;13835:2;13815:18;;;13808:30;-1:-1:-1;;;13854:18:1;;;13847:50;13914:18;;9762:40:0;13594:344:1;9762:40:0;8339:1471;8206:1604;;;;:::o;6324:335::-;6410:6;6395:11;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;6567:13:0;;;;;;:9;:13;;;;;;;;:23;;;;;;6619:32;160:25:1;;;-1:-1:-1;;;;;;;;;;;6619:32:0;133:18:1;6619:32:0;;;;;;;;6324:335;;:::o;39778:309::-;39936:31;;-1:-1:-1;;;39936:31:0;;;;;160:25:1;;;39916:17:0;;39936:6;-1:-1:-1;;;;;39936:23:0;;;;133:18:1;;39936:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39916:51;-1:-1:-1;39982:21:0;;39978:102;;40027:41;;-1:-1:-1;;;40027:41:0;;;;;160:25:1;;;133:18;;40027:41:0;14:177:1;6667:338:0;-1:-1:-1;;;;;6740:15:0;;;;;;:9;:15;;;;;:25;;6759:6;;6740:15;:25;;6759:6;;6740:25;:::i;:::-;;;;-1:-1:-1;;6913:11:0;:21;;;;;;;6963:34;;160:25:1;;;-1:-1:-1;;;;;;;6963:34:0;;;-1:-1:-1;;;;;;;;;;;6963:34:0;148:2:1;133:18;6963:34:0;14:177:1;9818:1485:0;9935:12;10066:4;10060:11;-1:-1:-1;;;10192:17:0;10185:93;10326:2;10322:1;10303:17;10299:25;10292:37;10407:6;10402:2;10383:17;10379:26;10372:42;11219:2;11216:1;11212:2;11193:17;11190:1;11183:5;11176;11171:51;10735:16;10728:24;10722:2;10704:16;10701:24;10697:1;10693;10687:8;10684:15;10680:46;10677:76;10474:763;10463:774;;;11268:7;11260:35;;;;-1:-1:-1;;;11260:35:0;;14278:2:1;11260:35:0;;;14260:21:1;14317:2;14297:18;;;14290:30;-1:-1:-1;;;14336:18:1;;;14329:45;14391:18;;11260:35:0;14076:339:1;13387:166:0;13452:7;13479:21;13490:1;13493;13336:4;13479:10;:21::i;33942:204::-;34044:7;34053;34094:6;-1:-1:-1;;;;;34085:15:0;:6;-1:-1:-1;;;;;34085:15:0;;:53;;34123:6;34131;34085:53;;;34104:6;34112;34085:53;34078:60;;;;33942:204;;;;;:::o;33250:379::-;33386:7;;33432:14;:8;33443:3;33432:14;:::i;:::-;33406:40;-1:-1:-1;33457:17:0;33477:30;33496:10;33406:40;33477:30;:::i;:::-;33457:50;-1:-1:-1;33518:19:0;33562:15;33541:16;:9;33553:4;33541:16;:::i;:::-;33540:38;;;;:::i;:::-;33518:60;-1:-1:-1;33596:25:0;33518:60;33596:9;:25;:::i;:::-;33589:32;33250:379;-1:-1:-1;;;;;;;33250:379:0:o;196:472:1:-;238:3;276:5;270:12;303:6;298:3;291:19;328:1;338:162;352:6;349:1;346:13;338:162;;;414:4;470:13;;;466:22;;460:29;442:11;;;438:20;;431:59;367:12;338:162;;;518:6;515:1;512:13;509:87;;;584:1;577:4;568:6;563:3;559:16;555:27;548:38;509:87;-1:-1:-1;650:2:1;629:15;-1:-1:-1;;625:29:1;616:39;;;;657:4;612:50;;196:472;-1:-1:-1;;196:472:1:o;673:220::-;822:2;811:9;804:21;785:4;842:45;883:2;872:9;868:18;860:6;842:45;:::i;898:180::-;957:6;1010:2;998:9;989:7;985:23;981:32;978:52;;;1026:1;1023;1016:12;978:52;-1:-1:-1;1049:23:1;;898:180;-1:-1:-1;898:180:1:o;1083:173::-;1151:20;;-1:-1:-1;;;;;1200:31:1;;1190:42;;1180:70;;1246:1;1243;1236:12;1261:254;1329:6;1337;1390:2;1378:9;1369:7;1365:23;1361:32;1358:52;;;1406:1;1403;1396:12;1358:52;1429:29;1448:9;1429:29;:::i;:::-;1419:39;1505:2;1490:18;;;;1477:32;;-1:-1:-1;;;1261:254:1:o;2157:328::-;2234:6;2242;2250;2303:2;2291:9;2282:7;2278:23;2274:32;2271:52;;;2319:1;2316;2309:12;2271:52;2342:29;2361:9;2342:29;:::i;:::-;2332:39;;2390:38;2424:2;2413:9;2409:18;2390:38;:::i;:::-;2380:48;;2475:2;2464:9;2460:18;2447:32;2437:42;;2157:328;;;;;:::o;2861:186::-;2920:6;2973:2;2961:9;2952:7;2948:23;2944:32;2941:52;;;2989:1;2986;2979:12;2941:52;3012:29;3031:9;3012:29;:::i;3878:254::-;3946:6;3954;4007:2;3995:9;3986:7;3982:23;3978:32;3975:52;;;4023:1;4020;4013:12;3975:52;4059:9;4046:23;4036:33;;4088:38;4122:2;4111:9;4107:18;4088:38;:::i;:::-;4078:48;;3878:254;;;;;:::o;4137:328::-;4214:6;4222;4230;4283:2;4271:9;4262:7;4258:23;4254:32;4251:52;;;4299:1;4296;4289:12;4251:52;4335:9;4322:23;4312:33;;4364:38;4398:2;4387:9;4383:18;4364:38;:::i;:::-;4354:48;;4421:38;4455:2;4444:9;4440:18;4421:38;:::i;:::-;4411:48;;4137:328;;;;;:::o;4470:693::-;4581:6;4589;4597;4605;4613;4621;4629;4682:3;4670:9;4661:7;4657:23;4653:33;4650:53;;;4699:1;4696;4689:12;4650:53;4722:29;4741:9;4722:29;:::i;:::-;4712:39;;4770:38;4804:2;4793:9;4789:18;4770:38;:::i;:::-;4760:48;;4855:2;4844:9;4840:18;4827:32;4817:42;;4906:2;4895:9;4891:18;4878:32;4868:42;;4960:3;4949:9;4945:19;4932:33;5005:4;4998:5;4994:16;4987:5;4984:27;4974:55;;5025:1;5022;5015:12;4974:55;4470:693;;;;-1:-1:-1;4470:693:1;;;;5048:5;5100:3;5085:19;;5072:33;;-1:-1:-1;5152:3:1;5137:19;;;5124:33;;4470:693;-1:-1:-1;;4470:693:1:o;5168:260::-;5236:6;5244;5297:2;5285:9;5276:7;5272:23;5268:32;5265:52;;;5313:1;5310;5303:12;5265:52;5336:29;5355:9;5336:29;:::i;:::-;5326:39;;5384:38;5418:2;5407:9;5403:18;5384:38;:::i;5433:334::-;5510:6;5518;5526;5579:2;5567:9;5558:7;5554:23;5550:32;5547:52;;;5595:1;5592;5585:12;5547:52;5618:29;5637:9;5618:29;:::i;:::-;5608:39;;5666:38;5700:2;5689:9;5685:18;5666:38;:::i;5772:380::-;5851:1;5847:12;;;;5894;;;5915:61;;5969:4;5961:6;5957:17;5947:27;;5915:61;6022:2;6014:6;6011:14;5991:18;5988:38;5985:161;;6068:10;6063:3;6059:20;6056:1;6049:31;6103:4;6100:1;6093:15;6131:4;6128:1;6121:15;5985:161;;5772:380;;;:::o;6157:127::-;6218:10;6213:3;6209:20;6206:1;6199:31;6249:4;6246:1;6239:15;6273:4;6270:1;6263:15;6289:125;6329:4;6357:1;6354;6351:8;6348:34;;;6362:18;;:::i;:::-;-1:-1:-1;6399:9:1;;6289:125::o;6419:277::-;6486:6;6539:2;6527:9;6518:7;6514:23;6510:32;6507:52;;;6555:1;6552;6545:12;6507:52;6587:9;6581:16;6640:5;6633:13;6626:21;6619:5;6616:32;6606:60;;6662:1;6659;6652:12;6833:127;6894:10;6889:3;6885:20;6882:1;6875:31;6925:4;6922:1;6915:15;6949:4;6946:1;6939:15;7261:184;7331:6;7384:2;7372:9;7363:7;7359:23;7355:32;7352:52;;;7400:1;7397;7390:12;7352:52;-1:-1:-1;7423:16:1;;7261:184;-1:-1:-1;7261:184:1:o;10879:1104::-;11009:3;11038:1;11071:6;11065:13;11101:3;11123:1;11151:9;11147:2;11143:18;11133:28;;11211:2;11200:9;11196:18;11233;11223:61;;11277:4;11269:6;11265:17;11255:27;;11223:61;11303:2;11351;11343:6;11340:14;11320:18;11317:38;11314:165;;-1:-1:-1;;;11378:33:1;;11434:4;11431:1;11424:15;11464:4;11385:3;11452:17;11314:165;11495:18;11522:104;;;;11640:1;11635:323;;;;11488:470;;11522:104;-1:-1:-1;;11555:24:1;;11543:37;;11600:16;;;;-1:-1:-1;11522:104:1;;11635:323;10826:1;10819:14;;;10863:4;10850:18;;11733:1;11747:165;11761:6;11758:1;11755:13;11747:165;;;11839:14;;11826:11;;;11819:35;11882:16;;;;11776:10;;11747:165;;;11751:3;;11941:6;11936:3;11932:16;11925:23;;11488:470;-1:-1:-1;11974:3:1;;10879:1104;-1:-1:-1;;;;;;;;10879:1104:1:o;12482:188::-;12561:13;;-1:-1:-1;;;;;12603:42:1;;12593:53;;12583:81;;12660:1;12657;12650:12;12675:450;12762:6;12770;12778;12831:2;12819:9;12810:7;12806:23;12802:32;12799:52;;;12847:1;12844;12837:12;12799:52;12870:40;12900:9;12870:40;:::i;:::-;12860:50;;12929:49;12974:2;12963:9;12959:18;12929:49;:::i;:::-;12919:59;;13021:2;13010:9;13006:18;13000:25;13065:10;13058:5;13054:22;13047:5;13044:33;13034:61;;13091:1;13088;13081:12;13034:61;13114:5;13104:15;;;12675:450;;;;;:::o;13130:459::-;13361:6;13350:9;13343:25;13404:6;13399:2;13388:9;13384:18;13377:34;13476:1;13472;13467:3;13463:11;13459:19;13451:6;13447:32;13442:2;13431:9;13427:18;13420:60;13516:3;13511:2;13500:9;13496:18;13489:31;13324:4;13537:46;13578:3;13567:9;13563:19;13555:6;13537:46;:::i;:::-;13529:54;13130:459;-1:-1:-1;;;;;;13130:459:1:o;13943:128::-;13983:3;14014:1;14010:6;14007:1;14004:13;14001:39;;;14020:18;;:::i;:::-;-1:-1:-1;14056:9:1;;13943:128::o;14420:168::-;14460:7;14526:1;14522;14518:6;14514:14;14511:1;14508:21;14503:1;14496:9;14489:17;14485:45;14482:71;;;14533:18;;:::i;:::-;-1:-1:-1;14573:9:1;;14420:168::o;14593:217::-;14633:1;14659;14649:132;;14703:10;14698:3;14694:20;14691:1;14684:31;14738:4;14735:1;14728:15;14766:4;14763:1;14756:15;14649:132;-1:-1:-1;14795:9:1;;14593:217::o

Swarm Source

ipfs://ae705acf5320f163b43d9c683429306e82ec7b221c1601b9a05cdc3bc5bb6937
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.