ETH Price: $2,350.23 (+0.52%)
Gas: 41 Gwei

Contract

0x01fE7ff1162D4b4aB41bdaf99296644b7b0eE27D
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Sponsored

Transaction Hash
Method
Block
From
To
Value
Transfer Ownersh...154408732022-08-30 14:24:56465 days 4 hrs ago1661869496IN
0x01fE7f...7b0eE27D
0 ETH0.0009154532
Set Initial Chil...154408732022-08-30 14:24:56465 days 4 hrs ago1661869496IN
0x01fE7f...7b0eE27D
0 ETH0.001771132
0x61012060154408402022-08-30 14:16:42465 days 4 hrs ago1661869002IN
 Create: AlphaBetaEqualDepositMaxSplitter
0 ETH0.0971546232

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AlphaBetaEqualDepositMaxSplitter

Compiler Version
v0.8.10+commit.fc410830

Optimization Enabled:
Yes with 20000 runs

Other Settings:
default evmVersion
File 1 of 13 : AlphaBetaEqualDepositMaxSplitter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.10;

/******************************************************************************\
* Author: Evert Kors <[email protected]> (https://twitter.com/evert0x)
* Sherlock Protocol: https://sherlock.xyz
/******************************************************************************/

import './AlphaBetaEqualDepositSplitter.sol';

/**
  ChildOne is the first node that is being used to withdraw from
  Only when ChildOne balance = 0 it will start withdrawing from ChildTwo

  If the deposit amount is at least `MIN_AMOUNT_FOR_EQUAL_SPLIT` of USDC
  It will try to balance out the childs by havng the option to deposit in both

  If the deposit amount is less then `MIN_AMOUNT_FOR_EQUAL_SPLIT` of USDC
  It will deposit in the child that returns the lowest balance

  Either childOne or childTwo can have a limit for the amount of USDC to receive

  Note: the child without a limit can receive two `deposit()` calls
  if the initial amount is at least `MIN_AMOUNT_FOR_EQUAL_SPLIT` USDC
*/
contract AlphaBetaEqualDepositMaxSplitter is AlphaBetaEqualDepositSplitter {
  uint256 private constant NO_LIMIT = type(uint256).max;
  // Max amount of USDC childOne can hold (type(uint256).max = no limit)
  uint256 public immutable MAX_AMOUNT_FOR_CHILD_ONE;
  // Max amount of USDC childTwo can hold (type(uint256).max = no limit)
  uint256 public immutable MAX_AMOUNT_FOR_CHILD_TWO;

  /// @param _initialParent Contract that will be the parent in the tree structure
  /// @param _initialChildOne Contract that will be the initial childOne in the tree structure
  /// @param _initialChildTwo Contract that will be the initial childTwo in the tree structure
  /// @param _MIN_AMOUNT_FOR_EQUAL_SPLIT Min USDC deposit amount to activate logic to equal out balances
  /// @param _MAX_AMOUNT_FOR_CHILD_ONE Max amount of USDC childOne can hold (type(uint256).max = no limit)
  /// @param _MAX_AMOUNT_FOR_CHILD_TWO Max amount of USDC childTwo can hold (type(uint256).max = no limit)
  /// @notice Either `_MAX_AMOUNT_FOR_CHILD_ONE` or `_MAX_AMOUNT_FOR_CHILD_TWO` has to be type(uint256).max
  constructor(
    IMaster _initialParent,
    INode _initialChildOne,
    INode _initialChildTwo,
    uint256 _MIN_AMOUNT_FOR_EQUAL_SPLIT,
    uint256 _MAX_AMOUNT_FOR_CHILD_ONE,
    uint256 _MAX_AMOUNT_FOR_CHILD_TWO
  )
    AlphaBetaEqualDepositSplitter(
      _initialParent,
      _initialChildOne,
      _initialChildTwo,
      _MIN_AMOUNT_FOR_EQUAL_SPLIT
    )
  {
    // Either `_MAX_AMOUNT_FOR_CHILD_ONE` or `_MAX_AMOUNT_FOR_CHILD_TWO` has to be type(uint256).max
    if (_MAX_AMOUNT_FOR_CHILD_ONE != NO_LIMIT && _MAX_AMOUNT_FOR_CHILD_TWO != NO_LIMIT) {
      revert InvalidArg();
    }

    // Either `_MAX_AMOUNT_FOR_CHILD_ONE` or `_MAX_AMOUNT_FOR_CHILD_TWO` has to be non type(uint256).max
    if (_MAX_AMOUNT_FOR_CHILD_ONE == NO_LIMIT && _MAX_AMOUNT_FOR_CHILD_TWO == NO_LIMIT) {
      revert InvalidArg();
    }

    // Write variables to storage
    MAX_AMOUNT_FOR_CHILD_ONE = _MAX_AMOUNT_FOR_CHILD_ONE;
    MAX_AMOUNT_FOR_CHILD_TWO = _MAX_AMOUNT_FOR_CHILD_TWO;
  }

  /// @notice Transfer USDC to one or both childs based on `MAX_AMOUNT_FOR_CHILD_ONE`
  /// @param _amount Amount of USDC to deposit
  function _childOneDeposit(uint256 _amount) internal virtual override {
    // Cache balance in memory
    uint256 childOneBalance = cachedChildOneBalance;

    // Do we want to deposit into childOne at all? If yes, continue
    if (childOneBalance < MAX_AMOUNT_FOR_CHILD_ONE) {
      // Will depositing the full amount result in exceeding the MAX? If yes, continue
      if (childOneBalance + _amount > MAX_AMOUNT_FOR_CHILD_ONE) {
        // How much room if left to hit the USDC cap in childOne
        uint256 childOneAmount = MAX_AMOUNT_FOR_CHILD_ONE - childOneBalance;

        // Deposit amount that will make us hit the cap for childOne
        AlphaBetaSplitter._childOneDeposit(childOneAmount);

        // Deposit leftover USDC into childTwo
        AlphaBetaSplitter._childTwoDeposit(_amount - childOneAmount);
      } else {
        // Deposit all in childOne if depositing full amount will not make us exceed the cap
        AlphaBetaSplitter._childOneDeposit(_amount);
      }
    } else {
      // Deposit all in childTwo (childOne deposit isn't used at all)
      AlphaBetaSplitter._childTwoDeposit(_amount);
    }
  }

  /// @notice Transfer USDC to one or both childs based on `MAX_AMOUNT_FOR_CHILD_TWO`
  /// @param _amount Amount of USDC to deposit
  function _childTwoDeposit(uint256 _amount) internal virtual override {
    // Cache balance in memory
    uint256 childTwoBalance = cachedChildTwoBalance;

    // Do we want to deposit into childTwo at all? If yes, continue
    if (childTwoBalance < MAX_AMOUNT_FOR_CHILD_TWO) {
      // Will depositing the full amount result in exceeding the MAX? If yes, continue
      if (childTwoBalance + _amount > MAX_AMOUNT_FOR_CHILD_TWO) {
        // How much room if left to hit the USDC cap in childTwo
        uint256 childTwoAmount = MAX_AMOUNT_FOR_CHILD_TWO - childTwoBalance;

        // Deposit amount that will make us hit the cap for childTwo
        AlphaBetaSplitter._childTwoDeposit(childTwoAmount);

        // Deposit leftover USDC into childOne
        AlphaBetaSplitter._childOneDeposit(_amount - childTwoAmount);
      } else {
        // Deposit all in childTwo if depositing full amount will not make us exceed the cap
        AlphaBetaSplitter._childTwoDeposit(_amount);
      }
    } else {
      // Deposit all in childOne (childTwo deposit isn't used at all)
      AlphaBetaSplitter._childOneDeposit(_amount);
    }
  }
}

File 2 of 13 : AlphaBetaEqualDepositSplitter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.10;

/******************************************************************************\
* Author: Evert Kors <[email protected]> (https://twitter.com/evert0x)
* Sherlock Protocol: https://sherlock.xyz
/******************************************************************************/

import './AlphaBetaSplitter.sol';

