Contract 0xae9e90b1c8e14515a2a83b4bd711b483af6c37d6

 
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x60850a1a3f521fe2011de0f1fa5e54d9f10909197a06f6abce5d65d377adf1fb0x60806040190878502021-09-14 6:20:31337 days 23 hrs ago0x3a893a7525c4263052c3c04f9c32d919c75cb8e0 IN  Create: AaveYield0 MATIC0.0224250510
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AaveYield

Compiler Version
v0.7.4+commit.3f05b770

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 19 : AaveYield.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.4;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";

import "../interfaces/ISymphony.sol";
import "../interfaces/IAaveToken.sol";
import "../interfaces/IAavePoolCore.sol";
import "../interfaces/IYieldAdapter.sol";
import "../interfaces/IAaveLendingPool.sol";
import "../interfaces/IAaveIncentivesController.sol";
import "../interfaces/IUniswapRouter.sol";
import "../libraries/UniswapLibrary.sol";

/**
 * @title Aave Yield contract
 * @notice Implements the functions to deposit/withdraw into Aave
 * @author Symphony Finance
 **/
contract AaveYield is IYieldAdapter, Initializable {
    using SafeERC20 for IERC20;
    using SafeMath for uint256;

    // Addresses related to aave
    address public aAsset;
    address public lendingPool;
    address public protocolDataProvider;
    IAaveIncentivesController public incentivesController;

    address public symphony;
    address public governance;
    address public REWARD_TOKEN;
    uint16 public referralCode;
    bool public isExternalRewardEnabled;
    uint256 public pendingRewards;
    uint256 public previousAccRewardPerShare;

    mapping(bytes32 => uint256) public orderRewardDebt;

    modifier onlySymphony() {
        require(
            msg.sender == symphony,
            "AaveYield: Only symphony contract can invoke this function"
        );
        _;
    }

    modifier onlyGovernance() {
        require(
            msg.sender == governance,
            "YearnYield: Only governance contract can invoke this function"
        );
        _;
    }

    /**
     * @dev To initialize the contract addresses interacting with this contract
     * @param _lendingPool the address of LendingPool
     * @param _protocolDataProvider the address of ProtocolDataProvider
     **/
    function initialize(
        address _symphony,
        address _governance,
        address _lendingPool,
        address _protocolDataProvider,
        address _incentivesController
    ) external initializer {
        require(_symphony != address(0), "AaveYield: Symphony:: zero address");
        require(
            _governance != address(0),
            "AaveYield: Governance:: zero address"
        );
        require(
            _protocolDataProvider != address(0),
            "AaveYield: protocolDataProvider:: zero address"
        );
        require(
            _lendingPool != address(0),
            "AaveYield: lendingPool:: zero address"
        );

        symphony = _symphony;
        governance = _governance;
        lendingPool = _lendingPool;
        protocolDataProvider = _protocolDataProvider;
        incentivesController = IAaveIncentivesController(_incentivesController);
        isExternalRewardEnabled = true;
        REWARD_TOKEN = incentivesController.REWARD_TOKEN();
    }

    /**
     * @dev Used to deposit tokens in available protocol
     * @param asset the address of token to invest
     * @param amount the amount of asset
     **/
    function deposit(address asset, uint256 amount)
        external
        override
        onlySymphony
    {
        require(amount != 0, "AaveYield::deposit: zero amount");

        emit Deposit(asset, amount);

        IERC20(asset).safeTransferFrom(msg.sender, address(this), amount);
        _depositERC20(asset, amount);
    }

    /**
     * @dev Used to withdraw tokens from available protocol
     **/
    function withdraw(
        address asset,
        uint256 amount,
        uint256 shares,
        uint256 totalShares,
        address recipient,
        bytes32 orderId
    ) external override onlySymphony {
        if (amount > 0) {
            emit Withdraw(asset, amount);

            _withdrawERC20(asset, amount);
        }

        if (isExternalRewardEnabled && shares > 0 && recipient != address(0)) {
            _calculateAndTransferReward(
                shares,
                totalShares,
                orderRewardDebt[orderId],
                recipient
            );
        }
    }

    /**
     * @dev Withdraw all tokens from the strategy
     * @param asset the address of token
     * @param data bytes of extra data
     **/
    function withdrawAll(address asset, bytes calldata data)
        external
        override
        onlySymphony
    {
        uint256 amount = IERC20(aAsset).balanceOf(address(this));

        if (amount > 0) {
            _withdrawERC20(asset, amount);
        }

        if (isExternalRewardEnabled) {
            uint256 rewardAmount = _calculateAndTransferReward(
                100,
                100,
                0,
                address(this)
            );

            (
                address router,
                uint256 slippage,
                bytes32 codeHash,
                address[] memory path
            ) = abi.decode(data, (address, uint256, bytes32, address[]));

            if (router != address(0)) {
                _swap(
                    incentivesController.REWARD_TOKEN(),
                    rewardAmount,
                    router,
                    slippage,
                    codeHash,
                    path
                );
            }
        }
    }

    /**
     * @dev Used to set external reward debt at the time of order creation
     * @param orderId the id of the order
     **/
    function setOrderRewardDebt(
        bytes32 orderId,
        address,
        uint256,
        uint256 totalShares
    ) external override onlySymphony {
        uint256 totalRewardBalance = getRewardBalance();
        uint256 accRewardPerShare = getAccumulatedRewardPerShare(
            totalShares,
            totalRewardBalance
        );

        pendingRewards = totalRewardBalance;
        previousAccRewardPerShare = accRewardPerShare;
        orderRewardDebt[orderId] = accRewardPerShare;
    }

    /**
     * @dev Used to approve max token and add token for reward
     * @param asset the address of token
     **/
    function maxApprove(address asset) external override onlySymphony {
        require(
            aAsset == address(0),
            "AaveYield: Asset can't be changed after initilization."
        );

        aAsset = getYieldTokenAddress(asset);

        IERC20(asset).safeApprove(lendingPool, uint256(-1));
        IERC20(aAsset).safeApprove(lendingPool, uint256(-1));
    }

    // *************** //
    // *** GETTERS *** //
    // *************** //

    /**
     * @dev Used to get amount of underlying tokens
     * @return amount amount of underlying tokens
     **/
    function getTotalUnderlying(address)
        public
        view
        override
        returns (uint256 amount)
    {
        amount = IERC20(aAsset).balanceOf(address(this));
    }

    /**
     * @dev Used to get IOU token address
     * @param asset the address of token
     * @return iouToken address of IOU token
     **/
    function getYieldTokenAddress(address asset)
        public
        view
        override
        returns (address iouToken)
    {
        (iouToken, , ) = IAavePoolCore(protocolDataProvider)
            .getReserveTokensAddresses(asset);
    }

    /**
     * @dev Used to get external reward balance
     **/
    function getRewardBalance() public view returns (uint256 amount) {
        address[] memory assets = new address[](1);
        assets[0] = aAsset;

        amount = incentivesController.getRewardsBalance(assets, address(this));
    }

    function getAccumulatedRewardPerShare(
        uint256 totalShares,
        uint256 rewardBalance
    ) public view returns (uint256 result) {
        if (totalShares > 0) {
            // ARPS = previous_APRS + (new_reward / total_shares)
            uint256 newReward = rewardBalance.sub(pendingRewards);

            // ARPS stored in 10^18 denomination.
            uint256 newRewardPerShare = newReward.mul(10**18).div(totalShares);

            result = previousAccRewardPerShare.add(newRewardPerShare);
        }
    }

    // ************************** //
    // *** GOVERNANCE METHODS *** //
    // ************************** //

    function updateReferralCode(uint16 _referralCode) external onlyGovernance {
        referralCode = _referralCode;
    }

    function updateIsExternalRewardEnabled(bool _status)
        external
        onlyGovernance
    {
        isExternalRewardEnabled = _status;
    }

    function updateIncentivesController(address _incetivesController)
        external
        onlyGovernance
    {
        incentivesController = IAaveIncentivesController(_incetivesController);
    }

    function updateRewardToken(address _token) external onlyGovernance {
        REWARD_TOKEN = _token;
    }

    function updateAaveAddresses(
        address _lendingPool,
        address _protocolDataProvider
    ) external onlyGovernance {
        require(
            _lendingPool != address(0),
            "AaveYield: lendingPool:: zero address"
        );
        require(
            _protocolDataProvider != address(0),
            "AaveYield: protocolDataProvider:: zero address"
        );

        lendingPool = _lendingPool;
        protocolDataProvider = _protocolDataProvider;
    }

    // ************************** //
    // *** INTERNAL FUNCTIONS *** //
    // ************************** //

    function _depositERC20(address _asset, uint256 _amount) internal {
        IAaveLendingPool(lendingPool).deposit(
            _asset,
            _amount,
            address(this),
            referralCode
        );
    }

    function _withdrawERC20(address _asset, uint256 _amount)
        internal
        returns (uint256 amount)
    {
        amount = IAaveLendingPool(lendingPool).withdraw(
            _asset,
            _amount,
            symphony
        );
    }

    function _calculateAndTransferReward(
        uint256 _shares,
        uint256 _totalShares,
        uint256 _rewardDebt,
        address _recipient
    ) internal returns (uint256 reward) {
        uint256 totalRewardBalance = getRewardBalance();
        uint256 accRewardPerShare = getAccumulatedRewardPerShare(
            _totalShares,
            totalRewardBalance
        );

        // reward_amount = shares x ((ARPS) - (reward_debt))
        reward = _shares.mul(accRewardPerShare.sub(_rewardDebt)).div(10**18);

        require(
            totalRewardBalance >= reward,
            "AaveYield:CATR:: total reward exceeds rewards"
        );

        pendingRewards = totalRewardBalance.sub(reward);
        previousAccRewardPerShare = accRewardPerShare;
        _transferReward(reward, _recipient);
    }

    /**
     * @notice Transfer WMATIC reward to order recipient
     */
    function _transferReward(uint256 _reward, address _recipient) internal {
        if (_reward > 0) {
            address[] memory assets = new address[](1);
            assets[0] = aAsset;

            incentivesController.claimRewards(assets, _reward, _recipient);
        }
    }

    function _swap(
        address _inputToken,
        uint256 _inputAmount,
        address _router,
        uint256 _slippage,
        bytes32 _codeHash,
        address[] memory _path
    ) internal {
        IERC20(_inputToken).safeApprove(_router, _inputAmount);

        uint256 amountOut = _getAmountOut(
            _inputAmount,
            _router,
            _codeHash,
            _path
        );

        // Swap Tokens
        IUniswapRouter(_router).swapExactTokensForTokens(
            _inputAmount,
            amountOut.mul(uint256(100).sub(_slippage)).div(100), // Slipage: 2 for 2%
            _path,
            symphony,
            block.timestamp.add(1800)
        );
    }

    function _getAmountOut(
        uint256 _inputAmount,
        address _router,
        bytes32 _codeHash,
        address[] memory _path
    ) internal view returns (uint256 amountOut) {
        address factory = IUniswapRouter(_router).factory();

        uint256[] memory _amounts = UniswapLibrary.getAmountsOut(
            factory,
            _inputAmount,
            _path,
            _codeHash
        );

        amountOut = _amounts[_amounts.length - 1];
    }

    receive() external payable {}
}

