ETH Price: $3,574.76 (-0.29%)
Gas: 34 Gwei

Contract

0x621ac2A927cc9323C23f7792e8FD25aAbc9cC04B
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
0x60806040126912302021-06-23 15:41:291008 days ago1624462889IN
 Create: LiquitySPWithdraw
0 ETH0.0349319324.1

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
LiquitySPWithdraw

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-06-23
*/

// SPDX-License-Identifier: MIT

pragma solidity =0.7.6;    
pragma experimental ABIEncoderV2;



interface IERC20 {
    function totalSupply() external view returns (uint256 supply);

    function balanceOf(address _owner) external view returns (uint256 balance);

    function transfer(address _to, uint256 _value) external returns (bool success);

    function transferFrom(
        address _from,
        address _to,
        uint256 _value
    ) external returns (bool success);

    function approve(address _spender, uint256 _value) external returns (bool success);

    function allowance(address _owner, address _spender) external view returns (uint256 remaining);

    function decimals() external view returns (uint256 digits);

    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}  





abstract contract IWETH {
    function allowance(address, address) public virtual view returns (uint256);

    function balanceOf(address) public virtual view returns (uint256);

    function approve(address, uint256) public virtual;

    function transfer(address, uint256) public virtual returns (bool);

    function transferFrom(
        address,
        address,
        uint256
    ) public virtual returns (bool);

    function deposit() public payable virtual;

    function withdraw(uint256) public virtual;
}    



library Address {
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            codehash := extcodehash(account)
        }
        return (codehash != accountHash && codehash != 0x0);
    }

    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return
            functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(
        address target,
        bytes memory data,
        uint256 weiValue,
        string memory errorMessage
    ) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{value: weiValue}(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}    



library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}    







library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

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

    /// @dev Edited so it always first approves 0 and then the value, because of non standard tokens
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(token.approve.selector, spender, newAllowance)
        );
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(
            value,
            "SafeERC20: decreased allowance below zero"
        );
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(token.approve.selector, spender, newAllowance)
        );
    }

    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        bytes memory returndata = address(token).functionCall(
            data,
            "SafeERC20: low-level call failed"
        );
        if (returndata.length > 0) {
            // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}    






library TokenUtils {
    using SafeERC20 for IERC20;

    address public constant WETH_ADDR = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    address public constant ETH_ADDR = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

    function approveToken(
        address _tokenAddr,
        address _to,
        uint256 _amount
    ) internal {
        if (_tokenAddr == ETH_ADDR) return;

        if (IERC20(_tokenAddr).allowance(address(this), _to) < _amount) {
            IERC20(_tokenAddr).safeApprove(_to, _amount);
        }
    }

    function pullTokensIfNeeded(
        address _token,
        address _from,
        uint256 _amount
    ) internal returns (uint256) {
        // handle max uint amount
        if (_amount == type(uint256).max) {
            _amount = getBalance(_token, _from);
        }

        if (_from != address(0) && _from != address(this) && _token != ETH_ADDR && _amount != 0) {
            IERC20(_token).safeTransferFrom(_from, address(this), _amount);
        }

        return _amount;
    }

    function withdrawTokens(
        address _token,
        address _to,
        uint256 _amount
    ) internal returns (uint256) {
        if (_amount == type(uint256).max) {
            _amount = getBalance(_token, address(this));
        }

        if (_to != address(0) && _to != address(this) && _amount != 0) {
            if (_token != ETH_ADDR) {
                IERC20(_token).safeTransfer(_to, _amount);
            } else {
                payable(_to).transfer(_amount);
            }
        }

        return _amount;
    }

    function depositWeth(uint256 _amount) internal {
        IWETH(WETH_ADDR).deposit{value: _amount}();
    }

    function withdrawWeth(uint256 _amount) internal {
        IWETH(WETH_ADDR).withdraw(_amount);
    }

    function getBalance(address _tokenAddr, address _acc) internal view returns (uint256) {
        if (_tokenAddr == ETH_ADDR) {
            return _acc.balance;
        } else {
            return IERC20(_tokenAddr).balanceOf(_acc);
        }
    }

    function getTokenDecimals(address _token) internal view returns (uint256) {
        if (_token == ETH_ADDR) return 18;

        return IERC20(_token).decimals();
    }
}    




// Common interface for the Trove Manager.
interface ITroveManager {
    
    // --- Events ---

    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);
    event PriceFeedAddressChanged(address _newPriceFeedAddress);
    event LUSDTokenAddressChanged(address _newLUSDTokenAddress);
    event ActivePoolAddressChanged(address _activePoolAddress);
    event DefaultPoolAddressChanged(address _defaultPoolAddress);
    event StabilityPoolAddressChanged(address _stabilityPoolAddress);
    event GasPoolAddressChanged(address _gasPoolAddress);
    event CollSurplusPoolAddressChanged(address _collSurplusPoolAddress);
    event SortedTrovesAddressChanged(address _sortedTrovesAddress);
    event LQTYTokenAddressChanged(address _lqtyTokenAddress);
    event LQTYStakingAddressChanged(address _lqtyStakingAddress);

    event Liquidation(uint _liquidatedDebt, uint _liquidatedColl, uint _collGasCompensation, uint _LUSDGasCompensation);
    event Redemption(uint _attemptedLUSDAmount, uint _actualLUSDAmount, uint _ETHSent, uint _ETHFee);
    event TroveUpdated(address indexed _borrower, uint _debt, uint _coll, uint stake, uint8 operation);
    event TroveLiquidated(address indexed _borrower, uint _debt, uint _coll, uint8 operation);
    event BaseRateUpdated(uint _baseRate);
    event LastFeeOpTimeUpdated(uint _lastFeeOpTime);
    event TotalStakesUpdated(uint _newTotalStakes);
    event SystemSnapshotsUpdated(uint _totalStakesSnapshot, uint _totalCollateralSnapshot);
    event LTermsUpdated(uint _L_ETH, uint _L_LUSDDebt);
    event TroveSnapshotsUpdated(uint _L_ETH, uint _L_LUSDDebt);
    event TroveIndexUpdated(address _borrower, uint _newIndex);

    function getTroveOwnersCount() external view returns (uint);

    function getTroveFromTroveOwnersArray(uint _index) external view returns (address);

    function getNominalICR(address _borrower) external view returns (uint);
    function getCurrentICR(address _borrower, uint _price) external view returns (uint);

    function liquidate(address _borrower) external;

    function liquidateTroves(uint _n) external;

    function batchLiquidateTroves(address[] calldata _troveArray) external;

    function redeemCollateral(
        uint _LUSDAmount,
        address _firstRedemptionHint,
        address _upperPartialRedemptionHint,
        address _lowerPartialRedemptionHint,
        uint _partialRedemptionHintNICR,
        uint _maxIterations,
        uint _maxFee
    ) external; 

    function updateStakeAndTotalStakes(address _borrower) external returns (uint);

    function updateTroveRewardSnapshots(address _borrower) external;

    function addTroveOwnerToArray(address _borrower) external returns (uint index);

    function applyPendingRewards(address _borrower) external;

    function getPendingETHReward(address _borrower) external view returns (uint);

    function getPendingLUSDDebtReward(address _borrower) external view returns (uint);

     function hasPendingRewards(address _borrower) external view returns (bool);

    function getEntireDebtAndColl(address _borrower) external view returns (
        uint debt, 
        uint coll, 
        uint pendingLUSDDebtReward, 
        uint pendingETHReward
    );

    function closeTrove(address _borrower) external;

    function removeStake(address _borrower) external;

    function getRedemptionRate() external view returns (uint);
    function getRedemptionRateWithDecay() external view returns (uint);

    function getRedemptionFeeWithDecay(uint _ETHDrawn) external view returns (uint);

    function getBorrowingRate() external view returns (uint);
    function getBorrowingRateWithDecay() external view returns (uint);

    function getBorrowingFee(uint LUSDDebt) external view returns (uint);
    function getBorrowingFeeWithDecay(uint _LUSDDebt) external view returns (uint);

    function decayBaseRateFromBorrowing() external;

    function getTroveStatus(address _borrower) external view returns (uint);
    
    function getTroveStake(address _borrower) external view returns (uint);

    function getTroveDebt(address _borrower) external view returns (uint);

    function getTroveColl(address _borrower) external view returns (uint);

    function setTroveStatus(address _borrower, uint num) external;

    function increaseTroveColl(address _borrower, uint _collIncrease) external returns (uint);

    function decreaseTroveColl(address _borrower, uint _collDecrease) external returns (uint); 

    function increaseTroveDebt(address _borrower, uint _debtIncrease) external returns (uint); 

    function decreaseTroveDebt(address _borrower, uint _collDecrease) external returns (uint); 

    function getTCR(uint _price) external view returns (uint);

    function checkRecoveryMode(uint _price) external view returns (bool);
}    



// Common interface for the Trove Manager.
interface IBorrowerOperations {

    // --- Events ---

    event TroveManagerAddressChanged(address _newTroveManagerAddress);
    event ActivePoolAddressChanged(address _activePoolAddress);
    event DefaultPoolAddressChanged(address _defaultPoolAddress);
    event StabilityPoolAddressChanged(address _stabilityPoolAddress);
    event GasPoolAddressChanged(address _gasPoolAddress);
    event CollSurplusPoolAddressChanged(address _collSurplusPoolAddress);
    event PriceFeedAddressChanged(address  _newPriceFeedAddress);
    event SortedTrovesAddressChanged(address _sortedTrovesAddress);
    event LUSDTokenAddressChanged(address _lusdTokenAddress);
    event LQTYStakingAddressChanged(address _lqtyStakingAddress);

    event TroveCreated(address indexed _borrower, uint arrayIndex);
    event TroveUpdated(address indexed _borrower, uint _debt, uint _coll, uint stake, uint8 operation);
    event LUSDBorrowingFeePaid(address indexed _borrower, uint _LUSDFee);

    // --- Functions ---

    function openTrove(uint _maxFee, uint _LUSDAmount, address _upperHint, address _lowerHint) external payable;

    function addColl(address _upperHint, address _lowerHint) external payable;

    function moveETHGainToTrove(address _user, address _upperHint, address _lowerHint) external payable;

    function withdrawColl(uint _amount, address _upperHint, address _lowerHint) external;

    function withdrawLUSD(uint _maxFee, uint _amount, address _upperHint, address _lowerHint) external;

    function repayLUSD(uint _amount, address _upperHint, address _lowerHint) external;

    function closeTrove() external;

    function adjustTrove(uint _maxFee, uint _collWithdrawal, uint _debtChange, bool isDebtIncrease, address _upperHint, address _lowerHint) external payable;

    function claimCollateral() external;

    function getCompositeDebt(uint _debt) external pure returns (uint);
}    



interface IPriceFeed {
    function lastGoodPrice() external pure returns (uint256);
}    



interface IHintHelpers {

    function getRedemptionHints(
        uint _LUSDamount, 
        uint _price,
        uint _maxIterations
    )
        external
        view
        returns (
            address firstRedemptionHint,
            uint partialRedemptionHintNICR,
            uint truncatedLUSDamount
        );

    function getApproxHint(uint _CR, uint _numTrials, uint _inputRandomSeed)
        external
        view
        returns (address hintAddress, uint diff, uint latestRandomSeed);

    function computeNominalCR(uint _coll, uint _debt) external pure returns (uint);

    function computeCR(uint _coll, uint _debt, uint _price) external pure returns (uint);
}    



// Common interface for the SortedTroves Doubly Linked List.
interface ISortedTroves {

    // --- Events ---
    
    event SortedTrovesAddressChanged(address _sortedDoublyLLAddress);
    event BorrowerOperationsAddressChanged(address _borrowerOperationsAddress);
    event NodeAdded(address _id, uint _NICR);
    event NodeRemoved(address _id);