/**
  ChildOne is the first node that is being used to withdraw from
  Only when ChildOne balance = 0 it will start withdrawing from ChildTwo

  If the deposit amount is at least `MIN_AMOUNT_FOR_EQUAL_SPLIT` of USDC
  It will try to balance out the childs by havng the option to deposit in both

  If the deposit amount is less then `MIN_AMOUNT_FOR_EQUAL_SPLIT` of USDC
  It will deposit in the child that returns the lowest balance
*/
contract AlphaBetaEqualDepositSplitter is AlphaBetaSplitter {
  // Min USDC deposit amount to activate logic to equal out balances
  uint256 public immutable MIN_AMOUNT_FOR_EQUAL_SPLIT;

  /// @param _initialParent Contract that will be the parent in the tree structure
  /// @param _initialChildOne Contract that will be the initial childOne in the tree structure
  /// @param _initialChildTwo Contract that will be the initial childTwo in the tree structure
  /// @param _MIN_AMOUNT_FOR_EQUAL_SPLIT Min USDC deposit amount to activate logic to equal out balances
  constructor(
    IMaster _initialParent,
    INode _initialChildOne,
    INode _initialChildTwo,
    uint256 _MIN_AMOUNT_FOR_EQUAL_SPLIT
  ) AlphaBetaSplitter(_initialParent, _initialChildOne, _initialChildTwo) {
    // Write variable to storage
    MIN_AMOUNT_FOR_EQUAL_SPLIT = _MIN_AMOUNT_FOR_EQUAL_SPLIT;
  }

  /// @notice Deposit USDC into one or both childs
  function _deposit() internal virtual override {
    // Amount of USDC in the contract
    uint256 amount = want.balanceOf(address(this));

    // Try to balance out childs if at least `MIN_AMOUNT_FOR_EQUAL_SPLIT` USDC is deposited
    if (amount >= MIN_AMOUNT_FOR_EQUAL_SPLIT) {
      // Cache balances in memory
      uint256 childOneBalance = cachedChildOneBalance;
      uint256 childTwoBalance = cachedChildTwoBalance;

      if (childOneBalance <= childTwoBalance) {
        // How much extra balance does childTWo have?
        // Can be 0
        uint256 childTwoBalanceExtra = childTwoBalance - childOneBalance;

        // If the difference exceeds the amount we can deposit it all in childOne
        // As this brings the two balances close to each other
        if (childTwoBalanceExtra >= amount) {
          // Deposit all USDC into childOne
          _childOneDeposit(amount);
        } else {
          // Depositing in a single child will not make the balances equal
          // So we have to deposit in both childs

          // We know childTwo has a bigger balance
          // Calculting how much to deposit in childTwo
          /**
            Example

            One = 180k USDC
            Two = 220k USDC
            amount = 100k USDC

            childTwoAdd = (100 - (220 - 180)) / 2 = 30k
            childOneAdd = 100k - 30k = 70k
            ---+
            One = 250k USDC
            Two = 250k USDC
          */
          uint256 childTwoAdd = (amount - childTwoBalanceExtra) / 2;
          // Deposit USDC into childTwo
          _childTwoDeposit(childTwoAdd);
          // Deposit leftover USDC into childOne
          _childOneDeposit(amount - childTwoAdd);
        }
      } else {
        // Do same logic as above but for the scenario childOne has a bigger balance

        uint256 childOneBalanceExtra = childOneBalance - childTwoBalance;

        if (childOneBalanceExtra >= amount) {
          // Deposit all USDC into childTwo
          _childTwoDeposit(amount);
        } else {
          uint256 childOneAdd = (amount - childOneBalanceExtra) / 2;
          // Deposit USDC into childOne
          _childOneDeposit(childOneAdd);
          // Deposit leftover USDC into childTwo
          _childTwoDeposit(amount - childOneAdd);
        }
      }
    } else {
      // Use deposit function based on balance
      AlphaBetaSplitter._deposit();
    }
  }
}

File 3 of 13 : AlphaBetaSplitter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.10;

/******************************************************************************\
* Author: Evert Kors <[email protected]> (https://twitter.com/evert0x)
* Sherlock Protocol: https://sherlock.xyz
/******************************************************************************/

import '../base/BaseSplitter.sol';

/**
  ChildOne is the first node that is being used to withdraw from
  Only when ChildOne balance = 0 it will start withdrawing from ChildTwo

  It will deposit in the child that returns the lowest balance (childOne first)
*/
contract AlphaBetaSplitter is BaseSplitter {
  using SafeERC20 for IERC20;

  /// @param _initialParent Contract that will be the parent in the tree structure
  /// @param _initialChildOne Contract that will be the initial childOne in the tree structure
  /// @param _initialChildTwo Contract that will be the initial childTwo in the tree structure
  constructor(
    IMaster _initialParent,
    INode _initialChildOne,
    INode _initialChildTwo
  ) BaseSplitter(_initialParent, _initialChildOne, _initialChildTwo) {}

  /// @notice Signal to withdraw `_amount` of USDC from the underlying nodes into core
  /// @param _amount Amount of USDC to withdraw
  function _withdraw(uint256 _amount) internal virtual override {
    // First in line for liquidations
    uint256 childOneBalance = cachedChildOneBalance;

    // If the amount exceeds childOne balance, it will start withdrawing from childTwo
    if (_amount > childOneBalance) {
      // Withdraw all USDC from childOne
      if (childOneBalance != 0) childOne.withdrawAll();

      // Withdraw USDC from childTwo when childOne balance hits zero
      childTwo.withdraw(_amount - childOneBalance);
    } else {
      // Withdraw from childOne
      childOne.withdraw(_amount);
    }
  }

  /// @notice Transfer USDC to childOne and call deposit
  /// @param _amount Amount of USDC to deposit
  function _childOneDeposit(uint256 _amount) internal virtual {
    // Transfer USDC to childOne
    want.safeTransfer(address(childOne), _amount);

    // Signal childOne it received a deposit
    childOne.deposit();
  }

  /// @notice Transfer USDC to childTwo and call deposit
  /// @param _amount Amount of USDC to deposit
  function _childTwoDeposit(uint256 _amount) internal virtual {
    // Transfer USDC to childTwo
    want.safeTransfer(address(childTwo), _amount);

    // Signal childOne it received a deposit
    childTwo.deposit();
  }

  /// @notice Deposit USDC into one child
  function _deposit() internal virtual override {
    // Deposit USDC into strategy that has the lowest balance
    if (cachedChildOneBalance <= cachedChildTwoBalance) {
      _childOneDeposit(want.balanceOf(address(this)));
    } else {
      _childTwoDeposit(want.balanceOf(address(this)));
    }
  }
}

File 4 of 13 : BaseSplitter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.10;

/******************************************************************************\
* Author: Evert Kors <[email protected]> (https://twitter.com/evert0x)
* Sherlock Protocol: https://sherlock.xyz
/******************************************************************************/

import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '@openzeppelin/contracts/security/Pausable.sol';

import '../../interfaces/strategy/INode.sol';
import './BaseMaster.sol';

