ETH Price: $3,638.42 (+0.69%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DharmaSmartWalletImplementationV10

Compiler Version
v0.5.17+commit.d19bba13

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-07-08
*/

pragma solidity 0.5.17; // optimization runs: 200, evm version: istanbul
// WARNING - `executeActionWithAtomicBatchCalls` has a `bytes[]` argument that
// requires ABIEncoderV2. Exercise caution when calling that specific function.
pragma experimental ABIEncoderV2;


interface DharmaSmartWalletImplementationV1Interface {
  event CallSuccess(
    bytes32 actionID,
    bool rolledBack,
    uint256 nonce,
    address to,
    bytes data,
    bytes returnData
  );

  event CallFailure(
    bytes32 actionID,
    uint256 nonce,
    address to,
    bytes data,
    string revertReason
  );

  // ABIEncoderV2 uses an array of Calls for executing generic batch calls.
  struct Call {
    address to;
    bytes data;
  }

  // ABIEncoderV2 uses an array of CallReturns for handling generic batch calls.
  struct CallReturn {
    bool ok;
    bytes returnData;
  }

  function withdrawEther(
    uint256 amount,
    address payable recipient,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external returns (bool ok);

  function executeAction(
    address to,
    bytes calldata data,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external returns (bool ok, bytes memory returnData);

  function recover(address newUserSigningKey) external;

  function executeActionWithAtomicBatchCalls(
    Call[] calldata calls,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external returns (bool[] memory ok, bytes[] memory returnData);

  function getNextGenericActionID(
    address to,
    bytes calldata data,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID);

  function getGenericActionID(
    address to,
    bytes calldata data,
    uint256 nonce,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID);

  function getNextGenericAtomicBatchActionID(
    Call[] calldata calls,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID);

  function getGenericAtomicBatchActionID(
    Call[] calldata calls,
    uint256 nonce,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID);
}


interface DharmaSmartWalletImplementationV3Interface {
  event Cancel(uint256 cancelledNonce);
  event EthWithdrawal(uint256 amount, address recipient);
}


interface DharmaSmartWalletImplementationV4Interface {
  event Escaped();

  function setEscapeHatch(
    address account,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external;

  function removeEscapeHatch(
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external;

  function permanentlyDisableEscapeHatch(
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external;

  function escape() external;
}


interface DharmaSmartWalletImplementationV7Interface {
  // Fires when a new user signing key is set on the smart wallet.
  event NewUserSigningKey(address userSigningKey);

  // Fires when an error occurs as part of an attempted action.
  event ExternalError(address indexed source, string revertReason);

  // The smart wallet recognizes DAI, USDC, ETH, and SAI as supported assets.
  enum AssetType {
    DAI,
    USDC,
    ETH,
    SAI
  }

  // Actions, or protected methods (i.e. not deposits) each have an action type.
  enum ActionType {
    Cancel,
    SetUserSigningKey,
    Generic,
    GenericAtomicBatch,
    SAIWithdrawal,
    USDCWithdrawal,
    ETHWithdrawal,
    SetEscapeHatch,
    RemoveEscapeHatch,
    DisableEscapeHatch,
    DAIWithdrawal,
    SignatureVerification,
    TradeEthForDai,
    DAIBorrow,
    USDCBorrow
  }

  function initialize(address userSigningKey) external;

  function repayAndDeposit() external;

  function withdrawDai(
    uint256 amount,
    address recipient,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external returns (bool ok);

  function withdrawUSDC(
    uint256 amount,
    address recipient,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external returns (bool ok);

  function cancel(
    uint256 minimumActionGas,
    bytes calldata signature
  ) external;

  function setUserSigningKey(
    address userSigningKey,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external;

  function migrateSaiToDai() external;

  function migrateCSaiToDDai() external;

  function migrateCDaiToDDai() external;

  function migrateCUSDCToDUSDC() external;

  function getBalances() external view returns (
    uint256 daiBalance,
    uint256 usdcBalance,
    uint256 etherBalance,
    uint256 dDaiUnderlyingDaiBalance,
    uint256 dUsdcUnderlyingUsdcBalance,
    uint256 dEtherUnderlyingEtherBalance // always returns zero
  );

  function getUserSigningKey() external view returns (address userSigningKey);

  function getNonce() external view returns (uint256 nonce);

  function getNextCustomActionID(
    ActionType action,
    uint256 amount,
    address recipient,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID);

  function getCustomActionID(
    ActionType action,
    uint256 amount,
    address recipient,
    uint256 nonce,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID);

  function getVersion() external pure returns (uint256 version);
}


interface DharmaSmartWalletImplementationV8Interface {
  function tradeEthForDaiAndMintDDai(
    uint256 ethToSupply,
    uint256 minimumDaiReceived,
    address target,
    bytes calldata data,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external returns (bool ok, bytes memory returnData);

  function getNextEthForDaiActionID(
    uint256 ethToSupply,
    uint256 minimumDaiReceived,
    address target,
    bytes calldata data,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID);

  function getEthForDaiActionID(
    uint256 ethToSupply,
    uint256 minimumDaiReceived,
    address target,
    bytes calldata data,
    uint256 nonce,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID);
}


interface ERC20Interface {
  function transfer(address recipient, uint256 amount) external returns (bool);
  function approve(address spender, uint256 amount) external returns (bool);

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


interface ERC1271Interface {
  function isValidSignature(
    bytes calldata data, bytes calldata signature
  ) external view returns (bytes4 magicValue);
}


interface CTokenInterface {
  function redeem(uint256 redeemAmount) external returns (uint256 err);
  function transfer(address recipient, uint256 value) external returns (bool);
  function approve(address spender, uint256 amount) external returns (bool);

  function balanceOf(address account) external view returns (uint256 balance);
  function allowance(address owner, address spender) external view returns (uint256);
}


interface DTokenInterface {
  // These external functions trigger accrual on the dToken and backing cToken.
  function mint(uint256 underlyingToSupply) external returns (uint256 dTokensMinted);
  function redeem(uint256 dTokensToBurn) external returns (uint256 underlyingReceived);
  function redeemUnderlying(uint256 underlyingToReceive) external returns (uint256 dTokensBurned);

  // These external functions only trigger accrual on the dToken.
  function mintViaCToken(uint256 cTokensToSupply) external returns (uint256 dTokensMinted);

  // View and pure functions do not trigger accrual on the dToken or the cToken.
  function balanceOfUnderlying(address account) external view returns (uint256 underlyingBalance);
}


interface USDCV1Interface {
  function isBlacklisted(address _account) external view returns (bool);
  function paused() external view returns (bool);
}


interface DharmaKeyRegistryInterface {
  function getKey() external view returns (address key);
}


interface DharmaEscapeHatchRegistryInterface {
  function setEscapeHatch(address newEscapeHatch) external;

  function removeEscapeHatch() external;

  function permanentlyDisableEscapeHatch() external;

  function getEscapeHatch() external view returns (
    bool exists, address escapeHatch
  );
}


interface TradeHelperInterface {
  function tradeEthForDai(
    uint256 daiExpected, address target, bytes calldata data
  ) external payable returns (uint256 daiReceived);
}


interface RevertReasonHelperInterface {
  function reason(uint256 code) external pure returns (string memory);
}


interface EtherizedInterface {
  function triggerEtherTransfer(
    address payable target, uint256 value
  ) external returns (bool success);
}


interface ConfigurationRegistryInterface {
  function get(bytes32 key) external view returns (bytes32 value);
}


library Address {
  function isContract(address account) internal view returns (bool) {
    uint256 size;
    assembly { size := extcodesize(account) }
    return size > 0;
  }
}


library ECDSA {
  function recover(
    bytes32 hash, bytes memory signature
  ) internal pure returns (address) {
    if (signature.length != 65) {
      return (address(0));
    }

    bytes32 r;
    bytes32 s;
    uint8 v;

    assembly {
      r := mload(add(signature, 0x20))
      s := mload(add(signature, 0x40))
      v := byte(0, mload(add(signature, 0x60)))
    }

    if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
      return address(0);
    }

    if (v != 27 && v != 28) {
      return address(0);
    }

    return ecrecover(hash, v, r, s);
  }

  function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
  }
}


contract Etherized is EtherizedInterface {
  address private constant _ETHERIZER = address(
    0x723B51b72Ae89A3d0c2a2760f0458307a1Baa191 
  );
  
  function triggerEtherTransfer(
    address payable target, uint256 amount
  ) external returns (bool success) {
    require(msg.sender == _ETHERIZER, "Etherized: only callable by Etherizer");
    (success, ) = target.call.value(amount)("");
    if (!success) {
      assembly {
        returndatacopy(0, 0, returndatasize())
        revert(0, returndatasize())
      }
    }
  }
}


/**
 * @title DharmaSmartWalletImplementationV10
 * @author 0age
 * @notice The V10 implementation for the Dharma smart wallet is a non-custodial,
 * meta-transaction-enabled wallet with helper functions to facilitate lending
 * funds through Dharma Dai and Dharma USD Coin (which in turn use CompoundV2),
 * and with an added security backstop provided by Dharma Labs prior to making
 * withdrawals. It adds support for Dharma Dai and Dharma USD Coin - they employ
 * the respective cTokens as backing tokens and mint and redeem them internally
 * as interest-bearing collateral. This implementation also contains methods to
 * support account recovery, escape hatch functionality, and generic actions,
 * including in an atomic batch. The smart wallet instances utilizing this
 * implementation are deployed through the Dharma Smart Wallet Factory via
 * `CREATE2`, which allows for their address to be known ahead of time, and any
 * Dai or USDC that has already been sent into that address will automatically
 * be deposited into the respective Dharma Token upon deployment of the new
 * smart wallet instance. V10 allows for deactivation of automatic USDC deposits
 * into cUSDC and deprecates Sai-related functionality.
 */
contract DharmaSmartWalletImplementationV10 is
  DharmaSmartWalletImplementationV1Interface,
  DharmaSmartWalletImplementationV3Interface,
  DharmaSmartWalletImplementationV4Interface,
  DharmaSmartWalletImplementationV7Interface,
  DharmaSmartWalletImplementationV8Interface,
  ERC1271Interface,
  Etherized {
  using Address for address;
  using ECDSA for bytes32;
  // WARNING: DO NOT REMOVE OR REORDER STORAGE WHEN WRITING NEW IMPLEMENTATIONS!

  // The user signing key associated with this account is in storage slot 0.
  // It is the core differentiator when it comes to the account in question.
  address private _userSigningKey;

  // The nonce associated with this account is in storage slot 1. Every time a
  // signature is submitted, it must have the appropriate nonce, and once it has
  // been accepted the nonce will be incremented.
  uint256 private _nonce;

  // The self-call context flag is in storage slot 2. Some protected functions
  // may only be called externally from calls originating from other methods on
  // this contract, which enables appropriate exception handling on reverts.
  // Any storage should only be set immediately preceding a self-call and should
  // be cleared upon entering the protected function being called.
  bytes4 internal _selfCallContext;

  // END STORAGE DECLARATIONS - DO NOT REMOVE OR REORDER STORAGE ABOVE HERE!

  // The smart wallet version will be used when constructing valid signatures.
  uint256 internal constant _DHARMA_SMART_WALLET_VERSION = 10;

  // DharmaKeyRegistryV2 holds a public key for verifying meta-transactions.
  DharmaKeyRegistryInterface internal constant _DHARMA_KEY_REGISTRY = (
    DharmaKeyRegistryInterface(0x000000000D38df53b45C5733c7b34000dE0BDF52)
  );

  // Account recovery is facilitated using a hard-coded recovery manager,
  // controlled by Dharma and implementing appropriate timelocks.
  address internal constant _ACCOUNT_RECOVERY_MANAGER = address(
    0x0000000000DfEd903aD76996FC07BF89C0127B1E
  );

  // Users can designate an "escape hatch" account with the ability to sweep all
  // funds from their smart wallet by using the Dharma Escape Hatch Registry.
  DharmaEscapeHatchRegistryInterface internal constant _ESCAPE_HATCH_REGISTRY = (
    DharmaEscapeHatchRegistryInterface(0x00000000005280B515004B998a944630B6C663f8)
  );

  // Interface with dDai, dUSDC, Dai, USDC, Sai, cSai, cDai, cUSDC, & migrator.
  DTokenInterface internal constant _DDAI = DTokenInterface(
    0x00000000001876eB1444c986fD502e618c587430 // mainnet
  );

  DTokenInterface internal constant _DUSDC = DTokenInterface(
    0x00000000008943c65cAf789FFFCF953bE156f6f8 // mainnet
  );

  ERC20Interface internal constant _DAI = ERC20Interface(
    0x6B175474E89094C44Da98b954EedeAC495271d0F // mainnet
  );

  ERC20Interface internal constant _USDC = ERC20Interface(
    0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 // mainnet
  );

  CTokenInterface internal constant _CDAI = CTokenInterface(
    0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643 // mainnet
  );

  CTokenInterface internal constant _CUSDC = CTokenInterface(
    0x39AA39c021dfbaE8faC545936693aC917d5E7563 // mainnet
  );
  
  // The "trade helper" facilitates Eth-to-Dai trades in an isolated context.
  TradeHelperInterface internal constant _TRADE_HELPER = TradeHelperInterface(
    0x421816CDFe2073945173c0c35799ec21261fB399
  );

  // The "revert reason helper" contains a collection of revert reason strings.
  RevertReasonHelperInterface internal constant _REVERT_REASON_HELPER = (
    RevertReasonHelperInterface(0x9C0ccB765D3f5035f8b5Dd30fE375d5F4997D8E4)
  );
  
  ConfigurationRegistryInterface internal constant _CONFIG_REGISTRY = (
    ConfigurationRegistryInterface(0xC5C0ead7Df3CeFC45c8F4592E3a0f1500949E75D)
  );
  
  bytes32 internal constant _ENABLE_USDC_MINTING_KEY = bytes32(
    0x596746115f08448433597980d42b4541c0197187d07ffad9c7f66a471c49dbba
  ); // keccak256("allowAvailableUSDCToBeUsedToMintCUSDC")

  // Compound returns a value of 0 to indicate success, or lack of an error.
  uint256 internal constant _COMPOUND_SUCCESS = 0;

  // ERC-1271 must return this magic value when `isValidSignature` is called.
  bytes4 internal constant _ERC_1271_MAGIC_VALUE = bytes4(0x20c13b0b);

  // Minimum supported deposit & non-maximum withdrawal size is .001 underlying.
  uint256 private constant _JUST_UNDER_ONE_1000th_DAI = 999999999999999;
  uint256 private constant _JUST_UNDER_ONE_1000th_USDC = 999;

  // Specify the amount of gas to supply when making Ether transfers.
  uint256 private constant _ETH_TRANSFER_GAS = 4999;
  
  constructor() public {
    assert(
      _ENABLE_USDC_MINTING_KEY == keccak256(
        bytes("allowAvailableUSDCToBeUsedToMintCUSDC")
      )
    );
  }

  /**
   * @notice Accept Ether in the fallback.
   */
  function () external payable {}

  /**
   * @notice In the initializer, set up the initial user signing key, set
   * approval on the Dharma Dai and Dharma USD Coin contracts, and deposit any
   * Dai or USDC already at this address to receive dDai or dUSDC. Note that
   * this initializer is only callable while the smart wallet instance is still
   * in the contract creation phase.
   * @param userSigningKey address The initial user signing key for the smart
   * wallet.
   */
  function initialize(address userSigningKey) external {
    // Ensure that this function is only callable during contract construction.
    assembly { if extcodesize(address) { revert(0, 0) } }

    // Set up the user's signing key and emit a corresponding event.
    _setUserSigningKey(userSigningKey);

    // Approve the dDai contract to transfer Dai on behalf of this contract.
    if (_setFullApproval(AssetType.DAI)) {
      // Get the current Dai balance on this contract.
      uint256 daiBalance = _DAI.balanceOf(address(this));

      // Try to deposit the full Dai balance to Dharma Dai.
      _depositDharmaToken(AssetType.DAI, daiBalance);
    }

    // Approve the dUSDC contract to transfer USDC on behalf of this contract.
    if (_setFullApproval(AssetType.USDC)) {
      // Get the current USDC balance on this contract.
      uint256 usdcBalance = _USDC.balanceOf(address(this));

      // Try to deposit the full Dai balance to Dharma USDC.
      _depositDharmaToken(AssetType.USDC, usdcBalance);
    }
  }

  /**
   * @notice Deposit all Dai and USDC currently residing at this address and
   * receive Dharma Dai or Dharma USD Coin in return. Note that "repay" is not
   * currently implemented, though it may be in a future implementation. If some
   * step of this function fails, the function itself will still succeed, but an
   * `ExternalError` with information on what went wrong will be emitted.
   */
  function repayAndDeposit() external {
    // Get the current Dai balance on this contract.
    uint256 daiBalance = _DAI.balanceOf(address(this));

    // If there is any Dai balance, check for adequate approval for dDai.
    if (daiBalance > 0) {
      uint256 daiAllowance = _DAI.allowance(address(this), address(_DDAI));
      // If allowance is insufficient, try to set it before depositing.
      if (daiAllowance < daiBalance) {
        if (_setFullApproval(AssetType.DAI)) {
          // Deposit the full available Dai balance to Dharma Dai.
          _depositDharmaToken(AssetType.DAI, daiBalance);
        }
      // Otherwise, just go ahead and try the Dai deposit.
      } else {
        // Deposit the full available Dai balance to Dharma Dai.
        _depositDharmaToken(AssetType.DAI, daiBalance);
      }
    }

    // Get the current USDC balance on this contract.
    uint256 usdcBalance = _USDC.balanceOf(address(this));

    // If there is any USDC balance, check for adequate approval for dUSDC.
    if (usdcBalance > 0) {
      uint256 usdcAllowance = _USDC.allowance(address(this), address(_DUSDC));
      // If allowance is insufficient, try to set it before depositing.
      if (usdcAllowance < usdcBalance) {
        if (_setFullApproval(AssetType.USDC)) {
          // Deposit the full available USDC balance to Dharma USDC.
          _depositDharmaToken(AssetType.USDC, usdcBalance);
        }
      // Otherwise, just go ahead and try the USDC deposit.
      } else {
        // Deposit the full available USDC balance to Dharma USDC.
        _depositDharmaToken(AssetType.USDC, usdcBalance);
      }
    }
  }

  /**
   * @notice Withdraw Dai to a provided recipient address by redeeming the
   * underlying Dai from the dDai contract and transferring it to the recipient.
   * All Dai in Dharma Dai and in the smart wallet itself can be withdrawn by
   * providing an amount of uint256(-1) or 0xfff...fff. This function can be
   * called directly by the account set as the global key on the Dharma Key
   * Registry, or by any relayer that provides a signed message from the same
   * keyholder. The nonce used for the signature must match the current nonce on
   * the smart wallet, and gas supplied to the call must exceed the specified
   * minimum action gas, plus the gas that will be spent before the gas check is
   * reached - usually somewhere around 25,000 gas. If the withdrawal fails, an
   * `ExternalError` with additional details on what went wrong will be emitted.
   * Note that some dust may still be left over, even in the event of a max
   * withdrawal, due to the fact that Dai has a higher precision than dDai. Also
   * note that the withdrawal will fail in the event that Compound does not have
   * sufficient Dai available to withdraw.
   * @param amount uint256 The amount of Dai to withdraw.
   * @param recipient address The account to transfer the withdrawn Dai to.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used. A unique hash returned from `getCustomActionID` is prefixed
   * and hashed to create the message hash for the signature.
   * @param dharmaSignature bytes A signature that resolves to the public key
   * returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getCustomActionID` is prefixed and hashed to create the
   * signed message.
   * @return True if the withdrawal succeeded, otherwise false.
   */
  function withdrawDai(
    uint256 amount,
    address recipient,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external returns (bool ok) {
    // Ensure caller and/or supplied signatures are valid and increment nonce.
    _validateActionAndIncrementNonce(
      ActionType.DAIWithdrawal,
      abi.encode(amount, recipient),
      minimumActionGas,
      userSignature,
      dharmaSignature
    );

    // Ensure that an amount of at least 0.001 Dai has been supplied.
    if (amount <= _JUST_UNDER_ONE_1000th_DAI) {
      revert(_revertReason(0));
    }

    // Ensure that a non-zero recipient has been supplied.
    if (recipient == address(0)) {
      revert(_revertReason(1));
    }

    // Set the self-call context in order to call _withdrawDaiAtomic.
    _selfCallContext = this.withdrawDai.selector;

    // Make the atomic self-call - if redeemUnderlying fails on dDai, it will
    // succeed but nothing will happen except firing an ExternalError event. If
    // the second part of the self-call (the Dai transfer) fails, it will revert
    // and roll back the first part of the call as well as fire an ExternalError
    // event after returning from the failed call.
    bytes memory returnData;
    (ok, returnData) = address(this).call(abi.encodeWithSelector(
      this._withdrawDaiAtomic.selector, amount, recipient
    ));

    // If the atomic call failed, emit an event signifying a transfer failure.
    if (!ok) {
      emit ExternalError(address(_DAI), _revertReason(2));
    } else {
      // Set ok to false if the call succeeded but the withdrawal failed.
      ok = abi.decode(returnData, (bool));
    }
  }

  /**
   * @notice Protected function that can only be called from `withdrawDai` on
   * this contract. It will attempt to withdraw the supplied amount of Dai, or
   * the maximum amount if specified using `uint256(-1)`, to the supplied
   * recipient address by redeeming the underlying Dai from the dDai contract
   * and transferring it to the recipient. An ExternalError will be emitted and
   * the transfer will be skipped if the call to `redeem` or `redeemUnderlying`
   * fails, and any revert will be caught by `withdrawDai` and diagnosed in
   * order to emit an appropriate `ExternalError` as well.
   * @param amount uint256 The amount of Dai to withdraw.
   * @param recipient address The account to transfer the withdrawn Dai to.
   * @return True if the withdrawal succeeded, otherwise false.
   */
  function _withdrawDaiAtomic(
    uint256 amount,
    address recipient
  ) external returns (bool success) {
    // Ensure caller is this contract and self-call context is correctly set.
    _enforceSelfCallFrom(this.withdrawDai.selector);

    // If amount = 0xfff...fff, withdraw the maximum amount possible.
    bool maxWithdraw = (amount == uint256(-1));
    if (maxWithdraw) {
      // First attempt to redeem all dDai if there is a balance.
      _withdrawMaxFromDharmaToken(AssetType.DAI);

      // Then transfer all Dai to recipient if there is a balance.
      require(_transferMax(_DAI, recipient, false));
      success = true;
    } else {
      // Attempt to withdraw specified Dai from Dharma Dai before proceeding.
      if (_withdrawFromDharmaToken(AssetType.DAI, amount)) {
        // At this point Dai transfer should never fail - wrap it just in case.
        require(_DAI.transfer(recipient, amount));
        success = true;
      }
    }
  }

  /**
   * @notice Withdraw USDC to a provided recipient address by redeeming the
   * underlying USDC from the dUSDC contract and transferring it to recipient.
   * All USDC in Dharma USD Coin and in the smart wallet itself can be withdrawn
   * by providing an amount of uint256(-1) or 0xfff...fff. This function can be
   * called directly by the account set as the global key on the Dharma Key
   * Registry, or by any relayer that provides a signed message from the same
   * keyholder. The nonce used for the signature must match the current nonce on
   * the smart wallet, and gas supplied to the call must exceed the specified
   * minimum action gas, plus the gas that will be spent before the gas check is
   * reached - usually somewhere around 25,000 gas. If the withdrawal fails, an
   * `ExternalError` with additional details on what went wrong will be emitted.
   * Note that the USDC contract can be paused and also allows for blacklisting
   * accounts - either of these possibilities may cause a withdrawal to fail. In
   * addition, Compound may not have sufficient USDC available at the time to
   * withdraw.
   * @param amount uint256 The amount of USDC to withdraw.
   * @param recipient address The account to transfer the withdrawn USDC to.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used. A unique hash returned from `getCustomActionID` is prefixed
   * and hashed to create the message hash for the signature.
   * @param dharmaSignature bytes A signature that resolves to the public key
   * returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getCustomActionID` is prefixed and hashed to create the
   * signed message.
   * @return True if the withdrawal succeeded, otherwise false.
   */
  function withdrawUSDC(
    uint256 amount,
    address recipient,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external returns (bool ok) {
    // Ensure caller and/or supplied signatures are valid and increment nonce.
    _validateActionAndIncrementNonce(
      ActionType.USDCWithdrawal,
      abi.encode(amount, recipient),
      minimumActionGas,
      userSignature,
      dharmaSignature
    );

    // Ensure that an amount of at least 0.001 USDC has been supplied.
    if (amount <= _JUST_UNDER_ONE_1000th_USDC) {
      revert(_revertReason(3));
    }

    // Ensure that a non-zero recipient has been supplied.
    if (recipient == address(0)) {
      revert(_revertReason(1));
    }

    // Set the self-call context in order to call _withdrawUSDCAtomic.
    _selfCallContext = this.withdrawUSDC.selector;

    // Make the atomic self-call - if redeemUnderlying fails on dUSDC, it will
    // succeed but nothing will happen except firing an ExternalError event. If
    // the second part of the self-call (USDC transfer) fails, it will revert
    // and roll back the first part of the call as well as fire an ExternalError
    // event after returning from the failed call.
    bytes memory returnData;
    (ok, returnData) = address(this).call(abi.encodeWithSelector(
      this._withdrawUSDCAtomic.selector, amount, recipient
    ));
    if (!ok) {
      // Find out why USDC transfer reverted (doesn't give revert reasons).
      _diagnoseAndEmitUSDCSpecificError(_USDC.transfer.selector);
    } else {
      // Set ok to false if the call succeeded but the withdrawal failed.
      ok = abi.decode(returnData, (bool));
    }
  }

  /**
   * @notice Protected function that can only be called from `withdrawUSDC` on
   * this contract. It will attempt to withdraw the supplied amount of USDC, or
   * the maximum amount if specified using `uint256(-1)`, to the supplied
   * recipient address by redeeming the underlying USDC from the dUSDC contract
   * and transferring it to the recipient. An ExternalError will be emitted and
   * the transfer will be skipped if the call to `redeemUnderlying` fails, and
   * any revert will be caught by `withdrawUSDC` and diagnosed in order to emit
   * an appropriate ExternalError as well.
   * @param amount uint256 The amount of USDC to withdraw.
   * @param recipient address The account to transfer the withdrawn USDC to.
   * @return True if the withdrawal succeeded, otherwise false.
   */
  function _withdrawUSDCAtomic(
    uint256 amount,
    address recipient
  ) external returns (bool success) {
    // Ensure caller is this contract and self-call context is correctly set.
    _enforceSelfCallFrom(this.withdrawUSDC.selector);

    // If amount = 0xfff...fff, withdraw the maximum amount possible.
    bool maxWithdraw = (amount == uint256(-1));
    if (maxWithdraw) {
      // Attempt to redeem all dUSDC from Dharma USDC if there is a balance.
      _withdrawMaxFromDharmaToken(AssetType.USDC);

      // Then transfer all USDC to recipient if there is a balance.
      require(_transferMax(_USDC, recipient, false));
      success = true;
    } else {
      // Attempt to withdraw specified USDC from Dharma USDC before proceeding.
      if (_withdrawFromDharmaToken(AssetType.USDC, amount)) {
        // Ensure that the USDC transfer does not fail.
        require(_USDC.transfer(recipient, amount));
        success = true;
      }
    }
  }

  /**
   * @notice Withdraw Ether to a provided recipient address by transferring it
   * to a recipient.
   * @param amount uint256 The amount of Ether to withdraw.
   * @param recipient address The account to transfer the Ether to.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used. A unique hash returned from `getCustomActionID` is prefixed
   * and hashed to create the message hash for the signature.
   * @param dharmaSignature bytes A signature that resolves to the public key
   * returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getCustomActionID` is prefixed and hashed to create the
   * signed message.
   * @return True if the transfer succeeded, otherwise false.
   */
  function withdrawEther(
    uint256 amount,
    address payable recipient,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external returns (bool ok) {
    // Ensure caller and/or supplied signatures are valid and increment nonce.
    _validateActionAndIncrementNonce(
      ActionType.ETHWithdrawal,
      abi.encode(amount, recipient),
      minimumActionGas,
      userSignature,
      dharmaSignature
    );

    // Ensure that a non-zero amount of Ether has been supplied.
    if (amount == 0) {
      revert(_revertReason(4));
    }

    // Ensure that a non-zero recipient has been supplied.
    if (recipient == address(0)) {
      revert(_revertReason(1));
    }

    // Attempt to transfer Ether to the recipient and emit an appropriate event.
    ok = _transferETH(recipient, amount);
  }

  /**
   * @notice Allow a signatory to increment the nonce at any point. The current
   * nonce needs to be provided as an argument to the signature so as not to
   * enable griefing attacks. All arguments can be omitted if called directly.
   * No value is returned from this function - it will either succeed or revert.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param signature bytes A signature that resolves to either the public key
   * set for this account in storage slot zero, `_userSigningKey`, or the public
   * key returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getCustomActionID` is prefixed and hashed to create the
   * signed message.
   */
  function cancel(
    uint256 minimumActionGas,
    bytes calldata signature
  ) external {
    // Get the current nonce.
    uint256 nonceToCancel = _nonce;

    // Ensure the caller or the supplied signature is valid and increment nonce.
    _validateActionAndIncrementNonce(
      ActionType.Cancel,
      abi.encode(),
      minimumActionGas,
      signature,
      signature
    );

    // Emit an event to validate that the nonce is no longer valid.
    emit Cancel(nonceToCancel);
  }

  /**
   * @notice Perform a generic call to another contract. Note that accounts with
   * no code may not be specified, nor may the smart wallet itself or the escape
   * hatch registry. In order to increment the nonce and invalidate the
   * signatures, a call to this function with a valid target, signatutes, and
   * gas will always succeed. To determine whether the call made as part of the
   * action was successful or not, either the return values or the `CallSuccess`
   * or `CallFailure` event can be used.
   * @param to address The contract to call.
   * @param data bytes The calldata to provide when making the call.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used. A unique hash returned from `getCustomActionID` is prefixed
   * and hashed to create the message hash for the signature.
   * @param dharmaSignature bytes A signature that resolves to the public key
   * returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getCustomActionID` is prefixed and hashed to create the
   * signed message.
   * @return A boolean signifying the status of the call, as well as any data
   * returned from the call.
   */
  function executeAction(
    address to,
    bytes calldata data,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external returns (bool ok, bytes memory returnData) {
    // Ensure that the `to` address is a contract and is not this contract.
    _ensureValidGenericCallTarget(to);

    // Ensure caller and/or supplied signatures are valid and increment nonce.
    (bytes32 actionID, uint256 nonce) = _validateActionAndIncrementNonce(
      ActionType.Generic,
      abi.encode(to, data),
      minimumActionGas,
      userSignature,
      dharmaSignature
    );

    // Note: from this point on, there are no reverts (apart from out-of-gas or
    // call-depth-exceeded) originating from this action. However, the call
    // itself may revert, in which case the function will return `false`, along
    // with the revert reason encoded as bytes, and fire an CallFailure event.

    // Perform the action via low-level call and set return values using result.
    (ok, returnData) = to.call(data);

    // Emit a CallSuccess or CallFailure event based on the outcome of the call.
    if (ok) {
      // Note: while the call succeeded, the action may still have "failed"
      // (for example, successful calls to Compound can still return an error).
      emit CallSuccess(actionID, false, nonce, to, data, returnData);
    } else {
      // Note: while the call failed, the nonce will still be incremented, which
      // will invalidate all supplied signatures.
      emit CallFailure(actionID, nonce, to, data, string(returnData));
    }
  }

  /**
   * @notice Allow signatory to set a new user signing key. The current nonce
   * needs to be provided as an argument to the signature so as not to enable
   * griefing attacks. No value is returned from this function - it will either
   * succeed or revert.
   * @param userSigningKey address The new user signing key to set on this smart
   * wallet.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used. A unique hash returned from `getCustomActionID` is prefixed
   * and hashed to create the message hash for the signature.
   * @param dharmaSignature bytes A signature that resolves to the public key
   * returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getCustomActionID` is prefixed and hashed to create the
   * signed message.
   */
  function setUserSigningKey(
    address userSigningKey,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external {
    // Ensure caller and/or supplied signatures are valid and increment nonce.
    _validateActionAndIncrementNonce(
      ActionType.SetUserSigningKey,
      abi.encode(userSigningKey),
      minimumActionGas,
      userSignature,
      dharmaSignature
    );

    // Set new user signing key on smart wallet and emit a corresponding event.
    _setUserSigningKey(userSigningKey);
  }

  /**
   * @notice Set a dedicated address as the "escape hatch" account. This account
   * can then call `escape()` at any point to "sweep" the entire Dai, USDC,
   * residual cDai, cUSDC, dDai, dUSDC, and Ether balance from the smart wallet.
   * This function call will revert if the smart wallet has previously called
   * `permanentlyDisableEscapeHatch` at any point and disabled the escape hatch.
   * No value is returned from this function - it will either succeed or revert.
   * @param account address The account to set as the escape hatch account.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used. A unique hash returned from `getCustomActionID` is prefixed
   * and hashed to create the message hash for the signature.
   * @param dharmaSignature bytes A signature that resolves to the public key
   * returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getCustomActionID` is prefixed and hashed to create the
   * signed message.
   */
  function setEscapeHatch(
    address account,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external {
    // Ensure caller and/or supplied signatures are valid and increment nonce.
    _validateActionAndIncrementNonce(
      ActionType.SetEscapeHatch,
      abi.encode(account),
      minimumActionGas,
      userSignature,
      dharmaSignature
    );

    // Ensure that an escape hatch account has been provided.
    if (account == address(0)) {
      revert(_revertReason(5));
    }

    // Set a new escape hatch for the smart wallet unless it has been disabled.
    _ESCAPE_HATCH_REGISTRY.setEscapeHatch(account);
  }

  /**
   * @notice Remove the "escape hatch" account if one is currently set. This
   * function call will revert if the smart wallet has previously called
   * `permanentlyDisableEscapeHatch` at any point and disabled the escape hatch.
   * No value is returned from this function - it will either succeed or revert.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used. A unique hash returned from `getCustomActionID` is prefixed
   * and hashed to create the message hash for the signature.
   * @param dharmaSignature bytes A signature that resolves to the public key
   * returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getCustomActionID` is prefixed and hashed to create the
   * signed message.
   */
  function removeEscapeHatch(
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external {
    // Ensure caller and/or supplied signatures are valid and increment nonce.
    _validateActionAndIncrementNonce(
      ActionType.RemoveEscapeHatch,
      abi.encode(),
      minimumActionGas,
      userSignature,
      dharmaSignature
    );

    // Remove the escape hatch for the smart wallet if one is currently set.
    _ESCAPE_HATCH_REGISTRY.removeEscapeHatch();
  }

  /**
   * @notice Permanently disable the "escape hatch" mechanism for this smart
   * wallet. This function call will revert if the smart wallet has already
   * called `permanentlyDisableEscapeHatch` at any point in the past. No value
   * is returned from this function - it will either succeed or revert.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used. A unique hash returned from `getCustomActionID` is prefixed
   * and hashed to create the message hash for the signature.
   * @param dharmaSignature bytes A signature that resolves to the public key
   * returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getCustomActionID` is prefixed and hashed to create the
   * signed message.
   */
  function permanentlyDisableEscapeHatch(
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external {
    // Ensure caller and/or supplied signatures are valid and increment nonce.
    _validateActionAndIncrementNonce(
      ActionType.DisableEscapeHatch,
      abi.encode(),
      minimumActionGas,
      userSignature,
      dharmaSignature
    );

    // Permanently disable the escape hatch mechanism for this smart wallet.
    _ESCAPE_HATCH_REGISTRY.permanentlyDisableEscapeHatch();
  }

  /**
   * @notice Swap Ether for Dai and use it to mint Dharma Dai. The trade is
   * facilitated by a "trade helper" contract in order to protect against
   * malicious calls related to processing swaps via potentially unsafe call
   * targets or other parameters. In the event that a swap does not result in
   * sufficient Dai being received, the swap will be rolled back. In either
   * case the nonce will still be incremented as long as signatures are valid.
   * @param ethToSupply uint256 The Ether to supply as part of the swap.
   * @param minimumDaiReceived uint256 The minimum amount of Dai that must be
   * received in exchange for the supplied Ether.
   * @param target address The contract that the trade helper should call in
   * order to facilitate the swap.
   * @param data bytes The payload that will be passed to the target, along with
   * the supplied Ether, by the trade helper in order to facilitate the swap.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used. A unique hash returned from `getEthForDaiActionID` is prefixed
   * and hashed to create the message hash for the signature.
   * @param dharmaSignature bytes A signature that resolves to the public key
   * returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getEthForDaiActionIDActionID` is prefixed and hashed to
   * create the signed message.
   */
  function tradeEthForDaiAndMintDDai(
    uint256 ethToSupply,
    uint256 minimumDaiReceived,
    address target,
    bytes calldata data,
    uint256 minimumActionGas,
    bytes calldata userSignature,
    bytes calldata dharmaSignature
  ) external returns (bool ok, bytes memory returnData) {
    // Ensure caller and/or supplied signatures are valid and increment nonce.
    _validateActionAndIncrementNonce(
      ActionType.TradeEthForDai,
      abi.encode(ethToSupply, minimumDaiReceived, target, data),
      minimumActionGas,
      userSignature,
      dharmaSignature
    );

    // Ensure that an amount of at least 0.001 Dai will be received.
    if (minimumDaiReceived <= _JUST_UNDER_ONE_1000th_DAI) {
      revert(_revertReason(31));
    }

    // Set the self-call context in order to call _tradeEthForDaiAndMintDDaiAtomic.
    _selfCallContext = this.tradeEthForDaiAndMintDDai.selector;

    // Make the atomic self-call - if the swap fails or the received dai is not
    // greater than or equal to the requirement, it will revert and roll back the
    // atomic call as well as fire an ExternalError. If dDai is not successfully
    // minted, the swap will succeed but an ExternalError for dDai will be fired.
    bytes memory returnData;
    (ok, returnData) = address(this).call(abi.encodeWithSelector(
      this._tradeEthForDaiAndMintDDaiAtomic.selector,
      ethToSupply, minimumDaiReceived, target, data
    ));

    // If the atomic call failed, emit an event signifying a trade failure.
    if (!ok) {
      emit ExternalError(
        address(_TRADE_HELPER), _decodeRevertReason(returnData)
      );
    }
  }
  
  function _tradeEthForDaiAndMintDDaiAtomic(
    uint256 ethToSupply,
    uint256 minimumDaiReceived,
    address target,
    bytes calldata data
  ) external returns (bool ok, bytes memory returnData) {
    // Ensure caller is this contract and self-call context is correctly set.
    _enforceSelfCallFrom(this.tradeEthForDaiAndMintDDai.selector);
    
    // Do swap using supplied Ether amount, minimum Dai, target, and data.
    uint256 daiReceived = _TRADE_HELPER.tradeEthForDai.value(ethToSupply)(
      minimumDaiReceived, target, data
    );
    
    // Ensure that sufficient Dai was returned as a result of the swap. 
    if (daiReceived < minimumDaiReceived) {
      revert(_revertReason(32));
    }
    
    // Attempt to deposit the dai received and mint Dharma Dai.
    _depositDharmaToken(AssetType.DAI, daiReceived);
  }

  /**
   * @notice Allow the designated escape hatch account to redeem and "sweep"
   * the entire Dai, USDC, residual dDai, dUSDC, cDai, cUSDC, & Ether balance
   * from the smart wallet. The call will revert for any other caller, or if
   * there is no escape hatch account on this smart wallet. First, an attempt
   * will be made to redeem any dDai or dUSDC that is currently deposited in a
   * dToken. Then, attempts will be made to transfer any balance in Dai, USDC,
   * residual cDai & cUSDC, and Ether to the escape hatch account. If any
   * portion of this operation does not succeed, it will simply be skipped,
   * allowing the rest of the operation to proceed. Finally, an `Escaped` event
   * will be emitted. No value is returned from this function - it will either
   * succeed or revert.
   */
  function escape() external {
    // Get the escape hatch account, if one exists, for this account.
    (bool exists, address escapeHatch) = _ESCAPE_HATCH_REGISTRY.getEscapeHatch();

    // Ensure that an escape hatch is currently set for this smart wallet.
    if (!exists) {
      revert(_revertReason(6));
    }

    // Ensure that the escape hatch account is the caller.
    if (msg.sender != escapeHatch) {
      revert(_revertReason(7));
    }

    // Attempt to redeem all dDai for Dai on Dharma Dai.
    _withdrawMaxFromDharmaToken(AssetType.DAI);

    // Attempt to redeem all dUSDC for USDC on Dharma USDC.
    _withdrawMaxFromDharmaToken(AssetType.USDC);

    // Attempt to transfer the total Dai balance to the caller.
    _transferMax(_DAI, msg.sender, true);

    // Attempt to transfer the total USDC balance to the caller.
    _transferMax(_USDC, msg.sender, true);

    // Attempt to transfer any residual cDai to the caller.
    _transferMax(ERC20Interface(address(_CDAI)), msg.sender, true);

    // Attempt to transfer any residual cUSDC to the caller.
    _transferMax(ERC20Interface(address(_CUSDC)), msg.sender, true);

    // Attempt to transfer any residual dDai to the caller.
    _transferMax(ERC20Interface(address(_DDAI)), msg.sender, true);

    // Attempt to transfer any residual dUSDC to the caller.
    _transferMax(ERC20Interface(address(_DUSDC)), msg.sender, true);

    // Determine if there is Ether at this address that should be transferred.
    uint256 balance = address(this).balance;
    if (balance > 0) {
      // Attempt to transfer any Ether to caller and emit an appropriate event.
      _transferETH(msg.sender, balance);
    }

    // Emit an `Escaped` event.
    emit Escaped();
  }

  /**
   * @notice Allow the account recovery manager to set a new user signing key on
   * the smart wallet. The call will revert for any other caller. The account
   * recovery manager implements a set of controls around the process, including
   * a timelock and an option to permanently opt out of account recover. No
   * value is returned from this function - it will either succeed or revert.
   * @param newUserSigningKey address The new user signing key to set on this
   * smart wallet.
   */
  function recover(address newUserSigningKey) external {
    // Only the Account Recovery Manager contract may call this function.
    if (msg.sender != _ACCOUNT_RECOVERY_MANAGER) {
      revert(_revertReason(8));
    }

    // Increment nonce to prevent signature reuse should original key be reset.
    _nonce++;

    // Set up the user's new dharma key and emit a corresponding event.
    _setUserSigningKey(newUserSigningKey);
  }

  /**
   * @notice This call is no longer supported.
   */
  function migrateSaiToDai() external {
    revert();
  }

  /**
   * @notice This call is no longer supported.
   */
  function migrateCSaiToDDai() external {
    revert();
  }

  /**
   * @notice Redeem all available cDAI for Dai and use that Dai to mint dDai. If
   * any step in the process fails, the call will revert and prior steps will be
   * rolled back. Also note that existing Sai and Dai are not included as part
   * of this operation.
   */
  function migrateCDaiToDDai() external {
     _migrateCTokenToDToken(AssetType.DAI);
  }

  /**
   * @notice Redeem all available cUSDC for USDC and use that USDC to mint
   * dUSDC. If any step in the process fails, the call will revert and prior
   * steps will be rolled back. Also note that existing USDC is not included as
   * part of this operation.
   */
  function migrateCUSDCToDUSDC() external {
     _migrateCTokenToDToken(AssetType.USDC);
  }

  /**
   * @notice View function to retrieve the Dai and USDC balances held by the
   * smart wallet, both directly and held in Dharma Dai and Dharma USD Coin, as
   * well as the Ether balance (the underlying dEther balance will always return
   * zero in this implementation, as there is no dEther yet).
   * @return The Dai balance, the USDC balance, the Ether balance, the
   * underlying Dai balance of the dDai balance, and the underlying USDC balance
   * of the dUSDC balance (zero will always be returned as the underlying Ether
   * balance of the dEther balance in this implementation).
   */
  function getBalances() external view returns (
    uint256 daiBalance,
    uint256 usdcBalance,
    uint256 etherBalance,
    uint256 dDaiUnderlyingDaiBalance,
    uint256 dUsdcUnderlyingUsdcBalance,
    uint256 dEtherUnderlyingEtherBalance // always returns 0
  ) {
    daiBalance = _DAI.balanceOf(address(this));
    usdcBalance = _USDC.balanceOf(address(this));
    etherBalance = address(this).balance;
    dDaiUnderlyingDaiBalance = _DDAI.balanceOfUnderlying(address(this));
    dUsdcUnderlyingUsdcBalance = _DUSDC.balanceOfUnderlying(address(this));
  }

  /**
   * @notice View function for getting the current user signing key for the
   * smart wallet.
   * @return The current user signing key.
   */
  function getUserSigningKey() external view returns (address userSigningKey) {
    userSigningKey = _userSigningKey;
  }

  /**
   * @notice View function for getting the current nonce of the smart wallet.
   * This nonce is incremented whenever an action is taken that requires a
   * signature and/or a specific caller.
   * @return The current nonce.
   */
  function getNonce() external view returns (uint256 nonce) {
    nonce = _nonce;
  }

  /**
   * @notice View function that, given an action type and arguments, will return
   * the action ID or message hash that will need to be prefixed (according to
   * EIP-191 0x45), hashed, and signed by both the user signing key and by the
   * key returned for this smart wallet by the Dharma Key Registry in order to
   * construct a valid signature for the corresponding action. Any nonce value
   * may be supplied, which enables constructing valid message hashes for
   * multiple future actions ahead of time.
   * @param action uint8 The type of action, designated by it's index. Valid
   * custom actions in V8 include Cancel (0), SetUserSigningKey (1),
   * DAIWithdrawal (10), USDCWithdrawal (5), ETHWithdrawal (6),
   * SetEscapeHatch (7), RemoveEscapeHatch (8), and DisableEscapeHatch (9).
   * @param amount uint256 The amount to withdraw for Withdrawal actions. This
   * value is ignored for non-withdrawal action types.
   * @param recipient address The account to transfer withdrawn funds to or the
   * new user signing key. This value is ignored for Cancel, RemoveEscapeHatch,
   * and DisableEscapeHatch action types.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @return The action ID, which will need to be prefixed, hashed and signed in
   * order to construct a valid signature.
   */
  function getNextCustomActionID(
    ActionType action,
    uint256 amount,
    address recipient,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID) {
    // Determine the actionID - this serves as a signature hash for an action.
    actionID = _getActionID(
      action,
      _validateCustomActionTypeAndGetArguments(action, amount, recipient),
      _nonce,
      minimumActionGas,
      _userSigningKey,
      _getDharmaSigningKey()
    );
  }

  /**
   * @notice View function that, given an action type and arguments, will return
   * the action ID or message hash that will need to be prefixed (according to
   * EIP-191 0x45), hashed, and signed by both the user signing key and by the
   * key returned for this smart wallet by the Dharma Key Registry in order to
   * construct a valid signature for the corresponding action. The current nonce
   * will be used, which means that it will only be valid for the next action
   * taken.
   * @param action uint8 The type of action, designated by it's index. Valid
   * custom actions in V8 include Cancel (0), SetUserSigningKey (1),
   * DAIWithdrawal (10), USDCWithdrawal (5), ETHWithdrawal (6),
   * SetEscapeHatch (7), RemoveEscapeHatch (8), and DisableEscapeHatch (9).
   * @param amount uint256 The amount to withdraw for Withdrawal actions. This
   * value is ignored for non-withdrawal action types.
   * @param recipient address The account to transfer withdrawn funds to or the
   * new user signing key. This value is ignored for Cancel, RemoveEscapeHatch,
   * and DisableEscapeHatch action types.
   * @param nonce uint256 The nonce to use.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @return The action ID, which will need to be prefixed, hashed and signed in
   * order to construct a valid signature.
   */
  function getCustomActionID(
    ActionType action,
    uint256 amount,
    address recipient,
    uint256 nonce,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID) {
    // Determine the actionID - this serves as a signature hash for an action.
    actionID = _getActionID(
      action,
      _validateCustomActionTypeAndGetArguments(action, amount, recipient),
      nonce,
      minimumActionGas,
      _userSigningKey,
      _getDharmaSigningKey()
    );
  }

  /**
   * @notice View function that will return the action ID or message hash that
   * will need to be prefixed (according to EIP-191 0x45), hashed, and signed by
   * both the user signing key and by the key returned for this smart wallet by
   * the Dharma Key Registry in order to construct a valid signature for a given
   * generic action. The current nonce will be used, which means that it will
   * only be valid for the next action taken.
   * @param to address The target to call into as part of the generic action.
   * @param data bytes The data to supply when calling into the target.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @return The action ID, which will need to be prefixed, hashed and signed in
   * order to construct a valid signature.
   */
  function getNextGenericActionID(
    address to,
    bytes calldata data,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID) {
    // Determine the actionID - this serves as a signature hash for an action.
    actionID = _getActionID(
      ActionType.Generic,
      abi.encode(to, data),
      _nonce,
      minimumActionGas,
      _userSigningKey,
      _getDharmaSigningKey()
    );
  }

  /**
   * @notice View function that will return the action ID or message hash that
   * will need to be prefixed (according to EIP-191 0x45), hashed, and signed by
   * both the user signing key and by the key returned for this smart wallet by
   * the Dharma Key Registry in order to construct a valid signature for a given
   * generic action. Any nonce value may be supplied, which enables constructing
   * valid message hashes for multiple future actions ahead of time.
   * @param to address The target to call into as part of the generic action.
   * @param data bytes The data to supply when calling into the target.
   * @param nonce uint256 The nonce to use.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @return The action ID, which will need to be prefixed, hashed and signed in
   * order to construct a valid signature.
   */
  function getGenericActionID(
    address to,
    bytes calldata data,
    uint256 nonce,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID) {
    // Determine the actionID - this serves as a signature hash for an action.
    actionID = _getActionID(
      ActionType.Generic,
      abi.encode(to, data),
      nonce,
      minimumActionGas,
      _userSigningKey,
      _getDharmaSigningKey()
    );
  }

  /**
   * @notice View function that will return the action ID or message hash that
   * will need to be prefixed (according to EIP-191 0x45), hashed, and signed by
   * both the user signing key and by the key returned for this smart wallet by
   * the Dharma Key Registry in order to construct a valid signature for an
   * Eth-to-Dai swap. The current nonce will be used, which means that it will
   * only be valid for the next action taken.
   * @param ethToSupply uint256 The Ether to supply as part of the swap.
   * @param minimumDaiReceived uint256 The minimum amount of Dai that must be
   * received in exchange for the supplied Ether.
   * @param target address The contract that the trade helper should call in
   * order to facilitate the swap.
   * @param data bytes The payload that will be passed to the target, along with
   * the supplied Ether, by the trade helper in order to facilitate the swap.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @return The action ID, which will need to be prefixed, hashed and signed in
   * order to construct a valid signature.
   */
  function getNextEthForDaiActionID(
    uint256 ethToSupply,
    uint256 minimumDaiReceived,
    address target,
    bytes calldata data,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID) {
    // Determine the actionID - this serves as a signature hash for an action.
    actionID = _getActionID(
      ActionType.TradeEthForDai,
      abi.encode(ethToSupply, minimumDaiReceived, target, data),
      _nonce,
      minimumActionGas,
      _userSigningKey,
      _getDharmaSigningKey()
    );
  }

  /**
   * @notice View function that will return the action ID or message hash that
   * will need to be prefixed (according to EIP-191 0x45), hashed, and signed by
   * both the user signing key and by the key returned for this smart wallet by
   * the Dharma Key Registry in order to construct a valid signature for an
   * Eth-to-Dai swap. Any nonce value may be supplied, which enables
   * constructing valid message hashes for multiple future actions ahead of
   * time.
   * @param ethToSupply uint256 The Ether to supply as part of the swap.
   * @param minimumDaiReceived uint256 The minimum amount of Dai that must be
   * received in exchange for the supplied Ether.
   * @param target address The contract that the trade helper should call in
   * order to facilitate the swap.
   * @param data bytes The payload that will be passed to the target, along with
   * the supplied Ether, by the trade helper in order to facilitate the swap.
   * @param nonce uint256 The nonce to use.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @return The action ID, which will need to be prefixed, hashed and signed in
   * order to construct a valid signature.
   */ 
  function getEthForDaiActionID(
    uint256 ethToSupply,
    uint256 minimumDaiReceived,
    address target,
    bytes calldata data,
    uint256 nonce,
    uint256 minimumActionGas
  ) external view returns (bytes32 actionID) {
    // Determine the actionID - this serves as a signature hash for an action.
    actionID = _getActionID(
      ActionType.TradeEthForDai,
      abi.encode(ethToSupply, minimumDaiReceived, target, data),
      nonce,
      minimumActionGas,
      _userSigningKey,
      _getDharmaSigningKey()
    );
  }

  /**
   * @notice View function that implements ERC-1271 and validates a set of
   * signatures, one from the owner (using ERC-1271 as well if the user signing
   * key is a contract) and one from the Dharma Key Registry against the
   * supplied data. The data must be ABI encoded as (bytes32, bytes), where the
   * first bytes32 parameter represents the hash digest for validating the
   * supplied signatures and the second bytes parameter contains context for the
   * requested validation. The two signatures are packed together, with the one
   * from Dharma coming first and that from the user coming second - this is so
   * that, in future versions, multiple user signatures may be supplied if the
   * associated key ring requires them.
   * @param data bytes The data used to validate the signature.
   * @param signatures bytes The two signatures, each 65 bytes - one from the
   * owner (using ERC-1271 as well if the user signing key is a contract) and
   * one from the Dharma Key Registry.
   * @return The 4-byte magic value to signify a valid signature in ERC-1271, if
   * the signatures are both valid.
   */
  function isValidSignature(
    bytes calldata data, bytes calldata signatures
  ) external view returns (bytes4 magicValue) {
    // Get message hash digest and any additional context from data argument.
    bytes32 digest;
    bytes memory context;

    if (data.length == 32) {
      digest = abi.decode(data, (bytes32));
    } else {
      if (data.length < 64) {
        revert(_revertReason(30));
      }
      (digest, context) = abi.decode(data, (bytes32, bytes));
    }

    // Get Dharma signature & user signature from combined signatures argument.
    if (signatures.length != 130) {
      revert(_revertReason(11));
    }
    bytes memory signaturesInMemory = signatures;
    bytes32 r;
    bytes32 s;
    uint8 v;
    assembly {
      r := mload(add(signaturesInMemory, 0x20))
      s := mload(add(signaturesInMemory, 0x40))
      v := byte(0, mload(add(signaturesInMemory, 0x60)))
    }
    bytes memory dharmaSignature = abi.encodePacked(r, s, v);

    assembly {
      r := mload(add(signaturesInMemory, 0x61))
      s := mload(add(signaturesInMemory, 0x81))
      v := byte(0, mload(add(signaturesInMemory, 0xa1)))
    }
    bytes memory userSignature = abi.encodePacked(r, s, v);

    // Validate user signature with `SignatureVerification` as the action type.
    if (
      !_validateUserSignature(
        digest,
        ActionType.SignatureVerification,
        context,
        _userSigningKey,
        userSignature
      )
    ) {
      revert(_revertReason(12));
    }

    // Recover Dharma signature against key returned from Dharma Key Registry.
    if (_getDharmaSigningKey() != digest.recover(dharmaSignature)) {
      revert(_revertReason(13));
    }

    // Return the ERC-1271 magic value to indicate success.
    magicValue = _ERC_1271_MAGIC_VALUE;
  }

  /**
   * @notice View function for getting the current Dharma Smart Wallet
   * implementation contract address set on the upgrade beacon.
   * @return The current Dharma Smart Wallet implementation contract.
   */ 
  function getImplementation() external view returns (address implementation) {
    (bool ok, bytes memory returnData) = address(
      0x000000000026750c571ce882B17016557279ADaa
    ).staticcall("");
    require(ok && returnData.length == 32, "Invalid implementation.");
    implementation = abi.decode(returnData, (address));
  }

  /**
   * @notice Pure function for getting the current Dharma Smart Wallet version.
   * @return The current Dharma Smart Wallet version.
   */
  function getVersion() external pure returns (uint256 version) {
    version = _DHARMA_SMART_WALLET_VERSION;
  }

  /**
   * @notice Perform a series of generic calls to other contracts. If any call
   * fails during execution, the preceding calls will be rolled back, but their
   * original return data will still be accessible. Calls that would otherwise
   * occur after the failed call will not be executed. Note that accounts with
   * no code may not be specified, nor may the smart wallet itself or the escape
   * hatch registry. In order to increment the nonce and invalidate the
   * signatures, a call to this function with valid targets, signatutes, and gas
   * will always succeed. To determine whether each call made as part of the
   * action was successful or not, either the corresponding return value or the
   * corresponding `CallSuccess` or `CallFailure` event can be used - note that
   * even calls that return a success status will have been rolled back unless
   * all of the calls returned a success status. Finally, note that this
   * function must currently be implemented as a public function (instead of as
   * an external one) due to an ABIEncoderV2 `UnimplementedFeatureError`.
   * @param calls Call[] A struct containing the target and calldata to provide
   * when making each call.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used. A unique hash returned from `getCustomActionID` is prefixed
   * and hashed to create the message hash for the signature.
   * @param dharmaSignature bytes A signature that resolves to the public key
   * returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getCustomActionID` is prefixed and hashed to create the
   * signed message.
   * @return An array of structs signifying the status of each call, as well as
   * any data returned from that call. Calls that are not executed will return
   * empty data.
   */
  function executeActionWithAtomicBatchCalls(
    Call[] memory calls,
    uint256 minimumActionGas,
    bytes memory userSignature,
    bytes memory dharmaSignature
  ) public returns (bool[] memory ok, bytes[] memory returnData) {
    // Ensure that each `to` address is a contract and is not this contract.
    for (uint256 i = 0; i < calls.length; i++) {
      _ensureValidGenericCallTarget(calls[i].to);
    }

    // Ensure caller and/or supplied signatures are valid and increment nonce.
    (bytes32 actionID, uint256 nonce) = _validateActionAndIncrementNonce(
      ActionType.GenericAtomicBatch,
      abi.encode(calls),
      minimumActionGas,
      userSignature,
      dharmaSignature
    );

    // Note: from this point on, there are no reverts (apart from out-of-gas or
    // call-depth-exceeded) originating from this contract. However, one of the
    // calls may revert, in which case the function will return `false`, along
    // with the revert reason encoded as bytes, and fire an CallFailure event.

    // Specify length of returned values in order to work with them in memory.
    ok = new bool[](calls.length);
    returnData = new bytes[](calls.length);

    // Set self-call context to call _executeActionWithAtomicBatchCallsAtomic.
    _selfCallContext = this.executeActionWithAtomicBatchCalls.selector;

    // Make the atomic self-call - if any call fails, calls that preceded it
    // will be rolled back and calls that follow it will not be made.
    (bool externalOk, bytes memory rawCallResults) = address(this).call(
      abi.encodeWithSelector(
        this._executeActionWithAtomicBatchCallsAtomic.selector, calls
      )
    );

    // Parse data returned from self-call into each call result and store / log.
    CallReturn[] memory callResults = abi.decode(rawCallResults, (CallReturn[]));
    for (uint256 i = 0; i < callResults.length; i++) {
      Call memory currentCall = calls[i];

      // Set the status and the return data / revert reason from the call.
      ok[i] = callResults[i].ok;
      returnData[i] = callResults[i].returnData;

      // Emit CallSuccess or CallFailure event based on the outcome of the call.
      if (callResults[i].ok) {
        // Note: while the call succeeded, the action may still have "failed".
        emit CallSuccess(
          actionID,
          !externalOk, // If another call failed this will have been rolled back
          nonce,
          currentCall.to,
          currentCall.data,
          callResults[i].returnData
        );
      } else {
        // Note: while the call failed, the nonce will still be incremented,
        // which will invalidate all supplied signatures.
        emit CallFailure(
          actionID,
          nonce,
          currentCall.to,
          currentCall.data,
          string(callResults[i].returnData)
        );

        // exit early - any calls after the first failed call will not execute.
        break;
      }
    }
  }

  /**
   * @notice Protected function that can only be called from
   * `executeActionWithAtomicBatchCalls` on this contract. It will attempt to
   * perform each specified call, populating the array of results as it goes,
   * unless a failure occurs, at which point it will revert and "return" the
   * array of results as revert data. Otherwise, it will simply return the array
   * upon successful completion of each call. Finally, note that this function
   * must currently be implemented as a public function (instead of as an
   * external one) due to an ABIEncoderV2 `UnimplementedFeatureError`.
   * @param calls Call[] A struct containing the target and calldata to provide
   * when making each call.
   * @return An array of structs signifying the status of each call, as well as
   * any data returned from that call. Calls that are not executed will return
   * empty data. If any of the calls fail, the array will be returned as revert
   * data.
   */
  function _executeActionWithAtomicBatchCallsAtomic(
    Call[] memory calls
  ) public returns (CallReturn[] memory callResults) {
    // Ensure caller is this contract and self-call context is correctly set.
    _enforceSelfCallFrom(this.executeActionWithAtomicBatchCalls.selector);

    bool rollBack = false;
    callResults = new CallReturn[](calls.length);

    for (uint256 i = 0; i < calls.length; i++) {
      // Perform low-level call and set return values using result.
      (bool ok, bytes memory returnData) = calls[i].to.call(calls[i].data);
      callResults[i] = CallReturn({ok: ok, returnData: returnData});
      if (!ok) {
        // Exit early - any calls after the first failed call will not execute.
        rollBack = true;
        break;
      }
    }

    if (rollBack) {
      // Wrap in length encoding and revert (provide data instead of a string).
      bytes memory callResultsBytes = abi.encode(callResults);
      assembly { revert(add(32, callResultsBytes), mload(callResultsBytes)) }
    }
  }

  /**
   * @notice View function that, given an action type and arguments, will return
   * the action ID or message hash that will need to be prefixed (according to
   * EIP-191 0x45), hashed, and signed by both the user signing key and by the
   * key returned for this smart wallet by the Dharma Key Registry in order to
   * construct a valid signature for a given generic atomic batch action. The
   * current nonce will be used, which means that it will only be valid for the
   * next action taken. Finally, note that this function must currently be
   * implemented as a public function (instead of as an external one) due to an
   * ABIEncoderV2 `UnimplementedFeatureError`.
   * @param calls Call[] A struct containing the target and calldata to provide
   * when making each call.
   * @param calls Call[] A struct containing the target and calldata to provide
   * when making each call.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @return The action ID, which will need to be prefixed, hashed and signed in
   * order to construct a valid signature.
   */
  function getNextGenericAtomicBatchActionID(
    Call[] memory calls,
    uint256 minimumActionGas
  ) public view returns (bytes32 actionID) {
    // Determine the actionID - this serves as a signature hash for an action.
    actionID = _getActionID(
      ActionType.GenericAtomicBatch,
      abi.encode(calls),
      _nonce,
      minimumActionGas,
      _userSigningKey,
      _getDharmaSigningKey()
    );
  }

  /**
   * @notice View function that, given an action type and arguments, will return
   * the action ID or message hash that will need to be prefixed (according to
   * EIP-191 0x45), hashed, and signed by both the user signing key and by the
   * key returned for this smart wallet by the Dharma Key Registry in order to
   * construct a valid signature for a given generic atomic batch action. Any
   * nonce value may be supplied, which enables constructing valid message
   * hashes for multiple future actions ahead of time. Finally, note that this
   * function must currently be implemented as a public function (instead of as
   * an external one) due to an ABIEncoderV2 `UnimplementedFeatureError`.
   * @param calls Call[] A struct containing the target and calldata to provide
   * when making each call.
   * @param calls Call[] A struct containing the target and calldata to provide
   * when making each call.
   * @param nonce uint256 The nonce to use.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @return The action ID, which will need to be prefixed, hashed and signed in
   * order to construct a valid signature.
   */
  function getGenericAtomicBatchActionID(
    Call[] memory calls,
    uint256 nonce,
    uint256 minimumActionGas
  ) public view returns (bytes32 actionID) {
    // Determine the actionID - this serves as a signature hash for an action.
    actionID = _getActionID(
      ActionType.GenericAtomicBatch,
      abi.encode(calls),
      nonce,
      minimumActionGas,
      _userSigningKey,
      _getDharmaSigningKey()
    );
  }

  /**
   * @notice Internal function for setting a new user signing key. Called by the
   * initializer, by the `setUserSigningKey` function, and by the `recover`
   * function. A `NewUserSigningKey` event will also be emitted.
   * @param userSigningKey address The new user signing key to set on this smart
   * wallet.
   */
  function _setUserSigningKey(address userSigningKey) internal {
    // Ensure that a user signing key is set on this smart wallet.
    if (userSigningKey == address(0)) {
      revert(_revertReason(14));
    }

    _userSigningKey = userSigningKey;
    emit NewUserSigningKey(userSigningKey);
  }

  /**
   * @notice Internal function for setting the allowance of a given ERC20 asset
   * to the maximum value. This enables the corresponding dToken for the asset
   * to pull in tokens in order to make deposits.
   * @param asset uint256 The ID of the asset, either Dai (0) or USDC (1).
   * @return True if the approval succeeded, otherwise false.
   */
  function _setFullApproval(AssetType asset) internal returns (bool ok) {
    // Get asset's underlying token address and corresponding dToken address.
    address token;
    address dToken;
    if (asset == AssetType.DAI) {
      token = address(_DAI);
      dToken = address(_DDAI);
    } else {
      token = address(_USDC);
      dToken = address(_DUSDC);
    }

    // Approve dToken contract to transfer underlying on behalf of this wallet.
    (ok, ) = address(token).call(abi.encodeWithSelector(
      // Note: since both Tokens have the same interface, just use DAI's.
      _DAI.approve.selector, dToken, uint256(-1)
    ));

    // Emit a corresponding event if the approval failed.
    if (!ok) {
      if (asset == AssetType.DAI) {
        emit ExternalError(address(_DAI), _revertReason(17));
      } else {
        // Find out why USDC transfer reverted (it doesn't give revert reasons).
        _diagnoseAndEmitUSDCSpecificError(_USDC.approve.selector);
      }
    }
  }

  /**
   * @notice Internal function for depositing a given ERC20 asset and balance on
   * the corresponding dToken. No value is returned, as no additional steps need
   * to be conditionally performed after the deposit.
   * @param asset uint256 The ID of the asset, either Dai (0) or USDC (1).
   * @param balance uint256 The amount of the asset to deposit. Note that an
   * attempt to deposit "dust" (i.e. very small amounts) may result in fewer
   * dTokens being minted than is implied by the current exchange rate due to a
   * lack of sufficient precision on the tokens in question. USDC deposits are
   * also dependent on a flag being set on the Configuration Registry contract.
   */
  function _depositDharmaToken(AssetType asset, uint256 balance) internal {
    // Only perform a deposit if the balance is at least .001 Dai or USDC.
    if (
      asset == AssetType.DAI && balance > _JUST_UNDER_ONE_1000th_DAI ||
      asset == AssetType.USDC && (
        balance > _JUST_UNDER_ONE_1000th_USDC &&
        uint256(_CONFIG_REGISTRY.get(_ENABLE_USDC_MINTING_KEY)) != 0
      )
    ) {
      // Get dToken address for the asset type.
      address dToken = asset == AssetType.DAI ? address(_DDAI) : address(_DUSDC);

      // Attempt to mint the balance on the dToken contract.
      (bool ok, bytes memory data) = dToken.call(abi.encodeWithSelector(
        // Note: since both dTokens have the same interface, just use dDai's.
        _DDAI.mint.selector, balance
      ));

      // Log an external error if something went wrong with the attempt.
      _checkDharmaTokenInteractionAndLogAnyErrors(
        asset, _DDAI.mint.selector, ok, data
      );
    }
  }

  /**
   * @notice Internal function for withdrawing a given underlying asset balance
   * from the corresponding dToken. Note that the requested balance may not be
   * currently available on Compound, which will cause the withdrawal to fail.
   * @param asset uint256 The asset's ID, either Dai (0) or USDC (1).
   * @param balance uint256 The amount of the asset to withdraw, denominated in
   * the underlying token. Note that an attempt to withdraw "dust" (i.e. very
   * small amounts) may result in 0 underlying tokens being redeemed, or in
   * fewer tokens being redeemed than is implied by the current exchange rate
   * (due to lack of sufficient precision on the tokens).
   * @return True if the withdrawal succeeded, otherwise false.
   */
  function _withdrawFromDharmaToken(
    AssetType asset, uint256 balance
  ) internal returns (bool success) {
    // Get dToken address for the asset type. (No custom ETH withdrawal action.)
    address dToken = asset == AssetType.DAI ? address(_DDAI) : address(_DUSDC);

    // Attempt to redeem the underlying balance from the dToken contract.
    (bool ok, bytes memory data) = dToken.call(abi.encodeWithSelector(
      // Note: function selector is the same for each dToken so just use dDai's.
      _DDAI.redeemUnderlying.selector, balance
    ));

    // Log an external error if something went wrong with the attempt.
    success = _checkDharmaTokenInteractionAndLogAnyErrors(
      asset, _DDAI.redeemUnderlying.selector, ok, data
    );
  }

  /**
   * @notice Internal function for withdrawing the total underlying asset
   * balance from the corresponding dToken. Note that the requested balance may
   * not be currently available on Compound, which will cause the withdrawal to
   * fail.
   * @param asset uint256 The asset's ID, either Dai (0) or USDC (1).
   */
  function _withdrawMaxFromDharmaToken(AssetType asset) internal {
    // Get dToken address for the asset type. (No custom ETH withdrawal action.)
    address dToken = asset == AssetType.DAI ? address(_DDAI) : address(_DUSDC);

    // Try to retrieve the current dToken balance for this account.
    ERC20Interface dTokenBalance;
    (bool ok, bytes memory data) = dToken.call(abi.encodeWithSelector(
      dTokenBalance.balanceOf.selector, address(this)
    ));

    uint256 redeemAmount = 0;
    if (ok && data.length == 32) {
      redeemAmount = abi.decode(data, (uint256));
    } else {
      // Something went wrong with the balance check - log an ExternalError.
      _checkDharmaTokenInteractionAndLogAnyErrors(
        asset, dTokenBalance.balanceOf.selector, ok, data
      );
    }

    // Only perform the call to redeem if there is a non-zero balance.
    if (redeemAmount > 0) {
      // Attempt to redeem the underlying balance from the dToken contract.
      (ok, data) = dToken.call(abi.encodeWithSelector(
        // Function selector is the same for all dTokens, so just use dDai's.
        _DDAI.redeem.selector, redeemAmount
      ));

      // Log an external error if something went wrong with the attempt.
      _checkDharmaTokenInteractionAndLogAnyErrors(
        asset, _DDAI.redeem.selector, ok, data
      );
    }
  }

  /**
   * @notice Internal function for transferring the total underlying balance of
   * the corresponding token to a designated recipient. It will return true if
   * tokens were successfully transferred (or there is no balance), signified by
   * the boolean returned by the transfer function, or the call status if the
   * `suppressRevert` boolean is set to true.
   * @param token IERC20 The interface of the token in question.
   * @param recipient address The account that will receive the tokens.
   * @param suppressRevert bool A boolean indicating whether reverts should be
   * suppressed or not. Used by the escape hatch so that a problematic transfer
   * will not block the rest of the call from executing.
   * @return True if tokens were successfully transferred or if there is no
   * balance, else false.
   */
  function _transferMax(
    ERC20Interface token, address recipient, bool suppressRevert
  ) internal returns (bool success) {
    // Get the current balance on the smart wallet for the supplied ERC20 token.
    uint256 balance = 0;
    bool balanceCheckWorked = true;
    if (!suppressRevert) {
      balance = token.balanceOf(address(this));
    } else {
      // Try to retrieve current token balance for this account with 1/2 gas.
      (bool ok, bytes memory data) = address(token).call.gas(gasleft() / 2)(
        abi.encodeWithSelector(token.balanceOf.selector, address(this))
      );

      if (ok && data.length == 32) {
        balance = abi.decode(data, (uint256));
      } else {
        // Something went wrong with the balance check.
        balanceCheckWorked = false;
      }
    }

    // Only perform the call to transfer if there is a non-zero balance.
    if (balance > 0) {
      if (!suppressRevert) {
        // Perform the transfer and pass along the returned boolean (or revert).
        success = token.transfer(recipient, balance);
      } else {
        // Attempt transfer with 1/2 gas, allow reverts, and return call status.
        (success, ) = address(token).call.gas(gasleft() / 2)(
          abi.encodeWithSelector(token.transfer.selector, recipient, balance)
        );
      }
    } else {
      // Skip the transfer and return true as long as the balance check worked.
      success = balanceCheckWorked;
    }
  }

  /**
   * @notice Internal function for transferring Ether to a designated recipient.
   * It will return true and emit an `EthWithdrawal` event if Ether was
   * successfully transferred - otherwise, it will return false and emit an
   * `ExternalError` event.
   * @param recipient address payable The account that will receive the Ether.
   * @param amount uint256 The amount of Ether to transfer.
   * @return True if Ether was successfully transferred, else false.
   */
  function _transferETH(
    address payable recipient, uint256 amount
  ) internal returns (bool success) {
    // Attempt to transfer any Ether to caller and emit an event if it fails.
    (success, ) = recipient.call.gas(_ETH_TRANSFER_GAS).value(amount)("");
    if (!success) {
      emit ExternalError(recipient, _revertReason(18));
    } else {
      emit EthWithdrawal(amount, recipient);
    }
  }

  /**
   * @notice Internal function for validating supplied gas (if specified),
   * retrieving the signer's public key from the Dharma Key Registry, deriving
   * the action ID, validating the provided caller and/or signatures using that
   * action ID, and incrementing the nonce. This function serves as the
   * entrypoint for all protected "actions" on the smart wallet, and is the only
   * area where these functions should revert (other than due to out-of-gas
   * errors, which can be guarded against by supplying a minimum action gas
   * requirement).
   * @param action uint8 The type of action, designated by it's index. Valid
   * actions in V8 include Cancel (0), SetUserSigningKey (1), Generic (2),
   * GenericAtomicBatch (3), DAIWithdrawal (10), USDCWithdrawal (5),
   * ETHWithdrawal (6), SetEscapeHatch (7), RemoveEscapeHatch (8), and
   * DisableEscapeHatch (9).
   * @param arguments bytes ABI-encoded arguments for the action.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used. A unique hash returned from `getCustomActionID` is prefixed
   * and hashed to create the message hash for the signature.
   * @param dharmaSignature bytes A signature that resolves to the public key
   * returned for this account from the Dharma Key Registry. A unique hash
   * returned from `getCustomActionID` is prefixed and hashed to create the
   * signed message.
   * @return The nonce of the current action (prior to incrementing it).
   */
  function _validateActionAndIncrementNonce(
    ActionType action,
    bytes memory arguments,
    uint256 minimumActionGas,
    bytes memory userSignature,
    bytes memory dharmaSignature
  ) internal returns (bytes32 actionID, uint256 actionNonce) {
    // Ensure that the current gas exceeds the minimum required action gas.
    // This prevents griefing attacks where an attacker can invalidate a
    // signature without providing enough gas for the action to succeed. Also
    // note that some gas will be spent before this check is reached - supplying
    // ~30,000 additional gas should suffice when submitting transactions. To
    // skip this requirement, supply zero for the minimumActionGas argument.
    if (minimumActionGas != 0) {
      if (gasleft() < minimumActionGas) {
        revert(_revertReason(19));
      }
    }

    // Get the current nonce for the action to be performed.
    actionNonce = _nonce;

    // Get the user signing key that will be used to verify their signature.
    address userSigningKey = _userSigningKey;

    // Get the Dharma signing key that will be used to verify their signature.
    address dharmaSigningKey = _getDharmaSigningKey();

    // Determine the actionID - this serves as the signature hash.
    actionID = _getActionID(
      action,
      arguments,
      actionNonce,
      minimumActionGas,
      userSigningKey,
      dharmaSigningKey
    );

    // Compute the message hash - the hashed, EIP-191-0x45-prefixed action ID.
    bytes32 messageHash = actionID.toEthSignedMessageHash();

    // Actions other than Cancel require both signatures; Cancel only needs one.
    if (action != ActionType.Cancel) {
      // Validate user signing key signature unless it is `msg.sender`.
      if (msg.sender != userSigningKey) {
        if (
          !_validateUserSignature(
            messageHash, action, arguments, userSigningKey, userSignature
          )
        ) {
          revert(_revertReason(20));
        }
      }

      // Validate Dharma signing key signature unless it is `msg.sender`.
      if (msg.sender != dharmaSigningKey) {
        if (dharmaSigningKey != messageHash.recover(dharmaSignature)) {
          revert(_revertReason(21));
        }
      }
    } else {
      // Validate signing key signature unless user or Dharma is `msg.sender`.
      if (msg.sender != userSigningKey && msg.sender != dharmaSigningKey) {
        if (
          dharmaSigningKey != messageHash.recover(dharmaSignature) &&
          !_validateUserSignature(
            messageHash, action, arguments, userSigningKey, userSignature
          )
        ) {
          revert(_revertReason(22));
        }
      }
    }

    // Increment nonce in order to prevent reuse of signatures after the call.
    _nonce++;
  }

  /**
   * @notice Use all available cTokens to mint the respective dTokens. If any
   * step in the process fails, the call will revert and prior steps will be
   * rolled back. Also note that existing underlying tokens are not included as
   * part of this operation.
   */
  function _migrateCTokenToDToken(AssetType token) internal {
    CTokenInterface cToken;
    DTokenInterface dToken;

    if (token == AssetType.DAI) {
      cToken = _CDAI;
      dToken = _DDAI;
    } else {
      cToken = _CUSDC;
      dToken = _DUSDC;
    }

    // Get the current cToken balance for this account.
    uint256 balance = cToken.balanceOf(address(this));

    // Only perform the conversion if there is a non-zero balance.
    if (balance > 0) {    
      // If the allowance is insufficient, set it before depositing.
      if (cToken.allowance(address(this), address(dToken)) < balance) {
        if (!cToken.approve(address(dToken), uint256(-1))) {
          revert(_revertReason(23));
        }
      }
      
      // Deposit the new balance on the Dharma Token.
      if (dToken.mintViaCToken(balance) == 0) {
        revert(_revertReason(24));
      }
    }
  }

  /**
   * @notice Internal function to determine whether a call to a given dToken
   * succeeded, and to emit a relevant ExternalError event if it failed.
   * @param asset uint256 The ID of the asset, either Dai (0) or USDC (1).
   * @param functionSelector bytes4 The function selector that was called on the
   * corresponding dToken of the asset type.
   * @param ok bool A boolean representing whether the call returned or
   * reverted.
   * @param data bytes The data provided by the returned or reverted call.
   * @return True if the interaction was successful, otherwise false. This will
   * be used to determine if subsequent steps in the action should be attempted
   * or not, specifically a transfer following a withdrawal.
   */
  function _checkDharmaTokenInteractionAndLogAnyErrors(
    AssetType asset,
    bytes4 functionSelector,
    bool ok,
    bytes memory data
  ) internal returns (bool success) {
    // Log an external error if something went wrong with the attempt.
    if (ok) {
      if (data.length == 32) {
        uint256 amount = abi.decode(data, (uint256));
        if (amount > 0) {
          success = true;
        } else {
          // Get called contract address, name of contract, and function name.
          (address account, string memory name, string memory functionName) = (
            _getDharmaTokenDetails(asset, functionSelector)
          );

          emit ExternalError(
            account,
            string(
              abi.encodePacked(
                name,
                " gave no tokens calling ",
                functionName,
                "."
              )
            )
          );         
        }
      } else {
        // Get called contract address, name of contract, and function name.
        (address account, string memory name, string memory functionName) = (
          _getDharmaTokenDetails(asset, functionSelector)
        );

        emit ExternalError(
          account,
          string(
            abi.encodePacked(
              name,
              " gave bad data calling ",
              functionName,
              "."
            )
          )
        );        
      }
      
    } else {
      // Get called contract address, name of contract, and function name.
      (address account, string memory name, string memory functionName) = (
        _getDharmaTokenDetails(asset, functionSelector)
      );

      // Decode the revert reason in the event one was returned.
      string memory revertReason = _decodeRevertReason(data);

      emit ExternalError(
        account,
        string(
          abi.encodePacked(
            name,
            " reverted calling ",
            functionName,
            ": ",
            revertReason
          )
        )
      );
    }
  }

  /**
   * @notice Internal function to diagnose the reason that a call to the USDC
   * contract failed and to emit a corresponding ExternalError event. USDC can
   * blacklist accounts and pause the contract, which can both cause a transfer
   * or approval to fail.
   * @param functionSelector bytes4 The function selector that was called on the
   * USDC contract.
   */
  function _diagnoseAndEmitUSDCSpecificError(bytes4 functionSelector) internal {
    // Determine the name of the function that was called on USDC.
    string memory functionName;
    if (functionSelector == _USDC.transfer.selector) {
      functionName = "transfer";
    } else {
      functionName = "approve";
    }
    
    USDCV1Interface usdcNaughty = USDCV1Interface(address(_USDC));

    // Find out why USDC transfer reverted (it doesn't give revert reasons).
    if (usdcNaughty.isBlacklisted(address(this))) {
      emit ExternalError(
        address(_USDC),
        string(
          abi.encodePacked(
            functionName, " failed - USDC has blacklisted this user."
          )
        )
      );
    } else { // Note: `else if` breaks coverage.
      if (usdcNaughty.paused()) {
        emit ExternalError(
          address(_USDC),
          string(
            abi.encodePacked(
              functionName, " failed - USDC contract is currently paused."
            )
          )
        );
      } else {
        emit ExternalError(
          address(_USDC),
          string(
            abi.encodePacked(
              "USDC contract reverted on ", functionName, "."
            )
          )
        );
      }
    }
  }

  /**
   * @notice Internal function to ensure that protected functions can only be
   * called from this contract and that they have the appropriate context set.
   * The self-call context is then cleared. It is used as an additional guard
   * against reentrancy, especially once generic actions are supported by the
   * smart wallet in future versions.
   * @param selfCallContext bytes4 The expected self-call context, equal to the
   * function selector of the approved calling function.
   */
  function _enforceSelfCallFrom(bytes4 selfCallContext) internal {
    // Ensure caller is this contract and self-call context is correctly set.
    if (msg.sender != address(this) || _selfCallContext != selfCallContext) {
      revert(_revertReason(25));
    }

    // Clear the self-call context.
    delete _selfCallContext;
  }

  /**
   * @notice Internal view function for validating a user's signature. If the
   * user's signing key does not have contract code, it will be validated via
   * ecrecover; otherwise, it will be validated using ERC-1271, passing the
   * message hash that was signed, the action type, and the arguments as data.
   * @param messageHash bytes32 The message hash that is signed by the user. It
   * is derived by prefixing (according to EIP-191 0x45) and hashing an actionID
   * returned from `getCustomActionID`.
   * @param action uint8 The type of action, designated by it's index. Valid
   * actions in V8 include Cancel (0), SetUserSigningKey (1), Generic (2),
   * GenericAtomicBatch (3), DAIWithdrawal (10), USDCWithdrawal (5),
   * ETHWithdrawal (6), SetEscapeHatch (7), RemoveEscapeHatch (8), and
   * DisableEscapeHatch (9).
   * @param arguments bytes ABI-encoded arguments for the action.
   * @param userSignature bytes A signature that resolves to the public key
   * set for this account in storage slot zero, `_userSigningKey`. If the user
   * signing key is not a contract, ecrecover will be used; otherwise, ERC1271
   * will be used.
   * @return A boolean representing the validity of the supplied user signature.
   */
  function _validateUserSignature(
    bytes32 messageHash,
    ActionType action,
    bytes memory arguments,
    address userSigningKey,
    bytes memory userSignature
  ) internal view returns (bool valid) {
    if (!userSigningKey.isContract()) {
      valid = userSigningKey == messageHash.recover(userSignature);
    } else {
      bytes memory data = abi.encode(messageHash, action, arguments);
      valid = (
        ERC1271Interface(userSigningKey).isValidSignature(
          data, userSignature
        ) == _ERC_1271_MAGIC_VALUE
      );
    }
  }

  /**
   * @notice Internal view function to get the Dharma signing key for the smart
   * wallet from the Dharma Key Registry. This key can be set for each specific
   * smart wallet - if none has been set, a global fallback key will be used.
   * @return The address of the Dharma signing key, or public key corresponding
   * to the secondary signer.
   */
  function _getDharmaSigningKey() internal view returns (
    address dharmaSigningKey
  ) {
    dharmaSigningKey = _DHARMA_KEY_REGISTRY.getKey();
  }

  /**
   * @notice Internal view function that, given an action type and arguments,
   * will return the action ID or message hash that will need to be prefixed
   * (according to EIP-191 0x45), hashed, and signed by the key designated by
   * the Dharma Key Registry in order to construct a valid signature for the
   * corresponding action. The current nonce will be supplied to this function
   * when reconstructing an action ID during protected function execution based
   * on the supplied parameters.
   * @param action uint8 The type of action, designated by it's index. Valid
   * actions in V8 include Cancel (0), SetUserSigningKey (1), Generic (2),
   * GenericAtomicBatch (3), DAIWithdrawal (10), USDCWithdrawal (5),
   * ETHWithdrawal (6), SetEscapeHatch (7), RemoveEscapeHatch (8), and
   * DisableEscapeHatch (9).
   * @param arguments bytes ABI-encoded arguments for the action.
   * @param nonce uint256 The nonce to use.
   * @param minimumActionGas uint256 The minimum amount of gas that must be
   * provided to this call - be aware that additional gas must still be included
   * to account for the cost of overhead incurred up until the start of this
   * function call.
   * @param dharmaSigningKey address The address of the secondary key, or public
   * key corresponding to the secondary signer.
   * @return The action ID, which will need to be prefixed, hashed and signed in
   * order to construct a valid signature.
   */
  function _getActionID(
    ActionType action,
    bytes memory arguments,
    uint256 nonce,
    uint256 minimumActionGas,
    address userSigningKey,
    address dharmaSigningKey
  ) internal view returns (bytes32 actionID) {
    // actionID is constructed according to EIP-191-0x45 to prevent replays.
    actionID = keccak256(
      abi.encodePacked(
        address(this),
        _DHARMA_SMART_WALLET_VERSION,
        userSigningKey,
        dharmaSigningKey,
        nonce,
        minimumActionGas,
        action,
        arguments
      )
    );
  }

  /**
   * @notice Internal pure function to get the dToken address, it's name, and
   * the name of the called function, based on a supplied asset type and
   * function selector. It is used to help construct ExternalError events.
   * @param asset uint256 The ID of the asset, either Dai (0) or USDC (1).
   * @param functionSelector bytes4 The function selector that was called on the
   * corresponding dToken of the asset type.
   * @return The dToken address, it's name, and the name of the called function.
   */
  function _getDharmaTokenDetails(
    AssetType asset,
    bytes4 functionSelector
  ) internal pure returns (
    address account,
    string memory name,
    string memory functionName
  ) {
    if (asset == AssetType.DAI) {
      account = address(_DDAI);
      name = "Dharma Dai";
    } else {
      account = address(_DUSDC);
      name = "Dharma USD Coin";
    }

    // Note: since both dTokens have the same interface, just use dDai's.
    if (functionSelector == _DDAI.mint.selector) {
      functionName = "mint";
    } else {
      if (functionSelector == ERC20Interface(account).balanceOf.selector) {
        functionName = "balanceOf";
      } else {
        functionName = string(abi.encodePacked(
          "redeem",
          functionSelector == _DDAI.redeem.selector ? "" : "Underlying"
        ));
      }
    }
  }

  /**
   * @notice Internal view function to ensure that a given `to` address provided
   * as part of a generic action is valid. Calls cannot be performed to accounts
   * without code or back into the smart wallet itself. Additionally, generic
   * calls cannot supply the address of the Dharma Escape Hatch registry - the
   * specific, designated functions must be used in order to make calls into it.
   * @param to address The address that will be targeted by the generic call.
   */
  function _ensureValidGenericCallTarget(address to) internal view {
    if (!to.isContract()) {
      revert(_revertReason(26));
    }
    
    if (to == address(this)) {
      revert(_revertReason(27));
    }

    if (to == address(_ESCAPE_HATCH_REGISTRY)) {
      revert(_revertReason(28));
    }
  }

  /**
   * @notice Internal pure function to ensure that a given action type is a
   * "custom" action type (i.e. is not a generic action type) and to construct
   * the "arguments" input to an actionID based on that action type.
   * @param action uint8 The type of action, designated by it's index. Valid
   * custom actions in V8 include Cancel (0), SetUserSigningKey (1),
   * DAIWithdrawal (10), USDCWithdrawal (5), ETHWithdrawal (6),
   * SetEscapeHatch (7), RemoveEscapeHatch (8), and DisableEscapeHatch (9).
   * @param amount uint256 The amount to withdraw for Withdrawal actions. This
   * value is ignored for all non-withdrawal action types.
   * @param recipient address The account to transfer withdrawn funds to or the
   * new user signing key. This value is ignored for Cancel, RemoveEscapeHatch,
   * and DisableEscapeHatch action types.
   * @return A bytes array containing the arguments that will be provided as
   * a component of the inputs when constructing a custom action ID.
   */
  function _validateCustomActionTypeAndGetArguments(
    ActionType action, uint256 amount, address recipient
  ) internal pure returns (bytes memory arguments) {
    // Ensure that the action type is a valid custom action type.
    bool validActionType = (
      action == ActionType.Cancel ||
      action == ActionType.SetUserSigningKey ||
      action == ActionType.DAIWithdrawal ||
      action == ActionType.USDCWithdrawal ||
      action == ActionType.ETHWithdrawal ||
      action == ActionType.SetEscapeHatch ||
      action == ActionType.RemoveEscapeHatch ||
      action == ActionType.DisableEscapeHatch
    );
    if (!validActionType) {
      revert(_revertReason(29));
    }

    // Use action type to determine parameters to include in returned arguments.
    if (
      action == ActionType.Cancel ||
      action == ActionType.RemoveEscapeHatch ||
      action == ActionType.DisableEscapeHatch
    ) {
      // Ignore parameters for Cancel, RemoveEscapeHatch, or DisableEscapeHatch.
      arguments = abi.encode();
    } else if (
      action == ActionType.SetUserSigningKey ||
      action == ActionType.SetEscapeHatch
    ) {
      // Ignore `amount` parameter for other, non-withdrawal actions.
      arguments = abi.encode(recipient);
    } else {
      // Use both `amount` and `recipient` parameters for withdrawals.
      arguments = abi.encode(amount, recipient);
    }
  }

  /**
   * @notice Internal pure function to decode revert reasons. The revert reason
   * prefix is removed and the remaining string argument is decoded.
   * @param revertData bytes The raw data supplied alongside the revert.
   * @return The decoded revert reason string.
   */
  function _decodeRevertReason(
    bytes memory revertData
  ) internal pure returns (string memory revertReason) {
    // Solidity prefixes revert reason with 0x08c379a0 -> Error(string) selector
    if (
      revertData.length > 68 && // prefix (4) + position (32) + length (32)
      revertData[0] == byte(0x08) &&
      revertData[1] == byte(0xc3) &&
      revertData[2] == byte(0x79) &&
      revertData[3] == byte(0xa0)
    ) {
      // Get the revert reason without the prefix from the revert data.
      bytes memory revertReasonBytes = new bytes(revertData.length - 4);
      for (uint256 i = 4; i < revertData.length; i++) {
        revertReasonBytes[i - 4] = revertData[i];
      }

      // Decode the resultant revert reason as a string.
      revertReason = abi.decode(revertReasonBytes, (string));
    } else {
      // Simply return the default, with no revert reason.
      revertReason = _revertReason(uint256(-1));
    }
  }

  /**
   * @notice Internal pure function call the revert reason helper contract,
   * supplying a revert "code" and receiving back a revert reason string.
   * @param code uint256 The code for the revert reason.
   * @return The revert reason string.
   */
  function _revertReason(
    uint256 code
  ) internal pure returns (string memory reason) {
    reason = _REVERT_REASON_HELPER.reason(code);
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"actionID","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"string","name":"revertReason","type":"string"}],"name":"CallFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"actionID","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"rolledBack","type":"bool"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"returnData","type":"bytes"}],"name":"CallSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"cancelledNonce","type":"uint256"}],"name":"Cancel","type":"event"},{"anonymous":false,"inputs":[],"name":"Escaped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"EthWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"string","name":"revertReason","type":"string"}],"name":"ExternalError","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userSigningKey","type":"address"}],"name":"NewUserSigningKey","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":false,"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DharmaSmartWalletImplementationV1Interface.Call[]","name":"calls","type":"tuple[]"}],"name":"_executeActionWithAtomicBatchCallsAtomic","outputs":[{"components":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"internalType":"struct DharmaSmartWalletImplementationV1Interface.CallReturn[]","name":"callResults","type":"tuple[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"ethToSupply","type":"uint256"},{"internalType":"uint256","name":"minimumDaiReceived","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"_tradeEthForDaiAndMintDDaiAtomic","outputs":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"_withdrawDaiAtomic","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"_withdrawUSDCAtomic","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"cancel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"escape","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"executeAction","outputs":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DharmaSmartWalletImplementationV1Interface.Call[]","name":"calls","type":"tuple[]"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"executeActionWithAtomicBatchCalls","outputs":[{"internalType":"bool[]","name":"ok","type":"bool[]"},{"internalType":"bytes[]","name":"returnData","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBalances","outputs":[{"internalType":"uint256","name":"daiBalance","type":"uint256"},{"internalType":"uint256","name":"usdcBalance","type":"uint256"},{"internalType":"uint256","name":"etherBalance","type":"uint256"},{"internalType":"uint256","name":"dDaiUnderlyingDaiBalance","type":"uint256"},{"internalType":"uint256","name":"dUsdcUnderlyingUsdcBalance","type":"uint256"},{"internalType":"uint256","name":"dEtherUnderlyingEtherBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"enum DharmaSmartWalletImplementationV7Interface.ActionType","name":"action","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getCustomActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"ethToSupply","type":"uint256"},{"internalType":"uint256","name":"minimumDaiReceived","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getEthForDaiActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getGenericActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DharmaSmartWalletImplementationV1Interface.Call[]","name":"calls","type":"tuple[]"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getGenericAtomicBatchActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getImplementation","outputs":[{"internalType":"address","name":"implementation","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"enum DharmaSmartWalletImplementationV7Interface.ActionType","name":"action","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getNextCustomActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"ethToSupply","type":"uint256"},{"internalType":"uint256","name":"minimumDaiReceived","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getNextEthForDaiActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getNextGenericActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DharmaSmartWalletImplementationV1Interface.Call[]","name":"calls","type":"tuple[]"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getNextGenericAtomicBatchActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getUserSigningKey","outputs":[{"internalType":"address","name":"userSigningKey","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getVersion","outputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"userSigningKey","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"migrateCDaiToDDai","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"migrateCSaiToDDai","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"migrateCUSDCToDUSDC","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"migrateSaiToDai","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"permanentlyDisableEscapeHatch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newUserSigningKey","type":"address"}],"name":"recover","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"removeEscapeHatch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"repayAndDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"setEscapeHatch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"userSigningKey","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"setUserSigningKey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"ethToSupply","type":"uint256"},{"internalType":"uint256","name":"minimumDaiReceived","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"tradeEthForDaiAndMintDDai","outputs":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"target","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"triggerEtherTransfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"withdrawDai","outputs":[{"internalType":"bool","name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"withdrawEther","outputs":[{"internalType":"bool","name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"withdrawUSDC","outputs":[{"internalType":"bool","name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405180606001604052806025815260200162005c856025913980516020909101207f596746115f08448433597980d42b4541c0197187d07ffad9c7f66a471c49dbba146200005d57fe5b615c18806200006d6000396000f3fe6080604052600436106102245760003560e01c8063a553d94111610123578063c77a1594116100ab578063ec9e14d41161006f578063ec9e14d41461064e578063f05fe81a1461067b578063fbaf10e314610690578063fc522bce146106b0578063fd8137d61461047757610224565b8063c77a1594146105c4578063cc90530a146105e4578063d087d28814610604578063d180667d14610619578063d771d75a1461062e57610224565b8063ae0f1f33116100f2578063ae0f1f3314610516578063b3461f2f14610536578063b848821d14610564578063baf260e114610584578063c4d66de8146105a457610224565b8063a553d941146104ac578063aaf10f42146104cc578063ab8ac8fd146104e1578063ad67283b1461050157610224565b8063550c9f36116101b157806381a078d01161017557806381a078d0146104155780638c5bf80f146104375780638cf422b514610457578063974f302114610477578063a3ccb2801461048c57610224565b8063550c9f36146103735780635a0d31f7146103935780635d8f1661146103a8578063680a3423146103c85780638016b320146103f557610224565b8063168d88b9116101f8578063168d88b9146102b85780631c9e742e146102e657806320c13b0b1461030657806344f62b3c146103335780634b3622021461035357610224565b8062113e0814610226578063094ed15e146102565780630cd865ec146102835780630d8e6e2c146102a3575b005b34801561023257600080fd5b5061023b6106d0565b60405161024d969594939291906159d9565b60405180910390f35b34801561026257600080fd5b50610276610271366004614c5c565b61090a565b60405161024d9190615712565b34801561028f57600080fd5b5061022461029e3660046143a3565b610963565b3480156102af57600080fd5b506102766109b9565b3480156102c457600080fd5b506102d86102d33660046146fa565b6109be565b60405161024d92919061569d565b3480156102f257600080fd5b50610224610301366004614b20565b610cf1565b34801561031257600080fd5b506103266103213660046148e5565b610db0565b60405161024d91906158e3565b34801561033f57600080fd5b5061022461034e3660046145c6565b610f3e565b34801561035f57600080fd5b5061027661036e366004614dd9565b610fe0565b34801561037f57600080fd5b5061022461038e366004614b75565b611034565b34801561039f57600080fd5b5061022461111b565b3480156103b457600080fd5b506102766103c33660046146c5565b611127565b3480156103d457600080fd5b506103e86103e3366004614a74565b611146565b60405161024d91906156e4565b34801561040157600080fd5b506102766104103660046149a8565b6112fd565b34801561042157600080fd5b5061042a611330565b60405161024d919061562a565b34801561044357600080fd5b50610276610452366004614419565b61133f565b34801561046357600080fd5b50610276610472366004614549565b611364565b34801561048357600080fd5b50610224611380565b34801561049857600080fd5b506102246104a7366004614b75565b611385565b3480156104b857600080fd5b506103e86104c7366004614a74565b61144d565b3480156104d857600080fd5b5061042a61149a565b3480156104ed57600080fd5b506103e86104fc366004614a44565b61154e565b34801561050d57600080fd5b50610224611657565b34801561052257600080fd5b506103e8610531366004614a44565b611661565b34801561054257600080fd5b50610556610551366004614ceb565b6116f1565b60405161024d9291906156f2565b34801561057057600080fd5b5061022461057f3660046145c6565b6118d6565b34801561059057600080fd5b506103e861059f366004614a74565b611972565b3480156105b057600080fd5b506102246105bf3660046143a3565b611ac5565b3480156105d057600080fd5b506105566105df366004614482565b611c2c565b3480156105f057600080fd5b506103e86105ff3660046143df565b611dd5565b34801561061057600080fd5b50610276611e7e565b34801561062557600080fd5b50610224611e84565b34801561063a57600080fd5b50610276610649366004614793565b612044565b34801561065a57600080fd5b5061066e610669366004614691565b612064565b60405161024d91906156c2565b34801561068757600080fd5b506102246121d4565b34801561069c57600080fd5b506105566106ab366004614bfa565b61249d565b3480156106bc57600080fd5b506102766106cb366004614953565b61256f565b600080600080600080736b175474e89094c44da98b954eedeac495271d0f6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016107199190615638565b60206040518083038186803b15801561073157600080fd5b505afa158015610745573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107699190810190614862565b6040516370a0823160e01b815290965073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a08231906107a3903090600401615638565b60206040518083038186803b1580156107bb57600080fd5b505afa1580156107cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107f39190810190614862565b604051633af9e66960e01b81529095504794506e1876eb1444c986fd502e618c58743090633af9e6699061082b903090600401615638565b60206040518083038186803b15801561084357600080fd5b505afa158015610857573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061087b9190810190614862565b604051633af9e66960e01b81529093506e8943c65caf789fffcf953be156f6f890633af9e669906108b0903090600401615638565b60206040518083038186803b1580156108c857600080fd5b505afa1580156108dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506109009190810190614862565b9150909192939495565b6000610958600c888888888860405160200161092a95949392919061599e565b60408051601f1981840301815291905260015460005486906001600160a01b0316610953612595565b61261d565b979650505050505050565b336edfed903ad76996fc07bf89c0127b1e146109a5576109836008612661565b60405162461bcd60e51b815260040161099c9190615916565b60405180910390fd5b60018054810190556109b6816126ef565b50565b600a90565b60608060005b86518110156109f5576109ed8782815181106109dc57fe5b60200260200101516000015161275d565b6001016109c4565b50600080610a26600389604051602001610a0f91906156d3565b6040516020818303038152906040528989896127c2565b915091508751604051908082528060200260200182016040528015610a55578160200160208202803883390190505b5093508751604051908082528060200260200182016040528015610a8d57816020015b6060815260200190600190039081610a785790505b506002805463ffffffff191663168d88b91790556040519093506000906060903090633b27853560e21b90610ac6908d906024016156d3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610b04919061550d565b6000604051808303816000865af19150503d8060008114610b41576040519150601f19603f3d011682016040523d82523d6000602084013e610b46565b606091505b5091509150606081806020019051610b61919081019061465d565b905060005b8151811015610ce257610b776140e8565b8c8281518110610b8357fe5b60200260200101519050828281518110610b9957fe5b602002602001015160000151898381518110610bb157fe5b602002602001019015159081151581525050828281518110610bcf57fe5b602002602001015160200151888381518110610be757fe5b6020026020010181905250828281518110610bfe57fe5b60200260200101516000015115610c75577fb4a7946c0772f99411b9461db61ae510087dfb48bc453a75b0b9915588f0c5cc8786158884600001518560200151888881518110610c4a57fe5b602002602001015160200151604051610c6896959493929190615789565b60405180910390a1610cd9565b7f66d25ad42aacf4cb4fd83716d3ee5ba48cddbe69bf2028b574a8510432c0afcb878783600001518460200151878781518110610cae57fe5b602002602001015160200151604051610ccb959493929190615860565b60405180910390a150610ce2565b50600101610b66565b50505050505094509492505050565b6001546040805160008082526020601f860181900481028301840184528201858152610d7193919291889190889088908190860183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506127c292505050565b50507f8bf30e7ff26833413be5f69e1d373744864d600b664204b4a2f9844a8eedb9ed81604051610da29190615712565b60405180910390a150505050565b60008060606020861415610dd157610dca86880188614844565b9150610df6565b6040861015610de457610983601e612661565b610df086880188614880565b90925090505b60828414610e0857610983600b612661565b606085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506020808601516040808801516060808a01519251999a509298909750931a94509250610e6e91869186918691016154c9565b6040516020818303038152906040529050606185015193506081850151925060a185015160001a91506060848484604051602001610eae939291906154c9565b60408051601f19818403018152919052600054909150610ede908990600b908a906001600160a01b031685612923565b610eec57610983600c612661565b610efc888363ffffffff612a2416565b6001600160a01b0316610f0d612595565b6001600160a01b031614610f2557610983600d612661565b506320c13b0b60e01b9c9b505050505050505050505050565b610fcd600187604051602001610f54919061562a565b60408051601f198184030181526020601f8901819004810284018101909252878352918991899089908190840183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b5050610fd8866126ef565b505050505050565b6000611028600c898989898960405160200161100095949392919061599e565b60408051601f19818403018152919052600054869086906001600160a01b0316610953612595565b98975050505050505050565b60408051600081526020601f8601819004810282018301835281018581526110b092600892918991899089908190860183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b50506e5280b515004b998a944630b6c663f86001600160a01b0316635014b4f46040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156110fc57600080fd5b505af1158015611110573d6000803e3d6000fd5b505050505050505050565b6111256000612b00565b565b600061113f60038460405160200161092a91906156d3565b9392505050565b60006111d960058989604051602001611160929190615947565b60408051601f198184030181526020601f8a01819004810284018101909252888352918a918a908a908190840183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506127c292505050565b50506103e788116111ee576109836003612661565b6001600160a01b038716611206576109836001612661565b6002805463ffffffff191663680a3423179055604051606090309063ab8ac8fd60e01b9061123a908c908c90602401615947565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611278919061550d565b6000604051808303816000865af19150503d80600081146112b5576040519150601f19603f3d011682016040523d82523d6000602084013e6112ba565b606091505b509092509050816112da576112d563a9059cbb60e01b612d9b565b6112f1565b808060200190516112ee91908101906147f6565b91505b50979650505050505050565b60006113268661130e888888613007565b600054869086906001600160a01b0316610953612595565b9695505050505050565b6000546001600160a01b031690565b600061135b600286868660405160200161092a93929190615661565b95945050505050565b6000611326600287878760405160200161100093929190615661565b600080fd5b60408051600081526020601f86018190048102820183018352810185815261140192600992918991899089908190860183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b50506e5280b515004b998a944630b6c663f86001600160a01b031663f02fedc46040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156110fc57600080fd5b600061146760068989604051602001611160929190615947565b505087611478576109836004612661565b6001600160a01b038716611490576109836001612661565b6110288789613198565b60008060606e26750c571ce882b17016557279adaa6001600160a01b03166040516114c4906155fd565b600060405180830381855afa9150503d80600081146114ff576040519150601f19603f3d011682016040523d82523d6000602084013e611504565b606091505b5091509150818015611517575080516020145b6115335760405162461bcd60e51b815260040161099c90615937565b8080602001905161154791908101906143c1565b9250505090565b600061156063680a342360e01b61327e565b600019831480156115a75761157560016132bf565b61159573a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488460006134c1565b61159e57600080fd5b60019150611650565b6115b260018561379f565b156116505760405163a9059cbb60e01b815273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063a9059cbb906115f09086908890600401615682565b602060405180830381600087803b15801561160a57600080fd5b505af115801561161e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061164291908101906147f6565b61164b57600080fd5b600191505b5092915050565b6111256001612b00565b600061167363baf260e160e01b61327e565b600019831480156116a85761168860006132bf565b611595736b175474e89094c44da98b954eedeac495271d0f8460006134c1565b6116b360008561379f565b156116505760405163a9059cbb60e01b8152736b175474e89094c44da98b954eedeac495271d0f9063a9059cbb906115f09086908890600401615682565b6000606061178c600c8d8d8d8d8d60405160200161171395949392919061599e565b60408051601f198184030181526020601f8b01819004810284018101909252898352918b918b908b908190840183828082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a90819084018382808284376000920191909152506127c292505050565b505066038d7ea4c67fff8b116117a657610983601f612661565b63b3461f2f60e01b600260006101000a81548163ffffffff021916908360e01c02179055506060306001600160a01b031663fbaf10e360e01b8e8e8e8e8e6040516024016117f895949392919061599e565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611836919061550d565b6000604051808303816000865af19150503d8060008114611873576040519150601f19603f3d011682016040523d82523d6000602084013e611878565b606091505b509093509050826118c65773421816cdfe2073945173c0c35799ec21261fb399600080516020615bb68339815191526118b0836138a1565b6040516118bd9190615916565b60405180910390a25b509a509a98505050505050505050565b6118ec600787604051602001610f54919061562a565b50506001600160a01b038616611906576109836005612661565b604051630916bbc360e31b81526e5280b515004b998a944630b6c663f8906348b5de189061193890899060040161562a565b600060405180830381600087803b15801561195257600080fd5b505af1158015611966573d6000803e3d6000fd5b50505050505050505050565b600061198c600a8989604051602001611160929190615947565b505066038d7ea4c67fff88116119a6576109836000612661565b6001600160a01b0387166119be576109836001612661565b6002805463ffffffff191663baf260e1179055604051606090309063ae0f1f3360e01b906119f2908c908c90602401615947565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611a30919061550d565b6000604051808303816000865af19150503d8060008114611a6d576040519150601f19603f3d011682016040523d82523d6000602084013e611a72565b606091505b509092509050816112da57736b175474e89094c44da98b954eedeac495271d0f600080516020615bb6833981519152611aab6002612661565b604051611ab89190615916565b60405180910390a26112f1565b303b15611ad157600080fd5b611ada816126ef565b611ae46000613a11565b15611b82576040516370a0823160e01b8152600090736b175474e89094c44da98b954eedeac495271d0f906370a0823190611b23903090600401615638565b60206040518083038186803b158015611b3b57600080fd5b505afa158015611b4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611b739190810190614862565b9050611b80600082613ba5565b505b611b8c6001613a11565b156109b6576040516370a0823160e01b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a0823190611bcb903090600401615638565b60206040518083038186803b158015611be357600080fd5b505afa158015611bf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611c1b9190810190614862565b9050611c28600182613ba5565b5050565b60006060611c398a61275d565b600080611ccf60028d8d8d604051602001611c5693929190615661565b60408051601f198184030181526020601f8d018190048102840181019092528b8352918d918d908d908190840183828082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c90819084018382808284376000920191909152506127c292505050565b915091508b6001600160a01b03168b8b604051611ced929190615500565b6000604051808303816000865af19150503d8060008114611d2a576040519150601f19603f3d011682016040523d82523d6000602084013e611d2f565b606091505b5090945092508315611d84577fb4a7946c0772f99411b9461db61ae510087dfb48bc453a75b0b9915588f0c5cc826000838f8f8f89604051611d779796959493929190615720565b60405180910390a1611dc6565b7f66d25ad42aacf4cb4fd83716d3ee5ba48cddbe69bf2028b574a8510432c0afcb82828e8e8e88604051611dbd96959493929190615811565b60405180910390a15b50509850989650505050505050565b60003373723b51b72ae89a3d0c2a2760f0458307a1baa19114611e0a5760405162461bcd60e51b815260040161099c90615927565b826001600160a01b031682604051611e21906155fd565b60006040518083038185875af1925050503d8060008114611e5e576040519150601f19603f3d011682016040523d82523d6000602084013e611e63565b606091505b50508091505080611e78573d6000803e3d6000fd5b92915050565b60015490565b6000806e5280b515004b998a944630b6c663f86001600160a01b031663a22947486040518163ffffffff1660e01b8152600401604080518083038186803b158015611ece57600080fd5b505afa158015611ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611f069190810190614814565b9150915081611f19576109836006612661565b336001600160a01b03821614611f33576109836007612661565b611f3d60006132bf565b611f4760016132bf565b611f67736b175474e89094c44da98b954eedeac495271d0f3360016134c1565b50611f8873a0b86991c6218b36c1d19d4a2e9eb0ce3606eb483360016134c1565b50611fa9735d3a536e4d6dbd6114cc1ead35777bab948e36433360016134c1565b50611fca7339aa39c021dfbae8fac545936693ac917d5e75633360016134c1565b50611fe66e1876eb1444c986fd502e618c5874303360016134c1565b506120026e8943c65caf789fffcf953be156f6f83360016134c1565b50478015612016576120143382613198565b505b6040517fe4355f8a8e7deececf128bcf29ced6b5cb7402a1851b6e435b057e0bd8101eac90600090a1505050565b600061205c60038560405160200161100091906156d3565b949350505050565b606061207663168d88b960e01b61327e565b815160408051828152602080840282010190915260009180156120b357816020015b6120a06140e8565b8152602001906001900390816120985790505b50915060005b835181101561219b57600060608583815181106120d257fe5b6020026020010151600001516001600160a01b03168684815181106120f357fe5b60200260200101516020015160405161210c919061550d565b6000604051808303816000865af19150503d8060008114612149576040519150601f19603f3d011682016040523d82523d6000602084013e61214e565b606091505b5091509150604051806040016040528083151581526020018281525085848151811061217657fe5b6020026020010181905250816121915760019350505061219b565b50506001016120b9565b5080156121ce576060826040516020016121b591906156c2565b6040516020818303038152906040529050805181602001fd5b50919050565b6040516370a0823160e01b8152600090736b175474e89094c44da98b954eedeac495271d0f906370a082319061220e903090600401615638565b60206040518083038186803b15801561222657600080fd5b505afa15801561223a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061225e9190810190614862565b9050801561233757604051636eb1769f60e11b8152600090736b175474e89094c44da98b954eedeac495271d0f9063dd62ed3e906122b19030906e1876eb1444c986fd502e618c58743090600401615646565b60206040518083038186803b1580156122c957600080fd5b505afa1580156122dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123019190810190614862565b90508181101561232a576123156000613a11565b1561232557612325600083613ba5565b612335565b612335600083613ba5565b505b6040516370a0823160e01b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a0823190612371903090600401615638565b60206040518083038186803b15801561238957600080fd5b505afa15801561239d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123c19190810190614862565b90508015611c2857604051636eb1769f60e11b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063dd62ed3e906124149030906e8943c65caf789fffcf953be156f6f890600401615646565b60206040518083038186803b15801561242c57600080fd5b505afa158015612440573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124649190810190614862565b90508181101561248d576124786001613a11565b1561248857612488600183613ba5565b612498565b612498600183613ba5565b505050565b600060606124b163b3461f2f60e01b61327e565b6040516390c6903760e01b815260009073421816cdfe2073945173c0c35799ec21261fb399906390c69037908a906124f3908b908b908b908b90600401615970565b6020604051808303818588803b15801561250c57600080fd5b505af1158015612520573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052506125459190810190614862565b905086811015612559576109836020612661565b612564600082613ba5565b509550959350505050565b600061135b85612580878787613007565b60015460005486906001600160a01b03166109535b60006f0d38df53b45c5733c7b34000de0bdf526001600160a01b03166382678dd66040518163ffffffff1660e01b815260040160206040518083038186803b1580156125e057600080fd5b505afa1580156125f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061261891908101906143c1565b905090565b600030600a848488888c8c60405160200161263f98979695949392919061543f565b6040516020818303038152906040528051906020012090509695505050505050565b6040516309ada4d560e21b8152606090739c0ccb765d3f5035f8b5dd30fe375d5f4997d8e4906326b693549061269b908590600401615712565b60006040518083038186803b1580156126b357600080fd5b505afa1580156126c7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611e789190810190614a10565b6001600160a01b03811661270757610983600e612661565b600080546001600160a01b0319166001600160a01b0383161790556040517f7083aac3cab97f1219cedd0ab328a5b138a10b0fc72dd9348f1dc50199b21fda9061275290839061562a565b60405180910390a150565b61276f816001600160a01b0316613d9e565b61277d57610983601a612661565b6001600160a01b03811630141561279857610983601b612661565b6001600160a01b0381166e5280b515004b998a944630b6c663f814156109b657610983601c612661565b60008084156127dd57845a10156127dd576109836013612661565b50600154600080546001600160a01b0316906127f7612595565b90506128078989858a868661261d565b9350600061281485613da4565b905060008a600e81111561282457fe5b1461289b57336001600160a01b0384161461285457612846818b8b868b612923565b612854576109836014612661565b336001600160a01b0383161461289657612874818763ffffffff612a2416565b6001600160a01b0316826001600160a01b031614612896576109836015612661565b61290c565b336001600160a01b038416148015906128bd5750336001600160a01b03831614155b1561290c576128d2818763ffffffff612a2416565b6001600160a01b0316826001600160a01b0316141580156128fd57506128fb818b8b868b612923565b155b1561290c576109836016612661565b505060018054810190555090969095509350505050565b6000612937836001600160a01b0316613d9e565b6129665761294b868363ffffffff612a2416565b6001600160a01b0316836001600160a01b031614905061135b565b606086868660405160200161297d939291906157e4565b60408051601f19818403018152908290526320c13b0b60e01b808352909250906001600160a01b038616906320c13b0b906129be90859088906004016158f1565b60206040518083038186803b1580156129d657600080fd5b505afa1580156129ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612a0e91908101906148c7565b6001600160e01b03191614979650505050505050565b60008151604114612a3757506000611e78565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612a7d5760009350505050611e78565b8060ff16601b14158015612a9557508060ff16601c14155b15612aa65760009350505050611e78565b60018682858560405160008152602001604052604051612ac994939291906158ae565b6020604051602081039080840390855afa158015612aeb573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60008080836003811115612b1057fe5b1415612b435750735d3a536e4d6dbd6114cc1ead35777bab948e364390506e1876eb1444c986fd502e618c587430612b6c565b507339aa39c021dfbae8fac545936693ac917d5e756390506e8943c65caf789fffcf953be156f6f85b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190612b9b903090600401615638565b60206040518083038186803b158015612bb357600080fd5b505afa158015612bc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612beb9190810190614862565b90508015612d9557604051636eb1769f60e11b815281906001600160a01b0385169063dd62ed3e90612c239030908790600401615646565b60206040518083038186803b158015612c3b57600080fd5b505afa158015612c4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612c739190810190614862565b1015612d095760405163095ea7b360e01b81526001600160a01b0384169063095ea7b390612ca990859060001990600401615682565b602060405180830381600087803b158015612cc357600080fd5b505af1158015612cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612cfb91908101906147f6565b612d09576109836017612661565b60405163d8da64f360e01b81526001600160a01b0383169063d8da64f390612d35908490600401615712565b602060405180830381600087803b158015612d4f57600080fd5b505af1158015612d63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d879190810190614862565b612d95576109836018612661565b50505050565b60606001600160e01b0319821663a9059cbb60e01b1415612ddb57506040805180820190915260088152673a3930b739b332b960c11b6020820152612dfb565b50604080518082019091526007815266617070726f766560c81b60208201525b60405163fe575a8760e01b815273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4890819063fe575a8790612e34903090600401615638565b60206040518083038186803b158015612e4c57600080fd5b505afa158015612e60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612e8491908101906147f6565b15612eee5773a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612ec791906155af565b60408051601f1981840301815290829052612ee191615916565b60405180910390a2612498565b806001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b158015612f2757600080fd5b505afa158015612f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612f5f91908101906147f6565b15612fa25773a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612ec79190615581565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612fe09190615608565b60408051601f1981840301815290829052612ffa91615916565b60405180910390a2505050565b606060008085600e81111561301857fe5b148061302f5750600185600e81111561302d57fe5b145b806130455750600a85600e81111561304357fe5b145b8061305b5750600585600e81111561305957fe5b145b806130715750600685600e81111561306f57fe5b145b806130875750600785600e81111561308557fe5b145b8061309d5750600885600e81111561309b57fe5b145b806130b35750600985600e8111156130b157fe5b145b9050806130c457610983601d612661565b600085600e8111156130d257fe5b14806130e95750600885600e8111156130e757fe5b145b806130ff5750600985600e8111156130fd57fe5b145b1561311a576040805160008152602081019091529150613190565b600185600e81111561312857fe5b148061313f5750600785600e81111561313d57fe5b145b1561316b5782604051602001613155919061562a565b6040516020818303038152906040529150613190565b838360405160200161317e929190615947565b60405160208183030381529060405291505b509392505050565b6000826001600160a01b0316611387836040516131b4906155fd565b600060405180830381858888f193505050503d80600081146131f2576040519150601f19603f3d011682016040523d82523d6000602084013e6131f7565b606091505b5050809150508061323f57826001600160a01b0316600080516020615bb68339815191526132256012612661565b6040516132329190615916565b60405180910390a2611e78565b7f7b41af3b6a6a16e290821a297090842bafd82f6da2d087a54b277aeef6f386da8284604051613270929190615955565b60405180910390a192915050565b33301415806132a0575060025460e01b6001600160e01b031990811690821614155b156132af576109836019612661565b506002805463ffffffff19169055565b6000808260038111156132ce57fe5b146132e8576e8943c65caf789fffcf953be156f6f86132f9565b6e1876eb1444c986fd502e618c5874305b60405190915060009081906060906001600160a01b038516906370a0823160e01b9061332990309060240161562a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613367919061550d565b6000604051808303816000865af19150503d80600081146133a4576040519150601f19603f3d011682016040523d82523d6000602084013e6133a9565b606091505b50909250905060008280156133bf575081516020145b156133df57818060200190516133d89190810190614862565b90506133f4565b6133f2866370a0823160e01b8585613dd4565b505b8015610fd8576040516001600160a01b0386169063db006a7560e01b9061341f908490602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161345d919061550d565b6000604051808303816000865af19150503d806000811461349a576040519150601f19603f3d011682016040523d82523d6000602084013e61349f565b606091505b5090935091506134b88663db006a7560e01b8585613dd4565b50505050505050565b60008060018361354e576040516370a0823160e01b81526001600160a01b038716906370a08231906134f7903090600401615638565b60206040518083038186803b15801561350f57600080fd5b505afa158015613523573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506135479190810190614862565b9150613640565b60006060876001600160a01b031660025a8161356657fe5b604051919004906370a0823160e01b9061358490309060240161562a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516135c2919061550d565b60006040518083038160008787f1925050503d8060008114613600576040519150601f19603f3d011682016040523d82523d6000602084013e613605565b606091505b5091509150818015613618575080516020145b1561363857808060200190516136319190810190614862565b935061363d565b600092505b50505b811561379257836136d25760405163a9059cbb60e01b81526001600160a01b0387169063a9059cbb906136799088908690600401615682565b602060405180830381600087803b15801561369357600080fd5b505af11580156136a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506136cb91908101906147f6565b925061378d565b856001600160a01b031660025a816136e657fe5b6040519190049063a9059cbb60e01b906137069089908790602401615682565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613744919061550d565b60006040518083038160008787f1925050503d8060008114613782576040519150601f19603f3d011682016040523d82523d6000602084013e613787565b606091505b50909350505b613796565b8092505b50509392505050565b600080808460038111156137af57fe5b146137c9576e8943c65caf789fffcf953be156f6f86137da565b6e1876eb1444c986fd502e618c5874305b6040519091506000906060906001600160a01b0384169063852a12e360e01b90613808908890602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613846919061550d565b6000604051808303816000865af19150503d8060008114613883576040519150601f19603f3d011682016040523d82523d6000602084013e613888565b606091505b5090925090506113268663852a12e360e01b8484613dd4565b6060604482511180156138d357508151600160fb1b9083906000906138c257fe5b01602001516001600160f81b031916145b80156139005750815160c360f81b90839060019081106138ef57fe5b01602001516001600160f81b031916145b801561392d57508151607960f81b908390600290811061391c57fe5b01602001516001600160f81b031916145b801561395a57508151600560fd1b908390600390811061394957fe5b01602001516001600160f81b031916145b15613a0157606060048351036040519080825280601f01601f191660200182016040528015613990576020820181803883390190505b50905060045b83518110156139e4578381815181106139ab57fe5b602001015160f81c60f81b8260048303815181106139c557fe5b60200101906001600160f81b031916908160001a905350600101613996565b50808060200190516139f99190810190614a10565b915050613a0c565b611e78600019612661565b919050565b6000808080846003811115613a2257fe5b1415613a555750736b175474e89094c44da98b954eedeac495271d0f90506e1876eb1444c986fd502e618c587430613a7e565b5073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4890506e8943c65caf789fffcf953be156f6f85b6040516001600160a01b0383169063095ea7b360e01b90613aa790849060001990602401615682565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613ae5919061550d565b6000604051808303816000865af19150503d8060008114613b22576040519150601f19603f3d011682016040523d82523d6000602084013e613b27565b606091505b50508093505082613b9e576000846003811115613b4057fe5b1415613b8e57736b175474e89094c44da98b954eedeac495271d0f600080516020615bb6833981519152613b746011612661565b604051613b819190615916565b60405180910390a2613b9e565b613b9e63095ea7b360e01b612d9b565b5050919050565b6000826003811115613bb357fe5b148015613bc6575066038d7ea4c67fff81115b80613c9857506001826003811115613bda57fe5b148015613c9857506103e781118015613c98575060405163023aa9ab60e61b815273c5c0ead7df3cefc45c8f4592e3a0f1500949e75d90638eaa6ac090613c45907f596746115f08448433597980d42b4541c0197187d07ffad9c7f66a471c49dbba90600401615712565b60206040518083038186803b158015613c5d57600080fd5b505afa158015613c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613c959190810190614862565b15155b15611c2857600080836003811115613cac57fe5b14613cc6576e8943c65caf789fffcf953be156f6f8613cd7565b6e1876eb1444c986fd502e618c5874305b6040519091506000906060906001600160a01b0384169063140e25ad60e31b90613d05908790602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613d43919061550d565b6000604051808303816000865af19150503d8060008114613d80576040519150601f19603f3d011682016040523d82523d6000602084013e613d85565b606091505b509092509050610fd88563140e25ad60e31b8484613dd4565b3b151590565b600081604051602001613db791906155c6565b604051602081830303815290604052805190602001209050919050565b60008215613ee657815160201415613e7a57600082806020019051613dfc9190810190614862565b90508015613e0d5760019150613e74565b6000606080613e1c8989613f64565b925092509250826001600160a01b0316600080516020615bb68339815191528383604051602001613e4e929190615598565b60408051601f1981840301815290829052613e6891615916565b60405180910390a25050505b50613ee1565b6000606080613e898888613f64565b925092509250826001600160a01b0316600080516020615bb68339815191528383604051602001613ebb929190615519565b60408051601f1981840301815290829052613ed591615916565b60405180910390a25050505b61205c565b6000606080613ef58888613f64565b9250925092506060613f06866138a1565b9050836001600160a01b0316600080516020615bb6833981519152848484604051602001613f3693929190615547565b60408051601f1981840301815290829052613f5091615916565b60405180910390a250505050949350505050565b600060608082856003811115613f7657fe5b1415613fb8576e1876eb1444c986fd502e618c58743092506040518060400160405280600a815260200169446861726d612044616960b01b8152509150613ff5565b6e8943c65caf789fffcf953be156f6f892506040518060400160405280600f81526020016e223430b936b0902aa9a21021b7b4b760891b81525091505b6001600160e01b0319841663140e25ad60e31b141561402f57506040805180820190915260048152631b5a5b9d60e21b60208201526140e1565b6001600160e01b031984166370a0823160e01b141561406e57506040805180820190915260098152683130b630b731b2a7b360b91b60208201526140e1565b6001600160e01b0319841663db006a7560e01b146140ae576040518060400160405280600a815260200169556e6465726c79696e6760b01b8152506140bf565b604051806020016040528060008152505b6040516020016140cf91906155e6565b60405160208183030381529060405290505b9250925092565b60408051808201909152600081526060602082015290565b8035611e7881615b79565b8051611e7881615b79565b600082601f83011261412757600080fd5b815161413a61413582615a4e565b615a28565b81815260209384019390925082018360005b83811015614178578151860161416288826142f3565b845250602092830192919091019060010161414c565b5050505092915050565b600082601f83011261419357600080fd5b81356141a161413582615a4e565b81815260209384019390925082018360005b8381101561417857813586016141c98882614351565b84525060209283019291909101906001016141b3565b8051611e7881615b8d565b8035611e7881615b96565b8051611e7881615b96565b8051611e7881615b9f565b60008083601f84011261421d57600080fd5b5081356001600160401b0381111561423457600080fd5b60208301915083600182028301111561424c57600080fd5b9250929050565b600082601f83011261426457600080fd5b813561427261413582615a6e565b9150808252602083016020830185838301111561428e57600080fd5b614299838284615b05565b50505092915050565b600082601f8301126142b357600080fd5b81516142c161413582615a6e565b915080825260208301602083018583830111156142dd57600080fd5b614299838284615b11565b8035611e7881615ba8565b60006040828403121561430557600080fd5b61430f6040615a28565b9050600061431d84846141df565b82525060208201516001600160401b0381111561433957600080fd5b614345848285016142a2565b60208301525092915050565b60006040828403121561436357600080fd5b61436d6040615a28565b9050600061437b8484614100565b82525060208201356001600160401b0381111561439757600080fd5b61434584828501614253565b6000602082840312156143b557600080fd5b600061205c8484614100565b6000602082840312156143d357600080fd5b600061205c848461410b565b600080604083850312156143f257600080fd5b60006143fe8585614100565b925050602061440f858286016141ea565b9150509250929050565b6000806000806060858703121561442f57600080fd5b600061443b8787614100565b94505060208501356001600160401b0381111561445757600080fd5b6144638782880161420b565b93509350506040614476878288016141ea565b91505092959194509250565b60008060008060008060008060a0898b03121561449e57600080fd5b60006144aa8b8b614100565b98505060208901356001600160401b038111156144c657600080fd5b6144d28b828c0161420b565b975097505060406144e58b828c016141ea565b95505060608901356001600160401b0381111561450157600080fd5b61450d8b828c0161420b565b945094505060808901356001600160401b0381111561452b57600080fd5b6145378b828c0161420b565b92509250509295985092959890939650565b60008060008060006080868803121561456157600080fd5b600061456d8888614100565b95505060208601356001600160401b0381111561458957600080fd5b6145958882890161420b565b945094505060406145a8888289016141ea565b92505060606145b9888289016141ea565b9150509295509295909350565b600080600080600080608087890312156145df57600080fd5b60006145eb8989614100565b96505060206145fc89828a016141ea565b95505060408701356001600160401b0381111561461857600080fd5b61462489828a0161420b565b945094505060608701356001600160401b0381111561464257600080fd5b61464e89828a0161420b565b92509250509295509295509295565b60006020828403121561466f57600080fd5b81516001600160401b0381111561468557600080fd5b61205c84828501614116565b6000602082840312156146a357600080fd5b81356001600160401b038111156146b957600080fd5b61205c84828501614182565b600080604083850312156146d857600080fd5b82356001600160401b038111156146ee57600080fd5b6143fe85828601614182565b6000806000806080858703121561471057600080fd5b84356001600160401b0381111561472657600080fd5b61473287828801614182565b9450506020614743878288016141ea565b93505060408501356001600160401b0381111561475f57600080fd5b61476b87828801614253565b92505060608501356001600160401b0381111561478757600080fd5b61447687828801614253565b6000806000606084860312156147a857600080fd5b83356001600160401b038111156147be57600080fd5b6147ca86828701614182565b93505060206147db868287016141ea565b92505060406147ec868287016141ea565b9150509250925092565b60006020828403121561480857600080fd5b600061205c84846141df565b6000806040838503121561482757600080fd5b600061483385856141df565b925050602061440f8582860161410b565b60006020828403121561485657600080fd5b600061205c84846141ea565b60006020828403121561487457600080fd5b600061205c84846141f5565b6000806040838503121561489357600080fd5b600061489f85856141ea565b92505060208301356001600160401b038111156148bb57600080fd5b61440f85828601614253565b6000602082840312156148d957600080fd5b600061205c8484614200565b600080600080604085870312156148fb57600080fd5b84356001600160401b0381111561491157600080fd5b61491d8782880161420b565b945094505060208501356001600160401b0381111561493b57600080fd5b6149478782880161420b565b95989497509550505050565b6000806000806080858703121561496957600080fd5b600061497587876142e8565b9450506020614986878288016141ea565b935050604061499787828801614100565b9250506060614476878288016141ea565b600080600080600060a086880312156149c057600080fd5b60006149cc88886142e8565b95505060206149dd888289016141ea565b94505060406149ee88828901614100565b93505060606149ff888289016141ea565b92505060806145b9888289016141ea565b600060208284031215614a2257600080fd5b81516001600160401b03811115614a3857600080fd5b61205c848285016142a2565b60008060408385031215614a5757600080fd5b6000614a6385856141ea565b925050602061440f85828601614100565b600080600080600080600060a0888a031215614a8f57600080fd5b6000614a9b8a8a6141ea565b9750506020614aac8a828b01614100565b9650506040614abd8a828b016141ea565b95505060608801356001600160401b03811115614ad957600080fd5b614ae58a828b0161420b565b945094505060808801356001600160401b03811115614b0357600080fd5b614b0f8a828b0161420b565b925092505092959891949750929550565b600080600060408486031215614b3557600080fd5b6000614b4186866141ea565b93505060208401356001600160401b03811115614b5d57600080fd5b614b698682870161420b565b92509250509250925092565b600080600080600060608688031215614b8d57600080fd5b6000614b9988886141ea565b95505060208601356001600160401b03811115614bb557600080fd5b614bc18882890161420b565b945094505060408601356001600160401b03811115614bdf57600080fd5b614beb8882890161420b565b92509250509295509295909350565b600080600080600060808688031215614c1257600080fd5b6000614c1e88886141ea565b9550506020614c2f888289016141ea565b9450506040614c4088828901614100565b93505060608601356001600160401b03811115614bdf57600080fd5b60008060008060008060a08789031215614c7557600080fd5b6000614c8189896141ea565b9650506020614c9289828a016141ea565b9550506040614ca389828a01614100565b94505060608701356001600160401b03811115614cbf57600080fd5b614ccb89828a0161420b565b93509350506080614cde89828a016141ea565b9150509295509295509295565b60008060008060008060008060008060e08b8d031215614d0a57600080fd5b6000614d168d8d6141ea565b9a50506020614d278d828e016141ea565b9950506040614d388d828e01614100565b98505060608b01356001600160401b03811115614d5457600080fd5b614d608d828e0161420b565b97509750506080614d738d828e016141ea565b95505060a08b01356001600160401b03811115614d8f57600080fd5b614d9b8d828e0161420b565b945094505060c08b01356001600160401b03811115614db957600080fd5b614dc58d828e0161420b565b92509250509295989b9194979a5092959850565b600080600080600080600060c0888a031215614df457600080fd5b6000614e008a8a6141ea565b9750506020614e118a828b016141ea565b9650506040614e228a828b01614100565b95505060608801356001600160401b03811115614e3e57600080fd5b614e4a8a828b0161420b565b94509450506080614e5d8a828b016141ea565b92505060a0614e6e8a828b016141ea565b91505092959891949750929550565b6000614e898383615067565b505060200190565b600061113f83836150de565b600061113f83836153ea565b600061113f8383615416565b614ebe81615ae4565b82525050565b614ebe81615aa8565b614ebe614ed982615aa8565b615b3d565b6000614ee982615a9b565b614ef38185615a9f565b9350614efe83615a95565b8060005b83811015614f2c578151614f168882614e7d565b9750614f2183615a95565b925050600101614f02565b509495945050505050565b6000614f4282615a9b565b614f4c8185615a9f565b935083602082028501614f5e85615a95565b8060005b85811015614f985784840389528151614f7b8582614e91565b9450614f8683615a95565b60209a909a0199925050600101614f62565b5091979650505050505050565b6000614fb082615a9b565b614fba8185615a9f565b935083602082028501614fcc85615a95565b8060005b85811015614f985784840389528151614fe98582614e9d565b9450614ff483615a95565b60209a909a0199925050600101614fd0565b600061501182615a9b565b61501b8185615a9f565b93508360208202850161502d85615a95565b8060005b85811015614f98578484038952815161504a8582614ea9565b945061505583615a95565b60209a909a0199925050600101615031565b614ebe81615ab3565b614ebe81615ab8565b614ebe61508582615ab8565b615ab8565b614ebe81615abb565b600061509f8385615a9f565b93506150ac838584615b05565b6150b583615b59565b9093019392505050565b60006150cb8385613a0c565b93506150d8838584615b05565b50500190565b60006150e982615a9b565b6150f38185615a9f565b9350615103818560208601615b11565b6150b581615b59565b600061511782615a9b565b6151218185613a0c565b9350615131818560208601615b11565b9290920192915050565b614ebe81615aef565b614ebe61515082615aef565b615b4e565b6000615162601c83613a0c565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c0192915050565b600061519b601783613a0c565b7f20676176652062616420646174612063616c6c696e6720000000000000000000815260170192915050565b60006151d4601283613a0c565b710103932bb32b93a32b21031b0b63634b733960751b815260120192915050565b6000615202600683613a0c565b6572656465656d60d01b815260060192915050565b6000615224602c83613a0c565b7f206661696c6564202d205553444320636f6e747261637420697320637572726581526b373a363c903830bab9b2b21760a11b6020820152602c0192915050565b6000615272600183613a0c565b601760f91b815260010192915050565b600061528f602583615a9f565b7f4574686572697a65643a206f6e6c792063616c6c61626c6520627920457468658152643934bd32b960d91b602082015260400192915050565b60006152d6601783615a9f565b7f496e76616c696420696d706c656d656e746174696f6e2e000000000000000000815260200192915050565b6000611e78600083613a0c565b600061531c600283613a0c565b6101d160f51b815260020192915050565b600061533a601a83613a0c565b7f5553444320636f6e7472616374207265766572746564206f6e200000000000008152601a0192915050565b6000615373601883613a0c565b7f2067617665206e6f20746f6b656e732063616c6c696e67200000000000000000815260180192915050565b60006153ac602983613a0c565b7f206661696c6564202d20555344432068617320626c61636b6c697374656420748152683434b9903ab9b2b91760b91b602082015260290192915050565b805160009060408401906153fe8582615067565b506020830151848203602086015261135b82826150de565b805160009060408401906153fe8582614ec4565b614ebe81615ade565b614ebe61515082615ade565b600061544b828b614ecd565b60148201915061545b828a615079565b60208201915061546b8289614ecd565b60148201915061547b8288614ecd565b60148201915061548b8287615079565b60208201915061549b8286615079565b6020820191506154ab8285615144565b6001820191506154bb828461510c565b9a9950505050505050505050565b60006154d58286615079565b6020820191506154e58285615079565b6020820191506154f58284615433565b506001019392505050565b600061205c8284866150bf565b600061113f828461510c565b6000615525828561510c565b91506155308261518e565b915061553c828461510c565b915061205c82615265565b6000615553828661510c565b915061555e826151c7565b915061556a828561510c565b91506155758261530f565b915061135b828461510c565b600061558d828461510c565b915061113f82615217565b60006155a4828561510c565b915061553082615366565b60006155bb828461510c565b915061113f8261539f565b60006155d182615155565b91506155dd8284615079565b50602001919050565b60006155f1826151f5565b915061113f828461510c565b6000611e7882615302565b60006156138261532d565b915061561f828461510c565b915061113f82615265565b60208101611e788284614ec4565b60208101611e788284614eb5565b604081016156548285614eb5565b61113f6020830184614ec4565b6040810161566f8286614ec4565b818103602083015261135b818486615093565b604081016156908285614ec4565b61113f6020830184615070565b604080825281016156ae8185614ede565b9050818103602083015261205c8184614f37565b6020808252810161113f8184614fa5565b6020808252810161113f8184615006565b60208101611e788284615067565b604081016157008285615067565b818103602083015261205c81846150de565b60208101611e788284615070565b60c0810161572e828a615070565b61573b6020830189615067565b6157486040830188615070565b6157556060830187614ec4565b8181036080830152615768818587615093565b905081810360a083015261577c81846150de565b9998505050505050505050565b60c081016157978289615070565b6157a46020830188615067565b6157b16040830187615070565b6157be6060830186614ec4565b81810360808301526157d081856150de565b905081810360a083015261102881846150de565b606081016157f28286615070565b6157ff602083018561513b565b818103604083015261135b81846150de565b60a0810161581f8289615070565b61582c6020830188615070565b6158396040830187614ec4565b818103606083015261584c818587615093565b9050818103608083015261102881846150de565b60a0810161586e8288615070565b61587b6020830187615070565b6158886040830186614ec4565b818103606083015261589a81856150de565b9050818103608083015261095881846150de565b608081016158bc8287615070565b6158c9602083018661542a565b6158d66040830185615070565b61135b6060830184615070565b60208101611e78828461508a565b6040808252810161590281856150de565b9050818103602083015261205c81846150de565b6020808252810161113f81846150de565b60208082528101611e7881615282565b60208082528101611e78816152c9565b604081016156548285615070565b604081016159638285615070565b61113f6020830184614eb5565b6060810161597e8287615070565b61598b6020830186614ec4565b8181036040830152611326818486615093565b608081016159ac8288615070565b6159b96020830187615070565b6159c66040830186614ec4565b8181036060830152610958818486615093565b60c081016159e78289615070565b6159f46020830188615070565b615a016040830187615070565b615a0e6060830186615070565b615a1b6080830185615070565b61095860a0830184615070565b6040518181016001600160401b0381118282101715615a4657600080fd5b604052919050565b60006001600160401b03821115615a6457600080fd5b5060209081020190565b60006001600160401b03821115615a8457600080fd5b506020601f91909101601f19160190565b60200190565b5190565b90815260200190565b6000611e7882615ad2565b151590565b90565b6001600160e01b03191690565b80613a0c81615b6f565b6001600160a01b031690565b60ff1690565b6000611e7882615afa565b6000611e7882615ac8565b6000611e7882615aa8565b82818337506000910152565b60005b83811015615b2c578181015183820152602001615b14565b83811115612d955750506000910152565b6000611e78826000611e7882615b69565b6000611e7882615b63565b601f01601f191690565b60f81b90565b60601b90565b600f81106109b657fe5b615b8281615aa8565b81146109b657600080fd5b615b8281615ab3565b615b8281615ab8565b615b8281615abb565b600f81106109b657600080fdfe5bbd5ab79029b89a22c80c7b7bfdc2f0c8e3f0d2a7330c7148cabc044250674ba365627a7a723158209ecdeb27b72609ca0e8ec110d047738b99f3d520bc3127dbe5ffeebe65dc25946c6578706572696d656e74616cf564736f6c63430005110040616c6c6f77417661696c61626c6555534443546f426555736564546f4d696e744355534443

Deployed Bytecode

0x6080604052600436106102245760003560e01c8063a553d94111610123578063c77a1594116100ab578063ec9e14d41161006f578063ec9e14d41461064e578063f05fe81a1461067b578063fbaf10e314610690578063fc522bce146106b0578063fd8137d61461047757610224565b8063c77a1594146105c4578063cc90530a146105e4578063d087d28814610604578063d180667d14610619578063d771d75a1461062e57610224565b8063ae0f1f33116100f2578063ae0f1f3314610516578063b3461f2f14610536578063b848821d14610564578063baf260e114610584578063c4d66de8146105a457610224565b8063a553d941146104ac578063aaf10f42146104cc578063ab8ac8fd146104e1578063ad67283b1461050157610224565b8063550c9f36116101b157806381a078d01161017557806381a078d0146104155780638c5bf80f146104375780638cf422b514610457578063974f302114610477578063a3ccb2801461048c57610224565b8063550c9f36146103735780635a0d31f7146103935780635d8f1661146103a8578063680a3423146103c85780638016b320146103f557610224565b8063168d88b9116101f8578063168d88b9146102b85780631c9e742e146102e657806320c13b0b1461030657806344f62b3c146103335780634b3622021461035357610224565b8062113e0814610226578063094ed15e146102565780630cd865ec146102835780630d8e6e2c146102a3575b005b34801561023257600080fd5b5061023b6106d0565b60405161024d969594939291906159d9565b60405180910390f35b34801561026257600080fd5b50610276610271366004614c5c565b61090a565b60405161024d9190615712565b34801561028f57600080fd5b5061022461029e3660046143a3565b610963565b3480156102af57600080fd5b506102766109b9565b3480156102c457600080fd5b506102d86102d33660046146fa565b6109be565b60405161024d92919061569d565b3480156102f257600080fd5b50610224610301366004614b20565b610cf1565b34801561031257600080fd5b506103266103213660046148e5565b610db0565b60405161024d91906158e3565b34801561033f57600080fd5b5061022461034e3660046145c6565b610f3e565b34801561035f57600080fd5b5061027661036e366004614dd9565b610fe0565b34801561037f57600080fd5b5061022461038e366004614b75565b611034565b34801561039f57600080fd5b5061022461111b565b3480156103b457600080fd5b506102766103c33660046146c5565b611127565b3480156103d457600080fd5b506103e86103e3366004614a74565b611146565b60405161024d91906156e4565b34801561040157600080fd5b506102766104103660046149a8565b6112fd565b34801561042157600080fd5b5061042a611330565b60405161024d919061562a565b34801561044357600080fd5b50610276610452366004614419565b61133f565b34801561046357600080fd5b50610276610472366004614549565b611364565b34801561048357600080fd5b50610224611380565b34801561049857600080fd5b506102246104a7366004614b75565b611385565b3480156104b857600080fd5b506103e86104c7366004614a74565b61144d565b3480156104d857600080fd5b5061042a61149a565b3480156104ed57600080fd5b506103e86104fc366004614a44565b61154e565b34801561050d57600080fd5b50610224611657565b34801561052257600080fd5b506103e8610531366004614a44565b611661565b34801561054257600080fd5b50610556610551366004614ceb565b6116f1565b60405161024d9291906156f2565b34801561057057600080fd5b5061022461057f3660046145c6565b6118d6565b34801561059057600080fd5b506103e861059f366004614a74565b611972565b3480156105b057600080fd5b506102246105bf3660046143a3565b611ac5565b3480156105d057600080fd5b506105566105df366004614482565b611c2c565b3480156105f057600080fd5b506103e86105ff3660046143df565b611dd5565b34801561061057600080fd5b50610276611e7e565b34801561062557600080fd5b50610224611e84565b34801561063a57600080fd5b50610276610649366004614793565b612044565b34801561065a57600080fd5b5061066e610669366004614691565b612064565b60405161024d91906156c2565b34801561068757600080fd5b506102246121d4565b34801561069c57600080fd5b506105566106ab366004614bfa565b61249d565b3480156106bc57600080fd5b506102766106cb366004614953565b61256f565b600080600080600080736b175474e89094c44da98b954eedeac495271d0f6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016107199190615638565b60206040518083038186803b15801561073157600080fd5b505afa158015610745573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107699190810190614862565b6040516370a0823160e01b815290965073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a08231906107a3903090600401615638565b60206040518083038186803b1580156107bb57600080fd5b505afa1580156107cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107f39190810190614862565b604051633af9e66960e01b81529095504794506e1876eb1444c986fd502e618c58743090633af9e6699061082b903090600401615638565b60206040518083038186803b15801561084357600080fd5b505afa158015610857573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061087b9190810190614862565b604051633af9e66960e01b81529093506e8943c65caf789fffcf953be156f6f890633af9e669906108b0903090600401615638565b60206040518083038186803b1580156108c857600080fd5b505afa1580156108dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506109009190810190614862565b9150909192939495565b6000610958600c888888888860405160200161092a95949392919061599e565b60408051601f1981840301815291905260015460005486906001600160a01b0316610953612595565b61261d565b979650505050505050565b336edfed903ad76996fc07bf89c0127b1e146109a5576109836008612661565b60405162461bcd60e51b815260040161099c9190615916565b60405180910390fd5b60018054810190556109b6816126ef565b50565b600a90565b60608060005b86518110156109f5576109ed8782815181106109dc57fe5b60200260200101516000015161275d565b6001016109c4565b50600080610a26600389604051602001610a0f91906156d3565b6040516020818303038152906040528989896127c2565b915091508751604051908082528060200260200182016040528015610a55578160200160208202803883390190505b5093508751604051908082528060200260200182016040528015610a8d57816020015b6060815260200190600190039081610a785790505b506002805463ffffffff191663168d88b91790556040519093506000906060903090633b27853560e21b90610ac6908d906024016156d3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610b04919061550d565b6000604051808303816000865af19150503d8060008114610b41576040519150601f19603f3d011682016040523d82523d6000602084013e610b46565b606091505b5091509150606081806020019051610b61919081019061465d565b905060005b8151811015610ce257610b776140e8565b8c8281518110610b8357fe5b60200260200101519050828281518110610b9957fe5b602002602001015160000151898381518110610bb157fe5b602002602001019015159081151581525050828281518110610bcf57fe5b602002602001015160200151888381518110610be757fe5b6020026020010181905250828281518110610bfe57fe5b60200260200101516000015115610c75577fb4a7946c0772f99411b9461db61ae510087dfb48bc453a75b0b9915588f0c5cc8786158884600001518560200151888881518110610c4a57fe5b602002602001015160200151604051610c6896959493929190615789565b60405180910390a1610cd9565b7f66d25ad42aacf4cb4fd83716d3ee5ba48cddbe69bf2028b574a8510432c0afcb878783600001518460200151878781518110610cae57fe5b602002602001015160200151604051610ccb959493929190615860565b60405180910390a150610ce2565b50600101610b66565b50505050505094509492505050565b6001546040805160008082526020601f860181900481028301840184528201858152610d7193919291889190889088908190860183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506127c292505050565b50507f8bf30e7ff26833413be5f69e1d373744864d600b664204b4a2f9844a8eedb9ed81604051610da29190615712565b60405180910390a150505050565b60008060606020861415610dd157610dca86880188614844565b9150610df6565b6040861015610de457610983601e612661565b610df086880188614880565b90925090505b60828414610e0857610983600b612661565b606085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506020808601516040808801516060808a01519251999a509298909750931a94509250610e6e91869186918691016154c9565b6040516020818303038152906040529050606185015193506081850151925060a185015160001a91506060848484604051602001610eae939291906154c9565b60408051601f19818403018152919052600054909150610ede908990600b908a906001600160a01b031685612923565b610eec57610983600c612661565b610efc888363ffffffff612a2416565b6001600160a01b0316610f0d612595565b6001600160a01b031614610f2557610983600d612661565b506320c13b0b60e01b9c9b505050505050505050505050565b610fcd600187604051602001610f54919061562a565b60408051601f198184030181526020601f8901819004810284018101909252878352918991899089908190840183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b5050610fd8866126ef565b505050505050565b6000611028600c898989898960405160200161100095949392919061599e565b60408051601f19818403018152919052600054869086906001600160a01b0316610953612595565b98975050505050505050565b60408051600081526020601f8601819004810282018301835281018581526110b092600892918991899089908190860183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b50506e5280b515004b998a944630b6c663f86001600160a01b0316635014b4f46040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156110fc57600080fd5b505af1158015611110573d6000803e3d6000fd5b505050505050505050565b6111256000612b00565b565b600061113f60038460405160200161092a91906156d3565b9392505050565b60006111d960058989604051602001611160929190615947565b60408051601f198184030181526020601f8a01819004810284018101909252888352918a918a908a908190840183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506127c292505050565b50506103e788116111ee576109836003612661565b6001600160a01b038716611206576109836001612661565b6002805463ffffffff191663680a3423179055604051606090309063ab8ac8fd60e01b9061123a908c908c90602401615947565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611278919061550d565b6000604051808303816000865af19150503d80600081146112b5576040519150601f19603f3d011682016040523d82523d6000602084013e6112ba565b606091505b509092509050816112da576112d563a9059cbb60e01b612d9b565b6112f1565b808060200190516112ee91908101906147f6565b91505b50979650505050505050565b60006113268661130e888888613007565b600054869086906001600160a01b0316610953612595565b9695505050505050565b6000546001600160a01b031690565b600061135b600286868660405160200161092a93929190615661565b95945050505050565b6000611326600287878760405160200161100093929190615661565b600080fd5b60408051600081526020601f86018190048102820183018352810185815261140192600992918991899089908190860183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b50506e5280b515004b998a944630b6c663f86001600160a01b031663f02fedc46040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156110fc57600080fd5b600061146760068989604051602001611160929190615947565b505087611478576109836004612661565b6001600160a01b038716611490576109836001612661565b6110288789613198565b60008060606e26750c571ce882b17016557279adaa6001600160a01b03166040516114c4906155fd565b600060405180830381855afa9150503d80600081146114ff576040519150601f19603f3d011682016040523d82523d6000602084013e611504565b606091505b5091509150818015611517575080516020145b6115335760405162461bcd60e51b815260040161099c90615937565b8080602001905161154791908101906143c1565b9250505090565b600061156063680a342360e01b61327e565b600019831480156115a75761157560016132bf565b61159573a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488460006134c1565b61159e57600080fd5b60019150611650565b6115b260018561379f565b156116505760405163a9059cbb60e01b815273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063a9059cbb906115f09086908890600401615682565b602060405180830381600087803b15801561160a57600080fd5b505af115801561161e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061164291908101906147f6565b61164b57600080fd5b600191505b5092915050565b6111256001612b00565b600061167363baf260e160e01b61327e565b600019831480156116a85761168860006132bf565b611595736b175474e89094c44da98b954eedeac495271d0f8460006134c1565b6116b360008561379f565b156116505760405163a9059cbb60e01b8152736b175474e89094c44da98b954eedeac495271d0f9063a9059cbb906115f09086908890600401615682565b6000606061178c600c8d8d8d8d8d60405160200161171395949392919061599e565b60408051601f198184030181526020601f8b01819004810284018101909252898352918b918b908b908190840183828082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a90819084018382808284376000920191909152506127c292505050565b505066038d7ea4c67fff8b116117a657610983601f612661565b63b3461f2f60e01b600260006101000a81548163ffffffff021916908360e01c02179055506060306001600160a01b031663fbaf10e360e01b8e8e8e8e8e6040516024016117f895949392919061599e565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611836919061550d565b6000604051808303816000865af19150503d8060008114611873576040519150601f19603f3d011682016040523d82523d6000602084013e611878565b606091505b509093509050826118c65773421816cdfe2073945173c0c35799ec21261fb399600080516020615bb68339815191526118b0836138a1565b6040516118bd9190615916565b60405180910390a25b509a509a98505050505050505050565b6118ec600787604051602001610f54919061562a565b50506001600160a01b038616611906576109836005612661565b604051630916bbc360e31b81526e5280b515004b998a944630b6c663f8906348b5de189061193890899060040161562a565b600060405180830381600087803b15801561195257600080fd5b505af1158015611966573d6000803e3d6000fd5b50505050505050505050565b600061198c600a8989604051602001611160929190615947565b505066038d7ea4c67fff88116119a6576109836000612661565b6001600160a01b0387166119be576109836001612661565b6002805463ffffffff191663baf260e1179055604051606090309063ae0f1f3360e01b906119f2908c908c90602401615947565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611a30919061550d565b6000604051808303816000865af19150503d8060008114611a6d576040519150601f19603f3d011682016040523d82523d6000602084013e611a72565b606091505b509092509050816112da57736b175474e89094c44da98b954eedeac495271d0f600080516020615bb6833981519152611aab6002612661565b604051611ab89190615916565b60405180910390a26112f1565b303b15611ad157600080fd5b611ada816126ef565b611ae46000613a11565b15611b82576040516370a0823160e01b8152600090736b175474e89094c44da98b954eedeac495271d0f906370a0823190611b23903090600401615638565b60206040518083038186803b158015611b3b57600080fd5b505afa158015611b4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611b739190810190614862565b9050611b80600082613ba5565b505b611b8c6001613a11565b156109b6576040516370a0823160e01b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a0823190611bcb903090600401615638565b60206040518083038186803b158015611be357600080fd5b505afa158015611bf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611c1b9190810190614862565b9050611c28600182613ba5565b5050565b60006060611c398a61275d565b600080611ccf60028d8d8d604051602001611c5693929190615661565b60408051601f198184030181526020601f8d018190048102840181019092528b8352918d918d908d908190840183828082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c90819084018382808284376000920191909152506127c292505050565b915091508b6001600160a01b03168b8b604051611ced929190615500565b6000604051808303816000865af19150503d8060008114611d2a576040519150601f19603f3d011682016040523d82523d6000602084013e611d2f565b606091505b5090945092508315611d84577fb4a7946c0772f99411b9461db61ae510087dfb48bc453a75b0b9915588f0c5cc826000838f8f8f89604051611d779796959493929190615720565b60405180910390a1611dc6565b7f66d25ad42aacf4cb4fd83716d3ee5ba48cddbe69bf2028b574a8510432c0afcb82828e8e8e88604051611dbd96959493929190615811565b60405180910390a15b50509850989650505050505050565b60003373723b51b72ae89a3d0c2a2760f0458307a1baa19114611e0a5760405162461bcd60e51b815260040161099c90615927565b826001600160a01b031682604051611e21906155fd565b60006040518083038185875af1925050503d8060008114611e5e576040519150601f19603f3d011682016040523d82523d6000602084013e611e63565b606091505b50508091505080611e78573d6000803e3d6000fd5b92915050565b60015490565b6000806e5280b515004b998a944630b6c663f86001600160a01b031663a22947486040518163ffffffff1660e01b8152600401604080518083038186803b158015611ece57600080fd5b505afa158015611ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611f069190810190614814565b9150915081611f19576109836006612661565b336001600160a01b03821614611f33576109836007612661565b611f3d60006132bf565b611f4760016132bf565b611f67736b175474e89094c44da98b954eedeac495271d0f3360016134c1565b50611f8873a0b86991c6218b36c1d19d4a2e9eb0ce3606eb483360016134c1565b50611fa9735d3a536e4d6dbd6114cc1ead35777bab948e36433360016134c1565b50611fca7339aa39c021dfbae8fac545936693ac917d5e75633360016134c1565b50611fe66e1876eb1444c986fd502e618c5874303360016134c1565b506120026e8943c65caf789fffcf953be156f6f83360016134c1565b50478015612016576120143382613198565b505b6040517fe4355f8a8e7deececf128bcf29ced6b5cb7402a1851b6e435b057e0bd8101eac90600090a1505050565b600061205c60038560405160200161100091906156d3565b949350505050565b606061207663168d88b960e01b61327e565b815160408051828152602080840282010190915260009180156120b357816020015b6120a06140e8565b8152602001906001900390816120985790505b50915060005b835181101561219b57600060608583815181106120d257fe5b6020026020010151600001516001600160a01b03168684815181106120f357fe5b60200260200101516020015160405161210c919061550d565b6000604051808303816000865af19150503d8060008114612149576040519150601f19603f3d011682016040523d82523d6000602084013e61214e565b606091505b5091509150604051806040016040528083151581526020018281525085848151811061217657fe5b6020026020010181905250816121915760019350505061219b565b50506001016120b9565b5080156121ce576060826040516020016121b591906156c2565b6040516020818303038152906040529050805181602001fd5b50919050565b6040516370a0823160e01b8152600090736b175474e89094c44da98b954eedeac495271d0f906370a082319061220e903090600401615638565b60206040518083038186803b15801561222657600080fd5b505afa15801561223a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061225e9190810190614862565b9050801561233757604051636eb1769f60e11b8152600090736b175474e89094c44da98b954eedeac495271d0f9063dd62ed3e906122b19030906e1876eb1444c986fd502e618c58743090600401615646565b60206040518083038186803b1580156122c957600080fd5b505afa1580156122dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123019190810190614862565b90508181101561232a576123156000613a11565b1561232557612325600083613ba5565b612335565b612335600083613ba5565b505b6040516370a0823160e01b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a0823190612371903090600401615638565b60206040518083038186803b15801561238957600080fd5b505afa15801561239d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123c19190810190614862565b90508015611c2857604051636eb1769f60e11b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063dd62ed3e906124149030906e8943c65caf789fffcf953be156f6f890600401615646565b60206040518083038186803b15801561242c57600080fd5b505afa158015612440573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124649190810190614862565b90508181101561248d576124786001613a11565b1561248857612488600183613ba5565b612498565b612498600183613ba5565b505050565b600060606124b163b3461f2f60e01b61327e565b6040516390c6903760e01b815260009073421816cdfe2073945173c0c35799ec21261fb399906390c69037908a906124f3908b908b908b908b90600401615970565b6020604051808303818588803b15801561250c57600080fd5b505af1158015612520573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052506125459190810190614862565b905086811015612559576109836020612661565b612564600082613ba5565b509550959350505050565b600061135b85612580878787613007565b60015460005486906001600160a01b03166109535b60006f0d38df53b45c5733c7b34000de0bdf526001600160a01b03166382678dd66040518163ffffffff1660e01b815260040160206040518083038186803b1580156125e057600080fd5b505afa1580156125f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061261891908101906143c1565b905090565b600030600a848488888c8c60405160200161263f98979695949392919061543f565b6040516020818303038152906040528051906020012090509695505050505050565b6040516309ada4d560e21b8152606090739c0ccb765d3f5035f8b5dd30fe375d5f4997d8e4906326b693549061269b908590600401615712565b60006040518083038186803b1580156126b357600080fd5b505afa1580156126c7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611e789190810190614a10565b6001600160a01b03811661270757610983600e612661565b600080546001600160a01b0319166001600160a01b0383161790556040517f7083aac3cab97f1219cedd0ab328a5b138a10b0fc72dd9348f1dc50199b21fda9061275290839061562a565b60405180910390a150565b61276f816001600160a01b0316613d9e565b61277d57610983601a612661565b6001600160a01b03811630141561279857610983601b612661565b6001600160a01b0381166e5280b515004b998a944630b6c663f814156109b657610983601c612661565b60008084156127dd57845a10156127dd576109836013612661565b50600154600080546001600160a01b0316906127f7612595565b90506128078989858a868661261d565b9350600061281485613da4565b905060008a600e81111561282457fe5b1461289b57336001600160a01b0384161461285457612846818b8b868b612923565b612854576109836014612661565b336001600160a01b0383161461289657612874818763ffffffff612a2416565b6001600160a01b0316826001600160a01b031614612896576109836015612661565b61290c565b336001600160a01b038416148015906128bd5750336001600160a01b03831614155b1561290c576128d2818763ffffffff612a2416565b6001600160a01b0316826001600160a01b0316141580156128fd57506128fb818b8b868b612923565b155b1561290c576109836016612661565b505060018054810190555090969095509350505050565b6000612937836001600160a01b0316613d9e565b6129665761294b868363ffffffff612a2416565b6001600160a01b0316836001600160a01b031614905061135b565b606086868660405160200161297d939291906157e4565b60408051601f19818403018152908290526320c13b0b60e01b808352909250906001600160a01b038616906320c13b0b906129be90859088906004016158f1565b60206040518083038186803b1580156129d657600080fd5b505afa1580156129ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612a0e91908101906148c7565b6001600160e01b03191614979650505050505050565b60008151604114612a3757506000611e78565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612a7d5760009350505050611e78565b8060ff16601b14158015612a9557508060ff16601c14155b15612aa65760009350505050611e78565b60018682858560405160008152602001604052604051612ac994939291906158ae565b6020604051602081039080840390855afa158015612aeb573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60008080836003811115612b1057fe5b1415612b435750735d3a536e4d6dbd6114cc1ead35777bab948e364390506e1876eb1444c986fd502e618c587430612b6c565b507339aa39c021dfbae8fac545936693ac917d5e756390506e8943c65caf789fffcf953be156f6f85b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190612b9b903090600401615638565b60206040518083038186803b158015612bb357600080fd5b505afa158015612bc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612beb9190810190614862565b90508015612d9557604051636eb1769f60e11b815281906001600160a01b0385169063dd62ed3e90612c239030908790600401615646565b60206040518083038186803b158015612c3b57600080fd5b505afa158015612c4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612c739190810190614862565b1015612d095760405163095ea7b360e01b81526001600160a01b0384169063095ea7b390612ca990859060001990600401615682565b602060405180830381600087803b158015612cc357600080fd5b505af1158015612cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612cfb91908101906147f6565b612d09576109836017612661565b60405163d8da64f360e01b81526001600160a01b0383169063d8da64f390612d35908490600401615712565b602060405180830381600087803b158015612d4f57600080fd5b505af1158015612d63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d879190810190614862565b612d95576109836018612661565b50505050565b60606001600160e01b0319821663a9059cbb60e01b1415612ddb57506040805180820190915260088152673a3930b739b332b960c11b6020820152612dfb565b50604080518082019091526007815266617070726f766560c81b60208201525b60405163fe575a8760e01b815273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4890819063fe575a8790612e34903090600401615638565b60206040518083038186803b158015612e4c57600080fd5b505afa158015612e60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612e8491908101906147f6565b15612eee5773a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612ec791906155af565b60408051601f1981840301815290829052612ee191615916565b60405180910390a2612498565b806001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b158015612f2757600080fd5b505afa158015612f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612f5f91908101906147f6565b15612fa25773a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612ec79190615581565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612fe09190615608565b60408051601f1981840301815290829052612ffa91615916565b60405180910390a2505050565b606060008085600e81111561301857fe5b148061302f5750600185600e81111561302d57fe5b145b806130455750600a85600e81111561304357fe5b145b8061305b5750600585600e81111561305957fe5b145b806130715750600685600e81111561306f57fe5b145b806130875750600785600e81111561308557fe5b145b8061309d5750600885600e81111561309b57fe5b145b806130b35750600985600e8111156130b157fe5b145b9050806130c457610983601d612661565b600085600e8111156130d257fe5b14806130e95750600885600e8111156130e757fe5b145b806130ff5750600985600e8111156130fd57fe5b145b1561311a576040805160008152602081019091529150613190565b600185600e81111561312857fe5b148061313f5750600785600e81111561313d57fe5b145b1561316b5782604051602001613155919061562a565b6040516020818303038152906040529150613190565b838360405160200161317e929190615947565b60405160208183030381529060405291505b509392505050565b6000826001600160a01b0316611387836040516131b4906155fd565b600060405180830381858888f193505050503d80600081146131f2576040519150601f19603f3d011682016040523d82523d6000602084013e6131f7565b606091505b5050809150508061323f57826001600160a01b0316600080516020615bb68339815191526132256012612661565b6040516132329190615916565b60405180910390a2611e78565b7f7b41af3b6a6a16e290821a297090842bafd82f6da2d087a54b277aeef6f386da8284604051613270929190615955565b60405180910390a192915050565b33301415806132a0575060025460e01b6001600160e01b031990811690821614155b156132af576109836019612661565b506002805463ffffffff19169055565b6000808260038111156132ce57fe5b146132e8576e8943c65caf789fffcf953be156f6f86132f9565b6e1876eb1444c986fd502e618c5874305b60405190915060009081906060906001600160a01b038516906370a0823160e01b9061332990309060240161562a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613367919061550d565b6000604051808303816000865af19150503d80600081146133a4576040519150601f19603f3d011682016040523d82523d6000602084013e6133a9565b606091505b50909250905060008280156133bf575081516020145b156133df57818060200190516133d89190810190614862565b90506133f4565b6133f2866370a0823160e01b8585613dd4565b505b8015610fd8576040516001600160a01b0386169063db006a7560e01b9061341f908490602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161345d919061550d565b6000604051808303816000865af19150503d806000811461349a576040519150601f19603f3d011682016040523d82523d6000602084013e61349f565b606091505b5090935091506134b88663db006a7560e01b8585613dd4565b50505050505050565b60008060018361354e576040516370a0823160e01b81526001600160a01b038716906370a08231906134f7903090600401615638565b60206040518083038186803b15801561350f57600080fd5b505afa158015613523573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506135479190810190614862565b9150613640565b60006060876001600160a01b031660025a8161356657fe5b604051919004906370a0823160e01b9061358490309060240161562a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516135c2919061550d565b60006040518083038160008787f1925050503d8060008114613600576040519150601f19603f3d011682016040523d82523d6000602084013e613605565b606091505b5091509150818015613618575080516020145b1561363857808060200190516136319190810190614862565b935061363d565b600092505b50505b811561379257836136d25760405163a9059cbb60e01b81526001600160a01b0387169063a9059cbb906136799088908690600401615682565b602060405180830381600087803b15801561369357600080fd5b505af11580156136a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506136cb91908101906147f6565b925061378d565b856001600160a01b031660025a816136e657fe5b6040519190049063a9059cbb60e01b906137069089908790602401615682565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613744919061550d565b60006040518083038160008787f1925050503d8060008114613782576040519150601f19603f3d011682016040523d82523d6000602084013e613787565b606091505b50909350505b613796565b8092505b50509392505050565b600080808460038111156137af57fe5b146137c9576e8943c65caf789fffcf953be156f6f86137da565b6e1876eb1444c986fd502e618c5874305b6040519091506000906060906001600160a01b0384169063852a12e360e01b90613808908890602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613846919061550d565b6000604051808303816000865af19150503d8060008114613883576040519150601f19603f3d011682016040523d82523d6000602084013e613888565b606091505b5090925090506113268663852a12e360e01b8484613dd4565b6060604482511180156138d357508151600160fb1b9083906000906138c257fe5b01602001516001600160f81b031916145b80156139005750815160c360f81b90839060019081106138ef57fe5b01602001516001600160f81b031916145b801561392d57508151607960f81b908390600290811061391c57fe5b01602001516001600160f81b031916145b801561395a57508151600560fd1b908390600390811061394957fe5b01602001516001600160f81b031916145b15613a0157606060048351036040519080825280601f01601f191660200182016040528015613990576020820181803883390190505b50905060045b83518110156139e4578381815181106139ab57fe5b602001015160f81c60f81b8260048303815181106139c557fe5b60200101906001600160f81b031916908160001a905350600101613996565b50808060200190516139f99190810190614a10565b915050613a0c565b611e78600019612661565b919050565b6000808080846003811115613a2257fe5b1415613a555750736b175474e89094c44da98b954eedeac495271d0f90506e1876eb1444c986fd502e618c587430613a7e565b5073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4890506e8943c65caf789fffcf953be156f6f85b6040516001600160a01b0383169063095ea7b360e01b90613aa790849060001990602401615682565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613ae5919061550d565b6000604051808303816000865af19150503d8060008114613b22576040519150601f19603f3d011682016040523d82523d6000602084013e613b27565b606091505b50508093505082613b9e576000846003811115613b4057fe5b1415613b8e57736b175474e89094c44da98b954eedeac495271d0f600080516020615bb6833981519152613b746011612661565b604051613b819190615916565b60405180910390a2613b9e565b613b9e63095ea7b360e01b612d9b565b5050919050565b6000826003811115613bb357fe5b148015613bc6575066038d7ea4c67fff81115b80613c9857506001826003811115613bda57fe5b148015613c9857506103e781118015613c98575060405163023aa9ab60e61b815273c5c0ead7df3cefc45c8f4592e3a0f1500949e75d90638eaa6ac090613c45907f596746115f08448433597980d42b4541c0197187d07ffad9c7f66a471c49dbba90600401615712565b60206040518083038186803b158015613c5d57600080fd5b505afa158015613c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613c959190810190614862565b15155b15611c2857600080836003811115613cac57fe5b14613cc6576e8943c65caf789fffcf953be156f6f8613cd7565b6e1876eb1444c986fd502e618c5874305b6040519091506000906060906001600160a01b0384169063140e25ad60e31b90613d05908790602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613d43919061550d565b6000604051808303816000865af19150503d8060008114613d80576040519150601f19603f3d011682016040523d82523d6000602084013e613d85565b606091505b509092509050610fd88563140e25ad60e31b8484613dd4565b3b151590565b600081604051602001613db791906155c6565b604051602081830303815290604052805190602001209050919050565b60008215613ee657815160201415613e7a57600082806020019051613dfc9190810190614862565b90508015613e0d5760019150613e74565b6000606080613e1c8989613f64565b925092509250826001600160a01b0316600080516020615bb68339815191528383604051602001613e4e929190615598565b60408051601f1981840301815290829052613e6891615916565b60405180910390a25050505b50613ee1565b6000606080613e898888613f64565b925092509250826001600160a01b0316600080516020615bb68339815191528383604051602001613ebb929190615519565b60408051601f1981840301815290829052613ed591615916565b60405180910390a25050505b61205c565b6000606080613ef58888613f64565b9250925092506060613f06866138a1565b9050836001600160a01b0316600080516020615bb6833981519152848484604051602001613f3693929190615547565b60408051601f1981840301815290829052613f5091615916565b60405180910390a250505050949350505050565b600060608082856003811115613f7657fe5b1415613fb8576e1876eb1444c986fd502e618c58743092506040518060400160405280600a815260200169446861726d612044616960b01b8152509150613ff5565b6e8943c65caf789fffcf953be156f6f892506040518060400160405280600f81526020016e223430b936b0902aa9a21021b7b4b760891b81525091505b6001600160e01b0319841663140e25ad60e31b141561402f57506040805180820190915260048152631b5a5b9d60e21b60208201526140e1565b6001600160e01b031984166370a0823160e01b141561406e57506040805180820190915260098152683130b630b731b2a7b360b91b60208201526140e1565b6001600160e01b0319841663db006a7560e01b146140ae576040518060400160405280600a815260200169556e6465726c79696e6760b01b8152506140bf565b604051806020016040528060008152505b6040516020016140cf91906155e6565b60405160208183030381529060405290505b9250925092565b60408051808201909152600081526060602082015290565b8035611e7881615b79565b8051611e7881615b79565b600082601f83011261412757600080fd5b815161413a61413582615a4e565b615a28565b81815260209384019390925082018360005b83811015614178578151860161416288826142f3565b845250602092830192919091019060010161414c565b5050505092915050565b600082601f83011261419357600080fd5b81356141a161413582615a4e565b81815260209384019390925082018360005b8381101561417857813586016141c98882614351565b84525060209283019291909101906001016141b3565b8051611e7881615b8d565b8035611e7881615b96565b8051611e7881615b96565b8051611e7881615b9f565b60008083601f84011261421d57600080fd5b5081356001600160401b0381111561423457600080fd5b60208301915083600182028301111561424c57600080fd5b9250929050565b600082601f83011261426457600080fd5b813561427261413582615a6e565b9150808252602083016020830185838301111561428e57600080fd5b614299838284615b05565b50505092915050565b600082601f8301126142b357600080fd5b81516142c161413582615a6e565b915080825260208301602083018583830111156142dd57600080fd5b614299838284615b11565b8035611e7881615ba8565b60006040828403121561430557600080fd5b61430f6040615a28565b9050600061431d84846141df565b82525060208201516001600160401b0381111561433957600080fd5b614345848285016142a2565b60208301525092915050565b60006040828403121561436357600080fd5b61436d6040615a28565b9050600061437b8484614100565b82525060208201356001600160401b0381111561439757600080fd5b61434584828501614253565b6000602082840312156143b557600080fd5b600061205c8484614100565b6000602082840312156143d357600080fd5b600061205c848461410b565b600080604083850312156143f257600080fd5b60006143fe8585614100565b925050602061440f858286016141ea565b9150509250929050565b6000806000806060858703121561442f57600080fd5b600061443b8787614100565b94505060208501356001600160401b0381111561445757600080fd5b6144638782880161420b565b93509350506040614476878288016141ea565b91505092959194509250565b60008060008060008060008060a0898b03121561449e57600080fd5b60006144aa8b8b614100565b98505060208901356001600160401b038111156144c657600080fd5b6144d28b828c0161420b565b975097505060406144e58b828c016141ea565b95505060608901356001600160401b0381111561450157600080fd5b61450d8b828c0161420b565b945094505060808901356001600160401b0381111561452b57600080fd5b6145378b828c0161420b565b92509250509295985092959890939650565b60008060008060006080868803121561456157600080fd5b600061456d8888614100565b95505060208601356001600160401b0381111561458957600080fd5b6145958882890161420b565b945094505060406145a8888289016141ea565b92505060606145b9888289016141ea565b9150509295509295909350565b600080600080600080608087890312156145df57600080fd5b60006145eb8989614100565b96505060206145fc89828a016141ea565b95505060408701356001600160401b0381111561461857600080fd5b61462489828a0161420b565b945094505060608701356001600160401b0381111561464257600080fd5b61464e89828a0161420b565b92509250509295509295509295565b60006020828403121561466f57600080fd5b81516001600160401b0381111561468557600080fd5b61205c84828501614116565b6000602082840312156146a357600080fd5b81356001600160401b038111156146b957600080fd5b61205c84828501614182565b600080604083850312156146d857600080fd5b82356001600160401b038111156146ee57600080fd5b6143fe85828601614182565b6000806000806080858703121561471057600080fd5b84356001600160401b0381111561472657600080fd5b61473287828801614182565b9450506020614743878288016141ea565b93505060408501356001600160401b0381111561475f57600080fd5b61476b87828801614253565b92505060608501356001600160401b0381111561478757600080fd5b61447687828801614253565b6000806000606084860312156147a857600080fd5b83356001600160401b038111156147be57600080fd5b6147ca86828701614182565b93505060206147db868287016141ea565b92505060406147ec868287016141ea565b9150509250925092565b60006020828403121561480857600080fd5b600061205c84846141df565b6000806040838503121561482757600080fd5b600061483385856141df565b925050602061440f8582860161410b565b60006020828403121561485657600080fd5b600061205c84846141ea565b60006020828403121561487457600080fd5b600061205c84846141f5565b6000806040838503121561489357600080fd5b600061489f85856141ea565b92505060208301356001600160401b038111156148bb57600080fd5b61440f85828601614253565b6000602082840312156148d957600080fd5b600061205c8484614200565b600080600080604085870312156148fb57600080fd5b84356001600160401b0381111561491157600080fd5b61491d8782880161420b565b945094505060208501356001600160401b0381111561493b57600080fd5b6149478782880161420b565b95989497509550505050565b6000806000806080858703121561496957600080fd5b600061497587876142e8565b9450506020614986878288016141ea565b935050604061499787828801614100565b9250506060614476878288016141ea565b600080600080600060a086880312156149c057600080fd5b60006149cc88886142e8565b95505060206149dd888289016141ea565b94505060406149ee88828901614100565b93505060606149ff888289016141ea565b92505060806145b9888289016141ea565b600060208284031215614a2257600080fd5b81516001600160401b03811115614a3857600080fd5b61205c848285016142a2565b60008060408385031215614a5757600080fd5b6000614a6385856141ea565b925050602061440f85828601614100565b600080600080600080600060a0888a031215614a8f57600080fd5b6000614a9b8a8a6141ea565b9750506020614aac8a828b01614100565b9650506040614abd8a828b016141ea565b95505060608801356001600160401b03811115614ad957600080fd5b614ae58a828b0161420b565b945094505060808801356001600160401b03811115614b0357600080fd5b614b0f8a828b0161420b565b925092505092959891949750929550565b600080600060408486031215614b3557600080fd5b6000614b4186866141ea565b93505060208401356001600160401b03811115614b5d57600080fd5b614b698682870161420b565b92509250509250925092565b600080600080600060608688031215614b8d57600080fd5b6000614b9988886141ea565b95505060208601356001600160401b03811115614bb557600080fd5b614bc18882890161420b565b945094505060408601356001600160401b03811115614bdf57600080fd5b614beb8882890161420b565b92509250509295509295909350565b600080600080600060808688031215614c1257600080fd5b6000614c1e88886141ea565b9550506020614c2f888289016141ea565b9450506040614c4088828901614100565b93505060608601356001600160401b03811115614bdf57600080fd5b60008060008060008060a08789031215614c7557600080fd5b6000614c8189896141ea565b9650506020614c9289828a016141ea565b9550506040614ca389828a01614100565b94505060608701356001600160401b03811115614cbf57600080fd5b614ccb89828a0161420b565b93509350506080614cde89828a016141ea565b9150509295509295509295565b60008060008060008060008060008060e08b8d031215614d0a57600080fd5b6000614d168d8d6141ea565b9a50506020614d278d828e016141ea565b9950506040614d388d828e01614100565b98505060608b01356001600160401b03811115614d5457600080fd5b614d608d828e0161420b565b97509750506080614d738d828e016141ea565b95505060a08b01356001600160401b03811115614d8f57600080fd5b614d9b8d828e0161420b565b945094505060c08b01356001600160401b03811115614db957600080fd5b614dc58d828e0161420b565b92509250509295989b9194979a5092959850565b600080600080600080600060c0888a031215614df457600080fd5b6000614e008a8a6141ea565b9750506020614e118a828b016141ea565b9650506040614e228a828b01614100565b95505060608801356001600160401b03811115614e3e57600080fd5b614e4a8a828b0161420b565b94509450506080614e5d8a828b016141ea565b92505060a0614e6e8a828b016141ea565b91505092959891949750929550565b6000614e898383615067565b505060200190565b600061113f83836150de565b600061113f83836153ea565b600061113f8383615416565b614ebe81615ae4565b82525050565b614ebe81615aa8565b614ebe614ed982615aa8565b615b3d565b6000614ee982615a9b565b614ef38185615a9f565b9350614efe83615a95565b8060005b83811015614f2c578151614f168882614e7d565b9750614f2183615a95565b925050600101614f02565b509495945050505050565b6000614f4282615a9b565b614f4c8185615a9f565b935083602082028501614f5e85615a95565b8060005b85811015614f985784840389528151614f7b8582614e91565b9450614f8683615a95565b60209a909a0199925050600101614f62565b5091979650505050505050565b6000614fb082615a9b565b614fba8185615a9f565b935083602082028501614fcc85615a95565b8060005b85811015614f985784840389528151614fe98582614e9d565b9450614ff483615a95565b60209a909a0199925050600101614fd0565b600061501182615a9b565b61501b8185615a9f565b93508360208202850161502d85615a95565b8060005b85811015614f98578484038952815161504a8582614ea9565b945061505583615a95565b60209a909a0199925050600101615031565b614ebe81615ab3565b614ebe81615ab8565b614ebe61508582615ab8565b615ab8565b614ebe81615abb565b600061509f8385615a9f565b93506150ac838584615b05565b6150b583615b59565b9093019392505050565b60006150cb8385613a0c565b93506150d8838584615b05565b50500190565b60006150e982615a9b565b6150f38185615a9f565b9350615103818560208601615b11565b6150b581615b59565b600061511782615a9b565b6151218185613a0c565b9350615131818560208601615b11565b9290920192915050565b614ebe81615aef565b614ebe61515082615aef565b615b4e565b6000615162601c83613a0c565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c0192915050565b600061519b601783613a0c565b7f20676176652062616420646174612063616c6c696e6720000000000000000000815260170192915050565b60006151d4601283613a0c565b710103932bb32b93a32b21031b0b63634b733960751b815260120192915050565b6000615202600683613a0c565b6572656465656d60d01b815260060192915050565b6000615224602c83613a0c565b7f206661696c6564202d205553444320636f6e747261637420697320637572726581526b373a363c903830bab9b2b21760a11b6020820152602c0192915050565b6000615272600183613a0c565b601760f91b815260010192915050565b600061528f602583615a9f565b7f4574686572697a65643a206f6e6c792063616c6c61626c6520627920457468658152643934bd32b960d91b602082015260400192915050565b60006152d6601783615a9f565b7f496e76616c696420696d706c656d656e746174696f6e2e000000000000000000815260200192915050565b6000611e78600083613a0c565b600061531c600283613a0c565b6101d160f51b815260020192915050565b600061533a601a83613a0c565b7f5553444320636f6e7472616374207265766572746564206f6e200000000000008152601a0192915050565b6000615373601883613a0c565b7f2067617665206e6f20746f6b656e732063616c6c696e67200000000000000000815260180192915050565b60006153ac602983613a0c565b7f206661696c6564202d20555344432068617320626c61636b6c697374656420748152683434b9903ab9b2b91760b91b602082015260290192915050565b805160009060408401906153fe8582615067565b506020830151848203602086015261135b82826150de565b805160009060408401906153fe8582614ec4565b614ebe81615ade565b614ebe61515082615ade565b600061544b828b614ecd565b60148201915061545b828a615079565b60208201915061546b8289614ecd565b60148201915061547b8288614ecd565b60148201915061548b8287615079565b60208201915061549b8286615079565b6020820191506154ab8285615144565b6001820191506154bb828461510c565b9a9950505050505050505050565b60006154d58286615079565b6020820191506154e58285615079565b6020820191506154f58284615433565b506001019392505050565b600061205c8284866150bf565b600061113f828461510c565b6000615525828561510c565b91506155308261518e565b915061553c828461510c565b915061205c82615265565b6000615553828661510c565b915061555e826151c7565b915061556a828561510c565b91506155758261530f565b915061135b828461510c565b600061558d828461510c565b915061113f82615217565b60006155a4828561510c565b915061553082615366565b60006155bb828461510c565b915061113f8261539f565b60006155d182615155565b91506155dd8284615079565b50602001919050565b60006155f1826151f5565b915061113f828461510c565b6000611e7882615302565b60006156138261532d565b915061561f828461510c565b915061113f82615265565b60208101611e788284614ec4565b60208101611e788284614eb5565b604081016156548285614eb5565b61113f6020830184614ec4565b6040810161566f8286614ec4565b818103602083015261135b818486615093565b604081016156908285614ec4565b61113f6020830184615070565b604080825281016156ae8185614ede565b9050818103602083015261205c8184614f37565b6020808252810161113f8184614fa5565b6020808252810161113f8184615006565b60208101611e788284615067565b604081016157008285615067565b818103602083015261205c81846150de565b60208101611e788284615070565b60c0810161572e828a615070565b61573b6020830189615067565b6157486040830188615070565b6157556060830187614ec4565b8181036080830152615768818587615093565b905081810360a083015261577c81846150de565b9998505050505050505050565b60c081016157978289615070565b6157a46020830188615067565b6157b16040830187615070565b6157be6060830186614ec4565b81810360808301526157d081856150de565b905081810360a083015261102881846150de565b606081016157f28286615070565b6157ff602083018561513b565b818103604083015261135b81846150de565b60a0810161581f8289615070565b61582c6020830188615070565b6158396040830187614ec4565b818103606083015261584c818587615093565b9050818103608083015261102881846150de565b60a0810161586e8288615070565b61587b6020830187615070565b6158886040830186614ec4565b818103606083015261589a81856150de565b9050818103608083015261095881846150de565b608081016158bc8287615070565b6158c9602083018661542a565b6158d66040830185615070565b61135b6060830184615070565b60208101611e78828461508a565b6040808252810161590281856150de565b9050818103602083015261205c81846150de565b6020808252810161113f81846150de565b60208082528101611e7881615282565b60208082528101611e78816152c9565b604081016156548285615070565b604081016159638285615070565b61113f6020830184614eb5565b6060810161597e8287615070565b61598b6020830186614ec4565b8181036040830152611326818486615093565b608081016159ac8288615070565b6159b96020830187615070565b6159c66040830186614ec4565b8181036060830152610958818486615093565b60c081016159e78289615070565b6159f46020830188615070565b615a016040830187615070565b615a0e6060830186615070565b615a1b6080830185615070565b61095860a0830184615070565b6040518181016001600160401b0381118282101715615a4657600080fd5b604052919050565b60006001600160401b03821115615a6457600080fd5b5060209081020190565b60006001600160401b03821115615a8457600080fd5b506020601f91909101601f19160190565b60200190565b5190565b90815260200190565b6000611e7882615ad2565b151590565b90565b6001600160e01b03191690565b80613a0c81615b6f565b6001600160a01b031690565b60ff1690565b6000611e7882615afa565b6000611e7882615ac8565b6000611e7882615aa8565b82818337506000910152565b60005b83811015615b2c578181015183820152602001615b14565b83811115612d955750506000910152565b6000611e78826000611e7882615b69565b6000611e7882615b63565b601f01601f191690565b60f81b90565b60601b90565b600f81106109b657fe5b615b8281615aa8565b81146109b657600080fd5b615b8281615ab3565b615b8281615ab8565b615b8281615abb565b600f81106109b657600080fdfe5bbd5ab79029b89a22c80c7b7bfdc2f0c8e3f0d2a7330c7148cabc044250674ba365627a7a723158209ecdeb27b72609ca0e8ec110d047738b99f3d520bc3127dbe5ffeebe65dc25946c6578706572696d656e74616cf564736f6c63430005110040

Deployed Bytecode Sourcemap

12298:103506:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56512:572;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56512:572:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;66103:535;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;66103:535:0;;;;;;;;:::i;:::-;;;;;;;;54442:443;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;54442:443:0;;;;;;;;:::i;72317:113::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;72317:113:0;;;:::i;74739:3035::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;74739:3035:0;;;;;;;;:::i;:::-;;;;;;;;;35535:508;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;35535:508:0;;;;;;;;:::i;69751:1846::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;69751:1846:0;;;;;;;;:::i;:::-;;;;;;;;40611:572;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;40611:572:0;;;;;;;;:::i;68046:550::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;68046:550:0;;;;;;;;:::i;44587:534::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;44587:534:0;;;;;;;;:::i;55426:89::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;55426:89:0;;;:::i;81127:426::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;81127:426:0;;;;;;;;:::i;28948:1747::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;28948:1747:0;;;;;;;;:::i;:::-;;;;;;;;61320:501;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;61320:501:0;;;;;;;;:::i;57245:121::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57245:121:0;;;:::i;:::-;;;;;;;;62828:426;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;62828:426:0;;;;;;;;:::i;64332:441::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;64332:441:0;;;;;;;;:::i;54953:57::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;54953:57:0;;;:::i;46341:559::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;46341:559:0;;;;;;;;:::i;33713:882::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;33713:882:0;;;;;;;;:::i;71826:335::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;71826:335:0;;;:::i;31521:985::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;31521:985:0;;;;;;;;:::i;55800:92::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;55800:92:0;;;:::i;25705:988::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;25705:988:0;;;;;;;;:::i;48771:1679::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;48771:1679:0;;;;;;;;:::i;:::-;;;;;;;;;42656:703;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;42656:703:0;;;;;;;;:::i;23132:1740::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;23132:1740:0;;;;;;;;:::i;17714:1049::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;17714:1049:0;;;;;;;;:::i;37701:1638::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;37701:1638:0;;;;;;;;:::i;10651:389::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;10651:389:0;;;;;;;;:::i;57616:85::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57616:85:0;;;:::i;52145:1779::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52145:1779:0;;;:::i;82935:441::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;82935:441:0;;;;;;;;:::i;78765:1051::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;78765:1051:0;;;;;;;;:::i;:::-;;;;;;;;19180:1677;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19180:1677:0;;;:::i;50458:855::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;50458:855:0;;;;;;;;:::i;59258:486::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;59258:486:0;;;;;;;;:::i;56512:572::-;56564:18;56589:19;56615:20;56642:32;56681:34;56722:36;15087:42;-1:-1:-1;;;;;56804:14:0;;56827:4;56804:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56804:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56804:29:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;56804:29:0;;;;;;;;;56854:30;;-1:-1:-1;;;56854:30:0;;56791:42;;-1:-1:-1;15214:42:0;;56854:15;;:30;;56878:4;;56854:30;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56854:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56854:30:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;56854:30:0;;;;;;;;;56961:40;;-1:-1:-1;;;56961:40:0;;56840:44;;-1:-1:-1;56906:21:0;;-1:-1:-1;14831:42:0;;56961:25;;:40;;56995:4;;56961:40;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56961:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56961:40:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;56961:40:0;;;;;;;;;57037:41;;-1:-1:-1;;;57037:41:0;;56934:67;;-1:-1:-1;14961:42:0;;57037:26;;:41;;57072:4;;57037:41;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57037:41:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;57037:41:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;57037:41:0;;;;;;;;;57008:70;;56512:572;;;;;;:::o;66103:535::-;66302:16;66418:214;66439:25;66484:11;66497:18;66517:6;66525:4;;66473:57;;;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;66473:57:0;;;66539:6;;66579:15;;66554:16;;-1:-1:-1;;;;;66579:15:0;66603:22;:20;:22::i;:::-;66418:12;:214::i;:::-;66407:225;66103:535;-1:-1:-1;;;;;;;66103:535:0:o;54442:443::-;54581:10;14296:42;54581:39;54577:86;;54638:16;54652:1;54638:13;:16::i;:::-;54631:24;;-1:-1:-1;;;54631:24:0;;;;;;;;;;;;;;;;;54577:86;54752:6;:8;;;;;;54842:37;54861:17;54842:18;:37::i;:::-;54442:443;:::o;72317:113::-;13842:2;;72317:113::o;74739:3035::-;74928:16;;75063:9;75058:102;75082:5;:12;75078:1;:16;75058:102;;;75110:42;75140:5;75146:1;75140:8;;;;;;;;;;;;;;:11;;;75110:29;:42::i;:::-;75096:3;;75058:102;;;;75249:16;75267:13;75284:174;75325:29;75374:5;75363:17;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;75363:17:0;;;75389:16;75414:13;75436:15;75284:32;:174::i;:::-;75248:210;;;;75887:5;:12;75876:24;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;75876:24:0;;75871:29;;75932:5;:12;75920:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;76034:16:0;:66;;-1:-1:-1;;76034:66:0;76053:47;76034:66;;;76334:103;;75907:38;;-1:-1:-1;76034:16:0;;76276:27;;76315:4;;-1:-1:-1;;;76367:54:0;76334:103;;76423:5;;76334:103;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;76334:103:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;76334:103:0;;;179:29:-1;;;;160:49;;;76307:137:0;;;;76334:103;76307:137;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;76258:186:0;;;;76535:31;76580:14;76569:42;;;;;;;;;;;;;;76535:76;-1:-1:-1;76623:9:0;76618:1151;76642:11;:18;76638:1;:22;76618:1151;;;76676:23;;:::i;:::-;76702:5;76708:1;76702:8;;;;;;;;;;;;;;76676:34;;76805:11;76817:1;76805:14;;;;;;;;;;;;;;:17;;;76797:2;76800:1;76797:5;;;;;;;;;;;;;:25;;;;;;;;;;;76847:11;76859:1;76847:14;;;;;;;;;;;;;;:25;;;76831:10;76842:1;76831:13;;;;;;;;;;;;;:41;;;;76969:11;76981:1;76969:14;;;;;;;;;;;;;;:17;;;76965:797;;;77084:237;77108:8;77130:10;77129:11;77211:5;77229:11;:14;;;77256:11;:16;;;77285:11;77297:1;77285:14;;;;;;;;;;;;;;:25;;;77084:237;;;;;;;;;;;;;;;;;;;;76965:797;;;77490:163;77514:8;77535:5;77553:11;:14;;;77580:11;:16;;;77616:11;77628:1;77616:14;;;;;;;;;;;;;;:25;;;77490:163;;;;;;;;;;;;;;;;;;;77747:5;;;76965:797;-1:-1:-1;76662:3:0;;76618:1151;;;;74739:3035;;;;;;;;;;;;:::o;35535:508::-;35689:6;;35853:12;;;35665:21;6:49:-1;;;35853:12:0;35786:147;;;;;;;;;;;;;;35853:12;;35786:147;;;;;35665:21;;35853:12;35874:16;;35853:12;35899:9;;;;;;35786:147;;35899:9;;;;35786:147;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;35786:147:0;;;;137:4:-1;35786:147:0;;;;;;;;;;;;;;;;;;-1:-1:-1;35917:9:0;;-1:-1:-1;35917:9:0;;;;35786:147;;35917:9;;;;35786:147;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;35786:32:0;;-1:-1:-1;;;35786:147:0:i;:::-;;;36016:21;36023:13;36016:21;;;;;;;;;;;;;;;35535:508;;;;:::o;69751:1846::-;69858:17;;69984:20;70032:2;70017:17;;70013:229;;;70054:27;;;;70065:4;70054:27;;;70045:36;;70013:229;;;70122:2;70108:16;;70104:68;;;70144:17;70158:2;70144:13;:17::i;70104:68::-;70200:34;;;;70211:4;70200:34;;;70180:54;;-1:-1:-1;70180:54:0;-1:-1:-1;70013:229:0;70356:3;70335:24;;70331:72;;70377:17;70391:2;70377:13;:17::i;70331:72::-;70409:31;70443:10;;70409:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;-1:-1;70559:4:0;70535:29;;;70529:36;70608:4;70584:29;;;70578:36;70665:4;70641:29;;;70635:36;70716:25;;70409:44;;-1:-1:-1;70529:36:0;;70578;;-1:-1:-1;70627:45:0;;;-1:-1:-1;70665:4:0;-1:-1:-1;70716:25:0;;70529:36;;70578;;70627:45;;70716:25;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;70716:25:0;;;70685:56;;70803:4;70783:18;70779:29;70773:36;70768:41;;70852:4;70832:18;70828:29;70822:36;70817:41;;70909:4;70889:18;70885:29;70879:36;70876:1;70871:45;70866:50;;70929:26;70975:1;70978;70981;70958:25;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;70958:25:0;;;71197:15;;70958:25;;-1:-1:-1;71086:159:0;;71119:6;;71136:32;;71179:7;;-1:-1:-1;;;;;71197:15:0;70958:25;71086:22;:159::i;:::-;71073:222;;71269:17;71283:2;71269:13;:17::i;71073:222::-;71413:31;:6;71428:15;71413:31;:14;:31;:::i;:::-;-1:-1:-1;;;;;71387:57:0;:22;:20;:22::i;:::-;-1:-1:-1;;;;;71387:57:0;;71383:105;;71462:17;71476:2;71462:13;:17::i;71383:105::-;-1:-1:-1;;;;16620:18:0;69751:1846;-1:-1:-1;;;;;;;;;;;;69751:1846:0:o;40611:572::-;40871:182;40912:28;40960:14;40949:26;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;49:4;40871:182:0;;;;;;;;;;;;;;;;;;40949:26;40984:16;;41009:13;;;;;;40871:182;;41009:13;;;;40871:182;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;40871:182:0;;;;137:4:-1;40871:182:0;;;;;;;;;;;;;;;;;;-1:-1:-1;41031:15:0;;-1:-1:-1;41031:15:0;;;;40871:182;;41031:15;;;;40871:182;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;40871:32:0;;-1:-1:-1;;;40871:182:0:i;:::-;;;41143:34;41162:14;41143:18;:34::i;:::-;40611:572;;;;;;:::o;68046:550::-;68261:16;68377:213;68398:25;68443:11;68456:18;68476:6;68484:4;;68432:57;;;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;68432:57:0;;;68537:15;;68498:5;;68512:16;;-1:-1:-1;;;;;68537:15:0;68561:22;:20;:22::i;68377:213::-;68366:224;68046:550;-1:-1:-1;;;;;;;;68046:550:0:o;44587:534::-;44896:12;;;26:21:-1;6:49;;44896:12:0;44818:168;;;;;;;;;;;;;;44896:12;;44818:168;;;;;44859:28;;44896:12;44917:16;;44942:13;;;;;;44818:168;;44942:13;;;;44818:168;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;44818:168:0;;;;137:4:-1;44818:168:0;;;;;;;;;;;;;;;;;;-1:-1:-1;44964:15:0;;-1:-1:-1;44964:15:0;;;;44818:168;;44964:15;;;;44818:168;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;44818:32:0;;-1:-1:-1;;;44818:168:0:i;:::-;;;14631:42;-1:-1:-1;;;;;45073:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45073:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;45073:42:0;;;;44587:534;;;;;:::o;55426:89::-;55472:37;55495:13;55472:22;:37::i;:::-;55426:89::o;81127:426::-;81253:16;81369:178;81390:29;81439:5;81428:17;;;;;;;;;81369:178;81358:189;81127:426;-1:-1:-1;;;81127:426:0:o;28948:1747::-;29141:7;29237:182;29278:25;29323:6;29331:9;29312:29;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;49:4;29237:182:0;;;;;;;;;;;;;;;;;;29312:29;29350:16;;29375:13;;;;;;29237:182;;29375:13;;;;29237:182;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;29237:182:0;;;;137:4:-1;29237:182:0;;;;;;;;;;;;;;;;;;-1:-1:-1;29397:15:0;;-1:-1:-1;29397:15:0;;;;29237:182;;29397:15;;;;29237:182;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;29237:32:0;;-1:-1:-1;;;29237:182:0:i;:::-;;;16856:3;29504:6;:37;29500:84;;29559:16;29573:1;29559:13;:16::i;29500:84::-;-1:-1:-1;;;;;29656:23:0;;29652:70;;29697:16;29711:1;29697:13;:16::i;29652:70::-;29802:16;:45;;-1:-1:-1;;29802:45:0;29821:26;29802:45;;;30298:90;;30230:23;;30287:4;;-1:-1:-1;;;30329:33:0;30298:90;;30364:6;;30372:9;;30298:90;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;30298:90:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;30298:90:0;;;179:29:-1;;;;160:49;;;30279:110:0;;;;30298:90;30279:110;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;30260:129:0;;-1:-1:-1;30260:129:0;-1:-1:-1;30260:129:0;30396:294;;30491:58;-1:-1:-1;;;30491:33:0;:58::i;:::-;30396:294;;;30663:10;30652:30;;;;;;;;;;;;;;30647:35;;30396:294;28948:1747;;;;;;;;;;:::o;61320:501::-;61495:16;61611:204;61632:6;61647:67;61688:6;61696;61704:9;61647:40;:67::i;:::-;61762:15;;61723:5;;61737:16;;-1:-1:-1;;;;;61762:15:0;61786:22;:20;:22::i;61611:204::-;61600:215;61320:501;-1:-1:-1;;;;;;61320:501:0:o;57245:121::-;57297:22;57345:15;-1:-1:-1;;;;;57345:15:0;;57245:121::o;62828:426::-;62962:16;63078:170;63099:18;63137:2;63141:4;;63126:20;;;;;;;;;;;63078:170;63067:181;62828:426;-1:-1:-1;;;;;62828:426:0:o;64332:441::-;64482:16;64598:169;64619:18;64657:2;64661:4;;64646:20;;;;;;;;;;;54953:57;54996:8;;;46341:559;46663:12;;;26:21:-1;6:49;;46663:12:0;46584:169;;;;;;;;;;;;;;46663:12;;46584:169;;;;;46625:29;;46663:12;46684:16;;46709:13;;;;;;46584:169;;46709:13;;;;46584:169;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;46584:169:0;;;;137:4:-1;46584:169:0;;;;;;;;;;;;;;;;;;-1:-1:-1;46731:15:0;;-1:-1:-1;46731:15:0;;;;46584:169;;46731:15;;;;46584:169;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;46584:32:0;;-1:-1:-1;;;46584:169:0:i;:::-;;;14631:42;-1:-1:-1;;;;;46840:52:0;;:54;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;33713:882:0;33915:7;34011:181;34052:24;34096:6;34104:9;34085:29;;;;;;;;;;34011:181;-1:-1:-1;;34271:11:0;34267:58;;34300:16;34314:1;34300:13;:16::i;34267:58::-;-1:-1:-1;;;;;34397:23:0;;34393:70;;34438:16;34452:1;34438:13;:16::i;34393:70::-;34558:31;34571:9;34582:6;34558:12;:31::i;71826:335::-;71878:22;71910:7;71919:23;71962:42;-1:-1:-1;;;;;71946:76:0;:80;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;71909:117:0;;;;72041:2;:29;;;;;72047:10;:17;72068:2;72047:23;72041:29;72033:65;;;;-1:-1:-1;;;72033:65:0;;;;;;;;;72133:10;72122:33;;;;;;;;;;;;;;72105:50;;71826:335;;;:::o;31521:985::-;31618:12;31718:48;-1:-1:-1;;;31718:20:0;:48::i;:::-;-1:-1:-1;;31866:21:0;;31895:606;;;;31999:43;32027:14;31999:27;:43::i;:::-;32130:37;15214:42;32150:9;32161:5;32130:12;:37::i;:::-;32122:46;;;;;;32187:4;32177:14;;31895:606;;;32299:48;32324:14;32340:6;32299:24;:48::i;:::-;32295:199;;;32425:33;;-1:-1:-1;;;32425:33:0;;15214:42;;32425:14;;:33;;32440:9;;32451:6;;32425:33;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32425:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32425:33:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;32425:33:0;;;;;;;;;32417:42;;;;;;32480:4;32470:14;;32295:199;31521:985;;;;;:::o;55800:92::-;55848:38;55871:14;55848:22;:38::i;25705:988::-;25801:12;25901:47;-1:-1:-1;;;25901:20:0;:47::i;:::-;-1:-1:-1;;26048:21:0;;26077:611;;;;26169:42;26197:13;26169:27;:42::i;:::-;26298:36;15087:42;26317:9;26328:5;26298:12;:36::i;26077:611::-;26464:47;26489:13;26504:6;26464:24;:47::i;:::-;26460:221;;;26613:32;;-1:-1:-1;;;26613:32:0;;15087:42;;26613:13;;:32;;26627:9;;26638:6;;26613:32;;;;48771:1679;49038:7;49047:23;49159:210;49200:25;49245:11;49258:18;49278:6;49286:4;;49234:57;;;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;49:4;49159:210:0;;;;;;;;;;;;;;;;;;49234:57;49300:16;;49325:13;;;;;;49159:210;;49325:13;;;;49159:210;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;49159:210:0;;;;137:4:-1;49159:210:0;;;;;;;;;;;;;;;;;;-1:-1:-1;49347:15:0;;-1:-1:-1;49347:15:0;;;;49159:210;;49347:15;;;;49159:210;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;49159:32:0;;-1:-1:-1;;;49159:210:0:i;:::-;;;16781:15;49452:18;:48;49448:96;;49518:17;49532:2;49518:13;:17::i;49448:96::-;49656:39;;;49637:16;;:58;;;;;;;;;;;;;;;;;;50033:23;50090:4;-1:-1:-1;;;;;50082:18:0;50132:46;;;50187:11;50200:18;50220:6;50228:4;;50101:138;;;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;50101:138:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;50101:138:0;;;179:29:-1;;;;160:49;;;50082:158:0;;;;50101:138;50082:158;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;50063:177:0;;-1:-1:-1;50063:177:0;-1:-1:-1;50063:177:0;50326:119;;15701:42;-1:-1:-1;;;;;;;;;;;50397:31:0;50417:10;50397:19;:31::i;:::-;50349:88;;;;;;;;;;;;;;;50326:119;48771:1679;;;;;;;;;;;;;;:::o;42656:703::-;42906:172;42947:25;42992:7;42981:19;;;;;;;;;42906:172;-1:-1:-1;;;;;;;43154:21:0;;43150:68;;43193:16;43207:1;43193:13;:16::i;43150:68::-;43307:46;;-1:-1:-1;;;43307:46:0;;14631:42;;43307:37;;:46;;43345:7;;43307:46;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;43307:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;43307:46:0;;;;42656:703;;;;;;:::o;23132:1740::-;23324:7;23420:181;23461:24;23505:6;23513:9;23494:29;;;;;;;;;;23420:181;;;16781:15;23685:6;:36;23681:83;;23739:16;23753:1;23739:13;:16::i;23681:83::-;-1:-1:-1;;;;;23836:23:0;;23832:70;;23877:16;23891:1;23877:13;:16::i;23832:70::-;23981:16;:44;;-1:-1:-1;;23981:44:0;24000:25;23981:44;;;24478:89;;24410:23;;24467:4;;-1:-1:-1;;;24509:32:0;24478:89;;24543:6;;24551:9;;24478:89;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;24478:89:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;24478:89:0;;;179:29:-1;;;;160:49;;;24459:109:0;;;;24478:89;24459:109;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;24440:128:0;;-1:-1:-1;24440:128:0;-1:-1:-1;24440:128:0;24657:210;;15087:42;-1:-1:-1;;;;;;;;;;;24709:16:0;24723:1;24709:13;:16::i;:::-;24680:46;;;;;;;;;;;;;;;24657:210;;17714:1049;17881:7;17869:20;17866:2;;;17902:1;17899;17892:12;17866:2;17986:34;18005:14;17986:18;:34::i;:::-;18111:31;18128:13;18111:16;:31::i;:::-;18107:278;;;18230:29;;-1:-1:-1;;;18230:29:0;;18209:18;;15087:42;;18230:14;;:29;;18253:4;;18230:29;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;18230:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18230:29:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;18230:29:0;;;;;;;;;18209:50;;18331:46;18351:13;18366:10;18331:19;:46::i;:::-;18107:278;;18477:32;18494:14;18477:16;:32::i;:::-;18473:285;;;18599:30;;-1:-1:-1;;;18599:30:0;;18577:19;;15214:42;;18599:15;;:30;;18623:4;;18599:30;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;18599:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18599:30:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;18599:30:0;;;;;;;;;18577:52;;18702:48;18722:14;18738:11;18702:19;:48::i;:::-;18473:285;17714:1049;:::o;37701:1638::-;37893:7;37902:23;38011:33;38041:2;38011:29;:33::i;:::-;38134:16;38152:13;38169:166;38210:18;38248:2;38252:4;;38237:20;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;49:4;38169:166:0;;;;;;;;;;;;;;;;;;38237:20;38266:16;;38291:13;;;;;;38169:166;;38291:13;;;;38169:166;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;38169:166:0;;;;137:4:-1;38169:166:0;;;;;;;;;;;;;;;;;;-1:-1:-1;38313:15:0;;-1:-1:-1;38313:15:0;;;;38169:166;;38313:15;;;;38169:166;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;38169:32:0;;-1:-1:-1;;;38169:166:0:i;:::-;38133:202;;;;38766:2;-1:-1:-1;;;;;38766:7:0;38774:4;;38766:13;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;38747:32:0;;-1:-1:-1;38747:32:0;-1:-1:-1;38870:464:0;;;;39050:57;39062:8;39072:5;39079;39086:2;39090:4;;39096:10;39050:57;;;;;;;;;;;;;;;;;;;;;38870:464;;;39268:58;39280:8;39290:5;39297:2;39301:4;;39314:10;39268:58;;;;;;;;;;;;;;;;;;;;38870:464;37701:1638;;;;;;;;;;;;;:::o;10651:389::-;10749:12;10778:10;10594:42;10778:24;10770:74;;;;-1:-1:-1;;;10770:74:0;;;;;;;;;10865:6;-1:-1:-1;;;;;10865:11:0;10883:6;10865:29;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;10851:43:0;;;;;10906:7;10901:134;;10965:16;10962:1;10959;10944:38;11002:16;10999:1;10992:27;10933:95;10651:389;;;;:::o;57616:85::-;57689:6;;;57616:85::o;52145:1779::-;52251:11;52264:19;14631:42;-1:-1:-1;;;;;52287:37:0;;:39;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52287:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;52287:39:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;52287:39:0;;;;;;;;;52250:76;;;;52416:6;52411:54;;52440:16;52454:1;52440:13;:16::i;52411:54::-;52537:10;-1:-1:-1;;;;;52537:25:0;;;52533:72;;52580:16;52594:1;52580:13;:16::i;52533:72::-;52671:42;52699:13;52671:27;:42::i;:::-;52783:43;52811:14;52783:27;:43::i;:::-;52900:36;15087:42;52919:10;52931:4;52900:12;:36::i;:::-;;53011:37;15214:42;53031:10;53043:4;53011:12;:37::i;:::-;;53118:62;15343:42;53163:10;53175:4;53118:12;:62::i;:::-;;53251:63;15473:42;53297:10;53309:4;53251:12;:63::i;:::-;;53384:62;14831:42;53429:10;53441:4;53384:12;:62::i;:::-;;53517:63;14961:42;53563:10;53575:4;53517:12;:63::i;:::-;-1:-1:-1;53687:21:0;53719:11;;53715:148;;53822:33;53835:10;53847:7;53822:12;:33::i;:::-;;53715:148;53909:9;;;;;;;52145:1779;;;:::o;82935:441::-;83077:16;83193:177;83214:29;83263:5;83252:17;;;;;;;;;83193:177;83182:188;82935:441;-1:-1:-1;;;;82935:441:0:o;78765:1051::-;78862:31;78981:69;-1:-1:-1;;;78981:20:0;:69::i;:::-;79118:12;;79101:30;;;;;;;;;;;;;;;;79059:13;;79101:30;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;79087:44:0;-1:-1:-1;79145:9:0;79140:417;79164:5;:12;79160:1;:16;79140:417;;;79262:7;79271:23;79298:5;79304:1;79298:8;;;;;;;;;;;;;;:11;;;-1:-1:-1;;;;;79298:16:0;79315:5;79321:1;79315:8;;;;;;;;;;;;;;:13;;;79298:31;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;79261:68:0;;;;79355:44;;;;;;;;79371:2;79355:44;;;;;;79387:10;79355:44;;;79338:11;79350:1;79338:14;;;;;;;;;;;;;:61;;;;79413:2;79408:142;;79520:4;79509:15;;79535:5;;;;79408:142;-1:-1:-1;;79178:3:0;;79140:417;;;;79569:8;79565:246;;;79669:29;79712:11;79701:23;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;79701:23:0;;;79669:55;;79784:16;79778:23;79759:16;79755:2;79751:25;79744:58;79742:62;78765:1051;;;;:::o;19180:1677::-;19298:29;;-1:-1:-1;;;19298:29:0;;19277:18;;15087:42;;19298:14;;:29;;19321:4;;19298:29;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19298:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19298:29:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;19298:29:0;;;;;;;;;19277:50;-1:-1:-1;19415:14:0;;19411:612;;19463:45;;-1:-1:-1;;;19463:45:0;;19440:20;;15087:42;;19463:14;;:45;;19486:4;;14831:42;;19463:45;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19463:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19463:45:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;19463:45:0;;;;;;;;;19440:68;;19609:10;19594:12;:25;19590:426;;;19636:31;19653:13;19636:16;:31::i;:::-;19632:176;;;19750:46;19770:13;19785:10;19750:19;:46::i;:::-;19590:426;;;19960:46;19980:13;19995:10;19960:19;:46::i;:::-;19411:612;;20108:30;;-1:-1:-1;;;20108:30:0;;20086:19;;15214:42;;20108:15;;:30;;20132:4;;20108:30;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20108:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;20108:30:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;20108:30:0;;;;;;;;;20086:52;-1:-1:-1;20228:15:0;;20224:628;;20278:47;;-1:-1:-1;;;20278:47:0;;20254:21;;15214:42;;20278:15;;:47;;20302:4;;14961:42;;20278:47;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20278:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;20278:47:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;20278:47:0;;;;;;;;;20254:71;;20427:11;20411:13;:27;20407:438;;;20455:32;20472:14;20455:16;:32::i;:::-;20451:181;;;20572:48;20592:14;20608:11;20572:19;:48::i;:::-;20407:438;;;20787:48;20807:14;20823:11;20787:19;:48::i;:::-;20224:628;19180:1677;;:::o;50458:855::-;50629:7;50638:23;50749:61;-1:-1:-1;;;50749:20:0;:61::i;:::-;50921:95;;-1:-1:-1;;;50921:95:0;;50899:19;;15701:42;;50921:28;;50956:11;;50921:95;;50977:18;;50997:6;;51005:4;;;;50921:95;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;50921:95:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;50921:95:0;;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;50921:95:0;;;;;;;;;50899:117;;51121:18;51107:11;:32;51103:80;;;51157:17;51171:2;51157:13;:17::i;51103:80::-;51260:47;51280:13;51295:11;51260:19;:47::i;:::-;50458:855;;;;;;;;;:::o;59258:486::-;59417:16;59533:205;59554:6;59569:67;59610:6;59618;59626:9;59569:40;:67::i;:::-;59645:6;;59685:15;;59660:16;;-1:-1:-1;;;;;59685:15:0;59709:22;107234:152;107295:24;14031:42;-1:-1:-1;;;;;107351:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;107351:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;107351:29:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;107351:29:0;;;;;;;;;107332:48;;107234:152;:::o;108868:579::-;109082:16;109249:4;13842:2;109304:14;109329:16;109356:5;109372:16;109399:6;109416:9;109214:220;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;109214:220:0;;;109196:245;;;;;;109185:256;;108868:579;;;;;;;;:::o;115653:148::-;115761:34;;-1:-1:-1;;;115761:34:0;;115723:20;;15941:42;;115761:28;;:34;;115790:4;;115761:34;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;115761:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;115761:34:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;115761:34:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;115761:34:0;;;;;;;;83717:303;-1:-1:-1;;;;;83857:28:0;;83853:76;;83903:17;83917:2;83903:13;:17::i;83853:76::-;83937:15;:32;;-1:-1:-1;;;;;;83937:32:0;-1:-1:-1;;;;;83937:32:0;;;;;83981:33;;;;;;83937:32;;83981:33;;;;;;;;;;83717:303;:::o;111348:313::-;111425:15;:2;-1:-1:-1;;;;;111425:13:0;;:15::i;:::-;111420:64;;111458:17;111472:2;111458:13;:17::i;111420:64::-;-1:-1:-1;;;;;111500:19:0;;111514:4;111500:19;111496:67;;;111537:17;111551:2;111537:13;:17::i;111496:67::-;-1:-1:-1;;;;;111575:37:0;;14631:42;111575:37;111571:85;;;111630:17;111644:2;111630:13;:17::i;95561:2850::-;95778:16;;96297:21;;96293:123;;96345:16;96333:9;:28;96329:80;;;96381:17;96395:2;96381:13;:17::i;96329:80::-;-1:-1:-1;96500:6:0;;96593:22;96618:15;;-1:-1:-1;;;;;96618:15:0;;96749:22;:20;:22::i;:::-;96722:49;;96859:145;96880:6;96895:9;96913:11;96933:16;96958:14;96981:16;96859:12;:145::i;:::-;96848:156;;97093:19;97115:33;:8;:31;:33::i;:::-;97093:55;-1:-1:-1;97253:17:0;97243:6;:27;;;;;;;;;97239:1070;;97358:10;-1:-1:-1;;;;;97358:28:0;;;97354:244;;97416:111;97453:11;97466:6;97474:9;97485:14;97501:13;97416:22;:111::i;:::-;97399:190;;97559:17;97573:2;97559:13;:17::i;97399:190::-;97687:10;-1:-1:-1;;;;;97687:30:0;;;97683:168;;97754:36;:11;97774:15;97754:36;:19;:36;:::i;:::-;-1:-1:-1;;;;;97734:56:0;:16;-1:-1:-1;;;;;97734:56:0;;97730:112;;97812:17;97826:2;97812:13;:17::i;97730:112::-;97239:1070;;;97957:10;-1:-1:-1;;;;;97957:28:0;;;;;;:62;;-1:-1:-1;97989:10:0;-1:-1:-1;;;;;97989:30:0;;;;97957:62;97953:349;;;98068:36;:11;98088:15;98068:36;:19;:36;:::i;:::-;-1:-1:-1;;;;;98048:56:0;:16;-1:-1:-1;;;;;98048:56:0;;;:183;;;;;98120:111;98157:11;98170:6;98178:9;98189:14;98205:13;98120:22;:111::i;:::-;98119:112;98048:183;98032:261;;;98263:17;98277:2;98263:13;:17::i;98032:261::-;-1:-1:-1;;98397:6:0;:8;;;;;;-1:-1:-1;95561:2850:0;;;;-1:-1:-1;95561:2850:0;-1:-1:-1;;;;95561:2850:0:o;106286:575::-;106487:10;106511:27;:14;-1:-1:-1;;;;;106511:25:0;;:27::i;:::-;106506:350;;106575:34;:11;106595:13;106575:34;:19;:34;:::i;:::-;-1:-1:-1;;;;;106557:52:0;:14;-1:-1:-1;;;;;106557:52:0;;106549:60;;106506:350;;;106632:17;106663:11;106676:6;106684:9;106652:42;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;106652:42:0;;;;-1:-1:-1;;;106722:92:0;;;106652:42;;-1:-1:-1;16620:18:0;-1:-1:-1;;;;;106722:49:0;;;16627:10;;106722:92;;106652:42;;106790:13;;106722:92;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;106722:92:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;106722:92:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;106722:92:0;;;;;;;;;-1:-1:-1;;;;;;106722:117:0;;;106286:575;-1:-1:-1;;;;;;;106286:575:0:o;9706:608::-;9794:7;9814:9;:16;9834:2;9814:22;9810:64;;-1:-1:-1;9863:1:0;9847:19;;9810:64;9974:4;9959:20;;9953:27;10014:4;9999:20;;9993:27;10062:4;10047:20;;10041:27;9882:9;10033:36;10101:66;10088:79;;10084:119;;;10193:1;10178:17;;;;;;;10084:119;10215:1;:7;;10220:2;10215:7;;:18;;;;;10226:1;:7;;10231:2;10226:7;;10215:18;10211:58;;;10259:1;10244:17;;;;;;;10211:58;10284:24;10294:4;10300:1;10303;10306;10284:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;10284:24:0;;-1:-1:-1;;10284:24:0;;;9706:608;-1:-1:-1;;;;;;;9706:608:0:o;98699:914::-;98764:22;;;98828:5;:22;;;;;;;;;98824:144;;;-1:-1:-1;15343:42:0;;-1:-1:-1;14831:42:0;98824:144;;;-1:-1:-1;15473:42:0;;-1:-1:-1;14961:42:0;98824:144;99051:31;;-1:-1:-1;;;99051:31:0;;99033:15;;-1:-1:-1;;;;;99051:16:0;;;;;:31;;99076:4;;99051:31;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;99051:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;99051:31:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;99051:31:0;;;;;;;;;99033:49;-1:-1:-1;99163:11:0;;99159:449;;99263:48;;-1:-1:-1;;;99263:48:0;;99314:7;;-1:-1:-1;;;;;99263:16:0;;;;;:48;;99288:4;;99303:6;;99263:48;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;99263:48:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;99263:48:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;99263:48:0;;;;;;;;;:58;99259:185;;;99339:44;;-1:-1:-1;;;99339:44:0;;-1:-1:-1;;;;;99339:14:0;;;;;:44;;99362:6;;-1:-1:-1;;99379:2:0;99339:44;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;99339:44:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;99339:44:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;99339:44:0;;;;;;;;;99334:101;;99405:17;99419:2;99405:13;:17::i;99334:101::-;99519:29;;-1:-1:-1;;;99519:29:0;;-1:-1:-1;;;;;99519:20:0;;;;;:29;;99540:7;;99519:29;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;99519:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;99519:29:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;99519:29:0;;;;;;;;;99515:86;;99573:17;99587:2;99573:13;:17::i;99515:86::-;98699:914;;;;:::o;102877:1286::-;103029:26;-1:-1:-1;;;;;;103066:43:0;;-1:-1:-1;;;103066:43:0;103062:138;;;-1:-1:-1;103120:25:0;;;;;;;;;;;;-1:-1:-1;;;103120:25:0;;;;103062:138;;;-1:-1:-1;103168:24:0;;;;;;;;;;;;-1:-1:-1;;;103168:24:0;;;;103062:138;103364:40;;-1:-1:-1;;;103364:40:0;;15214:42;;;;103364:25;;:40;;103398:4;;103364:40;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;103364:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;103364:40:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;103364:40:0;;;;;;;;;103360:798;;;15214:42;-1:-1:-1;;;;;103420:189:0;-1:-1:-1;;;;;;;;;;;103519:12:0;103488:101;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;103488:101:0;;;;103420:189;;;;;;;;;;;;103360:798;;;103672:11;-1:-1:-1;;;;;103672:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;103672:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;103672:20:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;103672:20:0;;;;;;;;;103668:483;;;15214:42;-1:-1:-1;;;;;103710:206:0;-1:-1:-1;;;;;;;;;;;103817:12:0;103784:108;;;;;;;;;103668:483;15214:42;-1:-1:-1;;;;;103948:193:0;-1:-1:-1;;;;;;;;;;;104085:12:0;104022:95;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;104022:95:0;;;;103948:193;;;;;;;;;;;;102877:1286;;;:::o;112691:1433::-;112828:22;112926:20;;112958:6;:27;;;;;;;;;:76;;;-1:-1:-1;113006:28:0;112996:6;:38;;;;;;;;;112958:76;:121;;;-1:-1:-1;113055:24:0;113045:6;:34;;;;;;;;;112958:121;:167;;;-1:-1:-1;113100:25:0;113090:6;:35;;;;;;;;;112958:167;:212;;;-1:-1:-1;113146:24:0;113136:6;:34;;;;;;;;;112958:212;:258;;;-1:-1:-1;113191:25:0;113181:6;:35;;;;;;;;;112958:258;:307;;;-1:-1:-1;113237:28:0;113227:6;:38;;;;;;;;;112958:307;:357;;;-1:-1:-1;113286:29:0;113276:6;:39;;;;;;;;;112958:357;112926:396;;113334:15;113329:64;;113367:17;113381:2;113367:13;:17::i;113329:64::-;113505:17;113495:6;:27;;;;;;;;;:76;;;-1:-1:-1;113543:28:0;113533:6;:38;;;;;;;;;113495:76;:126;;;-1:-1:-1;113592:29:0;113582:6;:39;;;;;;;;;113495:126;113483:636;;;113732:12;;;26:21:-1;6:49;;113732:12:0;;;;;;;-1:-1:-1;113483:636:0;;;113780:28;113770:6;:38;;;;;;;;;:84;;;-1:-1:-1;113829:25:0;113819:6;:35;;;;;;;;;113770:84;113758:361;;;113965:9;113954:21;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;113954:21:0;;;113942:33;;113758:361;;;114093:6;114101:9;114082:29;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;114082:29:0;;;114070:41;;113758:361;112691:1433;;;;;;:::o;93203:413::-;93296:12;93410:9;-1:-1:-1;;;;;93410:14:0;16982:4;93454:6;93410:55;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;93396:69:0;;;;;93477:7;93472:139;;93514:9;-1:-1:-1;;;;;93500:43:0;-1:-1:-1;;;;;;;;;;;93525:17:0;93539:2;93525:13;:17::i;:::-;93500:43;;;;;;;;;;;;;;;93472:139;;;93571:32;93585:6;93593:9;93571:32;;;;;;;;;;;;;;;;93203:413;;;;:::o;104678:337::-;104831:10;104853:4;104831:27;;;:66;;-1:-1:-1;104862:16:0;;;;-1:-1:-1;;;;;;104862:35:0;;;;;;;;104831:66;104827:114;;;104915:17;104929:2;104915:13;:17::i;104827:114::-;-1:-1:-1;104993:16:0;104986:23;;-1:-1:-1;;104986:23:0;;;104678:337::o;88993:1378::-;89145:14;;89162:5;:22;;;;;;;;;:57;;14961:42;89162:57;;;14831:42;89162:57;89375:85;;89145:74;;-1:-1:-1;89297:28:0;;;;89342:17;;-1:-1:-1;;;;;89363:11:0;;;-1:-1:-1;;;89406:32:0;89375:85;;89448:4;;89375:85;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;89375:85:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;89375:85:0;;;179:29:-1;;;;160:49;;;89363:98:0;;;;89375:85;89363:98;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;89332:129:0;;-1:-1:-1;89332:129:0;-1:-1:-1;89470:20:0;89332:129;89505:23;;;;;89511:4;:11;89526:2;89511:17;89505:23;89501:301;;;89565:4;89554:27;;;;;;;;;;;;;;89539:42;;89501:301;;;89682:112;89736:5;-1:-1:-1;;;89777:2:0;89781:4;89682:43;:112::i;:::-;;89501:301;89886:16;;89882:484;;90015:156;;-1:-1:-1;;;;;90003:11:0;;;-1:-1:-1;;;90127:21:0;90015:156;;90150:12;;90015:156;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;90015:156:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;90015:156:0;;;179:29:-1;;;;160:49;;;90003:169:0;;;;90015:156;90003:169;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;89990:182:0;;-1:-1:-1;89990:182:0;-1:-1:-1;90257:101:0;90311:5;-1:-1:-1;;;89990:182:0;;90257:43;:101::i;:::-;;88993:1378;;;;;;:::o;91222:1489::-;91334:12;;91489:4;91505:14;91500:539;;91540:30;;-1:-1:-1;;;91540:30:0;;-1:-1:-1;;;;;91540:15:0;;;;;:30;;91564:4;;91540:30;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;91540:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;91540:30:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;91540:30:0;;;;;;;;;91530:40;;91500:539;;;91673:7;91682:17;91711:5;-1:-1:-1;;;;;91703:19:0;91739:1;91727:9;:13;;;;;91752:63;;91727:13;;;;-1:-1:-1;;;91775:24:0;91752:63;;91809:4;;91752:63;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;91752:63:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;91752:63:0;;;179:29:-1;;;;160:49;;;91703:121:0;;;;91752:63;91703:121;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;91672:152:0;;;;91839:2;:23;;;;;91845:4;:11;91860:2;91845:17;91839:23;91835:197;;;91896:4;91885:27;;;;;;;;;;;;;;91875:37;;91835:197;;;92017:5;91996:26;;91835:197;91500:539;;;92125:11;;92121:585;;92152:14;92147:420;;92271:34;;-1:-1:-1;;;92271:34:0;;-1:-1:-1;;;;;92271:14:0;;;;;:34;;92286:9;;92297:7;;92271:34;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;92271:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;92271:34:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;92271:34:0;;;;;;;;;92261:44;;92147:420;;;92436:5;-1:-1:-1;;;;;92428:19:0;92464:1;92452:9;:13;;;;;92479:67;;92452:13;;;;-1:-1:-1;;;92502:23:0;92479:67;;92527:9;;92538:7;;92479:67;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;92479:67:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;92479:67:0;;;179:29:-1;;;;160:49;;;92428:129:0;;;;92479:67;92428:129;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;92414:143:0;;-1:-1:-1;;92147:420:0;92121:585;;;92680:18;92670:28;;92121:585;91222:1489;;;;;;;:::o;87888:765::-;87984:12;;;88104:5;:22;;;;;;;;;:57;;14961:42;88104:57;;;14831:42;88104:57;88288:160;;88087:74;;-1:-1:-1;88246:7:0;;88255:17;;-1:-1:-1;;;;;88276:11:0;;;-1:-1:-1;;;88401:31:0;88288:160;;88434:7;;88288:160;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;88288:160:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;88288:160:0;;;179:29:-1;;;;160:49;;;88276:173:0;;;;88288:160;88276:173;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;88245:204:0;;-1:-1:-1;88245:204:0;-1:-1:-1;88540:107:0;88592:5;-1:-1:-1;;;88245:204:0;;88540:43;:107::i;114417:966::-;114504:26;114653:2;114633:10;:17;:22;:104;;;;-1:-1:-1;114710:13:0;;-1:-1:-1;;;114727:10:0;114710;;114721:1;;114710:13;;;;;;;;-1:-1:-1;;;;;;114710:13:0;:27;114633:104;:142;;;;-1:-1:-1;114748:13:0;;-1:-1:-1;;;114765:10:0;114748;;114759:1;;114748:13;;;;;;;;;;-1:-1:-1;;;;;;114748:13:0;:27;114633:142;:180;;;;-1:-1:-1;114786:13:0;;-1:-1:-1;;;114803:10:0;114786;;114797:1;;114786:13;;;;;;;;;;-1:-1:-1;;;;;;114786:13:0;:27;114633:180;:218;;;;-1:-1:-1;114824:13:0;;-1:-1:-1;;;114841:10:0;114824;;114835:1;;114824:13;;;;;;;;;;-1:-1:-1;;;;;;114824:13:0;:27;114633:218;114621:757;;;114941:30;115004:1;114984:10;:17;:21;114974:32;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;104:10;114974:32:0;87:34:-1;135:17;;-1:-1;114974:32:0;-1:-1:-1;114941:65:0;-1:-1:-1;115032:1:0;115015:109;115039:10;:17;115035:1;:21;115015:109;;;115101:10;115112:1;115101:13;;;;;;;;;;;;;;;;115074:17;115096:1;115092;:5;115074:24;;;;;;;;;;;:40;-1:-1:-1;;;;;115074:40:0;;;;;;;;-1:-1:-1;115058:3:0;;115015:109;;;;115218:17;115207:39;;;;;;;;;;;;;;115192:54;;114621:757;;;;115344:26;-1:-1:-1;;115344:13:0;:26::i;114621:757::-;114417:966;;;:::o;84391:1012::-;84452:7;;;;84592:5;:22;;;;;;;;;84588:176;;;-1:-1:-1;15087:42:0;;-1:-1:-1;14831:42:0;84588:176;;;-1:-1:-1;15214:42:0;;-1:-1:-1;14961:42:0;84588:176;84882:155;;-1:-1:-1;;;;;84862:19:0;;;-1:-1:-1;;;84988:21:0;84882:155;;85011:6;;-1:-1:-1;;85027:2:0;84882:155;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;84882:155:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;84882:155:0;;;179:29:-1;;;;160:49;;;84862:176:0;;;;84882:155;84862:176;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;84853:185:0;;;;;85111:2;85106:292;;85137:13;85128:5;:22;;;;;;;;;85124:267;;;15087:42;-1:-1:-1;;;;;;;;;;;85197:17:0;85211:2;85197:13;:17::i;:::-;85168:47;;;;;;;;;;;;;;;85124:267;;;85324:57;-1:-1:-1;;;85324:33:0;:57::i;:::-;84391:1012;;;;;:::o;86116:1000::-;86292:13;86283:5;:22;;;;;;;;;:62;;;;;16781:15;86309:7;:36;86283:62;:230;;;-1:-1:-1;86365:14:0;86356:5;:23;;;;;;;;;:157;;;;;16856:3;86394:7;:37;:110;;;;-1:-1:-1;86452:46:0;;-1:-1:-1;;;86452:46:0;;16104:42;;86452:20;;:46;;16228:66;;86452:46;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;86452:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;86452:46:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;86452:46:0;;;;;;;;;86444:60;;86394:110;86271:840;;;86579:14;;86596:5;:22;;;;;;;;;:57;;14961:42;86596:57;;;14831:42;86596:57;86769:149;;86579:74;;-1:-1:-1;86727:7:0;;86736:17;;-1:-1:-1;;;;;86757:11:0;;;-1:-1:-1;;;86881:19:0;86769:149;;86902:7;;86769:149;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;86769:149:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;86769:149:0;;;179:29:-1;;;;160:49;;;86757:162:0;;;;86769:149;86757:162;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;86726:193:0;;-1:-1:-1;86726:193:0;-1:-1:-1;87004:99:0;87058:5;-1:-1:-1;;;86726:193:0;;87004:43;:99::i;9518:160::-;9629:20;9664:8;;;9518:160::o;10320:167::-;10389:7;10475:4;10422:58;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;10422:58:0;;;10412:69;;;;;;10405:76;;10320:167;;;:::o;100378:2109::-;100544:12;100641:2;100637:1845;;;100658:4;:11;100673:2;100658:17;100654:1195;;;100688:14;100716:4;100705:27;;;;;;;;;;;;;;100688:44;-1:-1:-1;100747:10:0;;100743:593;;100782:4;100772:14;;100743:593;;;100898:15;100915:18;100935:26;100980:47;101003:5;101010:16;100980:22;:47::i;:::-;100897:143;;;;;;101088:7;-1:-1:-1;;;;;101060:255:0;-1:-1:-1;;;;;;;;;;;101168:4:0;101236:12;101133:154;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;101133:154:0;;;;101060:255;;;;;;;;;;;;100743:593;;;;100654:1195;;;;101441:15;101458:18;101478:26;101521:47;101544:5;101551:16;101521:22;:47::i;:::-;101440:139;;;;;;101623:7;-1:-1:-1;;;;;101597:234:0;-1:-1:-1;;;;;;;;;;;101697:4:0;101760:12;101664:143;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;101664:143:0;;;;101597:234;;;;;;;;;;;;100654:1195;;;;100637:1845;;;101956:15;101973:18;101993:26;102034:47;102057:5;102064:16;102034:22;:47::i;:::-;101955:135;;;;;;102167:26;102196:25;102216:4;102196:19;:25::i;:::-;102167:54;;102261:7;-1:-1:-1;;;;;102237:237:0;-1:-1:-1;;;;;;;;;;;102329:4:0;102383:12;102429;102298:156;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;102298:156:0;;;;102237:237;;;;;;;;;;;;100637:1845;;;;100378:2109;;;;;;:::o;109982:862::-;110100:15;110122:18;;110100:15;110190:5;:22;;;;;;;;;110186:178;;;14831:42;110223:24;;110256:19;;;;;;;;;;;;;-1:-1:-1;;;110256:19:0;;;;;110186:178;;;14961:42;110298:25;;110332:24;;;;;;;;;;;;;-1:-1:-1;;;110332:24:0;;;;;110186:178;-1:-1:-1;;;;;;110451:39:0;;-1:-1:-1;;;110451:39:0;110447:392;;;-1:-1:-1;110501:21:0;;;;;;;;;;;;-1:-1:-1;;;110501:21:0;;;;110447:392;;;-1:-1:-1;;;;;;110549:62:0;;-1:-1:-1;;;110549:62:0;110545:287;;;-1:-1:-1;110624:26:0;;;;;;;;;;;;-1:-1:-1;;;110624:26:0;;;;110545:287;;;-1:-1:-1;;;;;;110749:41:0;;-1:-1:-1;;;110749:41:0;:61;;;;;;;;;;;;;;;-1:-1:-1;;;110749:61:0;;;;;;;;;;;;;;;;;;;110699:122;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;110699:122:0;;;110677:145;;110545:287;109982:862;;;;;:::o;12298:103506::-;;;;;;;;;;-1:-1:-1;12298:103506:0;;;;;;;;:::o;5:130:-1:-;72:20;;97:33;72:20;97:33;;142:134;220:13;;238:33;220:13;238:33;;664:744;;810:3;803:4;795:6;791:17;787:27;777:2;;828:1;825;818:12;777:2;858:6;852:13;880:98;895:82;970:6;895:82;;;880:98;;;1006:21;;;1050:4;1038:17;;;;871:107;;-1:-1;1063:14;;1038:17;1158:1;1143:259;1168:6;1165:1;1162:13;1143:259;;;1244:3;1238:10;1230:6;1226:23;1268:70;1334:3;1322:10;1268:70;;;1256:83;;-1:-1;1362:4;1353:14;;;;1381;;;;;1190:1;1183:9;1143:259;;;1147:14;770:638;;;;;;;;1481:726;;1614:3;1607:4;1599:6;1595:17;1591:27;1581:2;;1632:1;1629;1622:12;1581:2;1669:6;1656:20;1691:96;1706:80;1779:6;1706:80;;1691:96;1815:21;;;1859:4;1847:17;;;;1682:105;;-1:-1;1872:14;;1847:17;1967:1;1952:249;1977:6;1974:1;1971:13;1952:249;;;2060:3;2047:17;2039:6;2035:30;2084:53;2133:3;2121:10;2084:53;;;2072:66;;-1:-1;2161:4;2152:14;;;;2180;;;;;1999:1;1992:9;1952:249;;2215:128;2290:13;;2308:30;2290:13;2308:30;;2350:130;2417:20;;2442:33;2417:20;2442:33;;2487:134;2565:13;;2583:33;2565:13;2583:33;;2628:132;2705:13;;2723:32;2705:13;2723:32;;2781:336;;;2895:3;2888:4;2880:6;2876:17;2872:27;2862:2;;2913:1;2910;2903:12;2862:2;-1:-1;2933:20;;-1:-1;;;;;2962:30;;2959:2;;;3005:1;3002;2995:12;2959:2;3039:4;3031:6;3027:17;3015:29;;3090:3;3082:4;3074:6;3070:17;3060:8;3056:32;3053:41;3050:2;;;3107:1;3104;3097:12;3050:2;2855:262;;;;;;3126:432;;3223:3;3216:4;3208:6;3204:17;3200:27;3190:2;;3241:1;3238;3231:12;3190:2;3278:6;3265:20;3300:60;3315:44;3352:6;3315:44;;3300:60;3291:69;;3380:6;3373:5;3366:21;3416:4;3408:6;3404:17;3449:4;3442:5;3438:16;3484:3;3475:6;3470:3;3466:16;3463:25;3460:2;;;3501:1;3498;3491:12;3460:2;3511:41;3545:6;3540:3;3535;3511:41;;;3183:375;;;;;;;;3567:434;;3675:3;3668:4;3660:6;3656:17;3652:27;3642:2;;3693:1;3690;3683:12;3642:2;3723:6;3717:13;3745:60;3760:44;3797:6;3760:44;;3745:60;3736:69;;3825:6;3818:5;3811:21;3861:4;3853:6;3849:17;3894:4;3887:5;3883:16;3929:3;3920:6;3915:3;3911:16;3908:25;3905:2;;;3946:1;3943;3936:12;3905:2;3956:39;3988:6;3983:3;3978;3956:39;;4458:158;4539:20;;4564:47;4539:20;4564:47;;5588:582;;5710:4;5698:9;5693:3;5689:19;5685:30;5682:2;;;5728:1;5725;5718:12;5682:2;5746:20;5761:4;5746:20;;;5737:29;-1:-1;5814:1;5846:57;5899:3;5879:9;5846:57;;;5821:83;;-1:-1;5992:2;5977:18;;5971:25;-1:-1;;;;;6005:30;;6002:2;;;6048:1;6045;6038:12;6002:2;6083:65;6144:3;6135:6;6124:9;6120:22;6083:65;;;6076:4;6069:5;6065:16;6058:91;5925:235;5676:494;;;;;6238:547;;6343:4;6331:9;6326:3;6322:19;6318:30;6315:2;;;6361:1;6358;6351:12;6315:2;6379:20;6394:4;6379:20;;;6370:29;-1:-1;6447:1;6479:49;6524:3;6504:9;6479:49;;;6454:75;;-1:-1;6618:2;6603:18;;6590:32;-1:-1;;;;;6631:30;;6628:2;;;6674:1;6671;6664:12;6628:2;6709:54;6759:3;6750:6;6739:9;6735:22;6709:54;;7070:241;;7174:2;7162:9;7153:7;7149:23;7145:32;7142:2;;;7190:1;7187;7180:12;7142:2;7225:1;7242:53;7287:7;7267:9;7242:53;;7318:263;;7433:2;7421:9;7412:7;7408:23;7404:32;7401:2;;;7449:1;7446;7439:12;7401:2;7484:1;7501:64;7557:7;7537:9;7501:64;;7874:382;;;8003:2;7991:9;7982:7;7978:23;7974:32;7971:2;;;8019:1;8016;8009:12;7971:2;8054:1;8071:61;8124:7;8104:9;8071:61;;;8061:71;;8033:105;8169:2;8187:53;8232:7;8223:6;8212:9;8208:22;8187:53;;;8177:63;;8148:98;7965:291;;;;;;8263:615;;;;;8420:2;8408:9;8399:7;8395:23;8391:32;8388:2;;;8436:1;8433;8426:12;8388:2;8471:1;8488:53;8533:7;8513:9;8488:53;;;8478:63;;8450:97;8606:2;8595:9;8591:18;8578:32;-1:-1;;;;;8622:6;8619:30;8616:2;;;8662:1;8659;8652:12;8616:2;8690:64;8746:7;8737:6;8726:9;8722:22;8690:64;;;8680:74;;;;8557:203;8791:2;8809:53;8854:7;8845:6;8834:9;8830:22;8809:53;;;8799:63;;8770:98;8382:496;;;;;;;;8885:1115;;;;;;;;;9114:3;9102:9;9093:7;9089:23;9085:33;9082:2;;;9131:1;9128;9121:12;9082:2;9166:1;9183:53;9228:7;9208:9;9183:53;;;9173:63;;9145:97;9301:2;9290:9;9286:18;9273:32;-1:-1;;;;;9317:6;9314:30;9311:2;;;9357:1;9354;9347:12;9311:2;9385:64;9441:7;9432:6;9421:9;9417:22;9385:64;;;9375:74;;;;9252:203;9486:2;9504:53;9549:7;9540:6;9529:9;9525:22;9504:53;;;9494:63;;9465:98;9622:2;9611:9;9607:18;9594:32;-1:-1;;;;;9638:6;9635:30;9632:2;;;9678:1;9675;9668:12;9632:2;9706:64;9762:7;9753:6;9742:9;9738:22;9706:64;;;9696:74;;;;9573:203;9835:3;9824:9;9820:19;9807:33;-1:-1;;;;;9852:6;9849:30;9846:2;;;9892:1;9889;9882:12;9846:2;9920:64;9976:7;9967:6;9956:9;9952:22;9920:64;;;9910:74;;;;9786:204;9076:924;;;;;;;;;;;;10007:741;;;;;;10181:3;10169:9;10160:7;10156:23;10152:33;10149:2;;;10198:1;10195;10188:12;10149:2;10233:1;10250:53;10295:7;10275:9;10250:53;;;10240:63;;10212:97;10368:2;10357:9;10353:18;10340:32;-1:-1;;;;;10384:6;10381:30;10378:2;;;10424:1;10421;10414:12;10378:2;10452:64;10508:7;10499:6;10488:9;10484:22;10452:64;;;10442:74;;;;10319:203;10553:2;10571:53;10616:7;10607:6;10596:9;10592:22;10571:53;;;10561:63;;10532:98;10661:2;10679:53;10724:7;10715:6;10704:9;10700:22;10679:53;;;10669:63;;10640:98;10143:605;;;;;;;;;10755:865;;;;;;;10948:3;10936:9;10927:7;10923:23;10919:33;10916:2;;;10965:1;10962;10955:12;10916:2;11000:1;11017:53;11062:7;11042:9;11017:53;;;11007:63;;10979:97;11107:2;11125:53;11170:7;11161:6;11150:9;11146:22;11125:53;;;11115:63;;11086:98;11243:2;11232:9;11228:18;11215:32;-1:-1;;;;;11259:6;11256:30;11253:2;;;11299:1;11296;11289:12;11253:2;11327:64;11383:7;11374:6;11363:9;11359:22;11327:64;;;11317:74;;;;11194:203;11456:2;11445:9;11441:18;11428:32;-1:-1;;;;;11472:6;11469:30;11466:2;;;11512:1;11509;11502:12;11466:2;11540:64;11596:7;11587:6;11576:9;11572:22;11540:64;;;11530:74;;;;11407:203;10910:710;;;;;;;;;11627:428;;11785:2;11773:9;11764:7;11760:23;11756:32;11753:2;;;11801:1;11798;11791:12;11753:2;11836:24;;-1:-1;;;;;11869:30;;11866:2;;;11912:1;11909;11902:12;11866:2;11932:107;12031:7;12022:6;12011:9;12007:22;11932:107;;12062:409;;12207:2;12195:9;12186:7;12182:23;12178:32;12175:2;;;12223:1;12220;12213:12;12175:2;12258:31;;-1:-1;;;;;12298:30;;12295:2;;;12341:1;12338;12331:12;12295:2;12361:94;12447:7;12438:6;12427:9;12423:22;12361:94;;12478:534;;;12640:2;12628:9;12619:7;12615:23;12611:32;12608:2;;;12656:1;12653;12646:12;12608:2;12691:31;;-1:-1;;;;;12731:30;;12728:2;;;12774:1;12771;12764:12;12728:2;12794:94;12880:7;12871:6;12860:9;12856:22;12794:94;;13019:993;;;;;13233:3;13221:9;13212:7;13208:23;13204:33;13201:2;;;13250:1;13247;13240:12;13201:2;13285:31;;-1:-1;;;;;13325:30;;13322:2;;;13368:1;13365;13358:12;13322:2;13388:94;13474:7;13465:6;13454:9;13450:22;13388:94;;;13378:104;;13264:224;13519:2;13537:53;13582:7;13573:6;13562:9;13558:22;13537:53;;;13527:63;;13498:98;13655:2;13644:9;13640:18;13627:32;-1:-1;;;;;13671:6;13668:30;13665:2;;;13711:1;13708;13701:12;13665:2;13731:62;13785:7;13776:6;13765:9;13761:22;13731:62;;;13721:72;;13606:193;13858:2;13847:9;13843:18;13830:32;-1:-1;;;;;13874:6;13871:30;13868:2;;;13914:1;13911;13904:12;13868:2;13934:62;13988:7;13979:6;13968:9;13964:22;13934:62;;14019:659;;;;14198:2;14186:9;14177:7;14173:23;14169:32;14166:2;;;14214:1;14211;14204:12;14166:2;14249:31;;-1:-1;;;;;14289:30;;14286:2;;;14332:1;14329;14322:12;14286:2;14352:94;14438:7;14429:6;14418:9;14414:22;14352:94;;;14342:104;;14228:224;14483:2;14501:53;14546:7;14537:6;14526:9;14522:22;14501:53;;;14491:63;;14462:98;14591:2;14609:53;14654:7;14645:6;14634:9;14630:22;14609:53;;;14599:63;;14570:98;14160:518;;;;;;14685:257;;14797:2;14785:9;14776:7;14772:23;14768:32;14765:2;;;14813:1;14810;14803:12;14765:2;14848:1;14865:61;14918:7;14898:9;14865:61;;14949:393;;;15078:2;15066:9;15057:7;15053:23;15049:32;15046:2;;;15094:1;15091;15084:12;15046:2;15129:1;15146:61;15199:7;15179:9;15146:61;;;15136:71;;15108:105;15244:2;15262:64;15318:7;15309:6;15298:9;15294:22;15262:64;;15349:241;;15453:2;15441:9;15432:7;15428:23;15424:32;15421:2;;;15469:1;15466;15459:12;15421:2;15504:1;15521:53;15566:7;15546:9;15521:53;;15597:263;;15712:2;15700:9;15691:7;15687:23;15683:32;15680:2;;;15728:1;15725;15718:12;15680:2;15763:1;15780:64;15836:7;15816:9;15780:64;;15867:462;;;15993:2;15981:9;15972:7;15968:23;15964:32;15961:2;;;16009:1;16006;15999:12;15961:2;16044:1;16061:53;16106:7;16086:9;16061:53;;;16051:63;;16023:97;16179:2;16168:9;16164:18;16151:32;-1:-1;;;;;16195:6;16192:30;16189:2;;;16235:1;16232;16225:12;16189:2;16255:58;16305:7;16296:6;16285:9;16281:22;16255:58;;16336:261;;16450:2;16438:9;16429:7;16425:23;16421:32;16418:2;;;16466:1;16463;16456:12;16418:2;16501:1;16518:63;16573:7;16553:9;16518:63;;16604:614;;;;;16763:2;16751:9;16742:7;16738:23;16734:32;16731:2;;;16779:1;16776;16769:12;16731:2;16814:31;;-1:-1;;;;;16854:30;;16851:2;;;16897:1;16894;16887:12;16851:2;16925:64;16981:7;16972:6;16961:9;16957:22;16925:64;;;16915:74;;;;16793:202;17054:2;17043:9;17039:18;17026:32;-1:-1;;;;;17070:6;17067:30;17064:2;;;17110:1;17107;17100:12;17064:2;17138:64;17194:7;17185:6;17174:9;17170:22;17138:64;;;16725:493;;;;-1:-1;17128:74;-1:-1;;;;16725:493;17225:645;;;;;17394:3;17382:9;17373:7;17369:23;17365:33;17362:2;;;17411:1;17408;17401:12;17362:2;17446:1;17463:67;17522:7;17502:9;17463:67;;;17453:77;;17425:111;17567:2;17585:53;17630:7;17621:6;17610:9;17606:22;17585:53;;;17575:63;;17546:98;17675:2;17693:53;17738:7;17729:6;17718:9;17714:22;17693:53;;;17683:63;;17654:98;17783:2;17801:53;17846:7;17837:6;17826:9;17822:22;17801:53;;17877:771;;;;;;18063:3;18051:9;18042:7;18038:23;18034:33;18031:2;;;18080:1;18077;18070:12;18031:2;18115:1;18132:67;18191:7;18171:9;18132:67;;;18122:77;;18094:111;18236:2;18254:53;18299:7;18290:6;18279:9;18275:22;18254:53;;;18244:63;;18215:98;18344:2;18362:53;18407:7;18398:6;18387:9;18383:22;18362:53;;;18352:63;;18323:98;18452:2;18470:53;18515:7;18506:6;18495:9;18491:22;18470:53;;;18460:63;;18431:98;18560:3;18579:53;18624:7;18615:6;18604:9;18600:22;18579:53;;18655:354;;18776:2;18764:9;18755:7;18751:23;18747:32;18744:2;;;18792:1;18789;18782:12;18744:2;18827:24;;-1:-1;;;;;18860:30;;18857:2;;;18903:1;18900;18893:12;18857:2;18923:70;18985:7;18976:6;18965:9;18961:22;18923:70;;19655:366;;;19776:2;19764:9;19755:7;19751:23;19747:32;19744:2;;;19792:1;19789;19782:12;19744:2;19827:1;19844:53;19889:7;19869:9;19844:53;;;19834:63;;19806:97;19934:2;19952:53;19997:7;19988:6;19977:9;19973:22;19952:53;;20028:1007;;;;;;;;20246:3;20234:9;20225:7;20221:23;20217:33;20214:2;;;20263:1;20260;20253:12;20214:2;20298:1;20315:53;20360:7;20340:9;20315:53;;;20305:63;;20277:97;20405:2;20423:61;20476:7;20467:6;20456:9;20452:22;20423:61;;;20413:71;;20384:106;20521:2;20539:53;20584:7;20575:6;20564:9;20560:22;20539:53;;;20529:63;;20500:98;20657:2;20646:9;20642:18;20629:32;-1:-1;;;;;20673:6;20670:30;20667:2;;;20713:1;20710;20703:12;20667:2;20741:64;20797:7;20788:6;20777:9;20773:22;20741:64;;;20731:74;;;;20608:203;20870:3;20859:9;20855:19;20842:33;-1:-1;;;;;20887:6;20884:30;20881:2;;;20927:1;20924;20917:12;20881:2;20955:64;21011:7;21002:6;20991:9;20987:22;20955:64;;;20945:74;;;;20821:204;20208:827;;;;;;;;;;;22040:490;;;;22180:2;22168:9;22159:7;22155:23;22151:32;22148:2;;;22196:1;22193;22186:12;22148:2;22231:1;22248:53;22293:7;22273:9;22248:53;;;22238:63;;22210:97;22366:2;22355:9;22351:18;22338:32;-1:-1;;;;;22382:6;22379:30;22376:2;;;22422:1;22419;22412:12;22376:2;22450:64;22506:7;22497:6;22486:9;22482:22;22450:64;;;22440:74;;;;22317:203;22142:388;;;;;;22537:739;;;;;;22713:2;22701:9;22692:7;22688:23;22684:32;22681:2;;;22729:1;22726;22719:12;22681:2;22764:1;22781:53;22826:7;22806:9;22781:53;;;22771:63;;22743:97;22899:2;22888:9;22884:18;22871:32;-1:-1;;;;;22915:6;22912:30;22909:2;;;22955:1;22952;22945:12;22909:2;22983:64;23039:7;23030:6;23019:9;23015:22;22983:64;;;22973:74;;;;22850:203;23112:2;23101:9;23097:18;23084:32;-1:-1;;;;;23128:6;23125:30;23122:2;;;23168:1;23165;23158:12;23122:2;23196:64;23252:7;23243:6;23232:9;23228:22;23196:64;;;23186:74;;;;23063:203;22675:601;;;;;;;;;23283:741;;;;;;23457:3;23445:9;23436:7;23432:23;23428:33;23425:2;;;23474:1;23471;23464:12;23425:2;23509:1;23526:53;23571:7;23551:9;23526:53;;;23516:63;;23488:97;23616:2;23634:53;23679:7;23670:6;23659:9;23655:22;23634:53;;;23624:63;;23595:98;23724:2;23742:53;23787:7;23778:6;23767:9;23763:22;23742:53;;;23732:63;;23703:98;23860:2;23849:9;23845:18;23832:32;-1:-1;;;;;23876:6;23873:30;23870:2;;;23916:1;23913;23906:12;24031:867;;;;;;;24222:3;24210:9;24201:7;24197:23;24193:33;24190:2;;;24239:1;24236;24229:12;24190:2;24274:1;24291:53;24336:7;24316:9;24291:53;;;24281:63;;24253:97;24381:2;24399:53;24444:7;24435:6;24424:9;24420:22;24399:53;;;24389:63;;24360:98;24489:2;24507:53;24552:7;24543:6;24532:9;24528:22;24507:53;;;24497:63;;24468:98;24625:2;24614:9;24610:18;24597:32;-1:-1;;;;;24641:6;24638:30;24635:2;;;24681:1;24678;24671:12;24635:2;24709:64;24765:7;24756:6;24745:9;24741:22;24709:64;;;24699:74;;;;24576:203;24810:3;24829:53;24874:7;24865:6;24854:9;24850:22;24829:53;;;24819:63;;24789:99;24184:714;;;;;;;;;24905:1367;;;;;;;;;;;25168:3;25156:9;25147:7;25143:23;25139:33;25136:2;;;25185:1;25182;25175:12;25136:2;25220:1;25237:53;25282:7;25262:9;25237:53;;;25227:63;;25199:97;25327:2;25345:53;25390:7;25381:6;25370:9;25366:22;25345:53;;;25335:63;;25306:98;25435:2;25453:53;25498:7;25489:6;25478:9;25474:22;25453:53;;;25443:63;;25414:98;25571:2;25560:9;25556:18;25543:32;-1:-1;;;;;25587:6;25584:30;25581:2;;;25627:1;25624;25617:12;25581:2;25655:64;25711:7;25702:6;25691:9;25687:22;25655:64;;;25645:74;;;;25522:203;25756:3;25775:53;25820:7;25811:6;25800:9;25796:22;25775:53;;;25765:63;;25735:99;25893:3;25882:9;25878:19;25865:33;-1:-1;;;;;25910:6;25907:30;25904:2;;;25950:1;25947;25940:12;25904:2;25978:64;26034:7;26025:6;26014:9;26010:22;25978:64;;;25968:74;;;;25844:204;26107:3;26096:9;26092:19;26079:33;-1:-1;;;;;26124:6;26121:30;26118:2;;;26164:1;26161;26154:12;26118:2;26192:64;26248:7;26239:6;26228:9;26224:22;26192:64;;;26182:74;;;;26058:204;25130:1142;;;;;;;;;;;;;;26279:993;;;;;;;;26487:3;26475:9;26466:7;26462:23;26458:33;26455:2;;;26504:1;26501;26494:12;26455:2;26539:1;26556:53;26601:7;26581:9;26556:53;;;26546:63;;26518:97;26646:2;26664:53;26709:7;26700:6;26689:9;26685:22;26664:53;;;26654:63;;26625:98;26754:2;26772:53;26817:7;26808:6;26797:9;26793:22;26772:53;;;26762:63;;26733:98;26890:2;26879:9;26875:18;26862:32;-1:-1;;;;;26906:6;26903:30;26900:2;;;26946:1;26943;26936:12;26900:2;26974:64;27030:7;27021:6;27010:9;27006:22;26974:64;;;26964:74;;;;26841:203;27075:3;27094:53;27139:7;27130:6;27119:9;27115:22;27094:53;;;27084:63;;27054:99;27184:3;27203:53;27248:7;27239:6;27228:9;27224:22;27203:53;;;27193:63;;27163:99;26449:823;;;;;;;;;;;27280:161;;27361:40;27397:3;27389:6;27361:40;;;-1:-1;;27430:4;27421:14;;27354:87;27450:177;;27561:60;27617:3;27609:6;27561:60;;27636:245;;27781:94;27871:3;27863:6;27781:94;;27890:221;;28023:82;28101:3;28093:6;28023:82;;28119:142;28210:45;28249:5;28210:45;;;28205:3;28198:58;28192:69;;;28268:137;28367:32;28393:5;28367:32;;28412:184;28529:61;28557:32;28583:5;28557:32;;;28529:61;;29017:666;;29156:51;29201:5;29156:51;;;29220:83;29296:6;29291:3;29220:83;;;29213:90;;29324:53;29371:5;29324:53;;;29397:7;29425:1;29410:251;29435:6;29432:1;29429:13;29410:251;;;29502:6;29496:13;29523:57;29576:3;29561:13;29523:57;;;29516:64;;29597:57;29647:6;29597:57;;;29587:67;-1:-1;;29457:1;29450:9;29410:251;;;-1:-1;29674:3;;29135:548;-1:-1;;;;;29135:548;29718:888;;29873:59;29926:5;29873:59;;;29945:91;30029:6;30024:3;29945:91;;;29938:98;;30059:3;30101:4;30093:6;30089:17;30084:3;30080:27;30128:61;30183:5;30128:61;;;30209:7;30237:1;30222:345;30247:6;30244:1;30241:13;30222:345;;;30309:9;30303:4;30299:20;30294:3;30287:33;30354:6;30348:13;30376:74;30445:4;30430:13;30376:74;;;30368:82;;30467:65;30525:6;30467:65;;;30555:4;30546:14;;;;;30457:75;-1:-1;;30269:1;30262:9;30222:345;;;-1:-1;30580:4;;29852:754;-1:-1;;;;;;;29852:754;30751:1024;;30940:76;31010:5;30940:76;;;31029:108;31130:6;31125:3;31029:108;;;31022:115;;31160:3;31202:4;31194:6;31190:17;31185:3;31181:27;31229:78;31301:5;31229:78;;;31327:7;31355:1;31340:396;31365:6;31362:1;31359:13;31340:396;;;31427:9;31421:4;31417:20;31412:3;31405:33;31472:6;31466:13;31494:108;31597:4;31582:13;31494:108;;;31486:116;;31619:82;31694:6;31619:82;;;31724:4;31715:14;;;;;31609:92;-1:-1;;31387:1;31380:9;31340:396;;31908:976;;32085:70;32149:5;32085:70;;;32168:102;32263:6;32258:3;32168:102;;;32161:109;;32293:3;32335:4;32327:6;32323:17;32318:3;32314:27;32362:72;32428:5;32362:72;;;32454:7;32482:1;32467:378;32492:6;32489:1;32486:13;32467:378;;;32554:9;32548:4;32544:20;32539:3;32532:33;32599:6;32593:13;32621:96;32712:4;32697:13;32621:96;;;32613:104;;32734:76;32803:6;32734:76;;;32833:4;32824:14;;;;;32724:86;-1:-1;;32514:1;32507:9;32467:378;;32892:94;32959:21;32974:5;32959:21;;33104:113;33187:24;33205:5;33187:24;;33224:152;33325:45;33345:24;33363:5;33345:24;;;33325:45;;33383:110;33464:23;33481:5;33464:23;;33523:297;;33637:70;33700:6;33695:3;33637:70;;;33630:77;;33719:43;33755:6;33750:3;33743:5;33719:43;;;33784:29;33806:6;33784:29;;;33775:39;;;;33623:197;-1:-1;;;33623:197;33851:310;;33983:88;34064:6;34059:3;33983:88;;;33976:95;;34083:43;34119:6;34114:3;34107:5;34083:43;;;-1:-1;;34139:16;;33969:192;34169:343;;34279:38;34311:5;34279:38;;;34329:70;34392:6;34387:3;34329:70;;;34322:77;;34404:52;34449:6;34444:3;34437:4;34430:5;34426:16;34404:52;;;34477:29;34499:6;34477:29;;34519:356;;34647:38;34679:5;34647:38;;;34697:88;34778:6;34773:3;34697:88;;;34690:95;;34790:52;34835:6;34830:3;34823:4;34816:5;34812:16;34790:52;;;34854:16;;;;;34627:248;-1:-1;;34627:248;35901:150;35996:49;36039:5;35996:49;;36058:187;36171:68;36189:49;36232:5;36189:49;;;36171:68;;36974:400;;37152:85;37234:2;37229:3;37152:85;;;37270:66;37250:87;;37365:2;37356:12;;37138:236;-1:-1;;37138:236;37383:359;;37561:85;37643:2;37638:3;37561:85;;;37679:25;37659:46;;37733:2;37724:12;;37547:195;-1:-1;;37547:195;37751:354;;37929:85;38011:2;38006:3;37929:85;;;-1:-1;;;38027:41;;38096:2;38087:12;;37915:190;-1:-1;;37915:190;38114:340;;38292:84;38374:1;38369:3;38292:84;;;-1:-1;;;38389:29;;38446:1;38437:11;;38278:176;-1:-1;;38278:176;38463:417;;38641:85;38723:2;38718:3;38641:85;;;38759:34;38739:55;;-1:-1;;;38823:2;38814:12;;38807:36;38871:2;38862:12;;38627:253;-1:-1;;38627:253;38889:335;;39067:84;39149:1;39144:3;39067:84;;;-1:-1;;;39164:24;;39216:1;39207:11;;39053:171;-1:-1;;39053:171;39233:374;;39393:67;39457:2;39452:3;39393:67;;;39493:34;39473:55;;-1:-1;;;39557:2;39548:12;;39541:29;39598:2;39589:12;;39379:228;-1:-1;;39379:228;39616:323;;39776:67;39840:2;39835:3;39776:67;;;39876:25;39856:46;;39930:2;39921:12;;39762:177;-1:-1;;39762:177;39948:296;;40125:83;40206:1;40201:3;40125:83;;40253:336;;40431:84;40513:1;40508:3;40431:84;;;-1:-1;;;40528:25;;40581:1;40572:11;;40417:172;-1:-1;;40417:172;40598:362;;40776:85;40858:2;40853:3;40776:85;;;40894:28;40874:49;;40951:2;40942:12;;40762:198;-1:-1;;40762:198;40969:360;;41147:85;41229:2;41224:3;41147:85;;;41265:26;41245:47;;41320:2;41311:12;;41133:196;-1:-1;;41133:196;41338:414;;41516:85;41598:2;41593:3;41516:85;;;41634:34;41614:55;;-1:-1;;;41698:2;41689:12;;41682:33;41743:2;41734:12;;41502:250;-1:-1;;41502:250;41891:551;42094:23;;41891:551;;42030:4;42021:14;;;42123:57;42025:3;42094:23;42123:57;;;42050:136;42265:4;42258:5;42254:16;42248:23;42317:3;42311:4;42307:14;42300:4;42295:3;42291:14;42284:38;42337:67;42399:4;42385:12;42337:67;;42568:539;42759:23;;42568:539;;42695:4;42686:14;;;42788:63;42690:3;42759:23;42788:63;;43393:107;43472:22;43488:5;43472:22;;43507:144;43604:41;43622:22;43638:5;43622:22;;43658:1290;;44019:91;44106:3;44097:6;44019:91;;;44132:2;44127:3;44123:12;44116:19;;44146:75;44217:3;44208:6;44146:75;;;44243:2;44238:3;44234:12;44227:19;;44257:75;44328:3;44319:6;44257:75;;;44354:2;44349:3;44345:12;44338:19;;44368:75;44439:3;44430:6;44368:75;;;44465:2;44460:3;44456:12;44449:19;;44479:75;44550:3;44541:6;44479:75;;;44576:2;44571:3;44567:12;44560:19;;44590:75;44661:3;44652:6;44590:75;;;44687:2;44682:3;44678:12;44671:19;;44701:87;44784:3;44775:6;44701:87;;;44810:1;44805:3;44801:11;44794:18;;44830:93;44919:3;44910:6;44830:93;;;44823:100;44007:941;-1:-1;;;;;;;;;;44007:941;44955:513;;45126:75;45197:3;45188:6;45126:75;;;45223:2;45218:3;45214:12;45207:19;;45237:75;45308:3;45299:6;45237:75;;;45334:2;45329:3;45325:12;45318:19;;45348:71;45415:3;45406:6;45348:71;;;-1:-1;45441:1;45432:11;;45114:354;-1:-1;;;45114:354;45475:282;;45629:103;45728:3;45719:6;45711;45629:103;;45764:254;;45904:89;45989:3;45980:6;45904:89;;46294:961;;46690:95;46781:3;46772:6;46690:95;;;46683:102;;46803:148;46947:3;46803:148;;;46796:155;;46969:95;47060:3;47051:6;46969:95;;;46962:102;;47082:148;47226:3;47082:148;;47262:1122;;47706:95;47797:3;47788:6;47706:95;;;47699:102;;47819:148;47963:3;47819:148;;;47812:155;;47985:95;48076:3;48067:6;47985:95;;;47978:102;;48098:148;48242:3;48098:148;;;48091:155;;48264:95;48355:3;48346:6;48264:95;;48391:533;;48638:95;48729:3;48720:6;48638:95;;;48631:102;;48751:148;48895:3;48751:148;;48931:961;;49327:95;49418:3;49409:6;49327:95;;;49320:102;;49440:148;49584:3;49440:148;;49899:533;;50146:95;50237:3;50228:6;50146:95;;;50139:102;;50259:148;50403:3;50259:148;;50439:511;;50666:148;50810:3;50666:148;;;50659:155;;50825:75;50896:3;50887:6;50825:75;;;-1:-1;50922:2;50913:12;;50647:303;-1:-1;50647:303;50957:533;;51204:148;51348:3;51204:148;;;51197:155;;51370:95;51461:3;51452:6;51370:95;;51497:370;;51695:147;51838:3;51695:147;;51874:800;;52222:148;52366:3;52222:148;;;52215:155;;52388:95;52479:3;52470:6;52388:95;;;52381:102;;52501:148;52645:3;52501:148;;52681:213;52799:2;52784:18;;52813:71;52788:9;52857:6;52813:71;;52901:229;53027:2;53012:18;;53041:79;53016:9;53093:6;53041:79;;53389:340;53543:2;53528:18;;53557:79;53532:9;53609:6;53557:79;;;53647:72;53715:2;53704:9;53700:18;53691:6;53647:72;;53736:428;53910:2;53895:18;;53924:71;53899:9;53968:6;53924:71;;;54043:9;54037:4;54033:20;54028:2;54017:9;54013:18;54006:48;54068:86;54149:4;54140:6;54132;54068:86;;54171:324;54317:2;54302:18;;54331:71;54306:9;54375:6;54331:71;;;54413:72;54481:2;54470:9;54466:18;54457:6;54413:72;;54502:628;54752:2;54766:47;;;54737:18;;54827:102;54737:18;54915:6;54827:102;;;54819:110;;54977:9;54971:4;54967:20;54962:2;54951:9;54947:18;54940:48;55002:118;55115:4;55106:6;55002:118;;55137:449;55349:2;55363:47;;;55334:18;;55424:152;55334:18;55562:6;55424:152;;55593:425;55793:2;55807:47;;;55778:18;;55868:140;55778:18;55994:6;55868:140;;56025:201;56137:2;56122:18;;56151:65;56126:9;56189:6;56151:65;;56233:396;56391:2;56376:18;;56405:65;56380:9;56443:6;56405:65;;;56518:9;56512:4;56508:20;56503:2;56492:9;56488:18;56481:48;56543:76;56614:4;56605:6;56543:76;;56636:213;56754:2;56739:18;;56768:71;56743:9;56812:6;56768:71;;56856:947;57154:3;57139:19;;57169:71;57143:9;57213:6;57169:71;;;57251:66;57313:2;57302:9;57298:18;57289:6;57251:66;;;57328:72;57396:2;57385:9;57381:18;57372:6;57328:72;;;57411;57479:2;57468:9;57464:18;57455:6;57411:72;;;57532:9;57526:4;57522:20;57516:3;57505:9;57501:19;57494:49;57557:86;57638:4;57629:6;57621;57557:86;;;57549:94;;57692:9;57686:4;57682:20;57676:3;57665:9;57661:19;57654:49;57717:76;57788:4;57779:6;57717:76;;;57709:84;57125:678;-1:-1;;;;;;;;;57125:678;57810:911;58090:3;58075:19;;58105:71;58079:9;58149:6;58105:71;;;58187:66;58249:2;58238:9;58234:18;58225:6;58187:66;;;58264:72;58332:2;58321:9;58317:18;58308:6;58264:72;;;58347;58415:2;58404:9;58400:18;58391:6;58347:72;;;58468:9;58462:4;58458:20;58452:3;58441:9;58437:19;58430:49;58493:72;58560:4;58551:6;58493:72;;;58485:80;;58614:9;58608:4;58604:20;58598:3;58587:9;58583:19;58576:49;58639:72;58706:4;58697:6;58639:72;;58728:543;58932:2;58917:18;;58946:71;58921:9;58990:6;58946:71;;;59028:84;59108:2;59097:9;59093:18;59084:6;59028:84;;;59160:9;59154:4;59150:20;59145:2;59134:9;59130:18;59123:48;59185:76;59256:4;59247:6;59185:76;;59278:851;59556:3;59541:19;;59571:71;59545:9;59615:6;59571:71;;;59653:72;59721:2;59710:9;59706:18;59697:6;59653:72;;;59736;59804:2;59793:9;59789:18;59780:6;59736:72;;;59856:9;59850:4;59846:20;59841:2;59830:9;59826:18;59819:48;59881:86;59962:4;59953:6;59945;59881:86;;;59873:94;;60016:9;60010:4;60006:20;60000:3;59989:9;59985:19;59978:49;60041:78;60114:4;60105:6;60041:78;;60136:823;60400:3;60385:19;;60415:71;60389:9;60459:6;60415:71;;;60497:72;60565:2;60554:9;60550:18;60541:6;60497:72;;;60580;60648:2;60637:9;60633:18;60624:6;60580:72;;;60700:9;60694:4;60690:20;60685:2;60674:9;60670:18;60663:48;60725:72;60792:4;60783:6;60725:72;;;60717:80;;60846:9;60840:4;60836:20;60830:3;60819:9;60815:19;60808:49;60871:78;60944:4;60935:6;60871:78;;60966:539;61164:3;61149:19;;61179:71;61153:9;61223:6;61179:71;;;61261:68;61325:2;61314:9;61310:18;61301:6;61261:68;;;61340:72;61408:2;61397:9;61393:18;61384:6;61340:72;;;61423;61491:2;61480:9;61476:18;61467:6;61423:72;;61512:209;61628:2;61613:18;;61642:69;61617:9;61684:6;61642:69;;61728:492;61910:2;61924:47;;;61895:18;;61985:76;61895:18;62047:6;61985:76;;;61977:84;;62109:9;62103:4;62099:20;62094:2;62083:9;62079:18;62072:48;62134:76;62205:4;62196:6;62134:76;;62227:301;62365:2;62379:47;;;62350:18;;62440:78;62350:18;62504:6;62440:78;;62535:407;62726:2;62740:47;;;62711:18;;62801:131;62711:18;62801:131;;62949:407;63140:2;63154:47;;;63125:18;;63215:131;63125:18;63215:131;;63583:324;63729:2;63714:18;;63743:71;63718:9;63787:6;63743:71;;63914:340;64068:2;64053:18;;64082:71;64057:9;64126:6;64082:71;;;64164:80;64240:2;64229:9;64225:18;64216:6;64164:80;;64624:539;64826:2;64811:18;;64840:71;64815:9;64884:6;64840:71;;;64922:72;64990:2;64979:9;64975:18;64966:6;64922:72;;;65042:9;65036:4;65032:20;65027:2;65016:9;65012:18;65005:48;65067:86;65148:4;65139:6;65131;65067:86;;65170:651;65400:3;65385:19;;65415:71;65389:9;65459:6;65415:71;;;65497:72;65565:2;65554:9;65550:18;65541:6;65497:72;;;65580;65648:2;65637:9;65633:18;65624:6;65580:72;;;65700:9;65694:4;65690:20;65685:2;65674:9;65670:18;65663:48;65725:86;65806:4;65797:6;65789;65725:86;;65828:771;66086:3;66071:19;;66101:71;66075:9;66145:6;66101:71;;;66183:72;66251:2;66240:9;66236:18;66227:6;66183:72;;;66266;66334:2;66323:9;66319:18;66310:6;66266:72;;;66349;66417:2;66406:9;66402:18;66393:6;66349:72;;;66432:73;66500:3;66489:9;66485:19;66476:6;66432:73;;;66516;66584:3;66573:9;66569:19;66560:6;66516:73;;66606:256;66668:2;66662:9;66694:17;;;-1:-1;;;;;66754:34;;66790:22;;;66751:62;66748:2;;;66826:1;66823;66816:12;66748:2;66842;66835:22;66646:216;;-1:-1;66646:216;66869:322;;-1:-1;;;;;67038:6;67035:30;67032:2;;;67078:1;67075;67068:12;67032:2;-1:-1;67113:4;67101:17;;;67166:15;;66969:222;67525:317;;-1:-1;;;;;67656:6;67653:30;67650:2;;;67696:1;67693;67686:12;67650:2;-1:-1;67827:4;67763;67740:17;;;;-1:-1;;67736:33;67817:15;;67587:255;68831:148;68952:4;68943:14;;68900:79;69503:134;69603:12;;69574:63;71001:175;71116:19;;;71165:4;71156:14;;71109:67;72599:91;;72661:24;72679:5;72661:24;;72803:85;72869:13;72862:21;;72845:43;72895:72;72957:5;72940:27;72974:144;-1:-1;;;;;;73035:78;;73018:100;73125:134;73201:5;73207:47;73201:5;73207:47;;73266:121;-1:-1;;;;;73328:54;;73311:76;73473:81;73544:4;73533:16;;73516:38;73561:129;;73648:37;73679:5;73648:37;;73697:134;;73788:38;73820:5;73788:38;;73838:121;;73917:37;73948:5;73917:37;;74082:145;74163:6;74158:3;74153;74140:30;-1:-1;74219:1;74201:16;;74194:27;74133:94;74236:268;74301:1;74308:101;74322:6;74319:1;74316:13;74308:101;;;74389:11;;;74383:18;74370:11;;;74363:39;74344:2;74337:10;74308:101;;;74424:6;74421:1;74418:13;74415:2;;;-1:-1;;74489:1;74471:16;;74464:27;74285:219;74512:95;;74576:26;74596:5;74805:89;74869:20;74883:5;74869:20;;74982:88;;75044:21;75059:5;75044:21;;75077:97;75165:2;75145:14;-1:-1;;75141:28;;75125:49;75182:96;75257:3;75253:15;;75225:53;75286:94;75360:2;75356:14;;75328:52;75388:106;75471:2;75464:5;75461:13;75451:2;;75478:9;75501:117;75570:24;75588:5;75570:24;;;75563:5;75560:35;75550:2;;75609:1;75606;75599:12;75765:111;75831:21;75846:5;75831:21;;75883:117;75952:24;75970:5;75952:24;;76007:115;76075:23;76092:5;76075:23;;76129:109;76212:2;76205:5;76202:13;76192:2;;76229:1;76226;76219:12

Swarm Source

bzzr://9ecdeb27b72609ca0e8ec110d047738b99f3d520bc3127dbe5ffeebe65dc2594

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

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.