    // --- Functions ---
    
    function setParams(uint256 _size, address _TroveManagerAddress, address _borrowerOperationsAddress) external;

    function insert(address _id, uint256 _ICR, address _prevId, address _nextId) external;

    function remove(address _id) external;

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

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

    function isFull() external view returns (bool);

    function isEmpty() external view returns (bool);

    function getSize() external view returns (uint256);

    function getMaxSize() external view returns (uint256);

    function getFirst() external view returns (address);

    function getLast() external view returns (address);

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

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

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

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


interface ICollSurplusPool {

    // --- Events ---
    
    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);
    event TroveManagerAddressChanged(address _newTroveManagerAddress);
    event ActivePoolAddressChanged(address _newActivePoolAddress);

    event CollBalanceUpdated(address indexed _account, uint _newBalance);
    event EtherSent(address _to, uint _amount);

    // --- Contract setters ---

    function setAddresses(
        address _borrowerOperationsAddress,
        address _troveManagerAddress,
        address _activePoolAddress
    ) external;

    function getETH() external view returns (uint);

    function getCollateral(address _account) external view returns (uint);

    function accountSurplus(address _account, uint _amount) external;

    function claimColl(address _account) external;
}    


interface IStabilityPool {

    // --- Events ---
    
    event StabilityPoolETHBalanceUpdated(uint _newBalance);
    event StabilityPoolLUSDBalanceUpdated(uint _newBalance);

    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);
    event TroveManagerAddressChanged(address _newTroveManagerAddress);
    event ActivePoolAddressChanged(address _newActivePoolAddress);
    event DefaultPoolAddressChanged(address _newDefaultPoolAddress);
    event LUSDTokenAddressChanged(address _newLUSDTokenAddress);
    event SortedTrovesAddressChanged(address _newSortedTrovesAddress);
    event PriceFeedAddressChanged(address _newPriceFeedAddress);
    event CommunityIssuanceAddressChanged(address _newCommunityIssuanceAddress);

    event P_Updated(uint _P);
    event S_Updated(uint _S, uint128 _epoch, uint128 _scale);
    event G_Updated(uint _G, uint128 _epoch, uint128 _scale);
    event EpochUpdated(uint128 _currentEpoch);
    event ScaleUpdated(uint128 _currentScale);

    event FrontEndRegistered(address indexed _frontEnd, uint _kickbackRate);
    event FrontEndTagSet(address indexed _depositor, address indexed _frontEnd);

    event DepositSnapshotUpdated(address indexed _depositor, uint _P, uint _S, uint _G);
    event FrontEndSnapshotUpdated(address indexed _frontEnd, uint _P, uint _G);
    event UserDepositChanged(address indexed _depositor, uint _newDeposit);
    event FrontEndStakeChanged(address indexed _frontEnd, uint _newFrontEndStake, address _depositor);

    event ETHGainWithdrawn(address indexed _depositor, uint _ETH, uint _LUSDLoss);
    event LQTYPaidToDepositor(address indexed _depositor, uint _LQTY);
    event LQTYPaidToFrontEnd(address indexed _frontEnd, uint _LQTY);
    event EtherSent(address _to, uint _amount);

    // --- Functions ---

    /*
     * Called only once on init, to set addresses of other Liquity contracts
     * Callable only by owner, renounces ownership at the end
     */
    function setAddresses(
        address _borrowerOperationsAddress,
        address _troveManagerAddress,
        address _activePoolAddress,
        address _lusdTokenAddress,
        address _sortedTrovesAddress,
        address _priceFeedAddress,
        address _communityIssuanceAddress
    ) external;

    /*
     * Initial checks:
     * - Frontend is registered or zero address
     * - Sender is not a registered frontend
     * - _amount is not zero
     * ---
     * - Triggers a LQTY issuance, based on time passed since the last issuance. The LQTY issuance is shared between *all* depositors and front ends
     * - Tags the deposit with the provided front end tag param, if it's a new deposit
     * - Sends depositor's accumulated gains (LQTY, ETH) to depositor
     * - Sends the tagged front end's accumulated LQTY gains to the tagged front end
     * - Increases deposit and tagged front end's stake, and takes new snapshots for each.
     */
    function provideToSP(uint _amount, address _frontEndTag) external;

    /*
     * Initial checks:
     * - _amount is zero or there are no under collateralized troves left in the system
     * - User has a non zero deposit
     * ---
     * - Triggers a LQTY issuance, based on time passed since the last issuance. The LQTY issuance is shared between *all* depositors and front ends
     * - Removes the deposit's front end tag if it is a full withdrawal
     * - Sends all depositor's accumulated gains (LQTY, ETH) to depositor
     * - Sends the tagged front end's accumulated LQTY gains to the tagged front end
     * - Decreases deposit and tagged front end's stake, and takes new snapshots for each.
     *
     * If _amount > userDeposit, the user withdraws all of their compounded deposit.
     */
    function withdrawFromSP(uint _amount) external;

    /*
     * Initial checks:
     * - User has a non zero deposit
     * - User has an open trove
     * - User has some ETH gain
     * ---
     * - Triggers a LQTY issuance, based on time passed since the last issuance. The LQTY issuance is shared between *all* depositors and front ends
     * - Sends all depositor's LQTY gain to  depositor
     * - Sends all tagged front end's LQTY gain to the tagged front end
     * - Transfers the depositor's entire ETH gain from the Stability Pool to the caller's trove
     * - Leaves their compounded deposit in the Stability Pool
     * - Updates snapshots for deposit and tagged front end stake
     */
    function withdrawETHGainToTrove(address _upperHint, address _lowerHint) external;

    /*
     * Initial checks:
     * - Frontend (sender) not already registered
     * - User (sender) has no deposit
     * - _kickbackRate is in the range [0, 100%]
     * ---
     * Front end makes a one-time selection of kickback rate upon registering
     */
    function registerFrontEnd(uint _kickbackRate) external;

    /*
     * Initial checks:
     * - Caller is TroveManager
     * ---
     * Cancels out the specified debt against the LUSD contained in the Stability Pool (as far as possible)
     * and transfers the Trove's ETH collateral from ActivePool to StabilityPool.
     * Only called by liquidation functions in the TroveManager.
     */
    function offset(uint _debt, uint _coll) external;

    /*
     * Returns the total amount of ETH held by the pool, accounted in an internal variable instead of `balance`,
     * to exclude edge cases like ETH received from a self-destruct.
     */
    function getETH() external view returns (uint);

    /*
     * Returns LUSD held in the pool. Changes when users deposit/withdraw, and when Trove debt is offset.
     */
    function getTotalLUSDDeposits() external view returns (uint);

    /*
     * Calculates the ETH gain earned by the deposit since its last snapshots were taken.
     */
    function getDepositorETHGain(address _depositor) external view returns (uint);

    /*
     * Calculate the LQTY gain earned by a deposit since its last snapshots were taken.
     * If not tagged with a front end, the depositor gets a 100% cut of what their deposit earned.
     * Otherwise, their cut of the deposit's earnings is equal to the kickbackRate, set by the front end through
     * which they made their deposit.
     */
    function getDepositorLQTYGain(address _depositor) external view returns (uint);

    /*
     * Return the LQTY gain earned by the front end.
     */
    function getFrontEndLQTYGain(address _frontEnd) external view returns (uint);

    /*
     * Return the user's compounded deposit.
     */
    function getCompoundedLUSDDeposit(address _depositor) external view returns (uint);

    /*
     * Return the front end's compounded stake.
     *
     * The front end's compounded stake is equal to the sum of its depositors' compounded deposits.
     */
    function getCompoundedFrontEndStake(address _frontEnd) external view returns (uint);
}    



interface ILQTYStaking {

    // --- Events --
    
    event LQTYTokenAddressSet(address _lqtyTokenAddress);
    event LUSDTokenAddressSet(address _lusdTokenAddress);
    event TroveManagerAddressSet(address _troveManager);
    event BorrowerOperationsAddressSet(address _borrowerOperationsAddress);
    event ActivePoolAddressSet(address _activePoolAddress);

    event StakeChanged(address indexed staker, uint newStake);
    event StakingGainsWithdrawn(address indexed staker, uint LUSDGain, uint ETHGain);
    event F_ETHUpdated(uint _F_ETH);
    event F_LUSDUpdated(uint _F_LUSD);
    event TotalLQTYStakedUpdated(uint _totalLQTYStaked);
    event EtherSent(address _account, uint _amount);
    event StakerSnapshotsUpdated(address _staker, uint _F_ETH, uint _F_LUSD);

    // --- Functions ---

    function setAddresses
    (
        address _lqtyTokenAddress,
        address _lusdTokenAddress,
        address _troveManagerAddress, 
        address _borrowerOperationsAddress,
        address _activePoolAddress
    )  external;

    function stake(uint _LQTYamount) external;

    function unstake(uint _LQTYamount) external;

    function increaseF_ETH(uint _ETHFee) external; 

    function increaseF_LUSD(uint _LQTYFee) external;  

    function getPendingETHGain(address _user) external view returns (uint);

    function getPendingLUSDGain(address _user) external view returns (uint);

    function stakes(address) external view returns (uint256);
}    













contract LiquityHelper {
    using TokenUtils for address;

    uint constant public LUSD_GAS_COMPENSATION = 200e18;
    address constant public LUSDTokenAddr = 0x5f98805A4E8be255a32880FDeC7F6728C6568bA0;
    address constant public LQTYTokenAddr = 0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D;
    address constant public PriceFeedAddr = 0x4c517D4e2C851CA76d7eC94B805269Df0f2201De;
    address constant public BorrowerOperationsAddr = 0x24179CD81c9e782A4096035f7eC97fB8B783e007;
    address constant public TroveManagerAddr = 0xA39739EF8b0231DbFA0DcdA07d7e29faAbCf4bb2;
    address constant public SortedTrovesAddr = 0x8FdD3fbFEb32b28fb73555518f8b361bCeA741A6;
    address constant public HintHelpersAddr = 0xE84251b93D9524E0d2e621Ba7dc7cb3579F997C0;
    address constant public CollSurplusPoolAddr = 0x3D32e8b97Ed5881324241Cf03b2DA5E2EBcE5521;
    address constant public StabilityPoolAddr = 0x66017D22b0f8556afDd19FC67041899Eb65a21bb;
    address constant public LQTYStakingAddr = 0x4f9Fbb3f1E99B56e0Fe2892e623Ed36A76Fc605d;
    address constant public LQTYFrontEndAddr = 0x76720aC2574631530eC8163e4085d6F98513fb27;

    IPriceFeed constant public PriceFeed = IPriceFeed(PriceFeedAddr);
    IBorrowerOperations constant public BorrowerOperations = IBorrowerOperations(BorrowerOperationsAddr);
    ITroveManager constant public TroveManager = ITroveManager(TroveManagerAddr);
    ISortedTroves constant public SortedTroves = ISortedTroves(SortedTrovesAddr);
    IHintHelpers constant public HintHelpers = IHintHelpers(HintHelpersAddr);
    ICollSurplusPool constant public CollSurplusPool = ICollSurplusPool(CollSurplusPoolAddr);
    IStabilityPool constant public StabilityPool = IStabilityPool(StabilityPoolAddr);
    ILQTYStaking constant public LQTYStaking = ILQTYStaking(LQTYStakingAddr);

    function withdrawStaking(uint256 _ethGain, uint256 _lusdGain, address _wethTo, address _lusdTo) internal {
        if (_ethGain > 0) {
            TokenUtils.depositWeth(_ethGain);
            TokenUtils.WETH_ADDR.withdrawTokens(_wethTo, _ethGain);
        }
        if (_lusdGain > 0) {
            LUSDTokenAddr.withdrawTokens(_lusdTo, _lusdGain);
        }
    }
    
    function withdrawStabilityGains(uint256 _ethGain, uint256 _lqtyGain, address _wethTo, address _lqtyTo) internal {
        if (_ethGain > 0) {
            TokenUtils.depositWeth(_ethGain);
            TokenUtils.WETH_ADDR.withdrawTokens(_wethTo, _ethGain);
        }      
        if (_lqtyGain > 0) {
            LQTYTokenAddr.withdrawTokens(_lqtyTo, _lqtyGain);
        }
    }
}    