// Interface used by every splitter
abstract contract BaseSplitter is BaseMaster, ISplitter {
  using SafeERC20 for IERC20;
  // ChildNode
  INode public override childTwo;

  /*//////////////////////////////////////////////////////////////
                        TREE STRUCTURE LOGIC
  //////////////////////////////////////////////////////////////*/

  /// @param _initialParent The initial parent of this node
  /// @param _initialChildOne The initial childOne of this node
  /// @param _initialChildTwo The initial childTwo of this node
  constructor(
    IMaster _initialParent,
    INode _initialChildOne,
    INode _initialChildTwo
  ) BaseNode(_initialParent) {
    if (address(_initialChildOne) != address(0)) {
      _verifySetChildSkipParentCheck(INode(address(0)), _initialChildOne);
      _setChildOne(INode(address(0)), _initialChildOne);
    }

    if (address(_initialChildTwo) != address(0)) {
      _verifySetChildSkipParentCheck(INode(address(0)), _initialChildTwo);
      _setChildTwo(INode(address(0)), _initialChildTwo);
    }
  }

  /// @notice Check if this splitter is a master node
  /// @dev This implementation has two childs, it can never be a master (needs one child)
  function isMaster() external view override returns (bool) {
    return false;
  }

  /// @notice Check if this splitter completed it's setup
  /// @return completed Boolean indicating if setup is completed
  function setupCompleted() external view override returns (bool completed) {
    (completed, , ) = _setupCompleted();
  }

  /// @notice Check if this splitter completed it's setup
  /// @return completed Boolean indicating if setup is completed
  /// @return _childOne ChildOne read from storage
  /// @return _childTwo ChildTwo read from storage
  function _setupCompleted()
    internal
    view
    returns (
      bool completed,
      INode _childOne,
      INode _childTwo
    )
  {
    _childOne = childOne;
    _childTwo = childTwo;

    completed = address(_childOne) != address(0) && address(_childTwo) != address(0);
  }

  /// @notice Replace this splitter
  /// @param _node Splitter to be replaced by
  /// @dev only callable by owner
  /// @dev Same as `replace()`
  function replaceForce(INode _node) external virtual override {
    replace(_node);
    emit ForceReplace();
  }

  /// @notice Replace this splitter
  /// @param __newNode Splitter to be replaced by
  /// @dev only callable by owner
  function replace(INode __newNode) public virtual override onlyOwner {
    // Get childs from storage
    (bool completed, INode _childOne, INode _childTwo) = _setupCompleted();
    // Check if setup of this is completed
    if (completed == false) revert SetupNotCompleted(INode(address(this)));

    // Use ISplitter interface
    ISplitter _newNode = ISplitter(address(__newNode));

    // Check if same childs are used in `_newNode`
    if (_newNode.childOne() != _childOne) revert InvalidChildOne();
    if (_newNode.childTwo() != _childTwo) revert InvalidChildTwo();

    // Replace this with `_newNode`
    _replace(_newNode);

    // Make sure children have reference to `_newNode`
    _childOne.updateParent(_newNode);
    _childTwo.updateParent(_newNode);
  }

  /// @notice Get notified by child that it wants to be replaced by `_newChild`
  /// @param _newChild address of new child
  function updateChild(INode _newChild) external virtual override {
    // Get childs from storage
    (bool completed, INode _childOne, INode _childTwo) = _setupCompleted();
    // Check if setup of this is completed
    if (completed == false) revert SetupNotCompleted(INode(address(this)));

    // Is sender childOne?
    if (msg.sender == address(_childOne)) {
      // Can't have duplicate childs
      if (_newChild == _childTwo) revert InvalidArg();

      // Check if we are able to update
      _verifySetChild(_childOne, _newChild);
      // Execute update
      _setChildOne(_childOne, _newChild);
    } else if (msg.sender == address(_childTwo)) {
      // Is sender childTwo?

      // Can't have duplicate childs
      if (_newChild == _childOne) revert InvalidArg();

      // Check if we are able to update
      _verifySetChild(_childTwo, _newChild);
      // Execute update
      _setChildTwo(_childTwo, _newChild);
    } else {
      // Sender wasn't actually a child
      revert SenderNotChild();
    }
  }

  /// @notice Get notified by child that it is removed
  function childRemoved() external virtual override {
    // Get childs from storage
    (bool completed, INode _childOne, INode _childTwo) = _setupCompleted();
    // Check if setup of this is completed
    if (completed == false) revert SetupNotCompleted(INode(address(this)));

    // Is sender childOne?
    if (msg.sender == address(_childOne)) {
      // Notify childTwo that it's sibling has been removed
      _childTwo.siblingRemoved();
      // Tell parent to make a relationship with our non removed child
      parent.updateChild(_childTwo);

      // Declare removed child obsolete
      emit Obsolete(_childOne);
    } else if (msg.sender == address(_childTwo)) {
      // Notify childOne that it's sibling has been removed
      _childOne.siblingRemoved();
      // Tell parent to make a relationship with our non removed child
      parent.updateChild(_childOne);

      // Declare removed child obsolete
      emit Obsolete(_childTwo);
    } else {
      revert SenderNotChild();
    }

    // Declare address(this) obsolete
    emit Obsolete(INode(address(this)));
  }

  /// @notice Set childTwo in storage
  /// @param _currentChild The `childTwo` currently stored
  /// @param _newChild The `childTwo` that is stored after this call
  function _setChildTwo(INode _currentChild, INode _newChild) internal {
    childTwo = _newChild;
    emit ChildTwoUpdate(_currentChild, _newChild);
  }

  /// @notice Set initial childTwo
  /// @param _newChild Address of the initial child
  function setInitialChildTwo(INode _newChild) external override onlyOwner {
    if (address(childTwo) != address(0)) revert InvalidState();

    _verifySetChild(INode(address(0)), _newChild);
    _setChildTwo(INode(address(0)), _newChild);
  }

  /*//////////////////////////////////////////////////////////////
                        YIELD STRATEGY LOGIC
  //////////////////////////////////////////////////////////////*/

  // Internal variables to cache balances during runtime
  // Will always be 0 (except during runtime)
  uint256 internal cachedChildOneBalance;
  uint256 internal cachedChildTwoBalance;

  /// @notice Cache balances of childs in storage
  /// @notice Can only be called by parent node
  /// @dev It will first tell childs to cache their balances
  /// @dev Cache is built up from the bottom of the tree
  /// @dev As the chain returns when the bottom (strategies) are being called
  function prepareBalanceCache() external override onlyParent returns (uint256) {
    // Query balance of childs
    uint256 _cachedChildOneBalance = childOne.prepareBalanceCache();
    uint256 _cachedChildTwoBalance = childTwo.prepareBalanceCache();

    // Write balances to storage
    // It's "cached" as we expect/assume `expireBalanceCache()` will be called in the same transaction
    cachedChildOneBalance = _cachedChildOneBalance;
    cachedChildTwoBalance = _cachedChildTwoBalance;

    // Return the balance of this splitter to parent
    // The balance this splitter represent is the sum of the childs
    return _cachedChildOneBalance + _cachedChildTwoBalance;
  }

  /// @notice Expired cached balances in storage
  /// @notice Can only be called by parent node
  /// @dev It assumes `prepareBalanceCache()` was called before
  function expireBalanceCache() external override onlyParent {
    // Set cached balances back to the value of the start of the transaction (--> 0)
    delete cachedChildOneBalance;
    delete cachedChildTwoBalance;
  }

  /// @notice Withdraw all funds
  /// @notice Can only be called by admin
  /// @notice Not implemented
  /// @return amount Amount of USDC withdrawn
  /// @dev More context: https://github.com/sherlock-protocol/sherlock-v2-core/issues/24
  function withdrawAllByAdmin() external override onlyOwner returns (uint256 amount) {
    revert NotImplemented(msg.sig);
  }

  /// @notice Withdraw `_amount` funds
  /// @notice Can only be called by admin
  /// @notice Not implemented
  /// @dev More context: https://github.com/sherlock-protocol/sherlock-v2-core/issues/24
  function withdrawByAdmin(uint256 _amount) external override onlyOwner {
    revert NotImplemented(msg.sig);
  }

  function _withdrawAll() internal virtual override returns (uint256 amount) {
    // Children will withdraw to core()
    amount = childOne.withdrawAll();
    amount += childTwo.withdrawAll();
  }

  function _balanceOf() internal view virtual override returns (uint256 amount) {
    amount = childOne.balanceOf();
    amount += childTwo.balanceOf();
  }
}

File 5 of 13 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 6 of 13 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)

pragma solidity ^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 7 of 13 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.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 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'
        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) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _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
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 8 of 13 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 9 of 13 : INode.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.10;

/******************************************************************************\
* Author: Evert Kors <[email protected]> (https://twitter.com/evert0x)
* Sherlock Protocol: https://sherlock.xyz
/******************************************************************************/

import '@openzeppelin/contracts/token/ERC20/IERC20.sol';

interface INode {
  event AdminWithdraw(uint256 amount);
  event ReplaceAsChild();
  event ParentUpdate(IMaster previous, IMaster current);
  event Obsolete(INode implementation);
  event ForceReplace();
  event Replace(INode newAddress);

  error NotImplemented(bytes4 func);
  error SenderNotParent();
  error SenderNotChild();
  error InvalidParent();
  error InvalidCore();
  error InvalidWant();
  error InvalidState();
  error ZeroArg();
  error InvalidArg();
  error NotSetup();
  error IsMaster();
  error BothChild();
  error NotChild();
  error InvalidParentAddress();
  error SetupNotCompleted(INode instance);
  error NonZeroBalance();

  /*//////////////////////////////////////////////////////////////
                        CONSTRUCTOR VARIABLES
  //////////////////////////////////////////////////////////////*/

  /// @return Returns the token type being deposited into a node
  function want() external view returns (IERC20);

  /// @notice Parent will always inherit IMaster interface.
  /// @notice Parent of root node will inherit IStrategyManager
  function parent() external view returns (IMaster);

  /// @notice View core controller of funds
  function core() external view returns (address);

  /*//////////////////////////////////////////////////////////////
                        TREE STRUCTURE LOGIC
  //////////////////////////////////////////////////////////////*/

  /// @notice Replace the node
  /// @notice If this is executed on a strategy, the funds will be withdrawn
  /// @notice If this is executed on a splitter, the children are expected to be the same
  function replace(INode _node) external;

  /// @notice Replace the node
  /// @notice If this is executed on a strategy, attempt is made to withdraw the funds
  /// @notice If this is executed on a splitter, check of children is skipped
  function replaceForce(INode _node) external;

  function setupCompleted() external view returns (bool);

  /// @notice Move the current node as the child of `_node`
  function replaceAsChild(ISplitter _node) external;

  /// @notice Update parent of node
  /// @dev Can only be called by current parent
  function updateParent(IMaster _node) external;

  function siblingRemoved() external;

  /*//////////////////////////////////////////////////////////////
                        YIELD STRATEGY LOGIC
  //////////////////////////////////////////////////////////////*/

  /// @return Returns the token balance managed by this contract
  /// @dev For Splitter this will be the sum of balances of the children
  function balanceOf() external view returns (uint256);

  /// @notice Withdraws all tokens back into core.
  /// @return The final amount withdrawn
  function withdrawAll() external returns (uint256);

  /// @notice Withdraws all token from the node back into core
  /// @return The final amount withdrawn
  function withdrawAllByAdmin() external returns (uint256);

  /// @notice Withdraws a specific amount of tokens from the node back into core
  /// @param _amount Amount of tokens to withdraw
  function withdraw(uint256 _amount) external;

  /// @notice Withdraws a specific amount of tokens from the node back into core
  /// @param _amount Amount of tokens to withdraw
  function withdrawByAdmin(uint256 _amount) external;

  /// @notice Deposits all tokens held in this contract into the children on strategy
  /// @dev Splitter will deposit the tokens in their children
  /// @dev Strategy will deposit the tokens into a yield strategy
  function deposit() external;

  function prepareBalanceCache() external returns (uint256);

  function expireBalanceCache() external;
}

interface IMaster is INode {
  event ChildOneUpdate(INode previous, INode current);

  /// @notice Call by child if it's needs to be updated
  function updateChild(INode _node) external;

  /// @notice Call by child if removed
  function childRemoved() external;

  function isMaster() external view returns (bool);

  function childOne() external view returns (INode);

  function setInitialChildOne(INode _child) external;
}

interface ISplitter is IMaster {
  event ChildTwoUpdate(INode previous, INode current);

  error InvalidChildOne();
  error InvalidChildTwo();

  function childTwo() external view returns (INode);

  function setInitialChildTwo(INode _child) external;
}

File 10 of 13 : BaseMaster.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.10;

/******************************************************************************\
* Author: Evert Kors <[email protected]> (https://twitter.com/evert0x)
* Sherlock Protocol: https://sherlock.xyz
/******************************************************************************/

import '@openzeppelin/contracts/access/Ownable.sol';

import '../../interfaces/strategy/INode.sol';
import '../../interfaces/strategy/INode.sol';
import './BaseNode.sol';