File 2 of 19 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 3 of 19 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using 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 Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _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));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        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");
        }
    }
}

File 4 of 19 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}

File 5 of 19 : Initializable.sol
// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version
pragma solidity >=0.4.24 <0.8.0;

import "../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /// @dev Returns true if and only if the function is running in the constructor
    function _isConstructor() private view returns (bool) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

File 6 of 19 : ISymphony.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.4;

interface ISymphony {
    function createOrder(
        address recipient,
        address inputToken,
        address outputToken,
        uint256 inputAmount,
        uint256 minReturnAmount,
        uint256 stoplossAmount
    ) external returns (bytes32 orderId);
}

File 7 of 19 : IAaveToken.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.4;

interface IAaveToken {
    /**
     * @dev Returns the scaled balance of the user. The scaled balance is the sum of all the
     * updated stored balance divided by the reserve's liquidity index at the moment of the update
     * @param user The user whose balance is calculated
     * @return The scaled balance of the user
     **/
    function scaledBalanceOf(address user) external view returns (uint256);
}

File 8 of 19 : IAavePoolCore.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;

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

interface IAavePoolCore {
    struct TokenData {
        string symbol;
        address tokenAddress;
    }

    function ADDRESSES_PROVIDER() external view returns (IAaveAddressProvider);

    function getAllReservesTokens() external view returns (TokenData[] memory);