abstract contract IDFSRegistry {
 
    function getAddr(bytes32 _id) public view virtual returns (address);

    function addNewContract(
        bytes32 _id,
        address _contractAddr,
        uint256 _waitPeriod
    ) public virtual;

    function startContractChange(bytes32 _id, address _newContractAddr) public virtual;

    function approveContractChange(bytes32 _id) public virtual;

    function cancelContractChange(bytes32 _id) public virtual;

    function changeWaitPeriod(bytes32 _id, uint256 _newWaitPeriod) public virtual;
}    



/// @title A stateful contract that holds and can change owner/admin
contract AdminVault {
    address public owner;
    address public admin;

    constructor() {
        owner = msg.sender;
        admin = 0x25eFA336886C74eA8E282ac466BdCd0199f85BB9;
    }

    /// @notice Admin is able to change owner
    /// @param _owner Address of new owner
    function changeOwner(address _owner) public {
        require(admin == msg.sender, "msg.sender not admin");
        owner = _owner;
    }

    /// @notice Admin is able to set new admin
    /// @param _admin Address of multisig that becomes new admin
    function changeAdmin(address _admin) public {
        require(admin == msg.sender, "msg.sender not admin");
        admin = _admin;
    }

}    








/// @title AdminAuth Handles owner/admin privileges over smart contracts
contract AdminAuth {
    using SafeERC20 for IERC20;

    address public constant ADMIN_VAULT_ADDR = 0xCCf3d848e08b94478Ed8f46fFead3008faF581fD;

    AdminVault public constant adminVault = AdminVault(ADMIN_VAULT_ADDR);

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

    modifier onlyAdmin() {
        require(adminVault.admin() == msg.sender, "msg.sender not admin");
        _;
    }

    /// @notice withdraw stuck funds
    function withdrawStuckFunds(address _token, address _receiver, uint256 _amount) public onlyOwner {
        if (_token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) {
            payable(_receiver).transfer(_amount);
        } else {
            IERC20(_token).safeTransfer(_receiver, _amount);
        }
    }

    /// @notice Destroy the contract
    function kill() public onlyAdmin {
        selfdestruct(payable(msg.sender));
    }
}    



contract DefisaverLogger {
    event LogEvent(
        address indexed contractAddress,
        address indexed caller,
        string indexed logName,
        bytes data
    );

    // solhint-disable-next-line func-name-mixedcase
    function Log(
        address _contract,
        address _caller,
        string memory _logName,
        bytes memory _data
    ) public {
        emit LogEvent(_contract, _caller, _logName, _data);
    }
}    






/// @title Stores all the important DFS addresses and can be changed (timelock)
contract DFSRegistry is AdminAuth {
    DefisaverLogger public constant logger = DefisaverLogger(
        0x5c55B921f590a89C1Ebe84dF170E655a82b62126
    );

    string public constant ERR_ENTRY_ALREADY_EXISTS = "Entry id already exists";
    string public constant ERR_ENTRY_NON_EXISTENT = "Entry id doesn't exists";
    string public constant ERR_ENTRY_NOT_IN_CHANGE = "Entry not in change process";
    string public constant ERR_WAIT_PERIOD_SHORTER = "New wait period must be bigger";
    string public constant ERR_CHANGE_NOT_READY = "Change not ready yet";
    string public constant ERR_EMPTY_PREV_ADDR = "Previous addr is 0";
    string public constant ERR_ALREADY_IN_CONTRACT_CHANGE = "Already in contract change";
    string public constant ERR_ALREADY_IN_WAIT_PERIOD_CHANGE = "Already in wait period change";

    struct Entry {
        address contractAddr;
        uint256 waitPeriod;
        uint256 changeStartTime;
        bool inContractChange;
        bool inWaitPeriodChange;
        bool exists;
    }

    mapping(bytes32 => Entry) public entries;
    mapping(bytes32 => address) public previousAddresses;

    mapping(bytes32 => address) public pendingAddresses;
    mapping(bytes32 => uint256) public pendingWaitTimes;

    /// @notice Given an contract id returns the registered address
    /// @dev Id is keccak256 of the contract name
    /// @param _id Id of contract
    function getAddr(bytes32 _id) public view returns (address) {
        return entries[_id].contractAddr;
    }

    /// @notice Helper function to easily query if id is registered
    /// @param _id Id of contract
    function isRegistered(bytes32 _id) public view returns (bool) {
        return entries[_id].exists;
    }

    /////////////////////////// OWNER ONLY FUNCTIONS ///////////////////////////

    /// @notice Adds a new contract to the registry
    /// @param _id Id of contract
    /// @param _contractAddr Address of the contract
    /// @param _waitPeriod Amount of time to wait before a contract address can be changed
    function addNewContract(
        bytes32 _id,
        address _contractAddr,
        uint256 _waitPeriod
    ) public onlyOwner {
        require(!entries[_id].exists, ERR_ENTRY_ALREADY_EXISTS);

        entries[_id] = Entry({
            contractAddr: _contractAddr,
            waitPeriod: _waitPeriod,
            changeStartTime: 0,
            inContractChange: false,
            inWaitPeriodChange: false,
            exists: true
        });

        // Remember tha address so we can revert back to old addr if needed
        previousAddresses[_id] = _contractAddr;

        logger.Log(
            address(this),
            msg.sender,
            "AddNewContract",
            abi.encode(_id, _contractAddr, _waitPeriod)
        );
    }

    /// @notice Reverts to the previous address immediately
    /// @dev In case the new version has a fault, a quick way to fallback to the old contract
    /// @param _id Id of contract
    function revertToPreviousAddress(bytes32 _id) public onlyOwner {
        require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT);
        require(previousAddresses[_id] != address(0), ERR_EMPTY_PREV_ADDR);

        address currentAddr = entries[_id].contractAddr;
        entries[_id].contractAddr = previousAddresses[_id];

        logger.Log(
            address(this),
            msg.sender,
            "RevertToPreviousAddress",
            abi.encode(_id, currentAddr, previousAddresses[_id])
        );
    }

    /// @notice Starts an address change for an existing entry
    /// @dev Can override a change that is currently in progress
    /// @param _id Id of contract
    /// @param _newContractAddr Address of the new contract
    function startContractChange(bytes32 _id, address _newContractAddr) public onlyOwner {
        require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT);
        require(!entries[_id].inWaitPeriodChange, ERR_ALREADY_IN_WAIT_PERIOD_CHANGE);

        entries[_id].changeStartTime = block.timestamp; // solhint-disable-line
        entries[_id].inContractChange = true;

        pendingAddresses[_id] = _newContractAddr;

        logger.Log(
            address(this),
            msg.sender,
            "StartContractChange",
            abi.encode(_id, entries[_id].contractAddr, _newContractAddr)
        );
    }

    /// @notice Changes new contract address, correct time must have passed
    /// @param _id Id of contract
    function approveContractChange(bytes32 _id) public onlyOwner {
        require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT);
        require(entries[_id].inContractChange, ERR_ENTRY_NOT_IN_CHANGE);
        require(
            block.timestamp >= (entries[_id].changeStartTime + entries[_id].waitPeriod), // solhint-disable-line
            ERR_CHANGE_NOT_READY
        );

        address oldContractAddr = entries[_id].contractAddr;
        entries[_id].contractAddr = pendingAddresses[_id];
        entries[_id].inContractChange = false;
        entries[_id].changeStartTime = 0;

        pendingAddresses[_id] = address(0);
        previousAddresses[_id] = oldContractAddr;

        logger.Log(
            address(this),
            msg.sender,
            "ApproveContractChange",
            abi.encode(_id, oldContractAddr, entries[_id].contractAddr)
        );
    }

    /// @notice Cancel pending change
    /// @param _id Id of contract
    function cancelContractChange(bytes32 _id) public onlyOwner {
        require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT);
        require(entries[_id].inContractChange, ERR_ENTRY_NOT_IN_CHANGE);

        address oldContractAddr = pendingAddresses[_id];

        pendingAddresses[_id] = address(0);
        entries[_id].inContractChange = false;
        entries[_id].changeStartTime = 0;

        logger.Log(
            address(this),
            msg.sender,
            "CancelContractChange",
            abi.encode(_id, oldContractAddr, entries[_id].contractAddr)
        );
    }

    /// @notice Starts the change for waitPeriod
    /// @param _id Id of contract
    /// @param _newWaitPeriod New wait time
    function startWaitPeriodChange(bytes32 _id, uint256 _newWaitPeriod) public onlyOwner {
        require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT);
        require(!entries[_id].inContractChange, ERR_ALREADY_IN_CONTRACT_CHANGE);

        pendingWaitTimes[_id] = _newWaitPeriod;

        entries[_id].changeStartTime = block.timestamp; // solhint-disable-line
        entries[_id].inWaitPeriodChange = true;

        logger.Log(
            address(this),
            msg.sender,
            "StartWaitPeriodChange",
            abi.encode(_id, _newWaitPeriod)
        );
    }

    /// @notice Changes new wait period, correct time must have passed
    /// @param _id Id of contract
    function approveWaitPeriodChange(bytes32 _id) public onlyOwner {
        require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT);
        require(entries[_id].inWaitPeriodChange, ERR_ENTRY_NOT_IN_CHANGE);
        require(
            block.timestamp >= (entries[_id].changeStartTime + entries[_id].waitPeriod), // solhint-disable-line
            ERR_CHANGE_NOT_READY
        );

        uint256 oldWaitTime = entries[_id].waitPeriod;
        entries[_id].waitPeriod = pendingWaitTimes[_id];
        
        entries[_id].inWaitPeriodChange = false;
        entries[_id].changeStartTime = 0;

        pendingWaitTimes[_id] = 0;

        logger.Log(
            address(this),
            msg.sender,
            "ApproveWaitPeriodChange",
            abi.encode(_id, oldWaitTime, entries[_id].waitPeriod)
        );
    }

    /// @notice Cancel wait period change
    /// @param _id Id of contract
    function cancelWaitPeriodChange(bytes32 _id) public onlyOwner {
        require(entries[_id].exists, ERR_ENTRY_NON_EXISTENT);
        require(entries[_id].inWaitPeriodChange, ERR_ENTRY_NOT_IN_CHANGE);

        uint256 oldWaitPeriod = pendingWaitTimes[_id];

        pendingWaitTimes[_id] = 0;
        entries[_id].inWaitPeriodChange = false;
        entries[_id].changeStartTime = 0;

        logger.Log(
            address(this),
            msg.sender,
            "CancelWaitPeriodChange",
            abi.encode(_id, oldWaitPeriod, entries[_id].waitPeriod)
        );
    }
}    