// Interface used by the MasterStrategy, the contract core will reference as `yieldStrategy`
abstract contract BaseMaster is IMaster, BaseNode {
  // ChildNode
  INode public override childOne;

  /// @notice Verify if `_newChild` is able to replace `_currentChild` without doing same parent check
  /// @param _currentChild Node that is the current child
  /// @param _newChild Node that is the new child
  function _verifySetChildSkipParentCheck(INode _currentChild, INode _newChild) internal {
    if (address(_newChild) == address(0)) revert ZeroArg();
    if (_newChild.setupCompleted() == false) revert SetupNotCompleted(_newChild);

    if (_newChild == _currentChild) revert InvalidArg();
    if (core != _newChild.core()) revert InvalidCore();
    if (want != _newChild.want()) revert InvalidWant();
  }

  /// @notice Verify if `_newChild` is able to replace `_currentChild`
  /// @param _currentChild Node that is the current child
  /// @param _newChild Node that is the new child
  function _verifySetChild(INode _currentChild, INode _newChild) internal {
    _verifySetChildSkipParentCheck(_currentChild, _newChild);
    // NOTE this check is basically one here for the `updateChild` call in splitter
    if (address(_newChild.parent()) != address(this)) revert InvalidParent();
  }

  /// @notice Set childOne in storage
  /// @param _currentChild The `childOne` currently stored
  /// @param _newChild The `childOne` that is stored after this call
  function _setChildOne(INode _currentChild, INode _newChild) internal {
    childOne = _newChild;
    emit ChildOneUpdate(_currentChild, _newChild);
  }

  /// @notice Set initial childOne
  /// @param _newChild Address of the initial child
  function setInitialChildOne(INode _newChild) external override onlyOwner {
    if (address(childOne) != address(0)) revert InvalidState();

    _verifySetChild(INode(address(0)), _newChild);
    _setChildOne(INode(address(0)), _newChild);
  }
}

File 11 of 13 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 12 of 13 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)