    function getAllATokens() external view returns (TokenData[] memory);

    function getReserveConfigurationData(address asset)
        external
        view
        returns (
            uint256 decimals,
            uint256 ltv,
            uint256 liquidationThreshold,
            uint256 liquidationBonus,
            uint256 reserveFactor,
            bool usageAsCollateralEnabled,
            bool borrowingEnabled,
            bool stableBorrowRateEnabled,
            bool isActive,
            bool isFrozen
        );

    function getReserveData(address asset)
        external
        view
        returns (
            uint256 availableLiquidity,
            uint256 totalStableDebt,
            uint256 totalVariableDebt,
            uint256 liquidityRate,
            uint256 variableBorrowRate,
            uint256 stableBorrowRate,
            uint256 averageStableBorrowRate,
            uint256 liquidityIndex,
            uint256 variableBorrowIndex,
            uint40 lastUpdateTimestamp
        );

    function getUserReserveData(address asset, address user)
        external
        view
        returns (
            uint256 currentATokenBalance,
            uint256 currentStableDebt,
            uint256 currentVariableDebt,
            uint256 principalStableDebt,
            uint256 scaledVariableDebt,
            uint256 stableBorrowRate,
            uint256 liquidityRate,
            uint40 stableRateLastUpdated,
            bool usageAsCollateralEnabled
        );

    function getReserveTokensAddresses(address asset)
        external
        view
        returns (
            address aTokenAddress,
            address stableDebtTokenAddress,
            address variableDebtTokenAddress
        );
}

File 9 of 19 : IYieldAdapter.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.4;

interface IYieldAdapter {
    /**
     * @dev emitted when tokens are deposited
     * @param investedTo the address of contract to invest in
     * @param sharesReceived the amount of shares received
     **/
    event Deposit(address investedTo, uint256 sharesReceived);

    /**
     * @dev emitted when tokens are withdrawn
     * @param investedTo the address of contract invested in
     * @param tokensReceived the amount of underlying asset received
     **/
    event Withdraw(address investedTo, uint256 tokensReceived);

    /**
     * @dev Used to deposit token
     * @param asset the address of token to invest
     * @param amount the amount of asset
     **/
    function deposit(address asset, uint256 amount) external;

    /**
     * @dev Used to withdraw from available protocol
     * @param asset the address of underlying token
     * @param amount the amount of liquidity shares to unlock
     * @param shares shares of the order (only for  external reward)
     * @param totalShares total share for particular asset
     * @param recipient address of reward receiever (if any)
     * @param orderId bytes32 format orderId
     **/
    function withdraw(
        address asset,
        uint256 amount,
        uint256 shares,
        uint256 totalShares,
        address recipient,
        bytes32 orderId
    ) external;

    /**
     * @dev Withdraw all tokens from the strategy
     * @param asset the address of token
     * @param data bytes of extra data
     **/
    function withdrawAll(address asset, bytes calldata data) external;

    /**
     * @dev Used to approve max token from yield provider contract
     * @param asset the address of token
     **/
    function maxApprove(address asset) external;

    /**
     * @dev Used to get amount of underlying tokens
     * @param asset the address of token
     * @return tokensAmount amount of underlying tokens
     **/
    function getTotalUnderlying(address asset)
        external
        view
        returns (uint256 tokensAmount);

    /**
     * @dev Used to get IOU token address
     * @param asset the address of token
     * @return iouToken address of IOU token
     **/
    function getYieldTokenAddress(address asset)
        external
        view
        returns (address iouToken);

    /**
     * @dev Used to set order current external reward debt
     * @param orderId the order Id
     * @param asset the address of token
     * @param shares shares of the order (only for  external reward)
     * @param totalShares total share for particular asset
     **/
    function setOrderRewardDebt(
        bytes32 orderId,
        address asset,
        uint256 shares,
        uint256 totalShares
    ) external;
}

File 10 of 19 : IAaveLendingPool.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;

import "./IAaveAddressProvider.sol";
import "../libraries/AaveDataTypes.sol";

interface IAaveLendingPool {
    function deposit(
        address asset,
        uint256 amount,
        address onBehalfOf,
        uint16 referralCode
    ) external;

    function withdraw(
        address asset,
        uint256 amount,
        address to
    ) external returns (uint256);

    /**
     * @dev Returns the state and configuration of the reserve
     * @param asset The address of the underlying asset of the reserve
     * @return The state of the reserve
     **/
    function getReserveData(address asset)
        external
        view
        returns (AaveDataTypes.ReserveData memory);

    function getAddressesProvider()
        external
        view
        returns (IAaveAddressProvider);
}

File 11 of 19 : IAaveIncentivesController.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.4;

interface IAaveIncentivesController {
    function claimRewards(
        address[] calldata assets,
        uint256 amount,
        address to
    ) external returns (uint256);

    function claimRewardsOnBehalf(
        address[] calldata assets,
        uint256 amount,
        address user,
        address to
    ) external returns (uint256);

    function getRewardsBalance(address[] calldata assets, address user)
        external
        view
        returns (uint256);

    function getUserUnclaimedRewards(address user)
        external
        view
        returns (uint256);

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

File 12 of 19 : IUniswapRouter.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;

import "./IUniswapRouter01.sol";

interface IUniswapRouter is IUniswapRouter01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountETH);

    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;

    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable;

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;
}

File 13 of 19 : UniswapLibrary.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.4;