/// @title Implements Action interface and common helpers for passing inputs
abstract contract ActionBase is AdminAuth {
    address public constant REGISTRY_ADDR = 0xD6049E1F5F3EfF1F921f5532aF1A1632bA23929C;
    DFSRegistry public constant registry = DFSRegistry(REGISTRY_ADDR);

    DefisaverLogger public constant logger = DefisaverLogger(
        0x5c55B921f590a89C1Ebe84dF170E655a82b62126
    );

    string public constant ERR_SUB_INDEX_VALUE = "Wrong sub index value";
    string public constant ERR_RETURN_INDEX_VALUE = "Wrong return index value";

    /// @dev Subscription params index range [128, 255]
    uint8 public constant SUB_MIN_INDEX_VALUE = 128;
    uint8 public constant SUB_MAX_INDEX_VALUE = 255;

    /// @dev Return params index range [1, 127]
    uint8 public constant RETURN_MIN_INDEX_VALUE = 1;
    uint8 public constant RETURN_MAX_INDEX_VALUE = 127;

    /// @dev If the input value should not be replaced
    uint8 public constant NO_PARAM_MAPPING = 0;

    /// @dev We need to parse Flash loan actions in a different way
    enum ActionType { FL_ACTION, STANDARD_ACTION, CUSTOM_ACTION }

    /// @notice Parses inputs and runs the implemented action through a proxy
    /// @dev Is called by the TaskExecutor chaining actions together
    /// @param _callData Array of input values each value encoded as bytes
    /// @param _subData Array of subscribed vales, replaces input values if specified
    /// @param _paramMapping Array that specifies how return and subscribed values are mapped in input
    /// @param _returnValues Returns values from actions before, which can be injected in inputs
    /// @return Returns a bytes32 value through DSProxy, each actions implements what that value is
    function executeAction(
        bytes[] memory _callData,
        bytes[] memory _subData,
        uint8[] memory _paramMapping,
        bytes32[] memory _returnValues
    ) public payable virtual returns (bytes32);

    /// @notice Parses inputs and runs the single implemented action through a proxy
    /// @dev Used to save gas when executing a single action directly
    function executeActionDirect(bytes[] memory _callData) public virtual payable;

    /// @notice Returns the type of action we are implementing
    function actionType() public pure virtual returns (uint8);


    //////////////////////////// HELPER METHODS ////////////////////////////

    /// @notice Given an uint256 input, injects return/sub values if specified
    /// @param _param The original input value
    /// @param _mapType Indicated the type of the input in paramMapping
    /// @param _subData Array of subscription data we can replace the input value with
    /// @param _returnValues Array of subscription data we can replace the input value with
    function _parseParamUint(
        uint _param,
        uint8 _mapType,
        bytes[] memory _subData,
        bytes32[] memory _returnValues
    ) internal pure returns (uint) {
        if (isReplaceable(_mapType)) {
            if (isReturnInjection(_mapType)) {
                _param = uint(_returnValues[getReturnIndex(_mapType)]);
            } else {
                _param = abi.decode(_subData[getSubIndex(_mapType)], (uint));
            }
        }

        return _param;
    }


    /// @notice Given an addr input, injects return/sub values if specified
    /// @param _param The original input value
    /// @param _mapType Indicated the type of the input in paramMapping
    /// @param _subData Array of subscription data we can replace the input value with
    /// @param _returnValues Array of subscription data we can replace the input value with
    function _parseParamAddr(
        address _param,
        uint8 _mapType,
        bytes[] memory _subData,
        bytes32[] memory _returnValues
    ) internal pure returns (address) {
        if (isReplaceable(_mapType)) {
            if (isReturnInjection(_mapType)) {
                _param = address(bytes20((_returnValues[getReturnIndex(_mapType)])));
            } else {
                _param = abi.decode(_subData[getSubIndex(_mapType)], (address));
            }
        }

        return _param;
    }

    /// @notice Given an bytes32 input, injects return/sub values if specified
    /// @param _param The original input value
    /// @param _mapType Indicated the type of the input in paramMapping
    /// @param _subData Array of subscription data we can replace the input value with
    /// @param _returnValues Array of subscription data we can replace the input value with
    function _parseParamABytes32(
        bytes32 _param,
        uint8 _mapType,
        bytes[] memory _subData,
        bytes32[] memory _returnValues
    ) internal pure returns (bytes32) {
        if (isReplaceable(_mapType)) {
            if (isReturnInjection(_mapType)) {
                _param = (_returnValues[getReturnIndex(_mapType)]);
            } else {
                _param = abi.decode(_subData[getSubIndex(_mapType)], (bytes32));
            }
        }

        return _param;
    }

    /// @notice Checks if the paramMapping value indicated that we need to inject values
    /// @param _type Indicated the type of the input
    function isReplaceable(uint8 _type) internal pure returns (bool) {
        return _type != NO_PARAM_MAPPING;
    }

    /// @notice Checks if the paramMapping value is in the return value range
    /// @param _type Indicated the type of the input
    function isReturnInjection(uint8 _type) internal pure returns (bool) {
        return (_type >= RETURN_MIN_INDEX_VALUE) && (_type <= RETURN_MAX_INDEX_VALUE);
    }

    /// @notice Transforms the paramMapping value to the index in return array value
    /// @param _type Indicated the type of the input
    function getReturnIndex(uint8 _type) internal pure returns (uint8) {
        require(isReturnInjection(_type), ERR_SUB_INDEX_VALUE);

        return (_type - RETURN_MIN_INDEX_VALUE);
    }

    /// @notice Transforms the paramMapping value to the index in sub array value
    /// @param _type Indicated the type of the input
    function getSubIndex(uint8 _type) internal pure returns (uint8) {
        require(_type >= SUB_MIN_INDEX_VALUE, ERR_RETURN_INDEX_VALUE);

        return (_type - SUB_MIN_INDEX_VALUE);
    }
}    