pragma solidity ^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;
        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");

        (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");

        (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");

        (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");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal 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

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 13 of 13 : BaseNode.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.10;

/******************************************************************************\
* Author: Evert Kors <[email protected]> (https://twitter.com/evert0x)
* Sherlock Protocol: https://sherlock.xyz
/******************************************************************************/

import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';

import '../../interfaces/strategy/INode.sol';

// Interface used by every node
abstract contract BaseNode is INode, Ownable {
  using SafeERC20 for IERC20;

  // Parent node
  IMaster public override parent;
  // Which token the strategy uses (USDC)
  IERC20 public immutable override want;
  // Reference to core (Sherlock.sol)
  address public immutable override core;

  /// @param _initialParent The initial parent of this node
  constructor(IMaster _initialParent) {
    if (address(_initialParent) == address(0)) revert ZeroArg();

    IERC20 _want = _initialParent.want();
    address _core = _initialParent.core();

    if (address(_want) == address(0)) revert InvalidWant();
    if (address(_core) == address(0)) revert InvalidCore();

    want = _want;
    core = _core;
    parent = _initialParent;

    emit ParentUpdate(IMaster(address(0)), _initialParent);
  }

  modifier onlyParent() {
    if (msg.sender != address(parent)) revert SenderNotParent();
    _;
  }

  /*//////////////////////////////////////////////////////////////
                        TREE STRUCTURE LOGIC
  //////////////////////////////////////////////////////////////*/

  /// @notice Replace this node to be a child of `_newParent`
  /// @param _newParent address of the new parent
  /// @dev Replace as child ensures that (this) is the child of the `_newParent`
  /// @dev It will also enfore a `_executeParentUpdate` to make that relation bi-directional
  /// @dev For the other child is does minimal checks, it only checks if it isn't the same as address(this)
  function replaceAsChild(ISplitter _newParent) external virtual override onlyOwner {
    /*
          m
          |
        this

          m
          |
          1
         / \
        z  this
    */

    // Gas savings
    IMaster _currentParent = parent;

    // Revert is parent is master
    // The master is always at the root of the tree
    if (_newParent.isMaster()) revert IsMaster();

    // Verify if the new parent has the right connections
    _verifyParentUpdate(_currentParent, _newParent);
    // Verify is childs of newParent are correct
    INode otherChild = _verifyNewParent(_newParent);

    // Revert if otherchild = 0
    // Revert if the other child has the right parent reference too
    // Check if `z` has the right parent (referencing comment on top function)
    if (otherChild.parent() != _newParent) revert InvalidParent();

    // Check if `_newParent` references our currentParent as their parent
    // Check if `m` == `1`.parent() (referencing comment on top function)
    if (_currentParent != _newParent.parent()) revert InvalidParent();

    // Make sure the parent recognizes the new child
    // Make sure `m` references `1` as it's child (referencing comment on top function)
    _currentParent.updateChild(_newParent);

    // Update parent
    _executeParentUpdate(_currentParent, _newParent);

    emit ReplaceAsChild();
  }

  /// @notice Replace parent of this node
  /// @param _newParent Address of the new parent
  /// @dev Only callable by current parent
  function updateParent(IMaster _newParent) external virtual override onlyParent {
    // Verify if the parent can be updated
    _verifyParentUpdate(IMaster(msg.sender), _newParent);
    _verifyNewParent(_newParent);

    // Update parent
    _executeParentUpdate(IMaster(msg.sender), _newParent);
  }

  /// @notice Get notified by parent that your sibling is removed
  /// @dev This contract will take the position of the parent
  /// @dev Only callable by current parent
  function siblingRemoved() external override onlyParent {
    // Get current parent of parent
    IMaster _newParent = parent.parent();

    // Take position of current parent
    _verifyParentUpdate(IMaster(msg.sender), _newParent);
    // NOTE: _verifyNewParent() is skipped on this call
    // As address(this) should be added as a child after the function returns
    _executeParentUpdate(IMaster(msg.sender), _newParent);
  }

  /// @notice Verify if `_newParent` is able to be our new parent
  /// @param _newParent Address of the new parent
  /// @return otherChild Address of the child that isn't address(this)
  function _verifyNewParent(IMaster _newParent) internal view returns (INode otherChild) {
    // The setup needs to be completed of parent
    if (_newParent.setupCompleted() == false) revert SetupNotCompleted(_newParent);

    // get first child
    INode firstChild = _newParent.childOne();
    INode secondChild;

    // is address(this) childOne?
    bool isFirstChild = address(firstChild) == address(this);
    bool isSecondChild = false;

    // Parent only has a childTwo if it isn't master
    if (!_newParent.isMaster()) {
      // get second child
      secondChild = ISplitter(address(_newParent)).childTwo();
      // is address(this) childTwo?
      isSecondChild = address(secondChild) == address(this);
    }

    // Check if address(this) is referenced as both childs
    if (isFirstChild && isSecondChild) revert BothChild();
    // Check if address(this) isn't referenced at all
    if (!isFirstChild && !isSecondChild) revert NotChild();

    // return child that isn't address(this)
    if (isFirstChild) {
      return secondChild;
    }
    return firstChild;
  }

  /// @notice Verify if `_newParent` can replace `_currentParent`
  /// @param _currentParent Address of our current `parent`
  /// @param _newParent Address of our future `parent`
  function _verifyParentUpdate(IMaster _currentParent, IMaster _newParent) internal view {
    // Revert if it's the same address
    if (address(_newParent) == address(this)) revert InvalidParentAddress();
    // Revert if the address is parent
    if (address(_newParent) == address(_currentParent)) revert InvalidParentAddress();
    // Revert if core is invalid
    if (_currentParent.core() != _newParent.core()) revert InvalidCore();
    // Revert if want is invalid
    if (_currentParent.want() != _newParent.want()) revert InvalidWant();
  }

  /// @notice Set parent in storage
  /// @param _currentParent Address of our current `parent`
  /// @param _newParent Address of our future `parent`
  function _executeParentUpdate(IMaster _currentParent, IMaster _newParent) internal {
    // Make `_newParent` our new parent
    parent = _newParent;
    emit ParentUpdate(_currentParent, _newParent);
  }

  /// @notice Replace address(this) with `_newNode`
  function _replace(INode _newNode) internal {
    if (address(_newNode) == address(0)) revert ZeroArg();
    if (_newNode.setupCompleted() == false) revert SetupNotCompleted(_newNode);
    if (address(_newNode) == address(this)) revert InvalidArg();
    if (_newNode.parent() != parent) revert InvalidParent();
    if (_newNode.core() != core) revert InvalidCore();
    if (_newNode.want() != want) revert InvalidWant();

    // Make sure our parent references `_newNode` as it's child
    parent.updateChild(_newNode);

    emit Replace(_newNode);
    emit Obsolete(INode(address(this)));
  }

  /*//////////////////////////////////////////////////////////////
                        YIELD STRATEGY LOGIC
  //////////////////////////////////////////////////////////////*/

  function balanceOf() external view override returns (uint256 amount) {
    return _balanceOf();
  }

  function withdrawAll() external override onlyParent returns (uint256 amount) {
    amount = _withdrawAll();
  }

  function withdrawAllByAdmin() external override onlyOwner returns (uint256 amount) {
    amount = _withdrawAll();
    emit AdminWithdraw(amount);
  }

  function withdraw(uint256 _amount) external override onlyParent {
    if (_amount == 0) revert ZeroArg();

    _withdraw(_amount);
  }

  function withdrawByAdmin(uint256 _amount) external override onlyOwner {
    if (_amount == 0) revert ZeroArg();

    _withdraw(_amount);
    emit AdminWithdraw(_amount);
  }

  function deposit() external override onlyParent {
    _deposit();
  }

  function _balanceOf() internal view virtual returns (uint256 amount) {}

  function _withdrawAll() internal virtual returns (uint256 amount) {}

  function _withdraw(uint256 _amount) internal virtual {}

  function _deposit() internal virtual {}
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IMaster","name":"_initialParent","type":"address"},{"internalType":"contract INode","name":"_initialChildOne","type":"address"},{"internalType":"contract INode","name":"_initialChildTwo","type":"address"},{"internalType":"uint256","name":"_MIN_AMOUNT_FOR_EQUAL_SPLIT","type":"uint256"},{"internalType":"uint256","name":"_MAX_AMOUNT_FOR_CHILD_ONE","type":"uint256"},{"internalType":"uint256","name":"_MAX_AMOUNT_FOR_CHILD_TWO","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BothChild","type":"error"},{"inputs":[],"name":"InvalidArg","type":"error"},{"inputs":[],"name":"InvalidChildOne","type":"error"},{"inputs":[],"name":"InvalidChildTwo","type":"error"},{"inputs":[],"name":"InvalidCore","type":"error"},{"inputs":[],"name":"InvalidParent","type":"error"},{"inputs":[],"name":"InvalidParentAddress","type":"error"},{"inputs":[],"name":"InvalidState","type":"error"},{"inputs":[],"name":"InvalidWant","type":"error"},{"inputs":[],"name":"IsMaster","type":"error"},{"inputs":[],"name":"NonZeroBalance","type":"error"},{"inputs":[],"name":"NotChild","type":"error"},{"inputs":[{"internalType":"bytes4","name":"func","type":"bytes4"}],"name":"NotImplemented","type":"error"},{"inputs":[],"name":"NotSetup","type":"error"},{"inputs":[],"name":"SenderNotChild","type":"error"},{"inputs":[],"name":"SenderNotParent","type":"error"},{"inputs":[{"internalType":"contract INode","name":"instance","type":"address"}],"name":"SetupNotCompleted","type":"error"},{"inputs":[],"name":"ZeroArg","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AdminWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract INode","name":"previous","type":"address"},{"indexed":false,"internalType":"contract INode","name":"current","type":"address"}],"name":"ChildOneUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract INode","name":"previous","type":"address"},{"indexed":false,"internalType":"contract INode","name":"current","type":"address"}],"name":"ChildTwoUpdate","type":"event"},{"anonymous":false,"inputs":[],"name":"ForceReplace","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract INode","name":"implementation","type":"address"}],"name":"Obsolete","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IMaster","name":"previous","type":"address"},{"indexed":false,"internalType":"contract IMaster","name":"current","type":"address"}],"name":"ParentUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract INode","name":"newAddress","type":"address"}],"name":"Replace","type":"event"},{"anonymous":false,"inputs":[],"name":"ReplaceAsChild","type":"event"},{"inputs":[],"name":"MAX_AMOUNT_FOR_CHILD_ONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_AMOUNT_FOR_CHILD_TWO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_AMOUNT_FOR_EQUAL_SPLIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"childOne","outputs":[{"internalType":"contract INode","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"childRemoved","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"childTwo","outputs":[{"internalType":"contract INode","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"core","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expireBalanceCache","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isMaster","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"parent","outputs":[{"internalType":"contract IMaster","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prepareBalanceCache","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract INode","name":"__newNode","type":"address"}],"name":"replace","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISplitter","name":"_newParent","type":"address"}],"name":"replaceAsChild","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract INode","name":"_node","type":"address"}],"name":"replaceForce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract INode","name":"_newChild","type":"address"}],"name":"setInitialChildOne","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract INode","name":"_newChild","type":"address"}],"name":"setInitialChildTwo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setupCompleted","outputs":[{"internalType":"bool","name":"completed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"siblingRemoved","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract INode","name":"_newChild","type":"address"}],"name":"updateChild","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMaster","name":"_newParent","type":"address"}],"name":"updateParent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"want","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAllByAdmin","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawByAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101206040523480156200001257600080fd5b5060405162003c0838038062003c08833981016040819052620000359162000622565b85858585838383828282826200004b33620002dc565b6001600160a01b03811662000073576040516362c0b8cd60e11b815260040160405180910390fd5b6000816001600160a01b0316631f1fcd516040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000b4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000da919062000692565b90506000826001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200011d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000143919062000692565b90506001600160a01b0382166200016d576040516341b30e2560e01b815260040160405180910390fd5b6001600160a01b038116620001955760405163c5c23c8d60e01b815260040160405180910390fd5b6001600160a01b0382811660805281811660a052600180546001600160a01b0319169185169182179055604080516000815260208101929092527f2a821884f0167e84fc3824c66c12861f8f72abb7c76fd899bf5039be1c4ac7b7910160405180910390a15050506001600160a01b0382161562000227576200021a6000836200032c565b6200022760008362000550565b6001600160a01b038116156200025157620002446000826200032c565b62000251600082620005b0565b50505060c0939093525050505060001984148015925090506200027657506000198114155b15620002955760405163d30917ed60e01b815260040160405180910390fd5b60001982148015620002a8575060001981145b15620002c75760405163d30917ed60e01b815260040160405180910390fd5b60e0919091526101005250620006dd92505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811662000354576040516362c0b8cd60e11b815260040160405180910390fd5b806001600160a01b031663609da8976040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000393573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003b99190620006b9565b620003e65760405163040d05c360e21b81526001600160a01b038216600482015260240160405180910390fd5b816001600160a01b0316816001600160a01b031614156200041a5760405163d30917ed60e01b815260040160405180910390fd5b806001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000459573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200047f919062000692565b6001600160a01b031660a0516001600160a01b031614620004b35760405163c5c23c8d60e01b815260040160405180910390fd5b806001600160a01b0316631f1fcd516040518163ffffffff1660e01b8152600401602060405180830381865afa158015620004f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000518919062000692565b6001600160a01b03166080516001600160a01b0316146200054c576040516341b30e2560e01b815260040160405180910390fd5b5050565b600280546001600160a01b0319166001600160a01b0383811691821790925560408051928516835260208301919091527fbd5e43cc7b243faaa8e808256df815d121be0fd579b46c17a3f993fb170972ec91015b60405180910390a15050565b600380546001600160a01b0319166001600160a01b0383811691821790925560408051928516835260208301919091527fc6df8dcbfc70e15ca180225a8f328727b3205e5bf99f25d94077862b53a6e6ee9101620005a4565b6001600160a01b03811681146200061f57600080fd5b50565b60008060008060008060c087890312156200063c57600080fd5b8651620006498162000609565b60208801519096506200065c8162000609565b60408801519095506200066f8162000609565b80945050606087015192506080870151915060a087015190509295509295509295565b600060208284031215620006a557600080fd5b8151620006b28162000609565b9392505050565b600060208284031215620006cc57600080fd5b81518015158114620006b257600080fd5b60805160a05160c05160e0516101005161347662000792600039600081816101e401528181612c0701528181612c2f0152612c660152600081816103a901528181612b5001528181612b780152612baf01526000818161034401526127280152600081816103f6015281816123ff0152612a20015260008181610228015281816124cb015281816126b101528181612aec01528181612ce401528181612d8901528181612e0d0152612eab01526134766000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c8063853828b611610104578063d0e30db0116100a2578063e84b725d11610071578063e84b725d146103de578063f2f4eb26146103f1578063f2fde38b14610418578063f947d5c91461042b57600080fd5b8063d0e30db014610389578063d921f2ee14610391578063e505ddce146103a4578063e573317b146103cb57600080fd5b8063b84c7f2d116100de578063b84c7f2d1461033f578063b8efa43514610366578063bec1c4731461036e578063cabfb9341461037657600080fd5b8063853828b61461031e5780638da5cb5b1461032657806394a368d21461033757600080fd5b80633d8db9111161017c578063645c04411161014b578063645c0441146102f45780636f791d2914610307578063715018a61461030e578063722713f71461031657600080fd5b80633d8db911146102a3578063562901d9146102b6578063609da897146102c957806360f96a8f146102e157600080fd5b806329627e59116101b857806329627e59146102625780632e1a7d4d146102755780632fd20a471461028857806332ce8ccd1461029057600080fd5b8063016b7dbd146101df57806301d05096146102195780631f1fcd5114610223575b600080fd5b6102067f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61022161043e565b005b61024a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610210565b610221610270366004613280565b61072f565b61022161028336600461329d565b6107ff565b610206610883565b61022161029e366004613280565b6109ec565b6102216102b136600461329d565b610a21565b6102216102c4366004613280565b610b06565b6102d1610e55565b6040519015158152602001610210565b60015461024a906001600160a01b031681565b610221610302366004613280565b610e67565b60006102d1565b610221610ec9565b610206610f49565b610206610f58565b6000546001600160a01b031661024a565b610206610fa7565b6102067f000000000000000000000000000000000000000000000000000000000000000081565b610221610faf565b610221611090565b610221610384366004613280565b6110e0565b6102216113f6565b60025461024a906001600160a01b031681565b6102067f000000000000000000000000000000000000000000000000000000000000000081565b6102216103d9366004613280565b611442565b6102216103ec366004613280565b61150f565b61024a7f000000000000000000000000000000000000000000000000000000000000000081565b610221610426366004613280565b611649565b60035461024a906001600160a01b031681565b600080600061044b61175c565b9194509250905082610490576040517f1034170c0000000000000000000000000000000000000000000000000000000081523060048201526024015b60405180910390fd5b336001600160a01b03831614156105af57806001600160a01b031663b8efa4356040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104dc57600080fd5b505af11580156104f0573d6000803e3d6000fd5b50506001546040517fe84b725d0000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152909116925063e84b725d9150602401600060405180830381600087803b15801561055457600080fd5b505af1158015610568573d6000803e3d6000fd5b50506040516001600160a01b03851681527fe3bee2269179dff609bde2667db864c00a1529211302f765535fd788510b629c925060200190505b60405180910390a16106f7565b336001600160a01b03821614156106c557816001600160a01b031663b8efa4356040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156105fb57600080fd5b505af115801561060f573d6000803e3d6000fd5b50506001546040517fe84b725d0000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152909116925063e84b725d9150602401600060405180830381600087803b15801561067357600080fd5b505af1158015610687573d6000803e3d6000fd5b50506040516001600160a01b03841681527fe3bee2269179dff609bde2667db864c00a1529211302f765535fd788510b629c925060200190506105a2565b6040517f01f65dd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040513081527fe3bee2269179dff609bde2667db864c00a1529211302f765535fd788510b629c9060200160405180910390a1505050565b6000546001600160a01b031633146107a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6003546001600160a01b0316156107e6576040517fbaf3f0f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107f1600082611790565b6107fc60008261184a565b50565b6001546001600160a01b03163314610843576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061087a576040517fc581719a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107fc816118c2565b6001546000906001600160a01b031633146108ca576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600254604080517f2fd20a4700000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691632fd20a47916004808301926020929190829003018187875af115801561092e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095291906132b6565b90506000600360009054906101000a90046001600160a01b03166001600160a01b0316632fd20a476040518163ffffffff1660e01b81526004016020604051808303816000875af11580156109ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109cf91906132b6565b6004839055600581905590506109e581836132fe565b9250505090565b6109f5816110e0565b6040517f71861b9f192277502a2209dde5e25ecfd52ca83931ffc892ef70282bf7b93a2a90600090a150565b335b6001600160a01b0316610a3e6000546001600160a01b031690565b6001600160a01b031614610aae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6040517fc79348a60000000000000000000000000000000000000000000000000000000081527fffffffff00000000000000000000000000000000000000000000000000000000600035166004820152602401610487565b6000546001600160a01b03163314610b7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b600154604080517f6f791d2900000000000000000000000000000000000000000000000000000000815290516001600160a01b0392831692841691636f791d299160048083019260209291908290030181865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c039190613316565b15610c3a576040517fef062dc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c448183611a07565b6000610c4f83611cb0565b9050826001600160a01b0316816001600160a01b03166360f96a8f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cbd9190613338565b6001600160a01b031614610cfd576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826001600160a01b03166360f96a8f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f9190613338565b6001600160a01b0316826001600160a01b031614610da9576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fe84b725d0000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015283169063e84b725d90602401600060405180830381600087803b158015610e0557600080fd5b505af1158015610e19573d6000803e3d6000fd5b50505050610e278284611f4d565b6040517f1fd0ed0afde2d0281930362705e45b089222803618cdbae0b540a3ad040e845690600090a1505050565b6000610e5f61175c565b509092915050565b6001546001600160a01b03163314610eab576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610eb53382611a07565b610ebe81611cb0565b506107fc3382611f4d565b6000546001600160a01b03163314610f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b610f476000611fbd565b565b6000610f53612025565b905090565b6001546000906001600160a01b03163314610f9f576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f5361212f565b600033610a23565b6001546001600160a01b03163314610ff3576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600154604080517f60f96a8f00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b0316916360f96a8f9160048083019260209291908290030181865afa158015611056573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107a9190613338565b90506110863382611a07565b6107fc3382611f4d565b6001546001600160a01b031633146110d4576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006004819055600555565b6000546001600160a01b03163314611154576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b600080600061116161175c565b91945092509050826111a1576040517f1034170c000000000000000000000000000000000000000000000000000000008152306004820152602401610487565b6000849050826001600160a01b0316816001600160a01b031663d921f2ee6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112129190613338565b6001600160a01b031614611252576040517fa575e80500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816001600160a01b0316816001600160a01b031663f947d5c96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be9190613338565b6001600160a01b0316146112fe576040517f899f893a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113078161220e565b6040517f645c04410000000000000000000000000000000000000000000000000000000081526001600160a01b03828116600483015284169063645c044190602401600060405180830381600087803b15801561136357600080fd5b505af1158015611377573d6000803e3d6000fd5b50506040517f645c04410000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301528516925063645c04419150602401600060405180830381600087803b1580156113d757600080fd5b505af11580156113eb573d6000803e3d6000fd5b505050505050505050565b6001546001600160a01b0316331461143a576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f47612680565b6000546001600160a01b031633146114b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6002546001600160a01b0316156114f9576040517fbaf3f0f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611504600082611790565b6107fc600082612814565b600080600061151c61175c565b919450925090508261155c576040517f1034170c000000000000000000000000000000000000000000000000000000008152306004820152602401610487565b336001600160a01b03831614156115d257806001600160a01b0316846001600160a01b031614156115b9576040517fd30917ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115c38285611790565b6115cd8285612814565b611643565b336001600160a01b03821614156106c557816001600160a01b0316846001600160a01b0316141561162f576040517fd30917ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116398185611790565b6115cd818561184a565b50505050565b6000546001600160a01b031633146116bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b038116611753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610487565b6107fc81611fbd565b6002546003546000916001600160a01b039081169116811580159061178957506001600160a01b03811615155b9250909192565b61179a8282612884565b306001600160a01b0316816001600160a01b03166360f96a8f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118069190613338565b6001600160a01b031614611846576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560408051928516835260208301919091527fc6df8dcbfc70e15ca180225a8f328727b3205e5bf99f25d94077862b53a6e6ee91015b60405180910390a15050565b600454808211156119bd57801561194e57600260009054906101000a90046001600160a01b03166001600160a01b031663853828b66040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194c91906132b6565b505b6003546001600160a01b0316632e1a7d4d6119698385613355565b6040518263ffffffff1660e01b815260040161198791815260200190565b600060405180830381600087803b1580156119a157600080fd5b505af11580156119b5573d6000803e3d6000fd5b505050505050565b6002546040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690632e1a7d4d90602401611987565b6001600160a01b038116301415611a4a576040517f3073085f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816001600160a01b0316816001600160a01b03161415611a96576040517f3073085f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ad4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af89190613338565b6001600160a01b0316826001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b639190613338565b6001600160a01b031614611ba3576040517fc5c23c8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b0316631f1fcd516040518163ffffffff1660e01b8152600401602060405180830381865afa158015611be1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c059190613338565b6001600160a01b0316826001600160a01b0316631f1fcd516040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c709190613338565b6001600160a01b031614611846576040517f41b30e2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000816001600160a01b031663609da8976040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d149190613316565b611d55576040517f1034170c0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610487565b6000826001600160a01b031663d921f2ee6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db99190613338565b9050600080306001600160a01b0316836001600160a01b03161490506000856001600160a01b0316636f791d296040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e399190613316565b611eaf57856001600160a01b031663f947d5c96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e9f9190613338565b9250506001600160a01b03821630145b818015611eb95750805b15611ef0576040517fbb0897ee00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81158015611efc575080155b15611f33576040517f1e203c1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115611f43575090949350505050565b5091949350505050565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560408051928516835260208301919091527f2a821884f0167e84fc3824c66c12861f8f72abb7c76fd899bf5039be1c4ac7b791016118b6565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600254604080517f722713f700000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163722713f79160048083019260209291908290030181865afa158015612088573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ac91906132b6565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663722713f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612101573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212591906132b6565b610f5390826132fe565b600254604080517f853828b600000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163853828b6916004808301926020929190829003018187875af1158015612193573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b791906132b6565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663853828b66040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612101573d6000803e3d6000fd5b6001600160a01b03811661224e576040517fc581719a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b031663609da8976040518163ffffffff1660e01b8152600401602060405180830381865afa15801561228c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b09190613316565b6122f1576040517f1034170c0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610487565b6001600160a01b038116301415612334576040517fd30917ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600154604080517f60f96a8f00000000000000000000000000000000000000000000000000000000815290516001600160a01b03928316928416916360f96a8f9160048083019260209291908290030181865afa158015612399573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123bd9190613338565b6001600160a01b0316146123fd576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015612465573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124899190613338565b6001600160a01b0316146124c9576040517fc5c23c8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316631f1fcd516040518163ffffffff1660e01b8152600401602060405180830381865afa158015612531573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125559190613338565b6001600160a01b031614612595576040517f41b30e2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546040517fe84b725d0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301529091169063e84b725d90602401600060405180830381600087803b1580156125f557600080fd5b505af1158015612609573d6000803e3d6000fd5b50506040516001600160a01b03841681527f2220a12ec67ab06fa89ad2bf6522745af04a8f29b466b9c896da126dc95e21839250602001905060405180910390a16040513081527fe3bee2269179dff609bde2667db864c00a1529211302f765535fd788510b629c9060200160405180910390a150565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612700573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272491906132b6565b90507f0000000000000000000000000000000000000000000000000000000000000000811061280c576004546005548082116127b45760006127668383613355565b9050838110612778576115cd84612b4b565b600060026127868387613355565b612790919061336c565b905061279b81612c02565b6127ad6127a88287613355565b612b4b565b5050505050565b60006127c08284613355565b90508381106127d2576115cd84612c02565b600060026127e08387613355565b6127ea919061336c565b90506127f581612b4b565b6127ad6128028287613355565b612c02565b505050565b6107fc612ca7565b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560408051928516835260208301919091527fbd5e43cc7b243faaa8e808256df815d121be0fd579b46c17a3f993fb170972ec91016118b6565b6001600160a01b0381166128c4576040517fc581719a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b031663609da8976040518163ffffffff1660e01b8152600401602060405180830381865afa158015612902573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129269190613316565b612967576040517f1034170c0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610487565b816001600160a01b0316816001600160a01b031614156129b3576040517fd30917ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a159190613338565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612a7f576040517fc5c23c8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b0316631f1fcd516040518163ffffffff1660e01b8152600401602060405180830381865afa158015612abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae19190613338565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614611846576040517f41b30e2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004547f0000000000000000000000000000000000000000000000000000000000000000811015612bf9577f0000000000000000000000000000000000000000000000000000000000000000612ba183836132fe565b1115612bf0576000612bd3827f0000000000000000000000000000000000000000000000000000000000000000613355565b9050612bde81612dfc565b612807612beb8285613355565b612e9a565b61184682612dfc565b61184682612e9a565b6005547f0000000000000000000000000000000000000000000000000000000000000000811015612bf0577f0000000000000000000000000000000000000000000000000000000000000000612c5883836132fe565b1115612bf9576000612c8a827f0000000000000000000000000000000000000000000000000000000000000000613355565b9050612c9581612e9a565b612807612ca28285613355565b612dfc565b60055460045411612d57576040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610f47907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612d33573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127a891906132b6565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610f47907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612dd8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280291906132b6565b600254612e36906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683612f24565b600260009054906101000a90046001600160a01b03166001600160a01b031663d0e30db06040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612e8657600080fd5b505af11580156127ad573d6000803e3d6000fd5b600354612ed4906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116911683612f24565b600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db06040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612e8657600080fd5b604080516001600160a01b03848116602483015260448083018590528351808403909101815260649092018352602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649084015261280792869291600091612fe291851690849061308c565b80519091501561280757808060200190518101906130009190613316565b612807576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610487565b606061309b84846000856130a5565b90505b9392505050565b606082471015613137576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610487565b843b61319f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b600080866001600160a01b031685876040516131bb91906133d3565b60006040518083038185875af1925050503d80600081146131f8576040519150601f19603f3d011682016040523d82523d6000602084013e6131fd565b606091505b509150915061320d828286613218565b979650505050505050565b6060831561322757508161309e565b8251156132375782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161048791906133ef565b6001600160a01b03811681146107fc57600080fd5b60006020828403121561329257600080fd5b813561309e8161326b565b6000602082840312156132af57600080fd5b5035919050565b6000602082840312156132c857600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115613311576133116132cf565b500190565b60006020828403121561332857600080fd5b8151801515811461309e57600080fd5b60006020828403121561334a57600080fd5b815161309e8161326b565b600082821015613367576133676132cf565b500390565b6000826133a2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b838110156133c25781810151838201526020016133aa565b838111156116435750506000910152565b600082516133e58184602087016133a7565b9190910192915050565b602081526000825180602084015261340e8160408501602087016133a7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220cec106db9ffadace82f8f012882447cb077d24d30d5323eec9069429cd4338bd64736f6c634300080a00330000000000000000000000001e8be946370a99019e323998acd37a1206bdd5070000000000000000000000007e0049866879151480d9ec01391bbf713f7705b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009184e72a000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000048c27395000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101da5760003560e01c8063853828b611610104578063d0e30db0116100a2578063e84b725d11610071578063e84b725d146103de578063f2f4eb26146103f1578063f2fde38b14610418578063f947d5c91461042b57600080fd5b8063d0e30db014610389578063d921f2ee14610391578063e505ddce146103a4578063e573317b146103cb57600080fd5b8063b84c7f2d116100de578063b84c7f2d1461033f578063b8efa43514610366578063bec1c4731461036e578063cabfb9341461037657600080fd5b8063853828b61461031e5780638da5cb5b1461032657806394a368d21461033757600080fd5b80633d8db9111161017c578063645c04411161014b578063645c0441146102f45780636f791d2914610307578063715018a61461030e578063722713f71461031657600080fd5b80633d8db911146102a3578063562901d9146102b6578063609da897146102c957806360f96a8f146102e157600080fd5b806329627e59116101b857806329627e59146102625780632e1a7d4d146102755780632fd20a471461028857806332ce8ccd1461029057600080fd5b8063016b7dbd146101df57806301d05096146102195780631f1fcd5114610223575b600080fd5b6102067f0000000000000000000000000000000000000000000000000000048c2739500081565b6040519081526020015b60405180910390f35b61022161043e565b005b61024a7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b6040516001600160a01b039091168152602001610210565b610221610270366004613280565b61072f565b61022161028336600461329d565b6107ff565b610206610883565b61022161029e366004613280565b6109ec565b6102216102b136600461329d565b610a21565b6102216102c4366004613280565b610b06565b6102d1610e55565b6040519015158152602001610210565b60015461024a906001600160a01b031681565b610221610302366004613280565b610e67565b60006102d1565b610221610ec9565b610206610f49565b610206610f58565b6000546001600160a01b031661024a565b610206610fa7565b6102067f000000000000000000000000000000000000000000000000000009184e72a00081565b610221610faf565b610221611090565b610221610384366004613280565b6110e0565b6102216113f6565b60025461024a906001600160a01b031681565b6102067fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81565b6102216103d9366004613280565b611442565b6102216103ec366004613280565b61150f565b61024a7f0000000000000000000000000865a889183039689034da55c1fd12af5083eabf81565b610221610426366004613280565b611649565b60035461024a906001600160a01b031681565b600080600061044b61175c565b9194509250905082610490576040517f1034170c0000000000000000000000000000000000000000000000000000000081523060048201526024015b60405180910390fd5b336001600160a01b03831614156105af57806001600160a01b031663b8efa4356040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104dc57600080fd5b505af11580156104f0573d6000803e3d6000fd5b50506001546040517fe84b725d0000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152909116925063e84b725d9150602401600060405180830381600087803b15801561055457600080fd5b505af1158015610568573d6000803e3d6000fd5b50506040516001600160a01b03851681527fe3bee2269179dff609bde2667db864c00a1529211302f765535fd788510b629c925060200190505b60405180910390a16106f7565b336001600160a01b03821614156106c557816001600160a01b031663b8efa4356040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156105fb57600080fd5b505af115801561060f573d6000803e3d6000fd5b50506001546040517fe84b725d0000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152909116925063e84b725d9150602401600060405180830381600087803b15801561067357600080fd5b505af1158015610687573d6000803e3d6000fd5b50506040516001600160a01b03841681527fe3bee2269179dff609bde2667db864c00a1529211302f765535fd788510b629c925060200190506105a2565b6040517f01f65dd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040513081527fe3bee2269179dff609bde2667db864c00a1529211302f765535fd788510b629c9060200160405180910390a1505050565b6000546001600160a01b031633146107a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6003546001600160a01b0316156107e6576040517fbaf3f0f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107f1600082611790565b6107fc60008261184a565b50565b6001546001600160a01b03163314610843576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061087a576040517fc581719a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107fc816118c2565b6001546000906001600160a01b031633146108ca576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600254604080517f2fd20a4700000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691632fd20a47916004808301926020929190829003018187875af115801561092e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095291906132b6565b90506000600360009054906101000a90046001600160a01b03166001600160a01b0316632fd20a476040518163ffffffff1660e01b81526004016020604051808303816000875af11580156109ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109cf91906132b6565b6004839055600581905590506109e581836132fe565b9250505090565b6109f5816110e0565b6040517f71861b9f192277502a2209dde5e25ecfd52ca83931ffc892ef70282bf7b93a2a90600090a150565b335b6001600160a01b0316610a3e6000546001600160a01b031690565b6001600160a01b031614610aae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6040517fc79348a60000000000000000000000000000000000000000000000000000000081527fffffffff00000000000000000000000000000000000000000000000000000000600035166004820152602401610487565b6000546001600160a01b03163314610b7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b600154604080517f6f791d2900000000000000000000000000000000000000000000000000000000815290516001600160a01b0392831692841691636f791d299160048083019260209291908290030181865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c039190613316565b15610c3a576040517fef062dc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c448183611a07565b6000610c4f83611cb0565b9050826001600160a01b0316816001600160a01b03166360f96a8f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cbd9190613338565b6001600160a01b031614610cfd576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826001600160a01b03166360f96a8f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f9190613338565b6001600160a01b0316826001600160a01b031614610da9576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fe84b725d0000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015283169063e84b725d90602401600060405180830381600087803b158015610e0557600080fd5b505af1158015610e19573d6000803e3d6000fd5b50505050610e278284611f4d565b6040517f1fd0ed0afde2d0281930362705e45b089222803618cdbae0b540a3ad040e845690600090a1505050565b6000610e5f61175c565b509092915050565b6001546001600160a01b03163314610eab576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610eb53382611a07565b610ebe81611cb0565b506107fc3382611f4d565b6000546001600160a01b03163314610f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b610f476000611fbd565b565b6000610f53612025565b905090565b6001546000906001600160a01b03163314610f9f576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f5361212f565b600033610a23565b6001546001600160a01b03163314610ff3576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600154604080517f60f96a8f00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b0316916360f96a8f9160048083019260209291908290030181865afa158015611056573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107a9190613338565b90506110863382611a07565b6107fc3382611f4d565b6001546001600160a01b031633146110d4576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006004819055600555565b6000546001600160a01b03163314611154576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b600080600061116161175c565b91945092509050826111a1576040517f1034170c000000000000000000000000000000000000000000000000000000008152306004820152602401610487565b6000849050826001600160a01b0316816001600160a01b031663d921f2ee6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112129190613338565b6001600160a01b031614611252576040517fa575e80500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816001600160a01b0316816001600160a01b031663f947d5c96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561129a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112be9190613338565b6001600160a01b0316146112fe576040517f899f893a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113078161220e565b6040517f645c04410000000000000000000000000000000000000000000000000000000081526001600160a01b03828116600483015284169063645c044190602401600060405180830381600087803b15801561136357600080fd5b505af1158015611377573d6000803e3d6000fd5b50506040517f645c04410000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301528516925063645c04419150602401600060405180830381600087803b1580156113d757600080fd5b505af11580156113eb573d6000803e3d6000fd5b505050505050505050565b6001546001600160a01b0316331461143a576040517fb70e2d7000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f47612680565b6000546001600160a01b031633146114b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6002546001600160a01b0316156114f9576040517fbaf3f0f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611504600082611790565b6107fc600082612814565b600080600061151c61175c565b919450925090508261155c576040517f1034170c000000000000000000000000000000000000000000000000000000008152306004820152602401610487565b336001600160a01b03831614156115d257806001600160a01b0316846001600160a01b031614156115b9576040517fd30917ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115c38285611790565b6115cd8285612814565b611643565b336001600160a01b03821614156106c557816001600160a01b0316846001600160a01b0316141561162f576040517fd30917ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116398185611790565b6115cd818561184a565b50505050565b6000546001600160a01b031633146116bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b038116611753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610487565b6107fc81611fbd565b6002546003546000916001600160a01b039081169116811580159061178957506001600160a01b03811615155b9250909192565b61179a8282612884565b306001600160a01b0316816001600160a01b03166360f96a8f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118069190613338565b6001600160a01b031614611846576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560408051928516835260208301919091527fc6df8dcbfc70e15ca180225a8f328727b3205e5bf99f25d94077862b53a6e6ee91015b60405180910390a15050565b600454808211156119bd57801561194e57600260009054906101000a90046001600160a01b03166001600160a01b031663853828b66040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194c91906132b6565b505b6003546001600160a01b0316632e1a7d4d6119698385613355565b6040518263ffffffff1660e01b815260040161198791815260200190565b600060405180830381600087803b1580156119a157600080fd5b505af11580156119b5573d6000803e3d6000fd5b505050505050565b6002546040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690632e1a7d4d90602401611987565b6001600160a01b038116301415611a4a576040517f3073085f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816001600160a01b0316816001600160a01b03161415611a96576040517f3073085f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ad4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af89190613338565b6001600160a01b0316826001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b639190613338565b6001600160a01b031614611ba3576040517fc5c23c8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b0316631f1fcd516040518163ffffffff1660e01b8152600401602060405180830381865afa158015611be1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c059190613338565b6001600160a01b0316826001600160a01b0316631f1fcd516040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c709190613338565b6001600160a01b031614611846576040517f41b30e2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000816001600160a01b031663609da8976040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d149190613316565b611d55576040517f1034170c0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610487565b6000826001600160a01b031663d921f2ee6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db99190613338565b9050600080306001600160a01b0316836001600160a01b03161490506000856001600160a01b0316636f791d296040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e399190613316565b611eaf57856001600160a01b031663f947d5c96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e9f9190613338565b9250506001600160a01b03821630145b818015611eb95750805b15611ef0576040517fbb0897ee00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81158015611efc575080155b15611f33576040517f1e203c1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115611f43575090949350505050565b5091949350505050565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560408051928516835260208301919091527f2a821884f0167e84fc3824c66c12861f8f72abb7c76fd899bf5039be1c4ac7b791016118b6565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600254604080517f722713f700000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163722713f79160048083019260209291908290030181865afa158015612088573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ac91906132b6565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663722713f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612101573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212591906132b6565b610f5390826132fe565b600254604080517f853828b600000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163853828b6916004808301926020929190829003018187875af1158015612193573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b791906132b6565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663853828b66040518163ffffffff1660e01b81526004016020604051808303816000875af1158015612101573d6000803e3d6000fd5b6001600160a01b03811661224e576040517fc581719a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b031663609da8976040518163ffffffff1660e01b8152600401602060405180830381865afa15801561228c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b09190613316565b6122f1576040517f1034170c0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610487565b6001600160a01b038116301415612334576040517fd30917ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600154604080517f60f96a8f00000000000000000000000000000000000000000000000000000000815290516001600160a01b03928316928416916360f96a8f9160048083019260209291908290030181865afa158015612399573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123bd9190613338565b6001600160a01b0316146123fd576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000865a889183039689034da55c1fd12af5083eabf6001600160a01b0316816001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa158015612465573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124899190613338565b6001600160a01b0316146124c9576040517fc5c23c8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316816001600160a01b0316631f1fcd516040518163ffffffff1660e01b8152600401602060405180830381865afa158015612531573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125559190613338565b6001600160a01b031614612595576040517f41b30e2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546040517fe84b725d0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301529091169063e84b725d90602401600060405180830381600087803b1580156125f557600080fd5b505af1158015612609573d6000803e3d6000fd5b50506040516001600160a01b03841681527f2220a12ec67ab06fa89ad2bf6522745af04a8f29b466b9c896da126dc95e21839250602001905060405180910390a16040513081527fe3bee2269179dff609bde2667db864c00a1529211302f765535fd788510b629c9060200160405180910390a150565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316906370a0823190602401602060405180830381865afa158015612700573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272491906132b6565b90507f000000000000000000000000000000000000000000000000000009184e72a000811061280c576004546005548082116127b45760006127668383613355565b9050838110612778576115cd84612b4b565b600060026127868387613355565b612790919061336c565b905061279b81612c02565b6127ad6127a88287613355565b612b4b565b5050505050565b60006127c08284613355565b90508381106127d2576115cd84612c02565b600060026127e08387613355565b6127ea919061336c565b90506127f581612b4b565b6127ad6128028287613355565b612c02565b505050565b6107fc612ca7565b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560408051928516835260208301919091527fbd5e43cc7b243faaa8e808256df815d121be0fd579b46c17a3f993fb170972ec91016118b6565b6001600160a01b0381166128c4576040517fc581719a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b031663609da8976040518163ffffffff1660e01b8152600401602060405180830381865afa158015612902573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129269190613316565b612967576040517f1034170c0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610487565b816001600160a01b0316816001600160a01b031614156129b3576040517fd30917ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b031663f2f4eb266040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a159190613338565b6001600160a01b03167f0000000000000000000000000865a889183039689034da55c1fd12af5083eabf6001600160a01b031614612a7f576040517fc5c23c8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b0316631f1fcd516040518163ffffffff1660e01b8152600401602060405180830381865afa158015612abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae19190613338565b6001600160a01b03167f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b031614611846576040517f41b30e2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811015612bf9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612ba183836132fe565b1115612bf0576000612bd3827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613355565b9050612bde81612dfc565b612807612beb8285613355565b612e9a565b61184682612dfc565b61184682612e9a565b6005547f0000000000000000000000000000000000000000000000000000048c27395000811015612bf0577f0000000000000000000000000000000000000000000000000000048c27395000612c5883836132fe565b1115612bf9576000612c8a827f0000000000000000000000000000000000000000000000000000048c27395000613355565b9050612c9581612e9a565b612807612ca28285613355565b612dfc565b60055460045411612d57576040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610f47907f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316906370a0823190602401602060405180830381865afa158015612d33573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127a891906132b6565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610f47907f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316906370a0823190602401602060405180830381865afa158015612dd8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280291906132b6565b600254612e36906001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488116911683612f24565b600260009054906101000a90046001600160a01b03166001600160a01b031663d0e30db06040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612e8657600080fd5b505af11580156127ad573d6000803e3d6000fd5b600354612ed4906001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488116911683612f24565b600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db06040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612e8657600080fd5b604080516001600160a01b03848116602483015260448083018590528351808403909101815260649092018352602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649084015261280792869291600091612fe291851690849061308c565b80519091501561280757808060200190518101906130009190613316565b612807576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610487565b606061309b84846000856130a5565b90505b9392505050565b606082471015613137576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610487565b843b61319f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b600080866001600160a01b031685876040516131bb91906133d3565b60006040518083038185875af1925050503d80600081146131f8576040519150601f19603f3d011682016040523d82523d6000602084013e6131fd565b606091505b509150915061320d828286613218565b979650505050505050565b6060831561322757508161309e565b8251156132375782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161048791906133ef565b6001600160a01b03811681146107fc57600080fd5b60006020828403121561329257600080fd5b813561309e8161326b565b6000602082840312156132af57600080fd5b5035919050565b6000602082840312156132c857600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115613311576133116132cf565b500190565b60006020828403121561332857600080fd5b8151801515811461309e57600080fd5b60006020828403121561334a57600080fd5b815161309e8161326b565b600082821015613367576133676132cf565b500390565b6000826133a2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b838110156133c25781810151838201526020016133aa565b838111156116435750506000910152565b600082516133e58184602087016133a7565b9190910192915050565b602081526000825180602084015261340e8160408501602087016133a7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea2646970667358221220cec106db9ffadace82f8f012882447cb077d24d30d5323eec9069429cd4338bd64736f6c634300080a0033

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

0000000000000000000000001e8be946370a99019e323998acd37a1206bdd5070000000000000000000000007e0049866879151480d9ec01391bbf713f7705b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009184e72a000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000048c27395000

-----Decoded View---------------
Arg [0] : _initialParent (address): 0x1E8bE946370a99019E323998Acd37A1206bdD507
Arg [1] : _initialChildOne (address): 0x7E0049866879151480d9Ec01391Bbf713F7705b1
Arg [2] : _initialChildTwo (address): 0x0000000000000000000000000000000000000000
Arg [3] : _MIN_AMOUNT_FOR_EQUAL_SPLIT (uint256): 10000000000000
Arg [4] : _MAX_AMOUNT_FOR_CHILD_ONE (uint256): 115792089237316195423570985008687907853269984665640564039457584007913129639935
Arg [5] : _MAX_AMOUNT_FOR_CHILD_TWO (uint256): 5000000000000

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000001e8be946370a99019e323998acd37a1206bdd507
Arg [1] : 0000000000000000000000007e0049866879151480d9ec01391bbf713f7705b1
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 000000000000000000000000000000000000000000000000000009184e72a000
Arg [4] : ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Arg [5] : 0000000000000000000000000000000000000000000000000000048c27395000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

Validator Index Block Amount
View All Withdrawals

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

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