import "@openzeppelin/contracts/math/SafeMath.sol";
import "../interfaces/IUniswapPair.sol";

library UniswapLibrary {
    using SafeMath for uint256;

    /**
     * @notice Returns the current block timestamp within the range of uint32, i.e. [0, 2**32 - 1]
     * @return uint32 - block timestamp
     */
    function currentBlockTimestamp() internal view returns (uint32) {
        return uint32(block.timestamp % 2**32);
    }

    /**
     * @notice Returns sorted token addresses, used to handle return values from pairs sorted in this order
     * @param _tokenA - Address of the token A
     * @param _tokenB - Address of the token B
     * @return token0 - Address of the lower token
     * @return token1 - Address of the higher token
     */
    function sortTokens(address _tokenA, address _tokenB)
        internal
        pure
        returns (address token0, address token1)
    {
        require(
            _tokenA != _tokenB,
            "SushiswapUtils#sortTokens: IDENTICAL_ADDRESSES"
        );
        (token0, token1) = _tokenA < _tokenB
            ? (_tokenA, _tokenB)
            : (_tokenB, _tokenA);
        require(
            token0 != address(0),
            "SushiswapUtils#sortTokens: ZERO_ADDRESS"
        );
    }

    /**
     * @notice Calculates the CREATE2 address for a pair without making any external calls
     * @param _factory - Address of the sushiswapV2 factory contract
     * @param _tokenA - Address of the token A
     * @param _tokenB - Address of the token B
     * @param _initCodeHash - Bytes32 of the sushiswap v2 pair contract unit code hash
     * @return pair - Address of the pair
     */
    function pairFor(
        address _factory,
        address _tokenA,
        address _tokenB,
        bytes32 _initCodeHash
    ) internal pure returns (address pair) {
        (address token0, address token1) = sortTokens(_tokenA, _tokenB);
        pair = address(
            uint256(
                keccak256(
                    abi.encodePacked(
                        hex"ff",
                        _factory,
                        keccak256(abi.encodePacked(token0, token1)),
                        _initCodeHash // init code hash
                    )
                )
            )
        );
    }

    /**
     * @notice Calculates the CREATE2 address for a pair without making any external calls
     * @dev Tokens should be in order
     * @param _factory - Address of the sushiswapV2 factory contract
     * @param _token0 - Address of the token 0
     * @param _token1 - Address of the token 1
     * @param _initCodeHash - Bytes32 of the sushiswap v2 pair contract unit code hash
     * @return pair - Address of the pair
     */
    function pairForSorted(
        address _factory,
        address _token0,
        address _token1,
        bytes32 _initCodeHash
    ) internal pure returns (address pair) {
        pair = address(
            uint256(
                keccak256(
                    abi.encodePacked(
                        hex"ff",
                        _factory,
                        keccak256(abi.encodePacked(_token0, _token1)),
                        _initCodeHash // init code hash
                    )
                )
            )
        );
    }

    /**
     * @notice Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
     * @param _inputAmount - uint of the input token's amount
     * @param _reserveIn - uint of the input token's reserve
     * @param _reserveOut - uint of the output token's reserve
     * @return amountOut - Maximum output amount
     */
    function getAmountOut(
        uint256 _inputAmount,
        uint256 _reserveIn,
        uint256 _reserveOut
    ) internal pure returns (uint256 amountOut) {
        require(
            _inputAmount > 0,
            "UniswapUtils#getAmountOut: INSUFFICIENT_INPUT_AMOUNT"
        );
        require(
            _reserveIn > 0 && _reserveOut > 0,
            "UniswapUtils#getAmountOut: INSUFFICIENT_LIQUIDITY"
        );
        uint256 inputAmountWithFee = _inputAmount.mul(997);
        uint256 numerator = inputAmountWithFee.mul(_reserveOut);
        uint256 denominator = _reserveIn.mul(1000).add(inputAmountWithFee);
        if (denominator > 0) {
            amountOut = numerator / denominator;
        }
    }

    // performs chained getAmountOut calculations on any number of pairs
    function getAmountsOut(
        address factory,
        uint256 amountIn,
        address[] memory path,
        bytes32 initcodehash
    ) internal view returns (uint256[] memory amounts) {
        require(path.length >= 2, "UniswapV2Library: INVALID_PATH");
        amounts = new uint256[](path.length);
        amounts[0] = amountIn;
        for (uint256 i; i < path.length - 1; i++) {
            (uint256 reserveIn, uint256 reserveOut) = getReserves(
                factory,
                path[i],
                path[i + 1],
                initcodehash
            );
            amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
        }
    }

    // fetches and sorts the reserves for a pair
    function getReserves(
        address factory,
        address tokenA,
        address tokenB,
        bytes32 initcodehash
    ) internal view returns (uint256 reserveA, uint256 reserveB) {
        (address token0, ) = sortTokens(tokenA, tokenB);
        address pairAddress = pairFor(factory, tokenA, tokenB, initcodehash);

        uint256 size;
        assembly {
            size := extcodesize(pairAddress)
        }

        if (size > 0) {
            IUniswapPair pair = IUniswapPair(pairAddress);
            (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();

            (reserveA, reserveB) = tokenA == token0
                ? (reserve0, reserve1)
                : (reserve1, reserve0);
        } else {
            reserveA = 0;
            reserveB = 0;
        }
    }
}

File 14 of 19 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    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");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    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");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        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);
            }
        }
    }
}

File 15 of 19 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    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");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    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");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        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);
            }
        }
    }
}

File 16 of 19 : IAaveAddressProvider.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.4;

interface IAaveAddressProvider {
    function getMarketId() external view returns (string memory);

    function setMarketId(string calldata marketId) external;

    function setAddress(bytes32 id, address newAddress) external;

    function setAddressAsProxy(bytes32 id, address impl) external;

    function getAddress(bytes32 id) external view returns (address);

    function getLendingPool() external view returns (address);

    function setLendingPoolImpl(address pool) external;

    function getLendingPoolConfigurator() external view returns (address);

    function setLendingPoolConfiguratorImpl(address configurator) external;