contract LiquitySPWithdraw is ActionBase, LiquityHelper {
    using TokenUtils for address;
    using SafeMath for uint256;

    struct Params {
        uint256 lusdAmount; // Amount of LUSD tokens to withdraw
        address to;         // Address that will receive the tokens
        address wethTo;     // Address that will receive ETH(wrapped) gains
        address lqtyTo;     // Address that will receive LQTY token gains
    }

    /// @inheritdoc ActionBase
    function executeAction(
        bytes[] memory _callData,
        bytes[] memory _subData,
        uint8[] memory _paramMapping,
        bytes32[] memory _returnValues
    ) public payable virtual override returns (bytes32) {
        Params memory params = parseInputs(_callData);
        params.lusdAmount = _parseParamUint(params.lusdAmount, _paramMapping[0], _subData, _returnValues);
        params.to = _parseParamAddr(params.to, _paramMapping[1], _subData, _returnValues);
        params.wethTo = _parseParamAddr(params.wethTo, _paramMapping[2], _subData, _returnValues);
        params.lqtyTo = _parseParamAddr(params.lqtyTo, _paramMapping[3], _subData, _returnValues);

        params.lusdAmount = _liquitySPWithdraw(params);
        return bytes32(params.lusdAmount);
    }

    /// @inheritdoc ActionBase
    function executeActionDirect(bytes[] memory _callData) public payable virtual override {
        Params memory params = parseInputs(_callData);

        _liquitySPWithdraw(params);
    }

    /// @inheritdoc ActionBase
    function actionType() public pure virtual override returns (uint8) {
        return uint8(ActionType.STANDARD_ACTION);
    }

    //////////////////////////// ACTION LOGIC ////////////////////////////

    /// @notice Withdraws LUSD from the user's stability pool deposit
    function _liquitySPWithdraw(Params memory _params) internal returns (uint256) {
        uint256 ethGain = StabilityPool.getDepositorETHGain(address(this));
        uint256 lqtyBefore = LQTYTokenAddr.getBalance(address(this));

        uint256 deposit = StabilityPool.getCompoundedLUSDDeposit(address(this));
        _params.lusdAmount = deposit > _params.lusdAmount ? _params.lusdAmount : deposit;

        StabilityPool.withdrawFromSP(_params.lusdAmount);
        // Amount goes through min(amount, depositedAmount)
        LUSDTokenAddr.withdrawTokens(_params.to, _params.lusdAmount);

        uint256 lqtyGain = LQTYTokenAddr.getBalance(address(this)).sub(lqtyBefore);

        withdrawStabilityGains(ethGain, lqtyGain, _params.wethTo, _params.lqtyTo);

        logger.Log(
            address(this),
            msg.sender,
            "LiquitySPWithdraw",
            abi.encode(
                _params,
                ethGain,
                lqtyGain
            )
        );

        return _params.lusdAmount;
    }

    function parseInputs(bytes[] memory _callData) internal pure returns (Params memory params) {
        params = abi.decode(_callData[0], (Params));
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"ADMIN_VAULT_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BorrowerOperations","outputs":[{"internalType":"contract IBorrowerOperations","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BorrowerOperationsAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CollSurplusPool","outputs":[{"internalType":"contract ICollSurplusPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CollSurplusPoolAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_RETURN_INDEX_VALUE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERR_SUB_INDEX_VALUE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HintHelpers","outputs":[{"internalType":"contract IHintHelpers","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HintHelpersAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LQTYFrontEndAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LQTYStaking","outputs":[{"internalType":"contract ILQTYStaking","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LQTYStakingAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LQTYTokenAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LUSDTokenAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LUSD_GAS_COMPENSATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NO_PARAM_MAPPING","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PriceFeed","outputs":[{"internalType":"contract IPriceFeed","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PriceFeedAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REGISTRY_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RETURN_MAX_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RETURN_MIN_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUB_MAX_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUB_MIN_INDEX_VALUE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SortedTroves","outputs":[{"internalType":"contract ISortedTroves","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SortedTrovesAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"StabilityPool","outputs":[{"internalType":"contract IStabilityPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"StabilityPoolAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TroveManager","outputs":[{"internalType":"contract ITroveManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TroveManagerAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"actionType","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"adminVault","outputs":[{"internalType":"contract AdminVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"_callData","type":"bytes[]"},{"internalType":"bytes[]","name":"_subData","type":"bytes[]"},{"internalType":"uint8[]","name":"_paramMapping","type":"uint8[]"},{"internalType":"bytes32[]","name":"_returnValues","type":"bytes32[]"}],"name":"executeAction","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"_callData","type":"bytes[]"}],"name":"executeActionDirect","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"kill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"logger","outputs":[{"internalType":"contract DefisaverLogger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract DFSRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawStuckFunds","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50611940806100206000396000f3fe60806040526004361061021a5760003560e01c80637ae7743711610123578063c93a2c35116100ab578063e4dde9ab1161006f578063e4dde9ab1461038a578063e910afb214610450578063f24ccbfe14610472578063f5a8a7fc1461043b578063f8e2fb00146104875761021a565b8063c93a2c35146103fe578063ca5ff78014610413578063cd4709cb146103b4578063d3c2e7ed14610426578063da9fc0ea1461043b5761021a565b80638cedca71116100f25780638cedca71146103b457806394199016146103215780639864dcdd146103c9578063b15c40001461021f578063c579d490146103de5761021a565b80637ae774371461024a5780637b1039991461038a5780637b57d630146103365780638bcb62161461039f5761021a565b80634acd820e116101a6578063663b630911610175578063663b63091461036057806369a02818146103755780636b7ba7fe1461030c5780636ba2ea8f1461034b5780637a92236c146103755761021a565b80634acd820e1461030c578063567f8e25146103215780635915b3a414610336578063591938911461034b5761021a565b8063247492f8116101ed578063247492f8146102965780632650c57a146102ab5780632e86bbd8146102c05780632fa13cb8146102e257806341c0e1b5146102f75761021a565b806304d27a721461021f57806308b7fa311461024a5780630f2eee421461025f5780631afd15be14610281575b600080fd5b34801561022b57600080fd5b5061023461049c565b60405161024191906116a9565b60405180910390f35b34801561025657600080fd5b506102346104b4565b34801561026b57600080fd5b506102746104cc565b6040516102419190611876565b61029461028f366004611477565b6104d1565b005b3480156102a257600080fd5b506102746104ec565b3480156102b757600080fd5b506102346104f1565b3480156102cc57600080fd5b506102d5610509565b6040516102419190611734565b3480156102ee57600080fd5b50610274610516565b34801561030357600080fd5b5061029461051b565b34801561031857600080fd5b506102346105dc565b34801561032d57600080fd5b506102346105f4565b34801561034257600080fd5b5061023461060c565b34801561035757600080fd5b50610234610624565b34801561036c57600080fd5b5061023461063c565b34801561038157600080fd5b50610234610654565b34801561039657600080fd5b5061023461066c565b3480156103ab57600080fd5b50610274610684565b3480156103c057600080fd5b50610234610689565b3480156103d557600080fd5b506102746106a1565b3480156103ea57600080fd5b506102946103f9366004611437565b6106a6565b34801561040a57600080fd5b506102346107d0565b6102d56104213660046114aa565b6107e8565b34801561043257600080fd5b506102746108b8565b34801561044757600080fd5b506102346108bd565b34801561045c57600080fd5b506104656108d5565b604051610241919061173d565b34801561047e57600080fd5b50610234610909565b34801561049357600080fd5b50610465610921565b738fdd3fbfeb32b28fb73555518f8b361bcea741a681565b734c517d4e2c851ca76d7ec94b805269df0f2201de81565b608081565b60006104dc82610952565b90506104e781610988565b505050565b600190565b735f98805a4e8be255a32880fdec7f6728c6568ba081565b680ad78ebc5ac620000081565b600081565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561057257600080fd5b505afa158015610586573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105aa919061141b565b6001600160a01b0316146105d95760405162461bcd60e51b81526004016105d09061177e565b60405180910390fd5b33ff5b73e84251b93d9524e0d2e621ba7dc7cb3579f997c081565b7324179cd81c9e782a4096035f7ec97fb8b783e00781565b733d32e8b97ed5881324241cf03b2da5e2ebce552181565b7366017d22b0f8556afdd19fc67041899eb65a21bb81565b736dea81c8171d0ba574754ef6f8b412f2ed88c54d81565b73a39739ef8b0231dbfa0dcda07d7e29faabcf4bb281565b73d6049e1f5f3eff1f921f5532af1a1632ba23929c81565b600181565b73ccf3d848e08b94478ed8f46ffead3008faf581fd81565b607f81565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156106fd57600080fd5b505afa158015610711573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610735919061141b565b6001600160a01b03161461075b5760405162461bcd60e51b81526004016105d090611750565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03841614156107bc576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156107b6573d6000803e3d6000fd5b506104e7565b6104e76001600160a01b0384168383610c4c565b7376720ac2574631530ec8163e4085d6f98513fb2781565b6000806107f486610952565b905061081a81600001518560008151811061080b57fe5b60200260200101518786610ca2565b81526020810151845161084491908690600190811061083557fe5b60200260200101518786610d27565b6001600160a01b031660208201526040810151845161086b91908690600290811061083557fe5b6001600160a01b031660408201526060810151845161089291908690600390811061083557fe5b6001600160a01b031660608201526108a981610988565b9081905290505b949350505050565b60ff81565b734f9fbb3f1e99b56e0fe2892e623ed36a76fc605d81565b6040518060400160405280601881526020017757726f6e672072657475726e20696e6465782076616c756560401b81525081565b735c55b921f590a89c1ebe84df170e655a82b6212681565b6040518060400160405280601581526020017457726f6e672073756220696e6465782076616c756560581b81525081565b61095a6112d3565b8160008151811061096757fe5b602002602001015180602001905181019061098291906115d4565b92915050565b60405163389e92a560e01b815260009081907366017d22b0f8556afdd19fc67041899eb65a21bb9063389e92a5906109c49030906004016116a9565b60206040518083038186803b1580156109dc57600080fd5b505afa1580156109f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a149190611649565b90506000610a36736dea81c8171d0ba574754ef6f8b412f2ed88c54d30610da0565b604051621cdc4760e81b81529091506000907366017d22b0f8556afdd19fc67041899eb65a21bb90631cdc470090610a729030906004016116a9565b60206040518083038186803b158015610a8a57600080fd5b505afa158015610a9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac29190611649565b85519091508111610ad35780610ad6565b84515b808652604051632e54bf9560e01b81527366017d22b0f8556afdd19fc67041899eb65a21bb91632e54bf9591610b0f9190600401611734565b600060405180830381600087803b158015610b2957600080fd5b505af1158015610b3d573d6000803e3d6000fd5b5050505060208501518551610b6791735f98805a4e8be255a32880fdec7f6728c6568ba091610e5b565b506000610b9283610b8c736dea81c8171d0ba574754ef6f8b412f2ed88c54d30610da0565b90610f21565b9050610ba8848288604001518960600151610f63565b735c55b921f590a89c1ebe84df170e655a82b621266001600160a01b031663d061ce503033898886604051602001610be29392919061182d565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401610c0f939291906116bd565b600060405180830381600087803b158015610c2957600080fd5b505af1158015610c3d573d6000803e3d6000fd5b50509651979650505050505050565b6104e78363a9059cbb60e01b8484604051602401610c6b92919061171b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610fc0565b6000610cad8461104f565b15610d1e57610cbb84611057565b15610ce95781610cca85611076565b60ff1681518110610cd757fe5b602002602001015160001c9450610d1e565b82610cf3856110d6565b60ff1681518110610d0057fe5b6020026020010151806020019051810190610d1b9190611649565b94505b50929392505050565b6000610d328461104f565b15610d1e57610d4084611057565b15610d6e5781610d4f85611076565b60ff1681518110610d5c57fe5b602002602001015160601c9450610d1e565b82610d78856110d6565b60ff1681518110610d8557fe5b6020026020010151806020019051810190610d1b919061141b565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415610dd857506001600160a01b03811631610982565b6040516370a0823160e01b81526001600160a01b038416906370a0823190610e049085906004016116a9565b60206040518083038186803b158015610e1c57600080fd5b505afa158015610e30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e549190611649565b9392505050565b6000600019821415610e7457610e718430610da0565b91505b6001600160a01b03831615801590610e9557506001600160a01b0383163014155b8015610ea057508115155b15610f1a576001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610ee257610edd6001600160a01b0385168484610c4c565b610f1a565b6040516001600160a01b0384169083156108fc029084906000818181858888f19350505050158015610f18573d6000803e3d6000fd5b505b5092915050565b6000610e5483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611136565b8315610f9357610f7284611162565b610f9173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28386610e5b565b505b8215610fba57610fb8736dea81c8171d0ba574754ef6f8b412f2ed88c54d8285610e5b565b505b50505050565b6000611015826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166111cd9092919063ffffffff16565b8051909150156104e7578080602001905181019061103391906115b4565b6104e75760405162461bcd60e51b81526004016105d0906117e3565b60ff16151590565b6000600160ff831610801590610982575050607f60ff91909116111590565b600061108182611057565b6040518060400160405280601581526020017457726f6e672073756220696e6465782076616c756560581b815250906110cd5760405162461bcd60e51b81526004016105d0919061173d565b50506000190190565b60408051808201909152601881527757726f6e672072657475726e20696e6465782076616c756560401b6020820152600090608060ff8416101561112d5760405162461bcd60e51b81526004016105d0919061173d565b5050607f190190565b6000818484111561115a5760405162461bcd60e51b81526004016105d0919061173d565b505050900390565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156111b157600080fd5b505af11580156111c5573d6000803e3d6000fd5b505050505050565b60606108b0848460008560606111e28561129a565b6111fe5760405162461bcd60e51b81526004016105d0906117ac565b600080866001600160a01b0316858760405161121a919061168d565b60006040518083038185875af1925050503d8060008114611257576040519150601f19603f3d011682016040523d82523d6000602084013e61125c565b606091505b509150915081156112705791506108b09050565b8051156112805780518082602001fd5b8360405162461bcd60e51b81526004016105d0919061173d565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906108b0575050151592915050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b600082601f83011261130a578081fd5b8135602061131f61131a836118a8565b611884565b828152818101908583018385028701840188101561133b578586fd5b855b858110156113595781358452928401929084019060010161133d565b5090979650505050505050565b6000601f8381840112611377578182fd5b8235602061138761131a836118a8565b82815281810190868301865b8581101561140d57813589018a603f8201126113ad578889fd5b85810135604067ffffffffffffffff8211156113c557fe5b6113d6828b01601f19168901611884565b8281528d828486010111156113e9578b8cfd5b828285018a83013791820188018b9052508552509284019290840190600101611393565b509098975050505050505050565b60006020828403121561142c578081fd5b8151610e54816118f2565b60008060006060848603121561144b578182fd5b8335611456816118f2565b92506020840135611466816118f2565b929592945050506040919091013590565b600060208284031215611488578081fd5b813567ffffffffffffffff81111561149e578182fd5b6108b084828501611366565b600080600080608085870312156114bf578081fd5b843567ffffffffffffffff808211156114d6578283fd5b6114e288838901611366565b95506020915081870135818111156114f8578384fd5b61150489828a01611366565b955050604087013581811115611518578384fd5b8701601f81018913611528578384fd5b803561153661131a826118a8565b81815284810190838601868402850187018d1015611552578788fd5b8794505b8385101561158257803560ff8116811461156e578889fd5b835260019490940193918601918601611556565b509650505050606087013591508082111561159b578283fd5b506115a8878288016112fa565b91505092959194509250565b6000602082840312156115c5578081fd5b81518015158114610e54578182fd5b6000608082840312156115e5578081fd5b6040516080810181811067ffffffffffffffff8211171561160257fe5b604052825181526020830151611617816118f2565b6020820152604083015161162a816118f2565b6040820152606083015161163d816118f2565b60608201529392505050565b60006020828403121561165a578081fd5b5051919050565b600081518084526116798160208601602086016118c6565b601f01601f19169290920160200192915050565b6000825161169f8184602087016118c6565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03848116825283166020820152608060408201819052601190820152704c6971756974795350576974686472617760781b60a082015260c06060820181905260009061171290830184611661565b95945050505050565b6001600160a01b03929092168252602082015260400190565b90815260200190565b600060208252610e546020830184611661565b60208082526014908201527336b9b39739b2b73232b9103737ba1037bbb732b960611b604082015260600190565b60208082526014908201527336b9b39739b2b73232b9103737ba1030b236b4b760611b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b835181526020808501516001600160a01b03908116918301919091526040808601518216908301526060948501511693810193909352608083019190915260a082015260c00190565b60ff91909116815260200190565b60405181810167ffffffffffffffff811182821017156118a057fe5b604052919050565b600067ffffffffffffffff8211156118bc57fe5b5060209081020190565b60005b838110156118e15781810151838201526020016118c9565b83811115610fba5750506000910152565b6001600160a01b038116811461190757600080fd5b5056fea2646970667358221220965400530ce9f7eb9468744103101cf1a730c9663d3046130ceadadcb5c99c9164736f6c63430007060033

Deployed Bytecode

0x60806040526004361061021a5760003560e01c80637ae7743711610123578063c93a2c35116100ab578063e4dde9ab1161006f578063e4dde9ab1461038a578063e910afb214610450578063f24ccbfe14610472578063f5a8a7fc1461043b578063f8e2fb00146104875761021a565b8063c93a2c35146103fe578063ca5ff78014610413578063cd4709cb146103b4578063d3c2e7ed14610426578063da9fc0ea1461043b5761021a565b80638cedca71116100f25780638cedca71146103b457806394199016146103215780639864dcdd146103c9578063b15c40001461021f578063c579d490146103de5761021a565b80637ae774371461024a5780637b1039991461038a5780637b57d630146103365780638bcb62161461039f5761021a565b80634acd820e116101a6578063663b630911610175578063663b63091461036057806369a02818146103755780636b7ba7fe1461030c5780636ba2ea8f1461034b5780637a92236c146103755761021a565b80634acd820e1461030c578063567f8e25146103215780635915b3a414610336578063591938911461034b5761021a565b8063247492f8116101ed578063247492f8146102965780632650c57a146102ab5780632e86bbd8146102c05780632fa13cb8146102e257806341c0e1b5146102f75761021a565b806304d27a721461021f57806308b7fa311461024a5780630f2eee421461025f5780631afd15be14610281575b600080fd5b34801561022b57600080fd5b5061023461049c565b60405161024191906116a9565b60405180910390f35b34801561025657600080fd5b506102346104b4565b34801561026b57600080fd5b506102746104cc565b6040516102419190611876565b61029461028f366004611477565b6104d1565b005b3480156102a257600080fd5b506102746104ec565b3480156102b757600080fd5b506102346104f1565b3480156102cc57600080fd5b506102d5610509565b6040516102419190611734565b3480156102ee57600080fd5b50610274610516565b34801561030357600080fd5b5061029461051b565b34801561031857600080fd5b506102346105dc565b34801561032d57600080fd5b506102346105f4565b34801561034257600080fd5b5061023461060c565b34801561035757600080fd5b50610234610624565b34801561036c57600080fd5b5061023461063c565b34801561038157600080fd5b50610234610654565b34801561039657600080fd5b5061023461066c565b3480156103ab57600080fd5b50610274610684565b3480156103c057600080fd5b50610234610689565b3480156103d557600080fd5b506102746106a1565b3480156103ea57600080fd5b506102946103f9366004611437565b6106a6565b34801561040a57600080fd5b506102346107d0565b6102d56104213660046114aa565b6107e8565b34801561043257600080fd5b506102746108b8565b34801561044757600080fd5b506102346108bd565b34801561045c57600080fd5b506104656108d5565b604051610241919061173d565b34801561047e57600080fd5b50610234610909565b34801561049357600080fd5b50610465610921565b738fdd3fbfeb32b28fb73555518f8b361bcea741a681565b734c517d4e2c851ca76d7ec94b805269df0f2201de81565b608081565b60006104dc82610952565b90506104e781610988565b505050565b600190565b735f98805a4e8be255a32880fdec7f6728c6568ba081565b680ad78ebc5ac620000081565b600081565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561057257600080fd5b505afa158015610586573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105aa919061141b565b6001600160a01b0316146105d95760405162461bcd60e51b81526004016105d09061177e565b60405180910390fd5b33ff5b73e84251b93d9524e0d2e621ba7dc7cb3579f997c081565b7324179cd81c9e782a4096035f7ec97fb8b783e00781565b733d32e8b97ed5881324241cf03b2da5e2ebce552181565b7366017d22b0f8556afdd19fc67041899eb65a21bb81565b736dea81c8171d0ba574754ef6f8b412f2ed88c54d81565b73a39739ef8b0231dbfa0dcda07d7e29faabcf4bb281565b73d6049e1f5f3eff1f921f5532af1a1632ba23929c81565b600181565b73ccf3d848e08b94478ed8f46ffead3008faf581fd81565b607f81565b336001600160a01b031673ccf3d848e08b94478ed8f46ffead3008faf581fd6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156106fd57600080fd5b505afa158015610711573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610735919061141b565b6001600160a01b03161461075b5760405162461bcd60e51b81526004016105d090611750565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b03841614156107bc576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156107b6573d6000803e3d6000fd5b506104e7565b6104e76001600160a01b0384168383610c4c565b7376720ac2574631530ec8163e4085d6f98513fb2781565b6000806107f486610952565b905061081a81600001518560008151811061080b57fe5b60200260200101518786610ca2565b81526020810151845161084491908690600190811061083557fe5b60200260200101518786610d27565b6001600160a01b031660208201526040810151845161086b91908690600290811061083557fe5b6001600160a01b031660408201526060810151845161089291908690600390811061083557fe5b6001600160a01b031660608201526108a981610988565b9081905290505b949350505050565b60ff81565b734f9fbb3f1e99b56e0fe2892e623ed36a76fc605d81565b6040518060400160405280601881526020017757726f6e672072657475726e20696e6465782076616c756560401b81525081565b735c55b921f590a89c1ebe84df170e655a82b6212681565b6040518060400160405280601581526020017457726f6e672073756220696e6465782076616c756560581b81525081565b61095a6112d3565b8160008151811061096757fe5b602002602001015180602001905181019061098291906115d4565b92915050565b60405163389e92a560e01b815260009081907366017d22b0f8556afdd19fc67041899eb65a21bb9063389e92a5906109c49030906004016116a9565b60206040518083038186803b1580156109dc57600080fd5b505afa1580156109f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a149190611649565b90506000610a36736dea81c8171d0ba574754ef6f8b412f2ed88c54d30610da0565b604051621cdc4760e81b81529091506000907366017d22b0f8556afdd19fc67041899eb65a21bb90631cdc470090610a729030906004016116a9565b60206040518083038186803b158015610a8a57600080fd5b505afa158015610a9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac29190611649565b85519091508111610ad35780610ad6565b84515b808652604051632e54bf9560e01b81527366017d22b0f8556afdd19fc67041899eb65a21bb91632e54bf9591610b0f9190600401611734565b600060405180830381600087803b158015610b2957600080fd5b505af1158015610b3d573d6000803e3d6000fd5b5050505060208501518551610b6791735f98805a4e8be255a32880fdec7f6728c6568ba091610e5b565b506000610b9283610b8c736dea81c8171d0ba574754ef6f8b412f2ed88c54d30610da0565b90610f21565b9050610ba8848288604001518960600151610f63565b735c55b921f590a89c1ebe84df170e655a82b621266001600160a01b031663d061ce503033898886604051602001610be29392919061182d565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401610c0f939291906116bd565b600060405180830381600087803b158015610c2957600080fd5b505af1158015610c3d573d6000803e3d6000fd5b50509651979650505050505050565b6104e78363a9059cbb60e01b8484604051602401610c6b92919061171b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610fc0565b6000610cad8461104f565b15610d1e57610cbb84611057565b15610ce95781610cca85611076565b60ff1681518110610cd757fe5b602002602001015160001c9450610d1e565b82610cf3856110d6565b60ff1681518110610d0057fe5b6020026020010151806020019051810190610d1b9190611649565b94505b50929392505050565b6000610d328461104f565b15610d1e57610d4084611057565b15610d6e5781610d4f85611076565b60ff1681518110610d5c57fe5b602002602001015160601c9450610d1e565b82610d78856110d6565b60ff1681518110610d8557fe5b6020026020010151806020019051810190610d1b919061141b565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415610dd857506001600160a01b03811631610982565b6040516370a0823160e01b81526001600160a01b038416906370a0823190610e049085906004016116a9565b60206040518083038186803b158015610e1c57600080fd5b505afa158015610e30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e549190611649565b9392505050565b6000600019821415610e7457610e718430610da0565b91505b6001600160a01b03831615801590610e9557506001600160a01b0383163014155b8015610ea057508115155b15610f1a576001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610ee257610edd6001600160a01b0385168484610c4c565b610f1a565b6040516001600160a01b0384169083156108fc029084906000818181858888f19350505050158015610f18573d6000803e3d6000fd5b505b5092915050565b6000610e5483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611136565b8315610f9357610f7284611162565b610f9173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28386610e5b565b505b8215610fba57610fb8736dea81c8171d0ba574754ef6f8b412f2ed88c54d8285610e5b565b505b50505050565b6000611015826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166111cd9092919063ffffffff16565b8051909150156104e7578080602001905181019061103391906115b4565b6104e75760405162461bcd60e51b81526004016105d0906117e3565b60ff16151590565b6000600160ff831610801590610982575050607f60ff91909116111590565b600061108182611057565b6040518060400160405280601581526020017457726f6e672073756220696e6465782076616c756560581b815250906110cd5760405162461bcd60e51b81526004016105d0919061173d565b50506000190190565b60408051808201909152601881527757726f6e672072657475726e20696e6465782076616c756560401b6020820152600090608060ff8416101561112d5760405162461bcd60e51b81526004016105d0919061173d565b5050607f190190565b6000818484111561115a5760405162461bcd60e51b81526004016105d0919061173d565b505050900390565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156111b157600080fd5b505af11580156111c5573d6000803e3d6000fd5b505050505050565b60606108b0848460008560606111e28561129a565b6111fe5760405162461bcd60e51b81526004016105d0906117ac565b600080866001600160a01b0316858760405161121a919061168d565b60006040518083038185875af1925050503d8060008114611257576040519150601f19603f3d011682016040523d82523d6000602084013e61125c565b606091505b509150915081156112705791506108b09050565b8051156112805780518082602001fd5b8360405162461bcd60e51b81526004016105d0919061173d565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906108b0575050151592915050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b600082601f83011261130a578081fd5b8135602061131f61131a836118a8565b611884565b828152818101908583018385028701840188101561133b578586fd5b855b858110156113595781358452928401929084019060010161133d565b5090979650505050505050565b6000601f8381840112611377578182fd5b8235602061138761131a836118a8565b82815281810190868301865b8581101561140d57813589018a603f8201126113ad578889fd5b85810135604067ffffffffffffffff8211156113c557fe5b6113d6828b01601f19168901611884565b8281528d828486010111156113e9578b8cfd5b828285018a83013791820188018b9052508552509284019290840190600101611393565b509098975050505050505050565b60006020828403121561142c578081fd5b8151610e54816118f2565b60008060006060848603121561144b578182fd5b8335611456816118f2565b92506020840135611466816118f2565b929592945050506040919091013590565b600060208284031215611488578081fd5b813567ffffffffffffffff81111561149e578182fd5b6108b084828501611366565b600080600080608085870312156114bf578081fd5b843567ffffffffffffffff808211156114d6578283fd5b6114e288838901611366565b95506020915081870135818111156114f8578384fd5b61150489828a01611366565b955050604087013581811115611518578384fd5b8701601f81018913611528578384fd5b803561153661131a826118a8565b81815284810190838601868402850187018d1015611552578788fd5b8794505b8385101561158257803560ff8116811461156e578889fd5b835260019490940193918601918601611556565b509650505050606087013591508082111561159b578283fd5b506115a8878288016112fa565b91505092959194509250565b6000602082840312156115c5578081fd5b81518015158114610e54578182fd5b6000608082840312156115e5578081fd5b6040516080810181811067ffffffffffffffff8211171561160257fe5b604052825181526020830151611617816118f2565b6020820152604083015161162a816118f2565b6040820152606083015161163d816118f2565b60608201529392505050565b60006020828403121561165a578081fd5b5051919050565b600081518084526116798160208601602086016118c6565b601f01601f19169290920160200192915050565b6000825161169f8184602087016118c6565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03848116825283166020820152608060408201819052601190820152704c6971756974795350576974686472617760781b60a082015260c06060820181905260009061171290830184611661565b95945050505050565b6001600160a01b03929092168252602082015260400190565b90815260200190565b600060208252610e546020830184611661565b60208082526014908201527336b9b39739b2b73232b9103737ba1037bbb732b960611b604082015260600190565b60208082526014908201527336b9b39739b2b73232b9103737ba1030b236b4b760611b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b835181526020808501516001600160a01b03908116918301919091526040808601518216908301526060948501511693810193909352608083019190915260a082015260c00190565b60ff91909116815260200190565b60405181810167ffffffffffffffff811182821017156118a057fe5b604052919050565b600067ffffffffffffffff8211156118bc57fe5b5060209081020190565b60005b838110156118e15781810151838201526020016118c9565b83811115610fba5750506000910152565b6001600160a01b038116811461190757600080fd5b5056fea2646970667358221220965400530ce9f7eb9468744103101cf1a730c9663d3046130ceadadcb5c99c9164736f6c63430007060033

Deployed Bytecode Sourcemap

50407:3049:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30440:85;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;30996:64;;;;;;;;;;;;;:::i;44606:47::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;51725:190::-;;;;;;:::i;:::-;;:::i;:::-;;51955:126;;;;;;;;;;;;;:::i;29983:82::-;;;;;;;;;;;;;:::i;29925:51::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;44935:42::-;;;;;;;;;;;;;:::i;34789:85::-;;;;;;;;;;;;;:::i;31340:72::-;;;;;;;;;;;;;:::i;30250:91::-;;;;;;;;;;;;;:::i;31419:88::-;;;;;;;;;;;;;:::i;30718:86::-;;;;;;;;;;;;;:::i;30072:82::-;;;;;;;;;;;;;:::i;31174:76::-;;;;;;;;;;;;;:::i;44192:65::-;;;;;;;;;;;;;:::i;44765:48::-;;;;;;;;;;;;;:::i;34062:68::-;;;;;;;;;;;;;:::i;44820:50::-;;;;;;;;;;;;;:::i;34427:316::-;;;;;;;;;;-1:-1:-1;34427:316:0;;;;;:::i;:::-;;:::i;30902:85::-;;;;;;;;;;;;;:::i;50889:796::-;;;;;;:::i;:::-;;:::i;44660:47::-;;;;;;;;;;;;;:::i;30811:84::-;;;;;;;;;;;;;:::i;44466:74::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;44266:116::-;;;;;;;;;;;;;:::i;44391:68::-;;;;;;;;;;;;;:::i;30440:85::-;30483:42;30440:85;:::o;30996:64::-;30201:42;30996:64;:::o;44606:47::-;44650:3;44606:47;:::o;51725:190::-;51823:20;51846:22;51858:9;51846:11;:22::i;:::-;51823:45;;51881:26;51900:6;51881:18;:26::i;:::-;;51725:190;;:::o;51955:126::-;52046:26;;51955:126::o;29983:82::-;30023:42;29983:82;:::o;29925:51::-;29970:6;29925:51;:::o;44935:42::-;44976:1;44935:42;:::o;34789:85::-;34326:10;-1:-1:-1;;;;;34304:32:0;34011:42;-1:-1:-1;;;;;34304:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;34304:32:0;;34296:65;;;;-1:-1:-1;;;34296:65:0;;;;;;;:::i;:::-;;;;;;;;;34854:10:::1;34833:33;31340:72:::0;30574:42;31340:72;:::o;30250:91::-;30299:42;30250:91;:::o;31419:88::-;30669:42;31419:88;:::o;30718:86::-;30762:42;30718:86;:::o;30072:82::-;30112:42;30072:82;:::o;31174:76::-;30391:42;31174:76;:::o;44192:65::-;44143:42;44192:65;:::o;44765:48::-;44812:1;44765:48;:::o;34062:68::-;34011:42;34062:68;:::o;44820:50::-;44867:3;44820:50;:::o;34427:316::-;34201:10;-1:-1:-1;;;;;34179:32:0;34011:42;-1:-1:-1;;;;;34179:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;34179:32:0;;34171:65;;;;-1:-1:-1;;;34171:65:0;;;;;;;:::i;:::-;34549:42:::1;-1:-1:-1::0;;;;;34539:52:0;::::1;;34535:201;;;34608:36;::::0;-1:-1:-1;;;;;34608:27:0;::::1;::::0;:36;::::1;;;::::0;34636:7;;34608:36:::1;::::0;;;34636:7;34608:27;:36;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;34535:201;;;34677:47;-1:-1:-1::0;;;;;34677:27:0;::::1;34705:9:::0;34716:7;34677:27:::1;:47::i;30902:85::-:0;30945:42;30902:85;:::o;50889:796::-;51109:7;51129:20;51152:22;51164:9;51152:11;:22::i;:::-;51129:45;;51205:77;51221:6;:17;;;51240:13;51254:1;51240:16;;;;;;;;;;;;;;51258:8;51268:13;51205:15;:77::i;:::-;51185:97;;51321:9;;;;51332:16;;51305:69;;51321:9;51332:13;;51346:1;;51332:16;;;;;;;;;;;;51350:8;51360:13;51305:15;:69::i;:::-;-1:-1:-1;;;;;51293:81:0;:9;;;:81;51417:13;;;;51432:16;;51401:73;;51417:13;51432;;51446:1;;51432:16;;;;;51401:73;-1:-1:-1;;;;;51385:89:0;:13;;;:89;51517:13;;;;51532:16;;51501:73;;51517:13;51532;;51546:1;;51532:16;;;;;51501:73;-1:-1:-1;;;;;51485:89:0;:13;;;:89;51607:26;51485:6;51607:18;:26::i;:::-;51587:46;;;;;-1:-1:-1;50889:796:0;;;;;;;:::o;44660:47::-;44704:3;44660:47;:::o;30811:84::-;30853:42;30811:84;:::o;44466:74::-;;;;;;;;;;;;;;-1:-1:-1;;;44466:74:0;;;;:::o;44266:116::-;44333:42;44266:116;:::o;44391:68::-;;;;;;;;;;;;;;-1:-1:-1;;;44391:68:0;;;;:::o;53299:154::-;53369:20;;:::i;:::-;53422:9;53432:1;53422:12;;;;;;;;;;;;;;53411:34;;;;;;;;;;;;:::i;:::-;53402:43;53299:154;-1:-1:-1;;53299:154:0:o;52238:1053::-;52345:48;;-1:-1:-1;;;52345:48:0;;52307:7;;;;30762:42;;52345:33;;:48;;52387:4;;52345:48;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;52327:66;-1:-1:-1;52404:18:0;52425:39;30112:42;52458:4;52425:24;:39::i;:::-;52495:53;;-1:-1:-1;;;52495:53:0;;52404:60;;-1:-1:-1;52477:15:0;;30762:42;;52495:38;;:53;;52542:4;;52495:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;52590:18;;52477:71;;-1:-1:-1;52580:28:0;;:59;;52632:7;52580:59;;;52611:18;;52580:59;52559:80;;;52652:48;;-1:-1:-1;;;52652:48:0;;30762:42;;52652:28;;:48;;52559:80;52652:48;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;52801:10:0;;;;52813:18;;52772:60;;30023:42;;52772:28;:60::i;:::-;-1:-1:-1;52845:16:0;52864:55;52908:10;52864:39;30112:42;52897:4;52864:24;:39::i;:::-;:43;;:55::i;:::-;52845:74;;52932:73;52955:7;52964:8;52974:7;:14;;;52990:7;:14;;;52932:22;:73::i;:::-;44333:42;-1:-1:-1;;;;;53018:10:0;;53051:4;53071:10;53159:7;53185;53211:8;53130:104;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;53018:227;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;53265:18:0;;;52238:1053;-1:-1:-1;;;;;;;52238:1053:0:o;6578:211::-;6695:86;6715:5;6745:23;;;6770:2;6774:5;6722:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;6722:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;6722:58:0;-1:-1:-1;;;;;;6722:58:0;;;;;;;;;;6695:19;:86::i;46804:505::-;46981:4;47002:23;47016:8;47002:13;:23::i;:::-;46998:278;;;47046:27;47064:8;47046:17;:27::i;:::-;47042:223;;;47108:13;47122:24;47137:8;47122:14;:24::i;:::-;47108:39;;;;;;;;;;;;;;;;47103:45;;47094:54;;47042:223;;;47209:8;47218:21;47230:8;47218:11;:21::i;:::-;47209:31;;;;;;;;;;;;;;;;47198:51;;;;;;;;;;;;:::i;:::-;47189:60;;47042:223;-1:-1:-1;47295:6:0;;46804:505;-1:-1:-1;;;46804:505:0:o;47698:528::-;47878:7;47902:23;47916:8;47902:13;:23::i;:::-;47898:295;;;47946:27;47964:8;47946:17;:27::i;:::-;47942:240;;;48020:13;48034:24;48049:8;48034:14;:24::i;:::-;48020:39;;;;;;;;;;;;;;;;48003:59;;47994:68;;47942:240;;;48123:8;48132:21;48144:8;48132:11;:21::i;:::-;48123:31;;;;;;;;;;;;;;;;48112:54;;;;;;;;;;;;:::i;10668:252::-;10745:7;-1:-1:-1;;;;;10769:22:0;;8998:42;10769:22;10765:148;;;-1:-1:-1;;;;;;10815:12:0;;;10808:19;;10765:148;10867:34;;-1:-1:-1;;;10867:34:0;;-1:-1:-1;;;;;10867:28:0;;;;;:34;;10896:4;;10867:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10860:41;10668:252;-1:-1:-1;;;10668:252:0:o;9883:552::-;10005:7;-1:-1:-1;;10029:7:0;:28;10025:104;;;10084:33;10095:6;10111:4;10084:10;:33::i;:::-;10074:43;;10025:104;-1:-1:-1;;;;;10145:17:0;;;;;;:41;;-1:-1:-1;;;;;;10166:20:0;;10181:4;10166:20;;10145:41;:57;;;;-1:-1:-1;10190:12:0;;;10145:57;10141:260;;;-1:-1:-1;;;;;10223:18:0;;8998:42;10223:18;10219:171;;10262:41;-1:-1:-1;;;;;10262:27:0;;10290:3;10295:7;10262:27;:41::i;:::-;10219:171;;;10344:30;;-1:-1:-1;;;;;10344:21:0;;;:30;;;;;10366:7;;10344:30;;;;10366:7;10344:21;:30;;;;;;;;;;;;;;;;;;;;;10219:171;-1:-1:-1;10420:7:0;9883:552;-1:-1:-1;;9883:552:0:o;4808:136::-;4866:7;4893:43;4897:1;4900;4893:43;;;;;;;;;;;;;;;;;:3;:43::i;32067:386::-;32194:12;;32190:146;;32223:32;32246:8;32223:22;:32::i;:::-;32270:54;8914:42;32306:7;32315:8;32270:35;:54::i;:::-;;32190:146;32356:13;;32352:94;;32386:48;30112:42;32415:7;32424:9;32386:28;:48::i;:::-;;32352:94;32067:386;;;;:::o;8328:468::-;8409:23;8435:106;8477:4;8435:106;;;;;;;;;;;;;;;;;8443:5;-1:-1:-1;;;;;8435:27:0;;;:106;;;;;:::i;:::-;8556:17;;8409:132;;-1:-1:-1;8556:21:0;8552:237;;8711:10;8700:30;;;;;;;;;;;;:::i;:::-;8692:85;;;;-1:-1:-1;;;8692:85:0;;;;;;;:::i;49282:116::-;49365:25;;;;;49282:116::o;49539:165::-;49602:4;44812:1;49627:31;;;;;;;49626:70;;-1:-1:-1;;44867:3:0;49664:31;;;;;;;;49539:165::o;49852:192::-;49912:5;49938:24;49956:5;49938:17;:24::i;:::-;49964:19;;;;;;;;;;;;;-1:-1:-1;;;49964:19:0;;;49930:54;;;;;-1:-1:-1;;;49930:54:0;;;;;;;;:::i;:::-;-1:-1:-1;;;;50005:30:0;;49852:192::o;50189:193::-;50302:22;;;;;;;;;;;;-1:-1:-1;;;50302:22:0;;;;50246:5;;44650:3;50272:28;;;;;50264:61;;;;-1:-1:-1;;;50264:61:0;;;;;;;;:::i;:::-;-1:-1:-1;;;;50346:27:0;;50189:193::o;4952:226::-;5072:7;5108:12;5100:6;;;;5092:29;;;;-1:-1:-1;;;5092:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;5144:5:0;;;4952:226::o;10443:108::-;8914:42;-1:-1:-1;;;;;10501:24:0;;10533:7;10501:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10443:108;:::o;2674:230::-;2811:12;2843:53;2866:6;2874:4;2880:1;2883:12;3733;3766:18;3777:6;3766:10;:18::i;:::-;3758:60;;;;-1:-1:-1;;;3758:60:0;;;;;;;:::i;:::-;3892:12;3906:23;3933:6;-1:-1:-1;;;;;3933:11:0;3952:8;3962:4;3933:34;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3891:76;;;;3982:7;3978:595;;;4013:10;-1:-1:-1;4006:17:0;;-1:-1:-1;4006:17:0;3978:595;4127:17;;:21;4123:439;;4390:10;4384:17;4451:15;4438:10;4434:2;4430:19;4423:44;4338:148;4533:12;4526:20;;-1:-1:-1;;;4526:20:0;;;;;;;;:::i;1439:641::-;1499:4;1980:20;;1810:66;2029:23;;;;;;:42;;-1:-1:-1;;2056:15:0;;;2021:51;-1:-1:-1;;1439:641:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:705:1:-;;127:3;120:4;112:6;108:17;104:27;94:2;;149:5;142;135:20;94:2;189:6;176:20;215:4;239:65;254:49;300:2;254:49;:::i;:::-;239:65;:::i;:::-;338:15;;;369:12;;;;401:15;;;447:11;;;435:24;;431:33;;428:42;-1:-1:-1;425:2:1;;;487:5;480;473:20;425:2;513:5;527:163;541:2;538:1;535:9;527:163;;;598:17;;586:30;;636:12;;;;668;;;;559:1;552:9;527:163;;;-1:-1:-1;708:5:1;;84:635;-1:-1:-1;;;;;;;84:635:1:o;724:1180::-;;812:4;856:3;851:2;843:6;839:15;835:25;825:2;;878:5;871;864:20;825:2;918:6;905:20;944:4;968:65;983:49;1029:2;983:49;:::i;968:65::-;1067:15;;;1098:12;;;;1130:15;;;1163:5;1177:698;1191:2;1188:1;1185:9;1177:698;;;1271:3;1258:17;1250:6;1246:30;1316:3;1311:2;1307;1303:11;1299:21;1289:2;;1338:5;1331;1324:20;1289:2;1390;1386;1382:11;1369:25;1417:2;1442:18;1438:2;1435:26;1432:2;;;1464:9;1432:2;1503:50;1526:11;;;-1:-1:-1;;1522:25:1;1518:34;;1503:50;:::i;:::-;1582:2;1573:7;1566:19;1626:3;1621:2;1616;1612;1608:11;1604:20;1601:29;1598:2;;;1647:5;1640;1633:20;1598:2;1712;1707;1703;1699:11;1694:2;1685:7;1681:16;1668:47;1739:16;;;1735:25;;1728:40;;;-1:-1:-1;1781:20:1;;-1:-1:-1;1821:12:1;;;;1853;;;;1209:1;1202:9;1177:698;;;-1:-1:-1;1893:5:1;;792:1112;-1:-1:-1;;;;;;;;792:1112:1:o;1909:263::-;;2032:2;2020:9;2011:7;2007:23;2003:32;2000:2;;;2053:6;2045;2038:22;2000:2;2090:9;2084:16;2109:33;2136:5;2109:33;:::i;2453:470::-;;;;2599:2;2587:9;2578:7;2574:23;2570:32;2567:2;;;2620:6;2612;2605:22;2567:2;2664:9;2651:23;2683:33;2710:5;2683:33;:::i;:::-;2735:5;-1:-1:-1;2792:2:1;2777:18;;2764:32;2805:35;2764:32;2805:35;:::i;:::-;2557:366;;2859:7;;-1:-1:-1;;;2913:2:1;2898:18;;;;2885:32;;2557:366::o;2928:381::-;;3074:2;3062:9;3053:7;3049:23;3045:32;3042:2;;;3095:6;3087;3080:22;3042:2;3140:9;3127:23;3173:18;3165:6;3162:30;3159:2;;;3210:6;3202;3195:22;3159:2;3238:65;3295:7;3286:6;3275:9;3271:22;3238:65;:::i;3314:1822::-;;;;;3593:3;3581:9;3572:7;3568:23;3564:33;3561:2;;;3615:6;3607;3600:22;3561:2;3660:9;3647:23;3689:18;3730:2;3722:6;3719:14;3716:2;;;3751:6;3743;3736:22;3716:2;3779:65;3836:7;3827:6;3816:9;3812:22;3779:65;:::i;:::-;3769:75;;3863:2;3853:12;;3918:2;3907:9;3903:18;3890:32;3947:2;3937:8;3934:16;3931:2;;;3968:6;3960;3953:22;3931:2;3996:67;4055:7;4044:8;4033:9;4029:24;3996:67;:::i;:::-;3986:77;;;4116:2;4105:9;4101:18;4088:32;4145:2;4135:8;4132:16;4129:2;;;4166:6;4158;4151:22;4129:2;4194:24;;4249:4;4241:13;;4237:27;-1:-1:-1;4227:2:1;;4283:6;4275;4268:22;4227:2;4324;4311:16;4347:65;4362:49;4408:2;4362:49;:::i;4347:65::-;4446:15;;;4477:12;;;;4509:11;;;4547;;;4539:20;;4535:29;;4532:42;-1:-1:-1;4529:2:1;;;4592:6;4584;4577:22;4529:2;4619:6;4610:15;;4634:272;4648:2;4645:1;4642:9;4634:272;;;4719:3;4706:17;4767:4;4760:5;4756:16;4749:5;4746:27;4736:2;;4792:6;4784;4777:22;4736:2;4814:18;;4666:1;4659:9;;;;;4852:12;;;;4884;;4634:272;;;-1:-1:-1;4925:5:1;-1:-1:-1;;;;4983:2:1;4968:18;;4955:32;;-1:-1:-1;4999:16:1;;;4996:2;;;5033:6;5025;5018:22;4996:2;;5061:69;5122:7;5111:8;5100:9;5096:24;5061:69;:::i;:::-;5051:79;;;3551:1585;;;;;;;:::o;5141:297::-;;5261:2;5249:9;5240:7;5236:23;5232:32;5229:2;;;5282:6;5274;5267:22;5229:2;5319:9;5313:16;5372:5;5365:13;5358:21;5351:5;5348:32;5338:2;;5399:6;5391;5384:22;5443:840;;5590:3;5578:9;5569:7;5565:23;5561:33;5558:2;;;5612:6;5604;5597:22;5558:2;5650;5644:9;5692:3;5684:6;5680:16;5762:6;5750:10;5747:22;5726:18;5714:10;5711:34;5708:62;5705:2;;;5773:9;5705:2;5800;5793:22;5839:16;;5824:32;;5899:2;5884:18;;5878:25;5912:33;5878:25;5912:33;:::i;:::-;5973:2;5961:15;;5954:30;6029:2;6014:18;;6008:25;6042:35;6008:25;6042:35;:::i;:::-;6105:2;6093:15;;6086:32;6163:2;6148:18;;6142:25;6176:35;6142:25;6176:35;:::i;:::-;6239:2;6227:15;;6220:32;6231:6;5548:735;-1:-1:-1;;;5548:735:1:o;6288:194::-;;6411:2;6399:9;6390:7;6386:23;6382:32;6379:2;;;6432:6;6424;6417:22;6379:2;-1:-1:-1;6460:16:1;;6369:113;-1:-1:-1;6369:113:1:o;6487:259::-;;6568:5;6562:12;6595:6;6590:3;6583:19;6611:63;6667:6;6660:4;6655:3;6651:14;6644:4;6637:5;6633:16;6611:63;:::i;:::-;6728:2;6707:15;-1:-1:-1;;6703:29:1;6694:39;;;;6735:4;6690:50;;6538:208;-1:-1:-1;;6538:208:1:o;6751:274::-;;6918:6;6912:13;6934:53;6980:6;6975:3;6968:4;6960:6;6956:17;6934:53;:::i;:::-;7003:16;;;;;6888:137;-1:-1:-1;;6888:137:1:o;7030:203::-;-1:-1:-1;;;;;7194:32:1;;;;7176:51;;7164:2;7149:18;;7131:102::o;7238:665::-;-1:-1:-1;;;;;7588:15:1;;;7570:34;;7640:15;;7635:2;7620:18;;7613:43;7692:3;7687:2;7672:18;;7665:31;;;7733:2;7712:19;;;7705:31;-1:-1:-1;;;7550:3:1;7752:19;;7745:48;7829:3;7824:2;7809:18;;7802:31;;;7238:665;;7850:47;;7877:19;;7869:6;7850:47;:::i;:::-;7842:55;7522:381;-1:-1:-1;;;;;7522:381:1:o;7908:274::-;-1:-1:-1;;;;;8100:32:1;;;;8082:51;;8164:2;8149:18;;8142:34;8070:2;8055:18;;8037:145::o;8187:177::-;8333:25;;;8321:2;8306:18;;8288:76::o;10901:221::-;;11050:2;11039:9;11032:21;11070:46;11112:2;11101:9;11097:18;11089:6;11070:46;:::i;11127:344::-;11329:2;11311:21;;;11368:2;11348:18;;;11341:30;-1:-1:-1;;;11402:2:1;11387:18;;11380:50;11462:2;11447:18;;11301:170::o;11476:344::-;11678:2;11660:21;;;11717:2;11697:18;;;11690:30;-1:-1:-1;;;11751:2:1;11736:18;;11729:50;11811:2;11796:18;;11650:170::o;11825:353::-;12027:2;12009:21;;;12066:2;12046:18;;;12039:30;12105:31;12100:2;12085:18;;12078:59;12169:2;12154:18;;11999:179::o;12183:406::-;12385:2;12367:21;;;12424:2;12404:18;;;12397:30;12463:34;12458:2;12443:18;;12436:62;-1:-1:-1;;;12529:2:1;12514:18;;12507:40;12579:3;12564:19;;12357:232::o;12594:672::-;12863:13;;12845:32;;12924:4;12912:17;;;12906:24;-1:-1:-1;;;;;13006:21:1;;;12984:20;;;12977:51;;;;13088:4;13076:17;;;13070:24;13066:33;;13044:20;;;13037:63;13160:4;13148:17;;;13142:24;13138:33;13116:20;;;13109:63;;;;13203:3;13188:19;;13181:35;;;;12957:3;13232:19;;13225:35;12832:3;12817:19;;12799:467::o;13453:184::-;13625:4;13613:17;;;;13595:36;;13583:2;13568:18;;13550:87::o;13642:242::-;13712:2;13706:9;13742:17;;;13789:18;13774:34;;13810:22;;;13771:62;13768:2;;;13836:9;13768:2;13863;13856:22;13686:198;;-1:-1:-1;13686:198:1:o;13889:183::-;;13988:18;13980:6;13977:30;13974:2;;;14010:9;13974:2;-1:-1:-1;14061:4:1;14042:17;;;14038:28;;13964:108::o;14077:258::-;14149:1;14159:113;14173:6;14170:1;14167:13;14159:113;;;14249:11;;;14243:18;14230:11;;;14223:39;14195:2;14188:10;14159:113;;;14290:6;14287:1;14284:13;14281:2;;;-1:-1:-1;;14325:1:1;14307:16;;14300:27;14130:205::o;14340:133::-;-1:-1:-1;;;;;14417:31:1;;14407:42;;14397:2;;14463:1;14460;14453:12;14397:2;14387:86;:::o

Swarm Source

ipfs://965400530ce9f7eb9468744103101cf1a730c9663d3046130ceadadcb5c99c91

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

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