    function getLendingPoolCollateralManager() external view returns (address);

    function setLendingPoolCollateralManager(address manager) external;

    function getPoolAdmin() external view returns (address);

    function setPoolAdmin(address admin) external;

    function getEmergencyAdmin() external view returns (address);

    function setEmergencyAdmin(address admin) external;

    function getPriceOracle() external view returns (address);

    function setPriceOracle(address priceOracle) external;

    function getLendingRateOracle() external view returns (address);

    function setLendingRateOracle(address lendingRateOracle) external;
}

File 17 of 19 : AaveDataTypes.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.4;

library AaveDataTypes {
    // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
    struct ReserveData {
        //stores the reserve configuration
        ReserveConfigurationMap configuration;
        //the liquidity index. Expressed in ray
        uint128 liquidityIndex;
        //variable borrow index. Expressed in ray
        uint128 variableBorrowIndex;
        //the current supply rate. Expressed in ray
        uint128 currentLiquidityRate;
        //the current variable borrow rate. Expressed in ray
        uint128 currentVariableBorrowRate;
        //the current stable borrow rate. Expressed in ray
        uint128 currentStableBorrowRate;
        uint40 lastUpdateTimestamp;
        //tokens addresses
        address aTokenAddress;
        address stableDebtTokenAddress;
        address variableDebtTokenAddress;
        //address of the interest rate strategy
        address interestRateStrategyAddress;
        //the id of the reserve. Represents the position in the list of the active reserves
        uint8 id;
    }

    struct ReserveConfigurationMap {
        //bit 0-15: LTV
        //bit 16-31: Liq. threshold
        //bit 32-47: Liq. bonus
        //bit 48-55: Decimals
        //bit 56: Reserve is active
        //bit 57: reserve is frozen
        //bit 58: borrowing is enabled
        //bit 59: stable rate borrowing enabled
        //bit 60-63: reserved
        //bit 64-79: reserve factor
        uint256 data;
    }

    struct UserConfigurationMap {
        uint256 data;
    }

    enum InterestRateMode {NONE, STABLE, VARIABLE}
}

File 18 of 19 : IUniswapRouter01.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;

interface IUniswapRouter01 {
    function factory() external pure returns (address);

    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    )
        external
        returns (
            uint256 amountA,
            uint256 amountB,
            uint256 liquidity
        );

    function addLiquidityETH(
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
        external
        payable
        returns (
            uint256 amountToken,
            uint256 amountETH,
            uint256 liquidity
        );

    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETH(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountToken, uint256 amountETH);

    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETHWithPermit(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountToken, uint256 amountETH);

    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapTokensForExactTokens(
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function swapTokensForExactETH(
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactTokensForETH(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapETHForExactTokens(
        uint256 amountOut,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function quote(
        uint256 amountA,
        uint256 reserveA,
        uint256 reserveB
    ) external pure returns (uint256 amountB);

    function getAmountOut(
        uint256 amountIn,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountOut);

    function getAmountIn(
        uint256 amountOut,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountIn);

    function getAmountsOut(uint256 amountIn, address[] calldata path)
        external
        view
        returns (uint256[] memory amounts);

    function getAmountsIn(uint256 amountOut, address[] calldata path)
        external
        view
        returns (uint256[] memory amounts);
}

File 19 of 19 : IUniswapPair.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.4;

interface IUniswapPair {
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
    event Transfer(address indexed from, address indexed to, uint256 value);

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

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

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint256);

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

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

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

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

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

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

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    event Mint(address indexed sender, uint256 amount0, uint256 amount1);
    event Burn(
        address indexed sender,
        uint256 amount0,
        uint256 amount1,
        address indexed to
    );
    event Swap(
        address indexed sender,
        uint256 amount0In,
        uint256 amount1In,
        uint256 amount0Out,
        uint256 amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function factory() external view returns (address);

    function token0() external view returns (address);

    function token1() external view returns (address);

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

    function price0CumulativeLast() external view returns (uint256);

    function price1CumulativeLast() external view returns (uint256);

    function kLast() external view returns (uint256);

    function mint(address to) external returns (uint256 liquidity);

    function burn(address to)
        external
        returns (uint256 amount0, uint256 amount1);

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

    function skim(address to) external;

    function sync() external;

    function initialize(address, address) external;
}

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

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"investedTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"sharesReceived","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"investedTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokensReceived","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"REWARD_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"aAsset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"totalShares","type":"uint256"},{"internalType":"uint256","name":"rewardBalance","type":"uint256"}],"name":"getAccumulatedRewardPerShare","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardBalance","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getTotalUnderlying","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getYieldTokenAddress","outputs":[{"internalType":"address","name":"iouToken","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"incentivesController","outputs":[{"internalType":"contract IAaveIncentivesController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_symphony","type":"address"},{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_lendingPool","type":"address"},{"internalType":"address","name":"_protocolDataProvider","type":"address"},{"internalType":"address","name":"_incentivesController","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isExternalRewardEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lendingPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"maxApprove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"orderRewardDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"previousAccRewardPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolDataProvider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralCode","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderId","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"totalShares","type":"uint256"}],"name":"setOrderRewardDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symphony","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_lendingPool","type":"address"},{"internalType":"address","name":"_protocolDataProvider","type":"address"}],"name":"updateAaveAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_incetivesController","type":"address"}],"name":"updateIncentivesController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_status","type":"bool"}],"name":"updateIsExternalRewardEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_referralCode","type":"uint16"}],"name":"updateReferralCode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"updateRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"totalShares","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes32","name":"orderId","type":"bytes32"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b5061279b806100206000396000f3fe6080604052600436106101a05760003560e01c80639eaec3c5116100ec578063d8b6d2521161008a578063e833e80411610064578063e833e8041461061d578063eded3fda14610632578063f0d2460f14610647578063f8cf31cb14610671576101a7565b8063d8b6d25214610583578063e6904e1d146105af578063e77f6820146105ea576101a7565b8063adef4533116100c6578063adef4533146104d3578063af1df25514610506578063cbc7281a1461051b578063cdc391181461056e576101a7565b80639eaec3c51461041c578063a0956fca146104a9578063a59a9973146104be576101a7565b80635aa6e67511610159578063889c6b9011610133578063889c6b901461037557806394f131f2146103a857806399248ea7146103d45780639d192aff146103e9576101a7565b80635aa6e675146103065780635e42b4551461031b5780637e73de9314610330576101a7565b8063059bd0e7146101ac578063079822d1146101dc5780631459457a146102055780632bbc30071461025a5780633f843bce1461029c57806347e7ef24146102cd576101a7565b366101a757005b600080fd5b3480156101b857600080fd5b506101da600480360360208110156101cf57600080fd5b503561ffff166106a4565b005b3480156101e857600080fd5b506101f161070f565b604080519115158252519081900360200190f35b34801561021157600080fd5b506101da600480360360a081101561022857600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101358216916080909101351661071f565b34801561026657600080fd5b5061028a6004803603604081101561027d57600080fd5b50803590602001356109c5565b60408051918252519081900360200190f35b3480156102a857600080fd5b506102b1610a1f565b604080516001600160a01b039092168252519081900360200190f35b3480156102d957600080fd5b506101da600480360360408110156102f057600080fd5b506001600160a01b038135169060200135610a2e565b34801561031257600080fd5b506102b1610b30565b34801561032757600080fd5b5061028a610b3f565b34801561033c57600080fd5b506101da6004803603608081101561035357600080fd5b508035906001600160a01b036020820135169060408101359060600135610c57565b34801561038157600080fd5b506102b16004803603602081101561039857600080fd5b50356001600160a01b0316610cdc565b3480156103b457600080fd5b506101da600480360360208110156103cb57600080fd5b50351515610d57565b3480156103e057600080fd5b506102b1610dbe565b3480156103f557600080fd5b506101da6004803603602081101561040c57600080fd5b50356001600160a01b0316610dcd565b34801561042857600080fd5b506101da6004803603604081101561043f57600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561046a57600080fd5b82018360208201111561047c57600080fd5b8035906020019184600183028401116401000000008311171561049e57600080fd5b509092509050610ecc565b3480156104b557600080fd5b506102b1611126565b3480156104ca57600080fd5b506102b1611135565b3480156104df57600080fd5b5061028a600480360360208110156104f657600080fd5b50356001600160a01b0316611144565b34801561051257600080fd5b506102b1611195565b34801561052757600080fd5b506101da600480360360c081101561053e57600080fd5b506001600160a01b0381358116916020810135916040820135916060810135916080820135169060a001356111a4565b34801561057a57600080fd5b506102b161129b565b34801561058f57600080fd5b506105986112b0565b6040805161ffff9092168252519081900360200190f35b3480156105bb57600080fd5b506101da600480360360408110156105d257600080fd5b506001600160a01b03813581169160200135166112c1565b3480156105f657600080fd5b506101da6004803603602081101561060d57600080fd5b50356001600160a01b03166113c2565b34801561062957600080fd5b5061028a61142d565b34801561063e57600080fd5b5061028a611433565b34801561065357600080fd5b5061028a6004803603602081101561066a57600080fd5b5035611439565b34801561067d57600080fd5b506101da6004803603602081101561069457600080fd5b50356001600160a01b031661144b565b6005546001600160a01b031633146106ed5760405162461bcd60e51b815260040180806020018281038252603d815260200180612506603d913960400191505060405180910390fd5b6006805461ffff909216600160a01b0261ffff60a01b19909216919091179055565b600654600160b01b900460ff1681565b600054610100900460ff168061073857506107386114b6565b80610746575060005460ff16155b6107815760405162461bcd60e51b815260040180806020018281038252602e815260200180612570602e913960400191505060405180910390fd5b600054610100900460ff161580156107ac576000805460ff1961ff0019909116610100171660011790555b6001600160a01b0386166107f15760405162461bcd60e51b81526004018080602001828103825260228152602001806125c36022913960400191505060405180910390fd5b6001600160a01b0385166108365760405162461bcd60e51b81526004018080602001828103825260248152602001806124956024913960400191505060405180910390fd5b6001600160a01b03831661087b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806125e5602e913960400191505060405180910390fd5b6001600160a01b0384166108c05760405162461bcd60e51b815260040180806020018281038252602581526020018061259e6025913960400191505060405180910390fd5b600480546001600160a01b038089166001600160a01b031992831617835560058054898316908416179055600180548883169084161790556002805487831690841617905560038054868316931692909217918290556006805460ff60b01b1916600160b01b179055604080516399248ea760e01b8152905192909116926399248ea7928282019260209290829003018186803b15801561096057600080fd5b505afa158015610974573d6000803e3d6000fd5b505050506040513d602081101561098a57600080fd5b5051600680546001600160a01b0319166001600160a01b0390921691909117905580156109bd576000805461ff00191690555b505050505050565b60008215610a195760006109e4600754846114c790919063ffffffff16565b90506000610a04856109fe84670de0b6b3a7640000611524565b90611584565b600854909150610a1490826115eb565b925050505b92915050565b6002546001600160a01b031681565b6004546001600160a01b03163314610a775760405162461bcd60e51b815260040180806020018281038252603a8152602001806126f6603a913960400191505060405180910390fd5b80610ac9576040805162461bcd60e51b815260206004820152601f60248201527f416176655969656c643a3a6465706f7369743a207a65726f20616d6f756e7400604482015290519081900360640190fd5b604080516001600160a01b03841681526020810183905281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a1610b226001600160a01b038316333084611645565b610b2c828261169f565b5050565b6005546001600160a01b031681565b604080516001808252818301909252600091606091906020808301908036833750506000805483519394506201000090046001600160a01b031692849250610b8357fe5b6001600160a01b03928316602091820292909201810191909152600354604080516345accf9360e11b81523060248201819052600482019283528651604483015286519390951694638b599f269487949193928392606490910191868101910280838360005b83811015610c01578181015183820152602001610be9565b50505050905001935050505060206040518083038186803b158015610c2557600080fd5b505afa158015610c39573d6000803e3d6000fd5b505050506040513d6020811015610c4f57600080fd5b505192915050565b6004546001600160a01b03163314610ca05760405162461bcd60e51b815260040180806020018281038252603a8152602001806126f6603a913960400191505060405180910390fd5b6000610caa610b3f565b90506000610cb883836109c5565b60079290925550600881905560009485526009602052604090942093909355505050565b600254604080516334924edb60e21b81526001600160a01b0384811660048301529151600093929092169163d2493b6c91602480820192606092909190829003018186803b158015610d2d57600080fd5b505afa158015610d41573d6000803e3d6000fd5b505050506040513d6060811015610c4f57600080fd5b6005546001600160a01b03163314610da05760405162461bcd60e51b815260040180806020018281038252603d815260200180612506603d913960400191505060405180910390fd5b60068054911515600160b01b0260ff60b01b19909216919091179055565b6006546001600160a01b031681565b6004546001600160a01b03163314610e165760405162461bcd60e51b815260040180806020018281038252603a8152602001806126f6603a913960400191505060405180910390fd5b6000546201000090046001600160a01b031615610e645760405162461bcd60e51b81526004018080602001828103825260368152602001806126346036913960400191505060405180910390fd5b610e6d81610cdc565b6000805462010000600160b01b031916620100006001600160a01b0393841602179055600154610ea4918381169116600019611722565b600154600054610ec9916001600160a01b036201000090920482169116600019611722565b50565b6004546001600160a01b03163314610f155760405162461bcd60e51b815260040180806020018281038252603a8152602001806126f6603a913960400191505060405180910390fd5b60008054604080516370a0823160e01b81523060048201529051620100009092046001600160a01b0316916370a0823191602480820192602092909190829003018186803b158015610f6657600080fd5b505afa158015610f7a573d6000803e3d6000fd5b505050506040513d6020811015610f9057600080fd5b505190508015610fa657610fa4848261183a565b505b600654600160b01b900460ff1615611120576000610fc86064806000306118d3565b90506000806000606087876080811015610fe157600080fd5b6001600160a01b03823516916020810135916040820135919081019060808101606082013564010000000081111561101857600080fd5b82018360208201111561102a57600080fd5b8035906020019184602083028401116401000000008311171561104c57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250989c50969a50949850965050506001600160a01b03881615935061111a9250505057600354604080516399248ea760e01b8152905161111a926001600160a01b0316916399248ea7916004808301926020929190829003018186803b1580156110e457600080fd5b505afa1580156110f8573d6000803e3d6000fd5b505050506040513d602081101561110e57600080fd5b50518686868686611975565b50505050505b50505050565b6004546001600160a01b031681565b6001546001600160a01b031681565b60008054604080516370a0823160e01b81523060048201529051620100009092046001600160a01b0316916370a0823191602480820192602092909190829003018186803b158015610c2557600080fd5b6003546001600160a01b031681565b6004546001600160a01b031633146111ed5760405162461bcd60e51b815260040180806020018281038252603a8152602001806126f6603a913960400191505060405180910390fd5b841561124357604080516001600160a01b03881681526020810187905281517f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364929181900390910190a1611241868661183a565b505b600654600160b01b900460ff16801561125c5750600084115b801561127057506001600160a01b03821615155b156109bd576000818152600960205260409020546112929085908590856118d3565b50505050505050565b6000546201000090046001600160a01b031681565b600654600160a01b900461ffff1681565b6005546001600160a01b0316331461130a5760405162461bcd60e51b815260040180806020018281038252603d815260200180612506603d913960400191505060405180910390fd5b6001600160a01b03821661134f5760405162461bcd60e51b815260040180806020018281038252602581526020018061259e6025913960400191505060405180910390fd5b6001600160a01b0381166113945760405162461bcd60e51b815260040180806020018281038252602e8152602001806125e5602e913960400191505060405180910390fd5b600180546001600160a01b039384166001600160a01b03199182161790915560028054929093169116179055565b6005546001600160a01b0316331461140b5760405162461bcd60e51b815260040180806020018281038252603d815260200180612506603d913960400191505060405180910390fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60085481565b60075481565b60096020526000908152604090205481565b6005546001600160a01b031633146114945760405162461bcd60e51b815260040180806020018281038252603d815260200180612506603d913960400191505060405180910390fd5b600680546001600160a01b0319166001600160a01b0392909216919091179055565b60006114c130611b48565b15905090565b60008282111561151e576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60008261153357506000610a19565b8282028284828161154057fe5b041461157d5760405162461bcd60e51b81526004018080602001828103825260218152602001806126136021913960400191505060405180910390fd5b9392505050565b60008082116115da576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b8183816115e357fe5b049392505050565b60008282018381101561157d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611120908590611b4e565b6001546006546040805163e8eda9df60e01b81526001600160a01b03868116600483015260248201869052306044830152600160a01b90930461ffff1660648201529051919092169163e8eda9df91608480830192600092919082900301818387803b15801561170e57600080fd5b505af11580156109bd573d6000803e3d6000fd5b8015806117a8575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b15801561177a57600080fd5b505afa15801561178e573d6000803e3d6000fd5b505050506040513d60208110156117a457600080fd5b5051155b6117e35760405162461bcd60e51b81526004018080602001828103825260368152602001806127306036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052611835908490611b4e565b505050565b6001546004805460408051631a4ca37b60e21b81526001600160a01b03878116948201949094526024810186905291831660448301525160009392909216916369328dec9160648082019260209290919082900301818787803b1580156118a057600080fd5b505af11580156118b4573d6000803e3d6000fd5b505050506040513d60208110156118ca57600080fd5b50519392505050565b6000806118de610b3f565b905060006118ec86836109c5565b905061190e670de0b6b3a76400006109fe61190784896114c7565b8a90611524565b92508282101561194f5760405162461bcd60e51b815260040180806020018281038252602d815260200180612543602d913960400191505060405180910390fd5b61195982846114c7565b600755600881905561196b8385611bff565b5050949350505050565b6119896001600160a01b0387168587611722565b600061199786868585611d25565b90506001600160a01b0385166338ed1739876119c260646109fe6119bb828b6114c7565b8790611524565b60045486906001600160a01b03166119dc426107086115eb565b6040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b83811015611a4c578181015183820152602001611a34565b505050509050019650505050505050600060405180830381600087803b158015611a7557600080fd5b505af1158015611a89573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015611ab257600080fd5b8101908080516040519392919084640100000000821115611ad257600080fd5b908301906020820185811115611ae757600080fd5b8251866020820283011164010000000082111715611b0457600080fd5b82525081516020918201928201910280838360005b83811015611b31578181015183820152602001611b19565b505050509050016040525050505050505050505050565b3b151590565b6060611ba3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611dc39092919063ffffffff16565b80519091501561183557808060200190516020811015611bc257600080fd5b50516118355760405162461bcd60e51b815260040180806020018281038252602a81526020018061269e602a913960400191505060405180910390fd5b8115610b2c576040805160018082528183019092526060916020808301908036833750506000805483519394506201000090046001600160a01b031692849250611c4557fe5b6001600160a01b03928316602091820292909201810191909152600354604051633111e7b360e01b81526024810187905285841660448201526060600482019081528551606483015285519290941693633111e7b393869389938993928392608490920191878201910280838360005b83811015611ccd578181015183820152602001611cb5565b50505050905001945050505050602060405180830381600087803b158015611cf457600080fd5b505af1158015611d08573d6000803e3d6000fd5b505050506040513d6020811015611d1e57600080fd5b5050505050565b600080846001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b158015611d6157600080fd5b505afa158015611d75573d6000803e3d6000fd5b505050506040513d6020811015611d8b57600080fd5b505190506060611d9d82888688611dda565b905080600182510381518110611daf57fe5b602002602001015192505050949350505050565b6060611dd28484600085611f28565b949350505050565b6060600283511015611e33576040805162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f504154480000604482015290519081900360640190fd5b825167ffffffffffffffff81118015611e4b57600080fd5b50604051908082528060200260200182016040528015611e75578160200160208202803683370190505b5090508381600081518110611e8657fe5b60200260200101818152505060005b6001845103811015611f1f57600080611ed988878581518110611eb457fe5b6020026020010151888660010181518110611ecb57fe5b602002602001015188612084565b91509150611efb848481518110611eec57fe5b60200260200101518383612179565b848460010181518110611f0a57fe5b60209081029190910101525050600101611e95565b50949350505050565b606082471015611f695760405162461bcd60e51b81526004018080602001828103825260268152602001806124b96026913960400191505060405180910390fd5b611f7285611b48565b611fc3576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106120025780518252601f199092019160209182019101611fe3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612064576040519150601f19603f3d011682016040523d82523d6000602084013e612069565b606091505b5091509150612079828286612259565b979650505050505050565b600080600061209386866122fd565b50905060006120a4888888886123c5565b9050803b8015612164576000829050600080826001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b1580156120ef57600080fd5b505afa158015612103573d6000803e3d6000fd5b505050506040513d606081101561211957600080fd5b5080516020909101516dffffffffffffffffffffffffffff91821693501690506001600160a01b038b811690871614612153578082612156565b81815b909850965061216d92505050565b60009450600093505b50505094509492505050565b60008084116121b95760405162461bcd60e51b815260040180806020018281038252603481526020018061266a6034913960400191505060405180910390fd5b6000831180156121c95750600082115b6122045760405162461bcd60e51b81526004018080602001828103825260318152602001806124646031913960400191505060405180910390fd5b6000612212856103e5611524565b905060006122208285611524565b9050600061223a83612234886103e8611524565b906115eb565b9050801561224f5780828161224b57fe5b0493505b5050509392505050565b6060831561226857508161157d565b8251156122785782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156122c25781810151838201526020016122aa565b50505050905090810190601f1680156122ef5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b600080826001600160a01b0316846001600160a01b031614156123515760405162461bcd60e51b815260040180806020018281038252602e8152602001806126c8602e913960400191505060405180910390fd5b826001600160a01b0316846001600160a01b031610612371578284612374565b83835b90925090506001600160a01b0382166123be5760405162461bcd60e51b81526004018080602001828103825260278152602001806124df6027913960400191505060405180910390fd5b9250929050565b60008060006123d486866122fd565b604080516bffffffffffffffffffffffff19606094851b811660208084019190915293851b81166034830152825160288184030181526048830184528051908501206001600160f81b031960688401529b90941b9093166069840152607d830199909952609d808301969096528851808303909601865260bd909101909752505081519190940120939250505056fe556e69737761705574696c7323676574416d6f756e744f75743a20494e53554646494349454e545f4c4951554944495459416176655969656c643a20476f7665726e616e63653a3a207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c5375736869737761705574696c7323736f7274546f6b656e733a205a45524f5f41444452455353596561726e5969656c643a204f6e6c7920676f7665726e616e636520636f6e74726163742063616e20696e766f6b6520746869732066756e6374696f6e416176655969656c643a434154523a3a20746f74616c2072657761726420657863656564732072657761726473496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564416176655969656c643a206c656e64696e67506f6f6c3a3a207a65726f2061646472657373416176655969656c643a2053796d70686f6e793a3a207a65726f2061646472657373416176655969656c643a2070726f746f636f6c4461746150726f76696465723a3a207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416176655969656c643a2041737365742063616e2774206265206368616e67656420616674657220696e6974696c697a6174696f6e2e556e69737761705574696c7323676574416d6f756e744f75743a20494e53554646494349454e545f494e5055545f414d4f554e545361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645375736869737761705574696c7323736f7274546f6b656e733a204944454e544943414c5f414444524553534553416176655969656c643a204f6e6c792073796d70686f6e7920636f6e74726163742063616e20696e766f6b6520746869732066756e6374696f6e5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220dc8154f13f1cf0b86b4ffb70ca314bc182a11881c7e65cf6d6dbd0ebc4af301764736f6c63430007040033

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